diff options
-rw-r--r-- | Documentation/gpio.txt | 31 | ||||
-rw-r--r-- | drivers/block/cciss.c | 35 | ||||
-rw-r--r-- | drivers/md/bitmap.c | 4 | ||||
-rw-r--r-- | fs/autofs4/root.c | 6 | ||||
-rw-r--r-- | fs/reiserfs/item_ops.c | 2 | ||||
-rw-r--r-- | kernel/params.c | 4 | ||||
-rw-r--r-- | mm/nommu.c | 1 |
7 files changed, 59 insertions, 24 deletions
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index 989f1130f4f..f8528db967f 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -27,7 +27,7 @@ The exact capabilities of GPIOs vary between systems. Common options: - Output values are writable (high=1, low=0). Some chips also have options about how that value is driven, so that for example only one value might be driven ... supporting "wire-OR" and similar schemes - for the other value. + for the other value (notably, "open drain" signaling). - Input values are likewise readable (1, 0). Some chips support readback of pins configured as "output", which is very useful in such "wire-OR" @@ -247,6 +247,35 @@ with gpio_get_value(), for example to initialize or update driver state when the IRQ is edge-triggered. +Emulating Open Drain Signals +---------------------------- +Sometimes shared signals need to use "open drain" signaling, where only the +low signal level is actually driven. (That term applies to CMOS transistors; +"open collector" is used for TTL.) A pullup resistor causes the high signal +level. This is sometimes called a "wire-AND"; or more practically, from the +negative logic (low=true) perspective this is a "wire-OR". + +One common example of an open drain signal is a shared active-low IRQ line. +Also, bidirectional data bus signals sometimes use open drain signals. + +Some GPIO controllers directly support open drain outputs; many don't. When +you need open drain signaling but your hardware doesn't directly support it, +there's a common idiom you can use to emulate it with any GPIO pin that can +be used as either an input or an output: + + LOW: gpio_direction_output(gpio, 0) ... this drives the signal + and overrides the pullup. + + HIGH: gpio_direction_input(gpio) ... this turns off the output, + so the pullup (or some other device) controls the signal. + +If you are "driving" the signal high but gpio_get_value(gpio) reports a low +value (after the appropriate rise time passes), you know some other component +is driving the shared signal low. That's not necessarily an error. As one +common example, that's how I2C clocks are stretched: a slave that needs a +slower clock delays the rising edge of SCK, and the I2C master adjusts its +signaling rate accordingly. + What do these conventions omit? =============================== diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 14d780666c0..65a725cd342 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3423,6 +3423,25 @@ static void cciss_remove_one(struct pci_dev *pdev) "already be removed \n"); return; } + + remove_proc_entry(hba[i]->devname, proc_cciss); + unregister_blkdev(hba[i]->major, hba[i]->devname); + + /* remove it from the disk list */ + for (j = 0; j < CISS_MAX_LUN; j++) { + struct gendisk *disk = hba[i]->gendisk[j]; + if (disk) { + request_queue_t *q = disk->queue; + + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (q) + blk_cleanup_queue(q); + } + } + + cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ + /* Turn board interrupts off and send the flush cache command */ /* sendcmd will turn off interrupt, and send the flush... * To write all data in the battery backed cache to disks */ @@ -3444,22 +3463,6 @@ static void cciss_remove_one(struct pci_dev *pdev) #endif /* CONFIG_PCI_MSI */ iounmap(hba[i]->vaddr); - cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ - unregister_blkdev(hba[i]->major, hba[i]->devname); - remove_proc_entry(hba[i]->devname, proc_cciss); - - /* remove it from the disk list */ - for (j = 0; j < CISS_MAX_LUN; j++) { - struct gendisk *disk = hba[i]->gendisk[j]; - if (disk) { - request_queue_t *q = disk->queue; - - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); - if (q) - blk_cleanup_queue(q); - } - } pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 5554adaa58f..e61e0efe9ec 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -863,9 +863,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */ bitmap->filemap_attr = kzalloc( - (((num_pages*4/8)+sizeof(unsigned long)-1) - /sizeof(unsigned long)) - *sizeof(unsigned long), + roundup( DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), GFP_KERNEL); if (!bitmap->filemap_attr) goto out; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index b4631046867..d0e9b3a3905 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -470,9 +470,6 @@ void autofs4_dentry_release(struct dentry *de) if (inf) { struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); - inf->dentry = NULL; - inf->inode = NULL; - if (sbi) { spin_lock(&sbi->rehash_lock); if (!list_empty(&inf->rehash)) @@ -480,6 +477,9 @@ void autofs4_dentry_release(struct dentry *de) spin_unlock(&sbi->rehash_lock); } + inf->dentry = NULL; + inf->inode = NULL; + autofs4_free_ino(inf); } } diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index b9b423b22a8..9475557ab49 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c @@ -23,7 +23,7 @@ static void sd_decrement_key(struct cpu_key *key) { key->on_disk_key.k_objectid--; set_cpu_key_k_type(key, TYPE_ANY); - set_cpu_key_k_offset(key, (loff_t) (-1)); + set_cpu_key_k_offset(key, (loff_t)(~0ULL >> 1)); } static int sd_is_left_mergeable(struct reiserfs_key *key, unsigned long bsize) diff --git a/kernel/params.c b/kernel/params.c index e265b13195b..1fc4ac746cd 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -356,6 +356,10 @@ int param_set_copystring(const char *val, struct kernel_param *kp) { struct kparam_string *kps = kp->arg; + if (!val) { + printk(KERN_ERR "%s: missing param set value\n", kp->name); + return -EINVAL; + } if (strlen(val)+1 > kps->maxlen) { printk(KERN_ERR "%s: string doesn't fit in %u chars.\n", kp->name, kps->maxlen-1); diff --git a/mm/nommu.c b/mm/nommu.c index cbbc1377481..1f60194d9b9 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -45,6 +45,7 @@ int heap_stack_gap = 0; EXPORT_SYMBOL(mem_map); EXPORT_SYMBOL(__vm_enough_memory); +EXPORT_SYMBOL(num_physpages); /* list of shareable VMAs */ struct rb_root nommu_vma_tree = RB_ROOT; |