Commit 9b45d209 authored by Paul Mackerras's avatar Paul Mackerras

Merge samba.org:/home/paulus/kernel/linux-2.5

into samba.org:/home/paulus/kernel/for-linus-ppc64
parents 9d6cb0a2 ec7ee636
......@@ -1394,7 +1394,8 @@ S: USA
N: Marcel Holtmann
E: marcel@holtmann.org
W: http://www.holtmann.org
D: Author of the Linux Bluetooth Subsystem PC Card drivers
D: Author and maintainer of the various Bluetooth HCI drivers
D: Various other Bluetooth related patches, cleanups and fixes
S: Germany
N: Rob W. W. Hooft
......
......@@ -328,18 +328,66 @@ M: axboe@suse.de
L: linux-kernel@vger.kernel.org
S: Maintained
BLUETOOTH SUBSYSTEM (BlueZ)
BLUETOOTH SUBSYSTEM
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BLUETOOTH SUBSYSTEM (PC Card Drivers)
BLUETOOTH RFCOMM LAYER
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BLUETOOTH BNEP LAYER
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BLUETOOTH HCI USB DRIVER
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BLUETOOTH HCI UART DRIVER
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BLUETOOTH HCI DTL1 DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/
S: Maintained
BLUETOOTH HCI BLUECARD DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/
S: Maintained
BLUETOOTH HCI BT3C DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/
S: Maintained
BLUETOOTH HCI BTUART DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/
S: Maintained
BLUETOOTH HCI VHCI DRIVER
P: Maxim Krasnyansky
M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
BONDING DRIVER
P: Chad Tindel
M: ctindel@users.sourceforge.net
......
......@@ -39,7 +39,7 @@ static int delay_at_last_interrupt;
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */
static unsigned long long monotonic_base;
static rwlock_t monotonic_lock = RW_LOCK_UNLOCKED;
static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
/* convert from cycles(64bits) => nanoseconds (64bits)
* basic equation:
......@@ -111,12 +111,14 @@ static unsigned long get_offset_tsc(void)
static unsigned long long monotonic_clock_tsc(void)
{
unsigned long long last_offset, this_offset, base;
unsigned seq;
/* atomically read monotonic base & last_offset */
read_lock_irq(&monotonic_lock);
do {
seq = read_seqbegin(&monotonic_lock);
last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
base = monotonic_base;
read_unlock_irq(&monotonic_lock);
} while (read_seqretry(&monotonic_lock, seq));
/* Read the Time Stamp Counter */
rdtscll(this_offset);
......@@ -135,7 +137,7 @@ static void mark_offset_tsc(void)
unsigned long long this_offset, last_offset;
static int lost_count = 0;
write_lock(&monotonic_lock);
write_seqlock(&monotonic_lock);
last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
/*
* It is important that these two operations happen almost at
......@@ -204,7 +206,7 @@ static void mark_offset_tsc(void)
/* update the monotonic base value */
this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
monotonic_base += cycles_2_ns(this_offset - last_offset);
write_unlock(&monotonic_lock);
write_sequnlock(&monotonic_lock);
/* calculate delay_at_last_interrupt */
count = ((LATCH-1) - count) * TICK_SIZE;
......@@ -236,7 +238,7 @@ static void mark_offset_tsc_hpet(void)
unsigned long long this_offset, last_offset;
unsigned long offset, temp, hpet_current;
write_lock(&monotonic_lock);
write_seqlock(&monotonic_lock);
last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
/*
* It is important that these two operations happen almost at
......@@ -264,7 +266,7 @@ static void mark_offset_tsc_hpet(void)
/* update the monotonic base value */
this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
monotonic_base += cycles_2_ns(this_offset - last_offset);
write_unlock(&monotonic_lock);
write_sequnlock(&monotonic_lock);
/* calculate delay_at_last_interrupt */
/*
......
......@@ -1706,10 +1706,6 @@ void __init mem_init(void)
unsigned long addr, last;
int i;
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
#endif
i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
i += 1;
sparc64_valid_addr_bitmap = (unsigned long *)
......
......@@ -302,6 +302,7 @@ static int hci_usb_open(struct hci_dev *hdev)
hci_usb_bulk_rx_submit(husb);
#ifdef CONFIG_BT_USB_SCO
if (husb->isoc_iface)
hci_usb_isoc_rx_submit(husb);
#endif
} else {
......
......@@ -1562,6 +1562,20 @@ config CODA_FS
whenever you want), say M here and read
<file:Documentation/modules.txt>. The module will be called coda.
config CODA_FS_OLD_API
bool "Use 96-bit Coda file identifiers"
depends on CODA_FS
help
A new kernel-userspace API had to be introduced for Coda v6.0
to support larger 128-bit file identifiers as needed by the
new realms implementation.
However this new API is not backward compatible with older
clients. If you really need to run the old Coda userspace
cache manager then say Y.
For most cases you probably want to say N.
config INTERMEZZO_FS
tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
......
......@@ -23,13 +23,16 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_cache.h>
static atomic_t permission_epoch = ATOMIC_INIT(0);
/* replace or extend an acl cache hit */
void coda_cache_enter(struct inode *inode, int mask)
{
struct coda_inode_info *cii = ITOC(inode);
if ( !coda_cred_ok(&cii->c_cached_cred) ) {
coda_load_creds(&cii->c_cached_cred);
cii->c_cached_epoch = atomic_read(&permission_epoch);
if (cii->c_uid != current->fsuid) {
cii->c_uid = current->fsuid;
cii->c_cached_perm = mask;
} else
cii->c_cached_perm |= mask;
......@@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode)
cii->c_cached_perm = 0;
}
/* remove all acl caches for a principal (or all principals when cred == NULL)*/
void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred)
/* remove all acl caches */
void coda_cache_clear_all(struct super_block *sb)
{
struct coda_sb_info *sbi;
struct coda_inode_info *cii;
struct list_head *tmp;
sbi = coda_sbp(sb);
if (!sbi) BUG();
list_for_each(tmp, &sbi->sbi_cihead)
{
cii = list_entry(tmp, struct coda_inode_info, c_cilist);
if (!cred || coda_cred_eq(cred, &cii->c_cached_cred))
cii->c_cached_perm = 0;
}
atomic_inc(&permission_epoch);
}
......@@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask)
struct coda_inode_info *cii = ITOC(inode);
int hit;
hit = ((mask & cii->c_cached_perm) == mask) &&
coda_cred_ok(&cii->c_cached_cred);
hit = (mask & cii->c_cached_perm) == mask &&
cii->c_uid == current->fsuid &&
cii->c_cached_epoch == atomic_read(&permission_epoch);
return hit;
}
......
......@@ -11,18 +11,9 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
{
if (fid1->Vnode != fid2->Vnode) return 0;
if (fid1->Volume != fid2->Volume) return 0;
if (fid1->Unique != fid2->Unique) return 0;
return 1;
}
inline int coda_isnullfid(ViceFid *fid)
{
if (fid->Vnode || fid->Volume || fid->Unique) return 0;
return 1;
return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
}
static struct inode_operations coda_symlink_inode_operations = {
......@@ -52,13 +43,13 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
static int coda_test_inode(struct inode *inode, void *data)
{
ViceFid *fid = (ViceFid *)data;
struct CodaFid *fid = (struct CodaFid *)data;
return coda_fideq(&(ITOC(inode)->c_fid), fid);
}
static int coda_set_inode(struct inode *inode, void *data)
{
ViceFid *fid = (ViceFid *)data;
struct CodaFid *fid = (struct CodaFid *)data;
ITOC(inode)->c_fid = *fid;
return 0;
}
......@@ -68,12 +59,11 @@ static int coda_fail_inode(struct inode *inode, void *data)
return -1;
}
struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
struct coda_vattr * attr)
{
struct inode *inode;
struct coda_inode_info *cii;
struct coda_sb_info *sbi = coda_sbp(sb);
unsigned long hash = coda_f2i(fid);
inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
......@@ -86,7 +76,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
/* we still need to set i_ino for things like stat(2) */
inode->i_ino = hash;
cii->c_mapcount = 0;
list_add(&cii->c_cilist, &sbi->sbi_cihead);
unlock_new_inode(inode);
}
......@@ -101,7 +90,7 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
- link the two up if this is needed
- fill in the attributes
*/
int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_block *sb)
{
struct coda_vattr attr;
int error;
......@@ -122,8 +111,8 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
}
void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
struct ViceFid *newfid)
void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid,
struct CodaFid *newfid)
{
struct coda_inode_info *cii;
unsigned long hash = coda_f2i(newfid);
......@@ -142,7 +131,7 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
}
/* convert a fid to an inode. */
struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)
{
struct inode *inode;
unsigned long hash = coda_f2i(fid);
......
......@@ -25,10 +25,14 @@
int coda_fake_statfs;
/* print a fid */
char * coda_f2s(ViceFid *f)
char * coda_f2s(struct CodaFid *f)
{
static char s[60];
sprintf(s, "(%-#lx.%-#lx.%-#lx)", f->Volume, f->Vnode, f->Unique);
#ifdef CODA_FS_OLD_API
sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
#else
sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
#endif
return s;
}
......@@ -45,30 +49,6 @@ int coda_isroot(struct inode *i)
return ( i->i_sb->s_root->d_inode == i );
}
/* put the current process credentials in the cred */
void coda_load_creds(struct coda_cred *cred)
{
cred->cr_uid = (vuid_t) current->uid;
cred->cr_euid = (vuid_t) current->euid;
cred->cr_suid = (vuid_t) current->suid;
cred->cr_fsuid = (vuid_t) current->fsuid;
cred->cr_groupid = (vgid_t) current->gid;
cred->cr_egid = (vgid_t) current->egid;
cred->cr_sgid = (vgid_t) current->sgid;
cred->cr_fsgid = (vgid_t) current->fsgid;
}
int coda_cred_ok(struct coda_cred *cred)
{
return(current->fsuid == cred->cr_fsuid);
}
int coda_cred_eq(struct coda_cred *cred1, struct coda_cred *cred2)
{
return (cred1->cr_fsuid == cred2->cr_fsuid);
}
unsigned short coda_flags_to_cflags(unsigned short flags)
{
unsigned short coda_flags = 0;
......@@ -215,58 +195,3 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
}
}
void print_vattr(struct coda_vattr *attr)
{
char *typestr;
switch (attr->va_type) {
case C_VNON:
typestr = "C_VNON";
break;
case C_VREG:
typestr = "C_VREG";
break;
case C_VDIR:
typestr = "C_VDIR";
break;
case C_VBLK:
typestr = "C_VBLK";
break;
case C_VCHR:
typestr = "C_VCHR";
break;
case C_VLNK:
typestr = "C_VLNK";
break;
case C_VSOCK:
typestr = "C_VSCK";
break;
case C_VFIFO:
typestr = "C_VFFO";
break;
case C_VBAD:
typestr = "C_VBAD";
break;
default:
typestr = "????";
break;
}
printk("attr: type %s (%o) mode %o uid %d gid %d rdev %d\n",
typestr, (int)attr->va_type, (int)attr->va_mode,
(int)attr->va_uid, (int)attr->va_gid, (int)attr->va_rdev);
printk(" fileid %d nlink %d size %d blocksize %d bytes %d\n",
(int)attr->va_fileid, (int)attr->va_nlink,
(int)attr->va_size,
(int)attr->va_blocksize,(int)attr->va_bytes);
printk(" gen %ld flags %ld\n",
attr->va_gen, attr->va_flags);
printk(" atime sec %d nsec %d\n",
(int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec);
printk(" mtime sec %d nsec %d\n",
(int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec);
printk(" ctime sec %d nsec %d\n",
(int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec);
}
......@@ -93,7 +93,7 @@ struct file_operations coda_dir_operations = {
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{
struct inode *res_inode = NULL;
struct ViceFid resfid = {0,0,0};
struct CodaFid resfid = { { 0, } };
int dropme = 0; /* to indicate entry should not be cached */
int type = 0;
int error = 0;
......@@ -196,7 +196,7 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na
const char *name=de->d_name.name;
int length=de->d_name.len;
struct inode *inode;
struct ViceFid newfid;
struct CodaFid newfid;
struct coda_vattr attrs;
lock_kernel();
......@@ -236,7 +236,7 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev
const char *name=de->d_name.name;
int length=de->d_name.len;
struct inode *inode;
struct ViceFid newfid;
struct CodaFid newfid;
struct coda_vattr attrs;
if ( coda_hasmknod == 0 )
......@@ -283,7 +283,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
const char *name = de->d_name.name;
int len = de->d_name.len;
int error;
struct ViceFid newfid;
struct CodaFid newfid;
lock_kernel();
coda_vfs_stat.mkdir++;
......@@ -588,8 +588,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
break;
}
/* validate whether the directory file actually makes sense */
if (vdir->d_reclen < vdir_size + vdir->d_namlen ||
vdir->d_namlen > CODA_MAXNAMLEN) {
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
printk("coda_venus_readdir: Invalid dir: %ld\n",
filp->f_dentry->d_inode->i_ino);
ret = -EBADF;
......
......@@ -136,7 +136,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
cfi->cfi_magic = CODA_MAGIC;
cfi->cfi_mapcount = 0;
cfi->cfi_container = host_file;
coda_load_creds(&cfi->cfi_cred);
BUG_ON(coda_file->private_data != NULL);
coda_file->private_data = cfi;
......@@ -176,7 +175,7 @@ int coda_flush(struct file *coda_file)
coda_inode = coda_file->f_dentry->d_inode;
err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
&cfi->cfi_cred);
coda_file->f_uid);
if (err == -EOPNOTSUPP) {
use_coda_close = 1;
......@@ -214,7 +213,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
if (use_coda_close)
err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
coda_flags, &cfi->cfi_cred);
coda_flags, coda_file->f_uid);
host_inode = cfi->cfi_container->f_dentry->d_inode;
cii = ITOC(coda_inode);
......
......@@ -44,10 +44,9 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, SLAB_KERNEL);
if (!ei)
return NULL;
memset(&ei->c_fid, 0, sizeof(struct ViceFid));
memset(&ei->c_fid, 0, sizeof(struct CodaFid));
ei->c_flags = 0;
INIT_LIST_HEAD(&ei->c_cilist);
memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred));
ei->c_uid = 0;
ei->c_cached_perm = 0;
return &ei->vfs_inode;
}
......@@ -139,7 +138,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
struct inode *root = 0;
struct coda_sb_info *sbi = NULL;
struct venus_comm *vc = NULL;
ViceFid fid;
struct CodaFid fid;
int error;
int idx;
......@@ -169,9 +168,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
vc->vc_sb = sb;
sbi->sbi_sb = sb;
sbi->sbi_vcomm = vc;
INIT_LIST_HEAD(&sbi->sbi_cihead);
sb->s_fs_info = sbi;
sb->s_blocksize = 1024; /* XXXXX what do we put here?? */
......@@ -218,7 +215,6 @@ static void coda_put_super(struct super_block *sb)
sbi = coda_sbp(sb);
sbi->sbi_vcomm->vc_sb = NULL;
list_del_init(&sbi->sbi_cihead);
printk("Coda: Bye bye.\n");
kfree(sbi);
......@@ -226,9 +222,6 @@ static void coda_put_super(struct super_block *sb)
static void coda_clear_inode(struct inode *inode)
{
struct coda_inode_info *cii = ITOC(inode);
list_del_init(&cii->c_cilist);
coda_cache_clear_inode(inode);
}
......
......@@ -61,7 +61,6 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
struct venus_comm coda_comms[MAX_CODADEVS];
kmem_cache_t *cii_cache, *cred_cache, *upc_cache;
/*
* Device operations
......@@ -126,13 +125,13 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
}
if ( nbytes < sizeof(struct coda_out_hdr) ) {
printk("coda_downcall opc %ld uniq %ld, not enough!\n",
printk("coda_downcall opc %d uniq %d, not enough!\n",
hdr.opcode, hdr.unique);
count = nbytes;
goto out;
}
if ( nbytes > size ) {
printk("Coda: downcall opc %ld, uniq %ld, too much!",
printk("Coda: downcall opc %d, uniq %d, too much!",
hdr.opcode, hdr.unique);
nbytes = size;
}
......@@ -171,7 +170,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
unlock_kernel();
if (!req) {
printk("psdev_write: msg (%ld, %ld) not found\n",
printk("psdev_write: msg (%d, %d) not found\n",
hdr.opcode, hdr.unique);
retval = -ESRCH;
goto out;
......@@ -179,7 +178,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
/* move data into response buffer. */
if (req->uc_outSize < nbytes) {
printk("psdev_write: too much cnt: %d, cnt: %ld, opc: %ld, uniq: %ld.\n",
printk("psdev_write: too much cnt: %d, cnt: %ld, opc: %d, uniq: %d.\n",
req->uc_outSize, (long)nbytes, hdr.opcode, hdr.unique);
nbytes = req->uc_outSize; /* don't have more space! */
}
......@@ -325,10 +324,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
}
/* Wakeup clients so they can return. */
lh = vcp->vc_pending.next;
next = lh;
while ( (lh = next) != &vcp->vc_pending) {
next = lh->next;
list_for_each_safe(lh, next, &vcp->vc_pending) {
req = list_entry(lh, struct upc_req, uc_chain);
/* Async requests need to be freed here */
if (req->uc_flags & REQ_ASYNC) {
......@@ -340,9 +336,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
wake_up(&req->uc_sleep);
}
lh = &vcp->vc_processing;
while ( (lh = lh->next) != &vcp->vc_processing) {
req = list_entry(lh, struct upc_req, uc_chain);
list_for_each_entry(req, &vcp->vc_processing, uc_chain) {
req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep);
}
......@@ -390,7 +384,13 @@ static int __init init_coda(void)
{
int status;
int i;
printk(KERN_INFO "Coda Kernel/Venus communications, v5.3.15, coda@cs.cmu.edu\n");
printk(KERN_INFO "Coda Kernel/Venus communications, "
#ifdef CODA_FS_OLD_API
"v5.3.20"
#else
"v6.0.0"
#endif
", coda@cs.cmu.edu\n");
status = coda_init_inodecache();
if (status)
......
This diff is collapsed.
......@@ -3041,10 +3041,11 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
jfs_ip->next_index = le32_to_cpu(dip->di_next_index);
jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec);
jfs_ip->acltype = le32_to_cpu(dip->di_acltype);
jfs_ip->dev = le32_to_cpu(dip->di_rdev);
if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) {
jfs_ip->dev = le32_to_cpu(dip->di_rdev);
ip->i_rdev = old_decode_dev(jfs_ip->dev);
}
if (S_ISDIR(ip->i_mode)) {
memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384);
......@@ -3101,6 +3102,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip)
dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime);
dip->di_otime.tv_nsec = 0;
dip->di_acltype = cpu_to_le32(jfs_ip->acltype);
if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
dip->di_rdev = cpu_to_le32(jfs_ip->dev);
}
......
......@@ -4,4 +4,13 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
static void check_bugs(void) { }
#include <linux/config.h>
extern unsigned long loops_per_jiffy;
static void check_bugs(void)
{
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
#endif
}
......@@ -13,12 +13,6 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_SMP
#include <asm/smp.h>
#else
extern unsigned long loops_per_jiffy;
#endif
static __inline__ void __delay(unsigned long loops)
{
__asm__ __volatile__(
......
This diff is collapsed.
......@@ -13,7 +13,7 @@
/* credential cache */
void coda_cache_enter(struct inode *inode, int mask);
void coda_cache_clear_inode(struct inode *);
void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred);
void coda_cache_clear_all(struct super_block *sb);
int coda_cache_check(struct inode *inode, int mask);
/* for downcalls and attributes and lookups */
......
......@@ -17,11 +17,12 @@
* coda fs inode data
*/
struct coda_inode_info {
struct ViceFid c_fid; /* Coda identifier */
struct CodaFid c_fid; /* Coda identifier */
u_short c_flags; /* flags (see below) */
struct list_head c_cilist; /* list of all coda inodes */
unsigned int c_mapcount; /* nr of times this inode is mapped */
struct coda_cred c_cached_cred; /* credentials of cached perms */
unsigned int c_cached_epoch; /* epoch for cached permissions */
vuid_t c_uid; /* fsuid for cached permissions */
unsigned int c_cached_perm; /* cached access permissions */
struct inode vfs_inode;
};
......@@ -34,7 +35,6 @@ struct coda_file_info {
int cfi_magic; /* magic number */
struct file *cfi_container; /* container file for this cnode */
unsigned int cfi_mapcount; /* nr of times this file is mapped */
struct coda_cred cfi_cred; /* credentials of opener */
};
#define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data))
......@@ -45,11 +45,11 @@ struct coda_file_info {
#define C_DYING 0x4 /* from venus (which died) */
#define C_PURGE 0x8
int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
struct inode *coda_iget(struct super_block *sb, struct ViceFid *fid, struct coda_vattr *attr);
int coda_cnode_make(struct inode **, struct CodaFid *, struct super_block *);
struct inode *coda_iget(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *attr);
int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb);
void coda_replace_fid(struct inode *, ViceFid *, ViceFid *);
struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);
void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
#endif
#endif
......@@ -42,26 +42,21 @@ int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *);
int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *);
int coda_isnullfid(ViceFid *fid);
/* global variables */
extern int coda_fake_statfs;
/* this file: heloers */
static __inline__ struct ViceFid *coda_i2f(struct inode *);
static __inline__ struct CodaFid *coda_i2f(struct inode *);
static __inline__ char *coda_i2s(struct inode *);
static __inline__ void coda_flag_inode(struct inode *, int flag);
char *coda_f2s(ViceFid *f);
char *coda_f2s(struct CodaFid *f);
int coda_isroot(struct inode *i);
int coda_iscontrol(const char *name, size_t length);
void coda_load_creds(struct coda_cred *cred);
void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
unsigned short coda_flags_to_cflags(unsigned short);
void print_vattr( struct coda_vattr *attr );
int coda_cred_ok(struct coda_cred *cred);
int coda_cred_eq(struct coda_cred *cred1, struct coda_cred *cred2);
/* sysctl.h */
void coda_sysctl_init(void);
......@@ -88,7 +83,7 @@ static inline struct coda_inode_info *ITOC(struct inode *inode)
return list_entry(inode, struct coda_inode_info, vfs_inode);
}
static __inline__ struct ViceFid *coda_i2f(struct inode *inode)
static __inline__ struct CodaFid *coda_i2f(struct inode *inode)
{
return &(ITOC(inode)->c_fid);
}
......
......@@ -6,13 +6,11 @@
#define CODA_SUPER_MAGIC 0x73757245
struct statfs;
struct kstatfs;
struct coda_sb_info
{
struct venus_comm * sbi_vcomm;
struct super_block *sbi_sb;
struct list_head sbi_cihead;
struct venus_comm *sbi_vcomm;
};
/* communication pending/processing queues */
......@@ -33,46 +31,45 @@ static inline struct coda_sb_info *coda_sbp(struct super_block *sb)
/* upcalls */
int venus_rootfid(struct super_block *sb, ViceFid *fidp);
int venus_getattr(struct super_block *sb, struct ViceFid *fid,
int venus_rootfid(struct super_block *sb, struct CodaFid *fidp);
int venus_getattr(struct super_block *sb, struct CodaFid *fid,
struct coda_vattr *attr);
int venus_setattr(struct super_block *, struct ViceFid *,
struct coda_vattr *);
int venus_lookup(struct super_block *sb, struct ViceFid *fid,
int venus_setattr(struct super_block *, struct CodaFid *, struct coda_vattr *);
int venus_lookup(struct super_block *sb, struct CodaFid *fid,
const char *name, int length, int *type,
struct ViceFid *resfid);
int venus_store(struct super_block *sb, struct ViceFid *fid, int flags,
struct coda_cred *);
int venus_release(struct super_block *sb, struct ViceFid *fid, int flags);
int venus_close(struct super_block *sb, struct ViceFid *fid, int flags,
struct coda_cred *);
int venus_open(struct super_block *sb, struct ViceFid *fid,
int flags, struct file **f);
int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid,
struct CodaFid *resfid);
int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
vuid_t uid);
int venus_release(struct super_block *sb, struct CodaFid *fid, int flags);
int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
vuid_t uid);
int venus_open(struct super_block *sb, struct CodaFid *fid, int flags,
struct file **f);
int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length,
struct ViceFid *newfid, struct coda_vattr *attrs);
int venus_create(struct super_block *sb, struct ViceFid *dirfid,
struct CodaFid *newfid, struct coda_vattr *attrs);
int venus_create(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length, int excl, int mode, dev_t rdev,
struct ViceFid *newfid, struct coda_vattr *attrs) ;
int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid,
struct CodaFid *newfid, struct coda_vattr *attrs) ;
int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length);
int venus_remove(struct super_block *sb, struct ViceFid *dirfid,
int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length);
int venus_readlink(struct super_block *sb, struct ViceFid *fid,
int venus_readlink(struct super_block *sb, struct CodaFid *fid,
char *buffer, int *length);
int venus_rename(struct super_block *, struct ViceFid *new_fid,
struct ViceFid *old_fid, size_t old_length,
int venus_rename(struct super_block *, struct CodaFid *new_fid,
struct CodaFid *old_fid, size_t old_length,
size_t new_length, const char *old_name,
const char *new_name);
int venus_link(struct super_block *sb, struct ViceFid *fid,
struct ViceFid *dirfid, const char *name, int len );
int venus_symlink(struct super_block *sb, struct ViceFid *fid,
int venus_link(struct super_block *sb, struct CodaFid *fid,
struct CodaFid *dirfid, const char *name, int len );
int venus_symlink(struct super_block *sb, struct CodaFid *fid,
const char *name, int len, const char *symname, int symlen);
int venus_access(struct super_block *sb, struct ViceFid *fid, int mask);
int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
unsigned int cmd, struct PioctlData *data);
int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
int venus_fsync(struct super_block *sb, struct ViceFid *fid);
int venus_fsync(struct super_block *sb, struct CodaFid *fid);
int venus_statfs(struct super_block *sb, struct kstatfs *sfs);
......
......@@ -122,6 +122,52 @@ struct ipv6hdr {
struct in6_addr daddr;
};
/*
* This structure contains configuration options per IPv6 link.
*/
struct ipv6_devconf {
__s32 forwarding;
__s32 hop_limit;
__s32 mtu6;
__s32 accept_ra;
__s32 accept_redirects;
__s32 autoconf;
__s32 dad_transmits;
__s32 rtr_solicits;
__s32 rtr_solicit_interval;
__s32 rtr_solicit_delay;
#ifdef CONFIG_IPV6_PRIVACY
__s32 use_tempaddr;
__s32 temp_valid_lft;
__s32 temp_prefered_lft;
__s32 regen_max_retry;
__s32 max_desync_factor;
#endif
void *sysctl;
};
/* index values for the variables in ipv6_devconf */
enum {
DEVCONF_FORWARDING = 0,
DEVCONF_HOPLIMIT,
DEVCONF_MTU6,
DEVCONF_ACCEPT_RA,
DEVCONF_ACCEPT_REDIRECTS,
DEVCONF_AUTOCONF,
DEVCONF_DAD_TRANSMITS,
DEVCONF_RTR_SOLICITS,
DEVCONF_RTR_SOLICIT_INTERVAL,
DEVCONF_RTR_SOLICIT_DELAY,
#ifdef CONFIG_IPV6_PRIVACY
DEVCONF_USE_TEMPADDR,
DEVCONF_TEMP_VALID_LFT,
DEVCONF_TEMP_PREFERED_LFT,
DEVCONF_REGEN_MAX_RETRY,
DEVCONF_MAX_DESYNC_FACTOR,
#endif
DEVCONF_MAX
};
#ifdef __KERNEL__
#include <linux/in6.h> /* struct sockaddr_in6 */
#include <linux/icmpv6.h>
......
......@@ -28,8 +28,6 @@
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/device.h>
#include <linux/percpu.h>
#include <asm/atomic.h>
#include <asm/cache.h>
......@@ -37,6 +35,8 @@
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/device.h>
#include <linux/percpu.h>
struct divert_blk;
struct vlan_group;
......
......@@ -185,9 +185,10 @@ static inline void proc_net_remove(const char *name)
#else
#define proc_root_driver NULL
#define proc_net_fops_create(name,mode,fops) do {} while(0)
static inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode,
get_info_t *get_info) {return NULL;}
#define proc_net NULL
#define proc_net_fops_create(name, mode, fops) ({ (void)(mode), NULL; })
#define proc_net_create(name, mode, info) ({ (void)(mode), NULL; })
static inline void proc_net_remove(const char *name) {}
static inline struct dentry *proc_pid_unhash(struct task_struct *p) { return NULL; }
......
......@@ -508,10 +508,12 @@ enum
#define IFLA_MASTER IFLA_MASTER
IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
#define IFLA_WIRELESS IFLA_WIRELESS
IFLA_PROTINFO, /* Protocol specific information for a link */
#define IFLA_PROTINFO IFLA_PROTINFO
};
#define IFLA_MAX IFLA_WIRELESS
#define IFLA_MAX IFLA_PROTINFO
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
......@@ -545,6 +547,18 @@ enum
for IPIP tunnels, when route to endpoint is allowed to change)
*/
/* Subtype attributes for IFLA_PROTINFO */
enum
{
IFLA_INET6_UNSPEC,
IFLA_INET6_FLAGS, /* link flags */
IFLA_INET6_CONF, /* sysctl parameters */
IFLA_INET6_STATS, /* statistics */
IFLA_INET6_MCAST, /* MC things. What of them? */
};
#define IFLA_INET6_MAX IFLA_INET6_MCAST
/*****************************************************************
* Traffic control messages.
****/
......
......@@ -131,7 +131,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags);
uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
int bt_sock_w4_connect(struct sock *sk, int flags);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
......
......@@ -304,6 +304,8 @@ struct hci_cp_inquiry {
__u8 num_rsp;
} __attribute__ ((packed));
#define OCF_INQUIRY_CANCEL 0x0002
#define OCF_LINK_KEY_REPLY 0x000B
#define OCF_LINK_KEY_NEG_REPLY 0x000C
struct hci_cp_link_key_reply {
......
......@@ -220,6 +220,7 @@ struct l2cap_pinfo {
__u32 link_mode;
__u8 conf_state;
__u8 conf_retry;
__u16 conf_mtu;
__u8 ident;
......@@ -234,6 +235,7 @@ struct l2cap_pinfo {
#define L2CAP_CONF_REQ_SENT 0x01
#define L2CAP_CONF_INPUT_DONE 0x02
#define L2CAP_CONF_OUTPUT_DONE 0x04
#define L2CAP_CONF_MAX_RETRIES 2
void l2cap_load(void);
......
......@@ -16,7 +16,12 @@
#define _NET_IF_INET6_H
#include <net/snmp.h>
#include <linux/ipv6.h>
/* inet6_dev.if_flags */
#define IF_RA_OTHERCONF 0x80
#define IF_RA_MANAGED 0x40
#define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10
......@@ -132,28 +137,6 @@ struct ifacaddr6
#define IFA_SITE IPV6_ADDR_SITELOCAL
#define IFA_GLOBAL 0x0000U
struct ipv6_devconf
{
int forwarding;
int hop_limit;
int mtu6;
int accept_ra;
int accept_redirects;
int autoconf;
int dad_transmits;
int rtr_solicits;
int rtr_solicit_interval;
int rtr_solicit_delay;
#ifdef CONFIG_IPV6_PRIVACY
int use_tempaddr;
int temp_valid_lft;
int temp_prefered_lft;
int regen_max_retry;
int max_desync_factor;
#endif
void *sysctl;
};
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6);
......
......@@ -27,7 +27,7 @@
*
* $Id: af_bluetooth.c,v 1.3 2002/04/17 17:37:15 maxk Exp $
*/
#define VERSION "2.2"
#define VERSION "2.3"
#include <linux/config.h>
#include <linux/module.h>
......@@ -272,39 +272,35 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
return mask;
}
int bt_sock_w4_connect(struct sock *sk, int flags)
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
DECLARE_WAITQUEUE(wait, current);
long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
int err = 0;
BT_DBG("sk %p", sk);
add_wait_queue(sk->sk_sleep, &wait);
while (sk->sk_state != BT_CONNECTED) {
while (sk->sk_state != state) {
set_current_state(TASK_INTERRUPTIBLE);
if (!timeo) {
err = -EAGAIN;
break;
}
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
err = 0;
if (sk->sk_state == BT_CONNECTED)
break;
if (sk->sk_err) {
err = sock_error(sk);
break;
}
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
}
set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sk_sleep, &wait);
......
......@@ -168,11 +168,11 @@ struct bnep_session {
u64 mc_filter;
struct socket *sock;
struct net_device dev;
struct net_device *dev;
struct net_device_stats stats;
};
int bnep_net_init(struct net_device *dev);
void bnep_net_setup(struct net_device *dev);
int bnep_sock_init(void);
int bnep_sock_cleanup(void);
......
......@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
s->mc_filter = 0;
/* Always send broadcast */
set_bit(bnep_mc_hash(s->dev.broadcast), (ulong *) &s->mc_filter);
set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
/* Add address ranges to the multicast hash */
for (; n > 0; n--) {
......@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = {
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = &s->dev;
struct net_device *dev = s->dev;
struct sk_buff *nskb;
u8 type;
......@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
static int bnep_session(void *arg)
{
struct bnep_session *s = arg;
struct net_device *dev = &s->dev;
struct net_device *dev = s->dev;
struct sock *sk = s->sock->sk;
struct sk_buff *skb;
wait_queue_t wait;
......@@ -501,7 +501,7 @@ static int bnep_session(void *arg)
__bnep_unlink_session(s);
up_write(&bnep_session_sem);
kfree(s);
kfree(dev);
return 0;
}
......@@ -517,10 +517,13 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
baswap((void *) dst, &bt_sk(sock->sk)->dst);
baswap((void *) src, &bt_sk(sock->sk)->src);
s = kmalloc(sizeof(struct bnep_session), GFP_KERNEL);
if (!s)
return -ENOMEM;
memset(s, 0, sizeof(struct bnep_session));
/* session struct allocated as private part of net_device */
dev = alloc_netdev(sizeof(struct bnep_session),
(*req->device) ? req->device : "bnep%d",
bnep_net_setup);
if (!dev)
return ENOMEM;
down_write(&bnep_session_sem);
......@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
goto failed;
}
dev = &s->dev;
if (*req->device)
strcpy(dev->name, req->device);
else
strcpy(dev->name, "bnep%d");
memset(dev->broadcast, 0xff, ETH_ALEN);
s = dev->priv;
/* This is rx header therefore addresses are swapped.
* ie eh.h_dest is our local address. */
memcpy(s->eh.h_dest, &src, ETH_ALEN);
memcpy(s->eh.h_source, &dst, ETH_ALEN);
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
s->dev = dev;
s->sock = sock;
s->role = req->role;
s->state = BT_CONNECTED;
......@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->proto_filter[2].end = htons(0x86DD);
#endif
dev->init = bnep_net_init;
dev->priv = s;
err = register_netdev(dev);
if (err) {
goto failed;
......@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
failed:
up_write(&bnep_session_sem);
kfree(s);
kfree(dev);
return err;
}
......@@ -624,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{
memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev.name);
strcpy(ci->device, s->dev->name);
ci->flags = s->flags;
ci->state = s->state;
ci->role = s->role;
......
......@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
int bnep_net_init(struct net_device *dev)
void bnep_net_setup(struct net_device *dev)
{
struct bnep_session *s = dev->priv;
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
memset(dev->broadcast, 0xff, ETH_ALEN);
dev->addr_len = ETH_ALEN;
ether_setup(dev);
......@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev)
dev->watchdog_timeo = HZ * 2;
dev->tx_timeout = bnep_net_timeout;
return 0;
}
......@@ -394,7 +394,7 @@ int hci_inquiry(unsigned long arg)
{
struct hci_inquiry_req ir;
struct hci_dev *hdev;
int err = 0, do_inquiry = 0;
int err = 0, do_inquiry = 0, max_rsp;
long timeo;
__u8 *buf, *ptr;
......@@ -417,16 +417,19 @@ int hci_inquiry(unsigned long arg)
if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0)
goto done;
/* for unlimited number of responses we will use buffer with 255 entries */
max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space.
*/
if (!(buf = kmalloc(sizeof(struct inquiry_info) * ir.num_rsp, GFP_KERNEL))) {
if (!(buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL))) {
err = -ENOMEM;
goto done;
}
hci_dev_lock_bh(hdev);
ir.num_rsp = inquiry_cache_dump(hdev, ir.num_rsp, buf);
ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
hci_dev_unlock_bh(hdev);
BT_DBG("num_rsp %d", ir.num_rsp);
......
......@@ -62,9 +62,22 @@
/* Command Complete OGF LINK_CTL */
static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
__u8 status;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
switch (ocf) {
case OCF_INQUIRY_CANCEL:
status = *((__u8 *) skb->data);
if (status) {
BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status);
} else {
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
}
break;
default:
BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf);
break;
......
......@@ -75,7 +75,7 @@ static struct hci_sec_filter hci_sec_filter = {
/* OGF_LINK_POLICY */
{ 0x1200, 0x0, 0x0, 0x0 },
/* OGF_HOST_CTL */
{ 0x80100000, 0x2a, 0x0, 0x0 },
{ 0x80100000, 0x202a, 0x0, 0x0 },
/* OGF_INFO_PARAM */
{ 0x22a, 0x0, 0x0, 0x0 },
/* OGF_STATUS_PARAM */
......
......@@ -289,7 +289,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
struct l2cap_disconn_req req;
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ * 5);
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
......@@ -314,11 +314,9 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
static void l2cap_sock_close(struct sock *sk)
{
l2cap_sock_clear_timer(sk);
lock_sock(sk);
__l2cap_sock_close(sk, ECONNRESET);
release_sock(sk);
l2cap_sock_kill(sk);
}
......@@ -530,8 +528,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto done;
wait:
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
release_sock(sk);
return err;
......@@ -831,32 +829,39 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
static int l2cap_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
l2cap_sock_clear_timer(sk);
lock_sock(sk);
if (!sk->sk_shutdown) {
sk->sk_shutdown = SHUTDOWN_MASK;
__l2cap_sock_close(sk, ECONNRESET);
release_sock(sk);
l2cap_sock_clear_timer(sk);
__l2cap_sock_close(sk, 0);
return 0;
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
}
release_sock(sk);
return err;
}
static int l2cap_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
err = l2cap_sock_shutdown(sock, 2);
sock_orphan(sk);
l2cap_sock_close(sk);
return 0;
l2cap_sock_kill(sk);
return err;
}
/* ---- L2CAP channels ---- */
......@@ -981,9 +986,11 @@ static void l2cap_chan_del(struct sock *sk, int err)
}
sk->sk_state = BT_CLOSED;
sk->sk_err = err;
sk->sk_zapped = 1;
if (err)
sk->sk_err = err;
if (parent)
parent->sk_data_ready(parent, 0);
else
......@@ -1518,18 +1525,35 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
return -ENOENT;
if (result) {
struct l2cap_disconn_req req;
switch (result) {
case L2CAP_CONF_SUCCESS:
break;
/* They didn't like our options. Well... we do not negotiate.
* Close channel.
case L2CAP_CONF_UNACCEPT:
if (++l2cap_pi(sk)->conf_retry < L2CAP_CONF_MAX_RETRIES) {
char req[128];
/*
It does not make sense to adjust L2CAP parameters
that are currently defined in the spec. We simply
resend config request that we sent earlier. It is
stupid :) but it helps qualification testing
which expects at least some response from us.
*/
l2cap_send_req(conn, L2CAP_CONF_REQ,
l2cap_build_conf_req(sk, req), req);
goto done;
}
default:
sk->sk_state = BT_DISCONN;
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5);
{
struct l2cap_disconn_req req;
req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
l2cap_send_req(conn, L2CAP_DISCONN_REQ, sizeof(req), &req);
}
goto done;
}
......@@ -1590,7 +1614,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
return 0;
l2cap_chan_del(sk, ECONNABORTED);
l2cap_chan_del(sk, 0);
bh_unlock_sock(sk);
l2cap_sock_kill(sk);
......
......@@ -280,13 +280,13 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
{
struct rfcomm_session *s;
u8 dlci = __dlci(0, channel);
int err = 0;
u8 dlci;
BT_DBG("dlc %p state %ld %s %s channel %d dlci %d",
d, d->state, batostr(src), batostr(dst), channel, dlci);
BT_DBG("dlc %p state %ld %s %s channel %d",
d, d->state, batostr(src), batostr(dst), channel);
if (dlci < 1 || dlci > 62)
if (channel < 1 || channel > 30)
return -EINVAL;
if (d->state != BT_OPEN && d->state != BT_CLOSED)
......@@ -299,6 +299,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err;
}
dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */
if (rfcomm_dlc_get(s, dlci))
return -EBUSY;
......@@ -715,7 +717,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
hdr->len = __len8(sizeof(*mcc) + 1);
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(s->initiator, RFCOMM_NSC);
mcc->type = __mcc_type(cr, RFCOMM_NSC);
mcc->len = __len8(1);
/* Type that we didn't like */
......@@ -741,7 +743,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
hdr->len = __len8(sizeof(*mcc) + sizeof(*pn));
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(s->initiator, RFCOMM_PN);
mcc->type = __mcc_type(cr, RFCOMM_PN);
mcc->len = __len8(sizeof(*pn));
pn = (void *) ptr; ptr += sizeof(*pn);
......@@ -850,7 +852,51 @@ static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig
msc = (void *) ptr; ptr += sizeof(*msc);
msc->dlci = __addr(1, dlci);
msc->v24_sig = v24_sig;
msc->v24_sig = v24_sig | 0x01;
*ptr = __fcs(buf); ptr++;
return rfcomm_send_frame(s, buf, ptr - buf);
}
static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
{
struct rfcomm_hdr *hdr;
struct rfcomm_mcc *mcc;
u8 buf[16], *ptr = buf;
BT_DBG("%p cr %d", s, cr);
hdr = (void *) ptr; ptr += sizeof(*hdr);
hdr->addr = __addr(s->initiator, 0);
hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
hdr->len = __len8(sizeof(*mcc));
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(cr, RFCOMM_FCOFF);
mcc->len = __len8(0);
*ptr = __fcs(buf); ptr++;
return rfcomm_send_frame(s, buf, ptr - buf);
}
static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
{
struct rfcomm_hdr *hdr;
struct rfcomm_mcc *mcc;
u8 buf[16], *ptr = buf;
BT_DBG("%p cr %d", s, cr);
hdr = (void *) ptr; ptr += sizeof(*hdr);
hdr->addr = __addr(s->initiator, 0);
hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
hdr->len = __len8(sizeof(*mcc));
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(cr, RFCOMM_FCON);
mcc->len = __len8(0);
*ptr = __fcs(buf); ptr++;
......@@ -1085,6 +1131,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
d->state = BT_CONNECTED;
d->state_change(d, 0);
rfcomm_dlc_unlock(d);
rfcomm_send_msc(s, 1, dlci, d->v24_sig);
} else {
rfcomm_send_dm(s, dlci);
}
......@@ -1207,6 +1255,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
/* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
no flow control lines, normal XON/XOFF chars */
if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
bit_rate = rpn->bit_rate;
if (bit_rate != RFCOMM_RPN_BR_115200) {
BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
bit_rate = RFCOMM_RPN_BR_115200;
rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) {
......@@ -1232,22 +1288,25 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl);
flow_ctrl = rpn->flow_ctrl;
if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl);
flow_ctrl = RFCOMM_RPN_FLOW_NONE;
rpn_mask ^= RFCOMM_RPN_PM_FLOW;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char);
xon_char = rpn->xon_char;
if (xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", xon_char);
xon_char = RFCOMM_RPN_XON_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XON;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char);
xoff_char = rpn->xoff_char;
if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char);
xoff_char = RFCOMM_RPN_XOFF_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XOFF;
}
......@@ -1343,6 +1402,20 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
rfcomm_recv_msc(s, cr, skb);
break;
case RFCOMM_FCOFF:
if (cr) {
set_bit(RFCOMM_TX_THROTTLED, &s->flags);
rfcomm_send_fcoff(s, 0);
}
break;
case RFCOMM_FCON:
if (cr) {
clear_bit(RFCOMM_TX_THROTTLED, &s->flags);
rfcomm_send_fcon(s, 0);
}
break;
case RFCOMM_TEST:
if (cr)
rfcomm_send_test(s, 0, skb->data, skb->len);
......@@ -1533,6 +1606,9 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue;
}
if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
continue;
if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
d->mscex == RFCOMM_MSCEX_OK)
rfcomm_process_tx(d);
......
......@@ -192,8 +192,10 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent);
/* Close not yet accepted dlcs */
while ((sk = bt_accept_dequeue(parent, NULL)))
while ((sk = bt_accept_dequeue(parent, NULL))) {
rfcomm_sock_close(sk);
rfcomm_sock_kill(sk);
}
parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1;
......@@ -215,15 +217,10 @@ static void rfcomm_sock_kill(struct sock *sk)
sock_put(sk);
}
/* Close socket.
* Must be called on unlocked socket.
*/
static void rfcomm_sock_close(struct sock *sk)
static void __rfcomm_sock_close(struct sock *sk)
{
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
lock_sock(sk);
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
switch (sk->sk_state) {
......@@ -240,11 +237,17 @@ static void rfcomm_sock_close(struct sock *sk)
default:
sk->sk_zapped = 1;
break;
};
}
}
/* Close socket.
* Must be called on unlocked socket.
*/
static void rfcomm_sock_close(struct sock *sk)
{
lock_sock(sk);
__rfcomm_sock_close(sk);
release_sock(sk);
rfcomm_sock_kill(sk);
}
static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
......@@ -374,7 +377,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
if (!err)
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
release_sock(sk);
return err;
......@@ -558,9 +562,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
int target, err = 0, copied = 0;
long timeo;
if (sk->sk_state != BT_CONNECTED)
return -EINVAL;
if (flags & MSG_OOB)
return -EOPNOTSUPP;
......@@ -635,23 +636,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return copied ? : err;
}
static int rfcomm_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
if (sk->sk_state == BT_CONNECTED)
rfcomm_dlc_close(rfcomm_pi(sk)->dlc, 0);
release_sock(sk);
return 0;
}
static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{
struct sock *sk = sock->sk;
......@@ -710,19 +694,42 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
return err;
}
static int rfcomm_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
lock_sock(sk);
if (!sk->sk_shutdown) {
sk->sk_shutdown = SHUTDOWN_MASK;
__rfcomm_sock_close(sk);
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
}
release_sock(sk);
return err;
}
static int rfcomm_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk)
return 0;
sock_orphan(sk);
rfcomm_sock_close(sk);
err = rfcomm_sock_shutdown(sock, 2);
return 0;
sock_orphan(sk);
rfcomm_sock_kill(sk);
return err;
}
/* ---- RFCOMM core layer callbacks ----
......
......@@ -668,40 +668,8 @@ static int rfcomm_tty_write_room(struct tty_struct *tty)
return room;
}
static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint status)
{
u8 v24_sig, mask;
BT_DBG("dlc %p cmd 0x%02x", dlc, cmd);
if (cmd == TIOCMSET)
v24_sig = 0;
else
rfcomm_dlc_get_modem_status(dlc, &v24_sig);
mask = ((status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0) |
((status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0) |
((status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0) |
((status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0) |
((status & TIOCM_RI) ? RFCOMM_V24_IC : 0) |
((status & TIOCM_CD) ? RFCOMM_V24_DV : 0);
if (cmd == TIOCMBIC)
v24_sig &= ~mask;
else
v24_sig |= mask;
rfcomm_dlc_set_modem_status(dlc, v24_sig);
return 0;
}
static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
struct rfcomm_dlc *dlc = dev->dlc;
uint status;
int err;
BT_DBG("tty %p cmd 0x%02x", tty, cmd);
switch (cmd) {
......@@ -713,18 +681,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
BT_DBG("TCSETS is not supported");
return -ENOIOCTLCMD;
case TIOCMGET:
BT_DBG("TIOCMGET");
return put_user(dev->modem_status, (unsigned int *)arg);
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
case TIOCMBIS: /* Turns on the lines as specified by the mask */
case TIOCMBIC: /* Turns off the lines as specified by the mask */
if ((err = get_user(status, (unsigned int *)arg)))
return err;
return rfcomm_tty_set_modem_status(cmd, dlc, status);
case TIOCMIWAIT:
BT_DBG("TIOCMIWAIT");
break;
......@@ -851,6 +807,48 @@ static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
return 0;
}
static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p dev %p", tty, dev);
return dev->modem_status;
}
static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
struct rfcomm_dlc *dlc = dev->dlc;
u8 v24_sig;
BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
rfcomm_dlc_get_modem_status(dlc, &v24_sig);
if (set & TIOCM_DSR || set & TIOCM_DTR)
v24_sig |= RFCOMM_V24_RTC;
if (set & TIOCM_RTS || set & TIOCM_CTS)
v24_sig |= RFCOMM_V24_RTR;
if (set & TIOCM_RI)
v24_sig |= RFCOMM_V24_IC;
if (set & TIOCM_CD)
v24_sig |= RFCOMM_V24_DV;
if (clear & TIOCM_DSR || clear & TIOCM_DTR)
v24_sig &= ~RFCOMM_V24_RTC;
if (clear & TIOCM_RTS || clear & TIOCM_CTS)
v24_sig &= ~RFCOMM_V24_RTR;
if (clear & TIOCM_RI)
v24_sig &= ~RFCOMM_V24_IC;
if (clear & TIOCM_CD)
v24_sig &= ~RFCOMM_V24_DV;
rfcomm_dlc_set_modem_status(dlc, v24_sig);
return 0;
}
/* ---- TTY structure ---- */
static struct tty_driver *rfcomm_tty_driver;
......@@ -870,6 +868,8 @@ static struct tty_operations rfcomm_ops = {
.hangup = rfcomm_tty_hangup,
.wait_until_sent = rfcomm_tty_wait_until_sent,
.read_proc = rfcomm_tty_read_proc,
.tiocmget = rfcomm_tty_tiocmget,
.tiocmset = rfcomm_tty_tiocmset,
};
int rfcomm_init_ttys(void)
......@@ -878,18 +878,17 @@ int rfcomm_init_ttys(void)
if (!rfcomm_tty_driver)
return -1;
rfcomm_tty_driver->owner = THIS_MODULE,
rfcomm_tty_driver->driver_name = "rfcomm",
rfcomm_tty_driver->devfs_name = "bluetooth/rfcomm/",
rfcomm_tty_driver->name = "rfcomm",
rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR,
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR,
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW,
rfcomm_tty_driver->owner = THIS_MODULE;
rfcomm_tty_driver->driver_name = "rfcomm";
rfcomm_tty_driver->devfs_name = "bluetooth/rfcomm/";
rfcomm_tty_driver->name = "rfcomm";
rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR;
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW;
rfcomm_tty_driver->init_termios = tty_std_termios;
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
if (tty_register_driver(rfcomm_tty_driver)) {
......
......@@ -353,8 +353,10 @@ static void sco_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent);
/* Close not yet accepted channels */
while ((sk = bt_accept_dequeue(parent, NULL)))
while ((sk = bt_accept_dequeue(parent, NULL))) {
sco_sock_close(sk);
sco_sock_kill(sk);
}
parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1;
......@@ -523,7 +525,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
if ((err = sco_connect(sk)))
goto done;
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
release_sock(sk);
......@@ -727,16 +730,24 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
static int sco_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk)
return 0;
sock_orphan(sk);
sco_sock_close(sk);
return 0;
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
release_sock(sk);
}
sock_orphan(sk);
sco_sock_kill(sk);
return err;
}
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
......
......@@ -77,6 +77,6 @@ EXPORT_SYMBOL(bt_sock_recvmsg);
EXPORT_SYMBOL(bt_sock_poll);
EXPORT_SYMBOL(bt_accept_enqueue);
EXPORT_SYMBOL(bt_accept_dequeue);
EXPORT_SYMBOL(bt_sock_w4_connect);
EXPORT_SYMBOL(bt_sock_wait_state);
EXPORT_SYMBOL(proc_bt);
......@@ -201,7 +201,7 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
#ifdef CONFIG_NETFILTER_DEBUG
nf_debug_ip_local_deliver(skb);
skb->nf_debug =3D 0;
skb->nf_debug = 0;
#endif /*CONFIG_NETFILTER_DEBUG*/
__skb_pull(skb, ihl);
......
......@@ -101,7 +101,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct,
struct ip_conntrack_expect *exp = expect;
struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info;
struct ip_conntrack_tuple t = exp->tuple;
int port;
u_int16_t port;
MUST_BE_LOCKED(&ip_amanda_lock);
......@@ -115,7 +115,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct,
writable */
t.dst.ip = newip;
for (port = ct_amanda_info->port + 10; port != 0; port++) {
for (port = ct_amanda_info->port; port != 0; port++) {
t.dst.u.tcp.port = htons(port);
if (ip_conntrack_change_expect(exp, &t) == 0)
break;
......
......@@ -99,7 +99,7 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
struct ip_conntrack_tuple t;
struct iphdr *iph = (*pskb)->nh.iph;
struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
int port;
u_int16_t port;
/* "4294967296 65635 " */
char buffer[18];
......
......@@ -2517,7 +2517,109 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFADDR, GFP_ATOMIC);
}
static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
__s32 *array, int bytes)
{
memset(array, 0, bytes);
array[DEVCONF_FORWARDING] = cnf->forwarding;
array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
array[DEVCONF_MTU6] = cnf->mtu6;
array[DEVCONF_ACCEPT_RA] = cnf->accept_ra;
array[DEVCONF_ACCEPT_REDIRECTS] = cnf->accept_redirects;
array[DEVCONF_AUTOCONF] = cnf->autoconf;
array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
#ifdef CONFIG_IPV6_PRIVACY
array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
array[DEVCONF_TEMP_VALID_LFT] = cnf->temp_valid_lft;
array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
#endif
}
static int inet6_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
struct inet6_dev *idev,
int type, u32 pid, u32 seq)
{
__s32 *array = NULL;
struct ifinfomsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct rtattr *subattr;
nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
r = NLMSG_DATA(nlh);
r->ifi_family = AF_INET6;
r->ifi_type = dev->type;
r->ifi_index = dev->ifindex;
r->ifi_flags = dev->flags;
r->ifi_change = 0;
if (!netif_running(dev) || !netif_carrier_ok(dev))
r->ifi_flags &= ~IFF_RUNNING;
else
r->ifi_flags |= IFF_RUNNING;
RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
subattr = (struct rtattr*)skb->tail;
RTA_PUT(skb, IFLA_PROTINFO, 0, NULL);
/* return the device flags */
RTA_PUT(skb, IFLA_INET6_FLAGS, sizeof(__u32), &idev->if_flags);
/* return the device sysctl params */
if ((array = kmalloc(DEVCONF_MAX * sizeof(*array), GFP_ATOMIC)) == NULL)
goto rtattr_failure;
ipv6_store_devconf(&idev->cnf, array, DEVCONF_MAX * sizeof(*array));
RTA_PUT(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(*array), array);
/* XXX - Statistics/MC not implemented */
subattr->rta_len = skb->tail - (u8*)subattr;
nlh->nlmsg_len = skb->tail - b;
kfree(array);
return skb->len;
nlmsg_failure:
rtattr_failure:
if (array)
kfree(array);
skb_trim(skb, b - skb->data);
return -1;
}
static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx, err;
int s_idx = cb->args[0];
struct net_device *dev;
struct inet6_dev *idev;
read_lock(&dev_base_lock);
for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if ((idev = in6_dev_get(dev)) == NULL)
continue;
err = inet6_fill_ifinfo(skb, dev, idev, RTM_NEWLINK,
NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq);
in6_dev_put(idev);
if (err <= 0)
break;
}
read_unlock(&dev_base_lock);
cb->args[0] = idx;
return skb->len;
}
static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
[RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, },
[RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, },
......
......@@ -1044,6 +1044,17 @@ static void ndisc_router_discovery(struct sk_buff *skb)
in6_dev->if_flags |= IF_RA_RCVD;
}
/*
* Remember the managed/otherconf flags from most recently
* received RA message (RFC 2462) -- yoshfuji
*/
in6_dev->if_flags = (in6_dev->if_flags & ~(IF_RA_MANAGED |
IF_RA_OTHERCONF)) |
(ra_msg->icmph.icmp6_addrconf_managed ?
IF_RA_MANAGED : 0) |
(ra_msg->icmph.icmp6_addrconf_other ?
IF_RA_OTHERCONF : 0);
lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment