Commit 230ac729 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-ppc
parents 37f68cc2 ec7ee636
...@@ -1394,7 +1394,8 @@ S: USA ...@@ -1394,7 +1394,8 @@ S: USA
N: Marcel Holtmann N: Marcel Holtmann
E: marcel@holtmann.org E: marcel@holtmann.org
W: http://www.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 S: Germany
N: Rob W. W. Hooft N: Rob W. W. Hooft
......
...@@ -328,18 +328,66 @@ M: axboe@suse.de ...@@ -328,18 +328,66 @@ M: axboe@suse.de
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
BLUETOOTH SUBSYSTEM (BlueZ) BLUETOOTH SUBSYSTEM
P: Maxim Krasnyansky P: Maxim Krasnyansky
M: maxk@qualcomm.com M: maxk@qualcomm.com
W: http://bluez.sf.net W: http://bluez.sf.net
S: Maintained 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 P: Marcel Holtmann
M: marcel@holtmann.org M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/ W: http://www.holtmann.org/linux/bluetooth/
S: Maintained 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 BONDING DRIVER
P: Chad Tindel P: Chad Tindel
M: ctindel@users.sourceforge.net M: ctindel@users.sourceforge.net
......
...@@ -39,7 +39,7 @@ static int delay_at_last_interrupt; ...@@ -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_low; /* lsb 32 bits of Time Stamp Counter */
static unsigned long last_tsc_high; /* msb 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 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) /* convert from cycles(64bits) => nanoseconds (64bits)
* basic equation: * basic equation:
...@@ -111,12 +111,14 @@ static unsigned long get_offset_tsc(void) ...@@ -111,12 +111,14 @@ static unsigned long get_offset_tsc(void)
static unsigned long long monotonic_clock_tsc(void) static unsigned long long monotonic_clock_tsc(void)
{ {
unsigned long long last_offset, this_offset, base; unsigned long long last_offset, this_offset, base;
unsigned seq;
/* atomically read monotonic base & last_offset */ /* 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; last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
base = monotonic_base; base = monotonic_base;
read_unlock_irq(&monotonic_lock); } while (read_seqretry(&monotonic_lock, seq));
/* Read the Time Stamp Counter */ /* Read the Time Stamp Counter */
rdtscll(this_offset); rdtscll(this_offset);
...@@ -135,7 +137,7 @@ static void mark_offset_tsc(void) ...@@ -135,7 +137,7 @@ static void mark_offset_tsc(void)
unsigned long long this_offset, last_offset; unsigned long long this_offset, last_offset;
static int lost_count = 0; 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; last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
/* /*
* It is important that these two operations happen almost at * It is important that these two operations happen almost at
...@@ -204,7 +206,7 @@ static void mark_offset_tsc(void) ...@@ -204,7 +206,7 @@ static void mark_offset_tsc(void)
/* update the monotonic base value */ /* update the monotonic base value */
this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
monotonic_base += cycles_2_ns(this_offset - last_offset); monotonic_base += cycles_2_ns(this_offset - last_offset);
write_unlock(&monotonic_lock); write_sequnlock(&monotonic_lock);
/* calculate delay_at_last_interrupt */ /* calculate delay_at_last_interrupt */
count = ((LATCH-1) - count) * TICK_SIZE; count = ((LATCH-1) - count) * TICK_SIZE;
...@@ -236,7 +238,7 @@ static void mark_offset_tsc_hpet(void) ...@@ -236,7 +238,7 @@ static void mark_offset_tsc_hpet(void)
unsigned long long this_offset, last_offset; unsigned long long this_offset, last_offset;
unsigned long offset, temp, hpet_current; 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; last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
/* /*
* It is important that these two operations happen almost at * It is important that these two operations happen almost at
...@@ -264,7 +266,7 @@ static void mark_offset_tsc_hpet(void) ...@@ -264,7 +266,7 @@ static void mark_offset_tsc_hpet(void)
/* update the monotonic base value */ /* update the monotonic base value */
this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
monotonic_base += cycles_2_ns(this_offset - last_offset); monotonic_base += cycles_2_ns(this_offset - last_offset);
write_unlock(&monotonic_lock); write_sequnlock(&monotonic_lock);
/* calculate delay_at_last_interrupt */ /* calculate delay_at_last_interrupt */
/* /*
......
...@@ -1706,10 +1706,6 @@ void __init mem_init(void) ...@@ -1706,10 +1706,6 @@ void __init mem_init(void)
unsigned long addr, last; unsigned long addr, last;
int i; int i;
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
#endif
i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
i += 1; i += 1;
sparc64_valid_addr_bitmap = (unsigned long *) sparc64_valid_addr_bitmap = (unsigned long *)
......
...@@ -302,6 +302,7 @@ static int hci_usb_open(struct hci_dev *hdev) ...@@ -302,6 +302,7 @@ static int hci_usb_open(struct hci_dev *hdev)
hci_usb_bulk_rx_submit(husb); hci_usb_bulk_rx_submit(husb);
#ifdef CONFIG_BT_USB_SCO #ifdef CONFIG_BT_USB_SCO
if (husb->isoc_iface)
hci_usb_isoc_rx_submit(husb); hci_usb_isoc_rx_submit(husb);
#endif #endif
} else { } else {
......
...@@ -1562,6 +1562,20 @@ config CODA_FS ...@@ -1562,6 +1562,20 @@ config CODA_FS
whenever you want), say M here and read whenever you want), say M here and read
<file:Documentation/modules.txt>. The module will be called coda. <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 config INTERMEZZO_FS
tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)" tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL depends on INET && EXPERIMENTAL
......
...@@ -23,13 +23,16 @@ ...@@ -23,13 +23,16 @@
#include <linux/coda_fs_i.h> #include <linux/coda_fs_i.h>
#include <linux/coda_cache.h> #include <linux/coda_cache.h>
static atomic_t permission_epoch = ATOMIC_INIT(0);
/* replace or extend an acl cache hit */ /* replace or extend an acl cache hit */
void coda_cache_enter(struct inode *inode, int mask) void coda_cache_enter(struct inode *inode, int mask)
{ {
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
if ( !coda_cred_ok(&cii->c_cached_cred) ) { cii->c_cached_epoch = atomic_read(&permission_epoch);
coda_load_creds(&cii->c_cached_cred); if (cii->c_uid != current->fsuid) {
cii->c_uid = current->fsuid;
cii->c_cached_perm = mask; cii->c_cached_perm = mask;
} else } else
cii->c_cached_perm |= mask; cii->c_cached_perm |= mask;
...@@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode) ...@@ -42,22 +45,15 @@ void coda_cache_clear_inode(struct inode *inode)
cii->c_cached_perm = 0; cii->c_cached_perm = 0;
} }
/* remove all acl caches for a principal (or all principals when cred == NULL)*/ /* remove all acl caches */
void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred) void coda_cache_clear_all(struct super_block *sb)
{ {
struct coda_sb_info *sbi; struct coda_sb_info *sbi;
struct coda_inode_info *cii;
struct list_head *tmp;
sbi = coda_sbp(sb); sbi = coda_sbp(sb);
if (!sbi) BUG(); if (!sbi) BUG();
list_for_each(tmp, &sbi->sbi_cihead) atomic_inc(&permission_epoch);
{
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;
}
} }
...@@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask) ...@@ -67,8 +63,9 @@ int coda_cache_check(struct inode *inode, int mask)
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
int hit; int hit;
hit = ((mask & cii->c_cached_perm) == mask) && hit = (mask & cii->c_cached_perm) == mask &&
coda_cred_ok(&cii->c_cached_cred); cii->c_uid == current->fsuid &&
cii->c_cached_epoch == atomic_read(&permission_epoch);
return hit; return hit;
} }
......
...@@ -11,18 +11,9 @@ ...@@ -11,18 +11,9 @@
#include <linux/coda_fs_i.h> #include <linux/coda_fs_i.h>
#include <linux/coda_psdev.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; return memcmp(fid1, fid2, sizeof(*fid1)) == 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;
} }
static struct inode_operations coda_symlink_inode_operations = { static struct inode_operations coda_symlink_inode_operations = {
...@@ -52,13 +43,13 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) ...@@ -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) 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); return coda_fideq(&(ITOC(inode)->c_fid), fid);
} }
static int coda_set_inode(struct inode *inode, void *data) 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; ITOC(inode)->c_fid = *fid;
return 0; return 0;
} }
...@@ -68,12 +59,11 @@ static int coda_fail_inode(struct inode *inode, void *data) ...@@ -68,12 +59,11 @@ static int coda_fail_inode(struct inode *inode, void *data)
return -1; 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 coda_vattr * attr)
{ {
struct inode *inode; struct inode *inode;
struct coda_inode_info *cii; struct coda_inode_info *cii;
struct coda_sb_info *sbi = coda_sbp(sb);
unsigned long hash = coda_f2i(fid); unsigned long hash = coda_f2i(fid);
inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, 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, ...@@ -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) */ /* we still need to set i_ino for things like stat(2) */
inode->i_ino = hash; inode->i_ino = hash;
cii->c_mapcount = 0; cii->c_mapcount = 0;
list_add(&cii->c_cilist, &sbi->sbi_cihead);
unlock_new_inode(inode); unlock_new_inode(inode);
} }
...@@ -101,7 +90,7 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, ...@@ -101,7 +90,7 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
- link the two up if this is needed - link the two up if this is needed
- fill in the attributes - 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; struct coda_vattr attr;
int error; int error;
...@@ -122,8 +111,8 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) ...@@ -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, void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid,
struct ViceFid *newfid) struct CodaFid *newfid)
{ {
struct coda_inode_info *cii; struct coda_inode_info *cii;
unsigned long hash = coda_f2i(newfid); unsigned long hash = coda_f2i(newfid);
...@@ -142,7 +131,7 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, ...@@ -142,7 +131,7 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
} }
/* convert a fid to an inode. */ /* 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; struct inode *inode;
unsigned long hash = coda_f2i(fid); unsigned long hash = coda_f2i(fid);
......
...@@ -25,10 +25,14 @@ ...@@ -25,10 +25,14 @@
int coda_fake_statfs; int coda_fake_statfs;
/* print a fid */ /* print a fid */
char * coda_f2s(ViceFid *f) char * coda_f2s(struct CodaFid *f)
{ {
static char s[60]; 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; return s;
} }
...@@ -45,30 +49,6 @@ int coda_isroot(struct inode *i) ...@@ -45,30 +49,6 @@ int coda_isroot(struct inode *i)
return ( i->i_sb->s_root->d_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_to_cflags(unsigned short flags)
{ {
unsigned short coda_flags = 0; unsigned short coda_flags = 0;
...@@ -215,58 +195,3 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr) ...@@ -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 = { ...@@ -93,7 +93,7 @@ struct file_operations coda_dir_operations = {
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{ {
struct inode *res_inode = NULL; 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 dropme = 0; /* to indicate entry should not be cached */
int type = 0; int type = 0;
int error = 0; int error = 0;
...@@ -196,7 +196,7 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na ...@@ -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; const char *name=de->d_name.name;
int length=de->d_name.len; int length=de->d_name.len;
struct inode *inode; struct inode *inode;
struct ViceFid newfid; struct CodaFid newfid;
struct coda_vattr attrs; struct coda_vattr attrs;
lock_kernel(); lock_kernel();
...@@ -236,7 +236,7 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev ...@@ -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; const char *name=de->d_name.name;
int length=de->d_name.len; int length=de->d_name.len;
struct inode *inode; struct inode *inode;
struct ViceFid newfid; struct CodaFid newfid;
struct coda_vattr attrs; struct coda_vattr attrs;
if ( coda_hasmknod == 0 ) if ( coda_hasmknod == 0 )
...@@ -283,7 +283,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) ...@@ -283,7 +283,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
const char *name = de->d_name.name; const char *name = de->d_name.name;
int len = de->d_name.len; int len = de->d_name.len;
int error; int error;
struct ViceFid newfid; struct CodaFid newfid;
lock_kernel(); lock_kernel();
coda_vfs_stat.mkdir++; coda_vfs_stat.mkdir++;
...@@ -588,8 +588,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir, ...@@ -588,8 +588,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
break; break;
} }
/* validate whether the directory file actually makes sense */ /* validate whether the directory file actually makes sense */
if (vdir->d_reclen < vdir_size + vdir->d_namlen || if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
vdir->d_namlen > CODA_MAXNAMLEN) {
printk("coda_venus_readdir: Invalid dir: %ld\n", printk("coda_venus_readdir: Invalid dir: %ld\n",
filp->f_dentry->d_inode->i_ino); filp->f_dentry->d_inode->i_ino);
ret = -EBADF; ret = -EBADF;
......
...@@ -136,7 +136,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) ...@@ -136,7 +136,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
cfi->cfi_magic = CODA_MAGIC; cfi->cfi_magic = CODA_MAGIC;
cfi->cfi_mapcount = 0; cfi->cfi_mapcount = 0;
cfi->cfi_container = host_file; cfi->cfi_container = host_file;
coda_load_creds(&cfi->cfi_cred);
BUG_ON(coda_file->private_data != NULL); BUG_ON(coda_file->private_data != NULL);
coda_file->private_data = cfi; coda_file->private_data = cfi;
...@@ -176,7 +175,7 @@ int coda_flush(struct file *coda_file) ...@@ -176,7 +175,7 @@ int coda_flush(struct file *coda_file)
coda_inode = coda_file->f_dentry->d_inode; coda_inode = coda_file->f_dentry->d_inode;
err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
&cfi->cfi_cred); coda_file->f_uid);
if (err == -EOPNOTSUPP) { if (err == -EOPNOTSUPP) {
use_coda_close = 1; use_coda_close = 1;
...@@ -214,7 +213,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file) ...@@ -214,7 +213,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
if (use_coda_close) if (use_coda_close)
err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode), 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; host_inode = cfi->cfi_container->f_dentry->d_inode;
cii = ITOC(coda_inode); cii = ITOC(coda_inode);
......
...@@ -44,10 +44,9 @@ static struct inode *coda_alloc_inode(struct super_block *sb) ...@@ -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); ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, SLAB_KERNEL);
if (!ei) if (!ei)
return NULL; return NULL;
memset(&ei->c_fid, 0, sizeof(struct ViceFid)); memset(&ei->c_fid, 0, sizeof(struct CodaFid));
ei->c_flags = 0; ei->c_flags = 0;
INIT_LIST_HEAD(&ei->c_cilist); ei->c_uid = 0;
memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred));
ei->c_cached_perm = 0; ei->c_cached_perm = 0;
return &ei->vfs_inode; return &ei->vfs_inode;
} }
...@@ -139,7 +138,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) ...@@ -139,7 +138,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
struct inode *root = 0; struct inode *root = 0;
struct coda_sb_info *sbi = NULL; struct coda_sb_info *sbi = NULL;
struct venus_comm *vc = NULL; struct venus_comm *vc = NULL;
ViceFid fid; struct CodaFid fid;
int error; int error;
int idx; int idx;
...@@ -169,9 +168,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) ...@@ -169,9 +168,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
vc->vc_sb = sb; vc->vc_sb = sb;
sbi->sbi_sb = sb;
sbi->sbi_vcomm = vc; sbi->sbi_vcomm = vc;
INIT_LIST_HEAD(&sbi->sbi_cihead);
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
sb->s_blocksize = 1024; /* XXXXX what do we put here?? */ sb->s_blocksize = 1024; /* XXXXX what do we put here?? */
...@@ -218,7 +215,6 @@ static void coda_put_super(struct super_block *sb) ...@@ -218,7 +215,6 @@ static void coda_put_super(struct super_block *sb)
sbi = coda_sbp(sb); sbi = coda_sbp(sb);
sbi->sbi_vcomm->vc_sb = NULL; sbi->sbi_vcomm->vc_sb = NULL;
list_del_init(&sbi->sbi_cihead);
printk("Coda: Bye bye.\n"); printk("Coda: Bye bye.\n");
kfree(sbi); kfree(sbi);
...@@ -226,9 +222,6 @@ static void coda_put_super(struct super_block *sb) ...@@ -226,9 +222,6 @@ static void coda_put_super(struct super_block *sb)
static void coda_clear_inode(struct inode *inode) 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); coda_cache_clear_inode(inode);
} }
......
...@@ -61,7 +61,6 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */ ...@@ -61,7 +61,6 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
struct venus_comm coda_comms[MAX_CODADEVS]; struct venus_comm coda_comms[MAX_CODADEVS];
kmem_cache_t *cii_cache, *cred_cache, *upc_cache;
/* /*
* Device operations * Device operations
...@@ -126,13 +125,13 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf, ...@@ -126,13 +125,13 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
} }
if ( nbytes < sizeof(struct coda_out_hdr) ) { 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); hdr.opcode, hdr.unique);
count = nbytes; count = nbytes;
goto out; goto out;
} }
if ( nbytes > size ) { 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); hdr.opcode, hdr.unique);
nbytes = size; nbytes = size;
} }
...@@ -171,7 +170,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf, ...@@ -171,7 +170,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
unlock_kernel(); unlock_kernel();
if (!req) { if (!req) {
printk("psdev_write: msg (%ld, %ld) not found\n", printk("psdev_write: msg (%d, %d) not found\n",
hdr.opcode, hdr.unique); hdr.opcode, hdr.unique);
retval = -ESRCH; retval = -ESRCH;
goto out; goto out;
...@@ -179,7 +178,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf, ...@@ -179,7 +178,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
/* move data into response buffer. */ /* move data into response buffer. */
if (req->uc_outSize < nbytes) { 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); req->uc_outSize, (long)nbytes, hdr.opcode, hdr.unique);
nbytes = req->uc_outSize; /* don't have more space! */ nbytes = req->uc_outSize; /* don't have more space! */
} }
...@@ -325,10 +324,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) ...@@ -325,10 +324,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
} }
/* Wakeup clients so they can return. */ /* Wakeup clients so they can return. */
lh = vcp->vc_pending.next; list_for_each_safe(lh, next, &vcp->vc_pending) {
next = lh;
while ( (lh = next) != &vcp->vc_pending) {
next = lh->next;
req = list_entry(lh, struct upc_req, uc_chain); req = list_entry(lh, struct upc_req, uc_chain);
/* Async requests need to be freed here */ /* Async requests need to be freed here */
if (req->uc_flags & REQ_ASYNC) { if (req->uc_flags & REQ_ASYNC) {
...@@ -340,9 +336,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) ...@@ -340,9 +336,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
wake_up(&req->uc_sleep); wake_up(&req->uc_sleep);
} }
lh = &vcp->vc_processing; list_for_each_entry(req, &vcp->vc_processing, uc_chain) {
while ( (lh = lh->next) != &vcp->vc_processing) {
req = list_entry(lh, struct upc_req, uc_chain);
req->uc_flags |= REQ_ABORT; req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep); wake_up(&req->uc_sleep);
} }
...@@ -390,7 +384,13 @@ static int __init init_coda(void) ...@@ -390,7 +384,13 @@ static int __init init_coda(void)
{ {
int status; int status;
int i; 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(); status = coda_init_inodecache();
if (status) if (status)
......
This diff is collapsed.
...@@ -3041,10 +3041,11 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) ...@@ -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->next_index = le32_to_cpu(dip->di_next_index);
jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec); jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec);
jfs_ip->acltype = le32_to_cpu(dip->di_acltype); 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); ip->i_rdev = old_decode_dev(jfs_ip->dev);
}
if (S_ISDIR(ip->i_mode)) { if (S_ISDIR(ip->i_mode)) {
memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384); memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384);
...@@ -3101,6 +3102,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip) ...@@ -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_sec = cpu_to_le32(jfs_ip->otime);
dip->di_otime.tv_nsec = 0; dip->di_otime.tv_nsec = 0;
dip->di_acltype = cpu_to_le32(jfs_ip->acltype); 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); dip->di_rdev = cpu_to_le32(jfs_ip->dev);
} }
......
...@@ -4,4 +4,13 @@ ...@@ -4,4 +4,13 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * 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 @@ ...@@ -13,12 +13,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_SMP
#include <asm/smp.h>
#else
extern unsigned long loops_per_jiffy;
#endif
static __inline__ void __delay(unsigned long loops) static __inline__ void __delay(unsigned long loops)
{ {
__asm__ __volatile__( __asm__ __volatile__(
......
This diff is collapsed.
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
/* credential cache */ /* credential cache */
void coda_cache_enter(struct inode *inode, int mask); void coda_cache_enter(struct inode *inode, int mask);
void coda_cache_clear_inode(struct inode *); 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); int coda_cache_check(struct inode *inode, int mask);
/* for downcalls and attributes and lookups */ /* for downcalls and attributes and lookups */
......
...@@ -17,11 +17,12 @@ ...@@ -17,11 +17,12 @@
* coda fs inode data * coda fs inode data
*/ */
struct coda_inode_info { struct coda_inode_info {
struct ViceFid c_fid; /* Coda identifier */ struct CodaFid c_fid; /* Coda identifier */
u_short c_flags; /* flags (see below) */ u_short c_flags; /* flags (see below) */
struct list_head c_cilist; /* list of all coda inodes */ struct list_head c_cilist; /* list of all coda inodes */
unsigned int c_mapcount; /* nr of times this inode is mapped */ 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 */ unsigned int c_cached_perm; /* cached access permissions */
struct inode vfs_inode; struct inode vfs_inode;
}; };
...@@ -34,7 +35,6 @@ struct coda_file_info { ...@@ -34,7 +35,6 @@ struct coda_file_info {
int cfi_magic; /* magic number */ int cfi_magic; /* magic number */
struct file *cfi_container; /* container file for this cnode */ struct file *cfi_container; /* container file for this cnode */
unsigned int cfi_mapcount; /* nr of times this file is mapped */ 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)) #define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data))
...@@ -45,11 +45,11 @@ struct coda_file_info { ...@@ -45,11 +45,11 @@ struct coda_file_info {
#define C_DYING 0x4 /* from venus (which died) */ #define C_DYING 0x4 /* from venus (which died) */
#define C_PURGE 0x8 #define C_PURGE 0x8
int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *); int coda_cnode_make(struct inode **, struct CodaFid *, struct super_block *);
struct inode *coda_iget(struct super_block *sb, struct ViceFid *fid, struct coda_vattr *attr); 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); int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
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);
void coda_replace_fid(struct inode *, ViceFid *, ViceFid *); void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
#endif #endif
#endif #endif
...@@ -42,26 +42,21 @@ int coda_permission(struct inode *inode, int mask, struct nameidata *nd); ...@@ -42,26 +42,21 @@ int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *); int coda_revalidate_inode(struct dentry *);
int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *); int coda_setattr(struct dentry *, struct iattr *);
int coda_isnullfid(ViceFid *fid);
/* global variables */ /* global variables */
extern int coda_fake_statfs; extern int coda_fake_statfs;
/* this file: heloers */ /* 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__ char *coda_i2s(struct inode *);
static __inline__ void coda_flag_inode(struct inode *, int flag); 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_isroot(struct inode *i);
int coda_iscontrol(const char *name, size_t length); 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_vattr_to_iattr(struct inode *, struct coda_vattr *);
void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *); void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
unsigned short coda_flags_to_cflags(unsigned short); 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 */ /* sysctl.h */
void coda_sysctl_init(void); void coda_sysctl_init(void);
...@@ -88,7 +83,7 @@ static inline struct coda_inode_info *ITOC(struct inode *inode) ...@@ -88,7 +83,7 @@ static inline struct coda_inode_info *ITOC(struct inode *inode)
return list_entry(inode, struct coda_inode_info, vfs_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); return &(ITOC(inode)->c_fid);
} }
......
...@@ -6,13 +6,11 @@ ...@@ -6,13 +6,11 @@
#define CODA_SUPER_MAGIC 0x73757245 #define CODA_SUPER_MAGIC 0x73757245
struct statfs; struct kstatfs;
struct coda_sb_info struct coda_sb_info
{ {
struct venus_comm * sbi_vcomm; struct venus_comm *sbi_vcomm;
struct super_block *sbi_sb;
struct list_head sbi_cihead;
}; };
/* communication pending/processing queues */ /* communication pending/processing queues */
...@@ -33,46 +31,45 @@ static inline struct coda_sb_info *coda_sbp(struct super_block *sb) ...@@ -33,46 +31,45 @@ static inline struct coda_sb_info *coda_sbp(struct super_block *sb)
/* upcalls */ /* upcalls */
int venus_rootfid(struct super_block *sb, ViceFid *fidp); int venus_rootfid(struct super_block *sb, struct CodaFid *fidp);
int venus_getattr(struct super_block *sb, struct ViceFid *fid, int venus_getattr(struct super_block *sb, struct CodaFid *fid,
struct coda_vattr *attr); struct coda_vattr *attr);
int venus_setattr(struct super_block *, struct ViceFid *, int venus_setattr(struct super_block *, struct CodaFid *, struct coda_vattr *);
struct coda_vattr *); int venus_lookup(struct super_block *sb, struct CodaFid *fid,
int venus_lookup(struct super_block *sb, struct ViceFid *fid,
const char *name, int length, int *type, const char *name, int length, int *type,
struct ViceFid *resfid); struct CodaFid *resfid);
int venus_store(struct super_block *sb, struct ViceFid *fid, int flags, int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
struct coda_cred *); vuid_t uid);
int venus_release(struct super_block *sb, struct ViceFid *fid, int flags); int venus_release(struct super_block *sb, struct CodaFid *fid, int flags);
int venus_close(struct super_block *sb, struct ViceFid *fid, int flags, int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
struct coda_cred *); vuid_t uid);
int venus_open(struct super_block *sb, struct ViceFid *fid, int venus_open(struct super_block *sb, struct CodaFid *fid, int flags,
int flags, struct file **f); struct file **f);
int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid, int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length, const char *name, int length,
struct ViceFid *newfid, struct coda_vattr *attrs); struct CodaFid *newfid, struct coda_vattr *attrs);
int venus_create(struct super_block *sb, struct ViceFid *dirfid, int venus_create(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length, int excl, int mode, dev_t rdev, const char *name, int length, int excl, int mode, dev_t rdev,
struct ViceFid *newfid, struct coda_vattr *attrs) ; struct CodaFid *newfid, struct coda_vattr *attrs) ;
int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid, int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length); 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); 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); char *buffer, int *length);
int venus_rename(struct super_block *, struct ViceFid *new_fid, int venus_rename(struct super_block *, struct CodaFid *new_fid,
struct ViceFid *old_fid, size_t old_length, struct CodaFid *old_fid, size_t old_length,
size_t new_length, const char *old_name, size_t new_length, const char *old_name,
const char *new_name); const char *new_name);
int venus_link(struct super_block *sb, struct ViceFid *fid, int venus_link(struct super_block *sb, struct CodaFid *fid,
struct ViceFid *dirfid, const char *name, int len ); struct CodaFid *dirfid, const char *name, int len );
int venus_symlink(struct super_block *sb, struct ViceFid *fid, int venus_symlink(struct super_block *sb, struct CodaFid *fid,
const char *name, int len, const char *symname, int symlen); const char *name, int len, const char *symname, int symlen);
int venus_access(struct super_block *sb, struct ViceFid *fid, int mask); int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
int venus_pioctl(struct super_block *sb, struct ViceFid *fid, int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
unsigned int cmd, struct PioctlData *data); unsigned int cmd, struct PioctlData *data);
int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb); 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); int venus_statfs(struct super_block *sb, struct kstatfs *sfs);
......
...@@ -122,6 +122,52 @@ struct ipv6hdr { ...@@ -122,6 +122,52 @@ struct ipv6hdr {
struct in6_addr daddr; 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__ #ifdef __KERNEL__
#include <linux/in6.h> /* struct sockaddr_in6 */ #include <linux/in6.h> /* struct sockaddr_in6 */
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/device.h>
#include <linux/percpu.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/cache.h> #include <asm/cache.h>
...@@ -37,6 +35,8 @@ ...@@ -37,6 +35,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/config.h> #include <linux/config.h>
#include <linux/device.h>
#include <linux/percpu.h>
struct divert_blk; struct divert_blk;
struct vlan_group; struct vlan_group;
......
...@@ -185,9 +185,10 @@ static inline void proc_net_remove(const char *name) ...@@ -185,9 +185,10 @@ static inline void proc_net_remove(const char *name)
#else #else
#define proc_root_driver NULL #define proc_root_driver NULL
#define proc_net_fops_create(name,mode,fops) do {} while(0) #define proc_net NULL
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_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 void proc_net_remove(const char *name) {}
static inline struct dentry *proc_pid_unhash(struct task_struct *p) { return NULL; } static inline struct dentry *proc_pid_unhash(struct task_struct *p) { return NULL; }
......
...@@ -508,10 +508,12 @@ enum ...@@ -508,10 +508,12 @@ enum
#define IFLA_MASTER IFLA_MASTER #define IFLA_MASTER IFLA_MASTER
IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
#define IFLA_WIRELESS IFLA_WIRELESS #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_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
...@@ -545,6 +547,18 @@ enum ...@@ -545,6 +547,18 @@ enum
for IPIP tunnels, when route to endpoint is allowed to change) 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. * Traffic control messages.
****/ ****/
......
...@@ -131,7 +131,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s); ...@@ -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); 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); 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); 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); void bt_accept_enqueue(struct sock *parent, struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
......
...@@ -304,6 +304,8 @@ struct hci_cp_inquiry { ...@@ -304,6 +304,8 @@ struct hci_cp_inquiry {
__u8 num_rsp; __u8 num_rsp;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define OCF_INQUIRY_CANCEL 0x0002
#define OCF_LINK_KEY_REPLY 0x000B #define OCF_LINK_KEY_REPLY 0x000B
#define OCF_LINK_KEY_NEG_REPLY 0x000C #define OCF_LINK_KEY_NEG_REPLY 0x000C
struct hci_cp_link_key_reply { struct hci_cp_link_key_reply {
......
...@@ -220,6 +220,7 @@ struct l2cap_pinfo { ...@@ -220,6 +220,7 @@ struct l2cap_pinfo {
__u32 link_mode; __u32 link_mode;
__u8 conf_state; __u8 conf_state;
__u8 conf_retry;
__u16 conf_mtu; __u16 conf_mtu;
__u8 ident; __u8 ident;
...@@ -234,6 +235,7 @@ struct l2cap_pinfo { ...@@ -234,6 +235,7 @@ struct l2cap_pinfo {
#define L2CAP_CONF_REQ_SENT 0x01 #define L2CAP_CONF_REQ_SENT 0x01
#define L2CAP_CONF_INPUT_DONE 0x02 #define L2CAP_CONF_INPUT_DONE 0x02
#define L2CAP_CONF_OUTPUT_DONE 0x04 #define L2CAP_CONF_OUTPUT_DONE 0x04
#define L2CAP_CONF_MAX_RETRIES 2
void l2cap_load(void); void l2cap_load(void);
......
...@@ -16,7 +16,12 @@ ...@@ -16,7 +16,12 @@
#define _NET_IF_INET6_H #define _NET_IF_INET6_H
#include <net/snmp.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_RA_RCVD 0x20
#define IF_RS_SENT 0x10 #define IF_RS_SENT 0x10
...@@ -132,28 +137,6 @@ struct ifacaddr6 ...@@ -132,28 +137,6 @@ struct ifacaddr6
#define IFA_SITE IPV6_ADDR_SITELOCAL #define IFA_SITE IPV6_ADDR_SITELOCAL
#define IFA_GLOBAL 0x0000U #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 ipv6_devstat {
struct proc_dir_entry *proc_dir_entry; struct proc_dir_entry *proc_dir_entry;
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6); DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6);
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* $Id: af_bluetooth.c,v 1.3 2002/04/17 17:37:15 maxk Exp $ * $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/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -272,39 +272,35 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w ...@@ -272,39 +272,35 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
return mask; 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); DECLARE_WAITQUEUE(wait, current);
long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
int err = 0; int err = 0;
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
add_wait_queue(sk->sk_sleep, &wait); add_wait_queue(sk->sk_sleep, &wait);
while (sk->sk_state != BT_CONNECTED) { while (sk->sk_state != state) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!timeo) { if (!timeo) {
err = -EAGAIN; err = -EAGAIN;
break; break;
} }
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk); release_sock(sk);
timeo = schedule_timeout(timeo); timeo = schedule_timeout(timeo);
lock_sock(sk); lock_sock(sk);
err = 0;
if (sk->sk_state == BT_CONNECTED)
break;
if (sk->sk_err) { if (sk->sk_err) {
err = sock_error(sk); err = sock_error(sk);
break; break;
} }
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
} }
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sk_sleep, &wait); remove_wait_queue(sk->sk_sleep, &wait);
......
...@@ -168,11 +168,11 @@ struct bnep_session { ...@@ -168,11 +168,11 @@ struct bnep_session {
u64 mc_filter; u64 mc_filter;
struct socket *sock; struct socket *sock;
struct net_device dev; struct net_device *dev;
struct net_device_stats stats; 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_init(void);
int bnep_sock_cleanup(void); int bnep_sock_cleanup(void);
......
...@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) ...@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
s->mc_filter = 0; s->mc_filter = 0;
/* Always send broadcast */ /* 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 */ /* Add address ranges to the multicast hash */
for (; n > 0; n--) { for (; n > 0; n--) {
...@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = { ...@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = {
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) 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; struct sk_buff *nskb;
u8 type; u8 type;
...@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) ...@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
static int bnep_session(void *arg) static int bnep_session(void *arg)
{ {
struct bnep_session *s = 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 sock *sk = s->sock->sk;
struct sk_buff *skb; struct sk_buff *skb;
wait_queue_t wait; wait_queue_t wait;
...@@ -501,7 +501,7 @@ static int bnep_session(void *arg) ...@@ -501,7 +501,7 @@ static int bnep_session(void *arg)
__bnep_unlink_session(s); __bnep_unlink_session(s);
up_write(&bnep_session_sem); up_write(&bnep_session_sem);
kfree(s); kfree(dev);
return 0; return 0;
} }
...@@ -517,10 +517,13 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -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 *) dst, &bt_sk(sock->sk)->dst);
baswap((void *) src, &bt_sk(sock->sk)->src); baswap((void *) src, &bt_sk(sock->sk)->src);
s = kmalloc(sizeof(struct bnep_session), GFP_KERNEL); /* session struct allocated as private part of net_device */
if (!s) dev = alloc_netdev(sizeof(struct bnep_session),
return -ENOMEM; (*req->device) ? req->device : "bnep%d",
memset(s, 0, sizeof(struct bnep_session)); bnep_net_setup);
if (!dev)
return ENOMEM;
down_write(&bnep_session_sem); down_write(&bnep_session_sem);
...@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
goto failed; goto failed;
} }
dev = &s->dev; s = dev->priv;
if (*req->device)
strcpy(dev->name, req->device);
else
strcpy(dev->name, "bnep%d");
memset(dev->broadcast, 0xff, ETH_ALEN);
/* This is rx header therefore addresses are swapped. /* This is rx header therefore addresses are swapped.
* ie eh.h_dest is our local address. */ * ie eh.h_dest is our local address. */
memcpy(s->eh.h_dest, &src, ETH_ALEN); memcpy(s->eh.h_dest, &src, ETH_ALEN);
memcpy(s->eh.h_source, &dst, 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->sock = sock;
s->role = req->role; s->role = req->role;
s->state = BT_CONNECTED; s->state = BT_CONNECTED;
...@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->proto_filter[2].end = htons(0x86DD); s->proto_filter[2].end = htons(0x86DD);
#endif #endif
dev->init = bnep_net_init;
dev->priv = s;
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
goto failed; goto failed;
...@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
failed: failed:
up_write(&bnep_session_sem); up_write(&bnep_session_sem);
kfree(s); kfree(dev);
return err; return err;
} }
...@@ -624,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) ...@@ -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) static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{ {
memcpy(ci->dst, s->eh.h_source, ETH_ALEN); 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->flags = s->flags;
ci->state = s->state; ci->state = s->state;
ci->role = s->role; ci->role = s->role;
......
...@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
return 0; 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; dev->addr_len = ETH_ALEN;
ether_setup(dev); ether_setup(dev);
...@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev) ...@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev)
dev->watchdog_timeo = HZ * 2; dev->watchdog_timeo = HZ * 2;
dev->tx_timeout = bnep_net_timeout; dev->tx_timeout = bnep_net_timeout;
return 0;
} }
...@@ -394,7 +394,7 @@ int hci_inquiry(unsigned long arg) ...@@ -394,7 +394,7 @@ int hci_inquiry(unsigned long arg)
{ {
struct hci_inquiry_req ir; struct hci_inquiry_req ir;
struct hci_dev *hdev; struct hci_dev *hdev;
int err = 0, do_inquiry = 0; int err = 0, do_inquiry = 0, max_rsp;
long timeo; long timeo;
__u8 *buf, *ptr; __u8 *buf, *ptr;
...@@ -417,16 +417,19 @@ int hci_inquiry(unsigned long arg) ...@@ -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) if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0)
goto done; 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 /* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space. * 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; err = -ENOMEM;
goto done; goto done;
} }
hci_dev_lock_bh(hdev); 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); hci_dev_unlock_bh(hdev);
BT_DBG("num_rsp %d", ir.num_rsp); BT_DBG("num_rsp %d", ir.num_rsp);
......
...@@ -62,9 +62,22 @@ ...@@ -62,9 +62,22 @@
/* Command Complete OGF LINK_CTL */ /* Command Complete OGF LINK_CTL */
static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) 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); BT_DBG("%s ocf 0x%x", hdev->name, ocf);
switch (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: default:
BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf); BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf);
break; break;
......
...@@ -75,7 +75,7 @@ static struct hci_sec_filter hci_sec_filter = { ...@@ -75,7 +75,7 @@ static struct hci_sec_filter hci_sec_filter = {
/* OGF_LINK_POLICY */ /* OGF_LINK_POLICY */
{ 0x1200, 0x0, 0x0, 0x0 }, { 0x1200, 0x0, 0x0, 0x0 },
/* OGF_HOST_CTL */ /* OGF_HOST_CTL */
{ 0x80100000, 0x2a, 0x0, 0x0 }, { 0x80100000, 0x202a, 0x0, 0x0 },
/* OGF_INFO_PARAM */ /* OGF_INFO_PARAM */
{ 0x22a, 0x0, 0x0, 0x0 }, { 0x22a, 0x0, 0x0, 0x0 },
/* OGF_STATUS_PARAM */ /* OGF_STATUS_PARAM */
......
...@@ -289,7 +289,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason) ...@@ -289,7 +289,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
struct l2cap_disconn_req req; struct l2cap_disconn_req req;
sk->sk_state = BT_DISCONN; 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.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
...@@ -314,11 +314,9 @@ static void __l2cap_sock_close(struct sock *sk, int reason) ...@@ -314,11 +314,9 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
static void l2cap_sock_close(struct sock *sk) static void l2cap_sock_close(struct sock *sk)
{ {
l2cap_sock_clear_timer(sk); l2cap_sock_clear_timer(sk);
lock_sock(sk); lock_sock(sk);
__l2cap_sock_close(sk, ECONNRESET); __l2cap_sock_close(sk, ECONNRESET);
release_sock(sk); release_sock(sk);
l2cap_sock_kill(sk); l2cap_sock_kill(sk);
} }
...@@ -530,8 +528,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al ...@@ -530,8 +528,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto done; goto done;
wait: wait:
err = bt_sock_w4_connect(sk, flags); err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done: done:
release_sock(sk); release_sock(sk);
return err; return err;
...@@ -831,32 +829,39 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch ...@@ -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) static int l2cap_sock_shutdown(struct socket *sock, int how)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0; if (!sk) return 0;
l2cap_sock_clear_timer(sk);
lock_sock(sk); lock_sock(sk);
if (!sk->sk_shutdown) {
sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_shutdown = SHUTDOWN_MASK;
__l2cap_sock_close(sk, ECONNRESET); l2cap_sock_clear_timer(sk);
release_sock(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) static int l2cap_sock_release(struct socket *sock)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0; if (!sk) return 0;
err = l2cap_sock_shutdown(sock, 2);
sock_orphan(sk); sock_orphan(sk);
l2cap_sock_close(sk); l2cap_sock_kill(sk);
return 0; return err;
} }
/* ---- L2CAP channels ---- */ /* ---- L2CAP channels ---- */
...@@ -981,9 +986,11 @@ static void l2cap_chan_del(struct sock *sk, int err) ...@@ -981,9 +986,11 @@ static void l2cap_chan_del(struct sock *sk, int err)
} }
sk->sk_state = BT_CLOSED; sk->sk_state = BT_CLOSED;
sk->sk_err = err;
sk->sk_zapped = 1; sk->sk_zapped = 1;
if (err)
sk->sk_err = err;
if (parent) if (parent)
parent->sk_data_ready(parent, 0); parent->sk_data_ready(parent, 0);
else else
...@@ -1518,18 +1525,35 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -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))) if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
return -ENOENT; return -ENOENT;
if (result) { switch (result) {
struct l2cap_disconn_req req; case L2CAP_CONF_SUCCESS:
break;
/* They didn't like our options. Well... we do not negotiate. case L2CAP_CONF_UNACCEPT:
* Close channel. 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_state = BT_DISCONN;
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5); l2cap_sock_set_timer(sk, HZ * 5);
{
struct l2cap_disconn_req req;
req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid); req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
l2cap_send_req(conn, L2CAP_DISCONN_REQ, sizeof(req), &req); l2cap_send_req(conn, L2CAP_DISCONN_REQ, sizeof(req), &req);
}
goto done; goto done;
} }
...@@ -1590,7 +1614,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -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))) if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
return 0; return 0;
l2cap_chan_del(sk, ECONNABORTED); l2cap_chan_del(sk, 0);
bh_unlock_sock(sk); bh_unlock_sock(sk);
l2cap_sock_kill(sk); l2cap_sock_kill(sk);
......
...@@ -280,13 +280,13 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) ...@@ -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) static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
{ {
struct rfcomm_session *s; struct rfcomm_session *s;
u8 dlci = __dlci(0, channel);
int err = 0; int err = 0;
u8 dlci;
BT_DBG("dlc %p state %ld %s %s channel %d dlci %d", BT_DBG("dlc %p state %ld %s %s channel %d",
d, d->state, batostr(src), batostr(dst), channel, dlci); d, d->state, batostr(src), batostr(dst), channel);
if (dlci < 1 || dlci > 62) if (channel < 1 || channel > 30)
return -EINVAL; return -EINVAL;
if (d->state != BT_OPEN && d->state != BT_CLOSED) 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, ...@@ -299,6 +299,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err; return err;
} }
dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */ /* Check if DLCI already exists */
if (rfcomm_dlc_get(s, dlci)) if (rfcomm_dlc_get(s, dlci))
return -EBUSY; return -EBUSY;
...@@ -715,7 +717,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type) ...@@ -715,7 +717,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
hdr->len = __len8(sizeof(*mcc) + 1); hdr->len = __len8(sizeof(*mcc) + 1);
mcc = (void *) ptr; ptr += sizeof(*mcc); 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); mcc->len = __len8(1);
/* Type that we didn't like */ /* 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 ...@@ -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)); hdr->len = __len8(sizeof(*mcc) + sizeof(*pn));
mcc = (void *) ptr; ptr += sizeof(*mcc); 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)); mcc->len = __len8(sizeof(*pn));
pn = (void *) ptr; ptr += 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 ...@@ -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 = (void *) ptr; ptr += sizeof(*msc);
msc->dlci = __addr(1, dlci); 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++; *ptr = __fcs(buf); ptr++;
...@@ -1085,6 +1131,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci) ...@@ -1085,6 +1131,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
d->state = BT_CONNECTED; d->state = BT_CONNECTED;
d->state_change(d, 0); d->state_change(d, 0);
rfcomm_dlc_unlock(d); rfcomm_dlc_unlock(d);
rfcomm_send_msc(s, 1, dlci, d->v24_sig);
} else { } else {
rfcomm_send_dm(s, dlci); rfcomm_send_dm(s, dlci);
} }
...@@ -1207,6 +1255,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -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, /* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
no flow control lines, normal XON/XOFF chars */ 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) { if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
data_bits = __get_rpn_data_bits(rpn->line_settings); data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) { 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_ ...@@ -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->param_mask & RFCOMM_RPN_PM_FLOW) {
if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) { flow_ctrl = rpn->flow_ctrl;
BT_DBG("RPN flow ctrl mismatch 0x%x", 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; flow_ctrl = RFCOMM_RPN_FLOW_NONE;
rpn_mask ^= RFCOMM_RPN_PM_FLOW; rpn_mask ^= RFCOMM_RPN_PM_FLOW;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XON) { if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) { xon_char = rpn->xon_char;
BT_DBG("RPN XON char mismatch 0x%x", 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; xon_char = RFCOMM_RPN_XON_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XON; rpn_mask ^= RFCOMM_RPN_PM_XON;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) { xoff_char = rpn->xoff_char;
BT_DBG("RPN XOFF char mismatch 0x%x", 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; xoff_char = RFCOMM_RPN_XOFF_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XOFF; rpn_mask ^= RFCOMM_RPN_PM_XOFF;
} }
...@@ -1343,6 +1402,20 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb) ...@@ -1343,6 +1402,20 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
rfcomm_recv_msc(s, cr, skb); rfcomm_recv_msc(s, cr, skb);
break; 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: case RFCOMM_TEST:
if (cr) if (cr)
rfcomm_send_test(s, 0, skb->data, skb->len); rfcomm_send_test(s, 0, skb->data, skb->len);
...@@ -1533,6 +1606,9 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) ...@@ -1533,6 +1606,9 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue; continue;
} }
if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
continue;
if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) && if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
d->mscex == RFCOMM_MSCEX_OK) d->mscex == RFCOMM_MSCEX_OK)
rfcomm_process_tx(d); rfcomm_process_tx(d);
......
...@@ -192,8 +192,10 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent) ...@@ -192,8 +192,10 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent); BT_DBG("parent %p", parent);
/* Close not yet accepted dlcs */ /* 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_close(sk);
rfcomm_sock_kill(sk);
}
parent->sk_state = BT_CLOSED; parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1; parent->sk_zapped = 1;
...@@ -215,15 +217,10 @@ static void rfcomm_sock_kill(struct sock *sk) ...@@ -215,15 +217,10 @@ static void rfcomm_sock_kill(struct sock *sk)
sock_put(sk); sock_put(sk);
} }
/* Close socket. static void __rfcomm_sock_close(struct sock *sk)
* Must be called on unlocked socket.
*/
static void rfcomm_sock_close(struct sock *sk)
{ {
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 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); BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
switch (sk->sk_state) { switch (sk->sk_state) {
...@@ -240,11 +237,17 @@ static void rfcomm_sock_close(struct sock *sk) ...@@ -240,11 +237,17 @@ static void rfcomm_sock_close(struct sock *sk)
default: default:
sk->sk_zapped = 1; sk->sk_zapped = 1;
break; 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); release_sock(sk);
rfcomm_sock_kill(sk);
} }
static void rfcomm_sock_init(struct sock *sk, struct sock *parent) 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 ...@@ -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); err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
if (!err) 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); release_sock(sk);
return err; return err;
...@@ -558,9 +562,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -558,9 +562,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
int target, err = 0, copied = 0; int target, err = 0, copied = 0;
long timeo; long timeo;
if (sk->sk_state != BT_CONNECTED)
return -EINVAL;
if (flags & MSG_OOB) if (flags & MSG_OOB)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -635,23 +636,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -635,23 +636,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return copied ? : err; 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) static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -710,19 +694,42 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon ...@@ -710,19 +694,42 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
return err; 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) static int rfcomm_sock_release(struct socket *sock)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) if (!sk)
return 0; return 0;
sock_orphan(sk); err = rfcomm_sock_shutdown(sock, 2);
rfcomm_sock_close(sk);
return 0; sock_orphan(sk);
rfcomm_sock_kill(sk);
return err;
} }
/* ---- RFCOMM core layer callbacks ---- /* ---- RFCOMM core layer callbacks ----
......
...@@ -668,40 +668,8 @@ static int rfcomm_tty_write_room(struct tty_struct *tty) ...@@ -668,40 +668,8 @@ static int rfcomm_tty_write_room(struct tty_struct *tty)
return room; 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) 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); BT_DBG("tty %p cmd 0x%02x", tty, cmd);
switch (cmd) { switch (cmd) {
...@@ -713,18 +681,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned ...@@ -713,18 +681,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
BT_DBG("TCSETS is not supported"); BT_DBG("TCSETS is not supported");
return -ENOIOCTLCMD; 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: case TIOCMIWAIT:
BT_DBG("TIOCMIWAIT"); BT_DBG("TIOCMIWAIT");
break; break;
...@@ -851,6 +807,48 @@ static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, ...@@ -851,6 +807,48 @@ static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
return 0; 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 ---- */ /* ---- TTY structure ---- */
static struct tty_driver *rfcomm_tty_driver; static struct tty_driver *rfcomm_tty_driver;
...@@ -870,6 +868,8 @@ static struct tty_operations rfcomm_ops = { ...@@ -870,6 +868,8 @@ static struct tty_operations rfcomm_ops = {
.hangup = rfcomm_tty_hangup, .hangup = rfcomm_tty_hangup,
.wait_until_sent = rfcomm_tty_wait_until_sent, .wait_until_sent = rfcomm_tty_wait_until_sent,
.read_proc = rfcomm_tty_read_proc, .read_proc = rfcomm_tty_read_proc,
.tiocmget = rfcomm_tty_tiocmget,
.tiocmset = rfcomm_tty_tiocmset,
}; };
int rfcomm_init_ttys(void) int rfcomm_init_ttys(void)
...@@ -878,18 +878,17 @@ int rfcomm_init_ttys(void) ...@@ -878,18 +878,17 @@ int rfcomm_init_ttys(void)
if (!rfcomm_tty_driver) if (!rfcomm_tty_driver)
return -1; return -1;
rfcomm_tty_driver->owner = THIS_MODULE, rfcomm_tty_driver->owner = THIS_MODULE;
rfcomm_tty_driver->driver_name = "rfcomm", rfcomm_tty_driver->driver_name = "rfcomm";
rfcomm_tty_driver->devfs_name = "bluetooth/rfcomm/", rfcomm_tty_driver->devfs_name = "bluetooth/rfcomm/";
rfcomm_tty_driver->name = "rfcomm", rfcomm_tty_driver->name = "rfcomm";
rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR, rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR;
rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR, rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL, rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW, rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW;
rfcomm_tty_driver->init_termios = tty_std_termios; rfcomm_tty_driver->init_termios = tty_std_termios;
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 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); tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
if (tty_register_driver(rfcomm_tty_driver)) { if (tty_register_driver(rfcomm_tty_driver)) {
......
...@@ -353,8 +353,10 @@ static void sco_sock_cleanup_listen(struct sock *parent) ...@@ -353,8 +353,10 @@ static void sco_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent); BT_DBG("parent %p", parent);
/* Close not yet accepted channels */ /* 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_close(sk);
sco_sock_kill(sk);
}
parent->sk_state = BT_CLOSED; parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1; parent->sk_zapped = 1;
...@@ -523,7 +525,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen ...@@ -523,7 +525,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
if ((err = sco_connect(sk))) if ((err = sco_connect(sk)))
goto done; goto done;
err = bt_sock_w4_connect(sk, flags); err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done: done:
release_sock(sk); release_sock(sk);
...@@ -727,16 +730,24 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva ...@@ -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) static int sco_sock_release(struct socket *sock)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) if (!sk)
return 0; return 0;
sock_orphan(sk);
sco_sock_close(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) static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
......
...@@ -77,6 +77,6 @@ EXPORT_SYMBOL(bt_sock_recvmsg); ...@@ -77,6 +77,6 @@ EXPORT_SYMBOL(bt_sock_recvmsg);
EXPORT_SYMBOL(bt_sock_poll); EXPORT_SYMBOL(bt_sock_poll);
EXPORT_SYMBOL(bt_accept_enqueue); EXPORT_SYMBOL(bt_accept_enqueue);
EXPORT_SYMBOL(bt_accept_dequeue); EXPORT_SYMBOL(bt_accept_dequeue);
EXPORT_SYMBOL(bt_sock_w4_connect); EXPORT_SYMBOL(bt_sock_wait_state);
EXPORT_SYMBOL(proc_bt); EXPORT_SYMBOL(proc_bt);
...@@ -201,7 +201,7 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) ...@@ -201,7 +201,7 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
#ifdef CONFIG_NETFILTER_DEBUG #ifdef CONFIG_NETFILTER_DEBUG
nf_debug_ip_local_deliver(skb); nf_debug_ip_local_deliver(skb);
skb->nf_debug =3D 0; skb->nf_debug = 0;
#endif /*CONFIG_NETFILTER_DEBUG*/ #endif /*CONFIG_NETFILTER_DEBUG*/
__skb_pull(skb, ihl); __skb_pull(skb, ihl);
......
...@@ -101,7 +101,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct, ...@@ -101,7 +101,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct,
struct ip_conntrack_expect *exp = expect; struct ip_conntrack_expect *exp = expect;
struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info; struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info;
struct ip_conntrack_tuple t = exp->tuple; struct ip_conntrack_tuple t = exp->tuple;
int port; u_int16_t port;
MUST_BE_LOCKED(&ip_amanda_lock); MUST_BE_LOCKED(&ip_amanda_lock);
...@@ -115,7 +115,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct, ...@@ -115,7 +115,7 @@ static int amanda_data_fixup(struct ip_conntrack *ct,
writable */ writable */
t.dst.ip = newip; 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); t.dst.u.tcp.port = htons(port);
if (ip_conntrack_change_expect(exp, &t) == 0) if (ip_conntrack_change_expect(exp, &t) == 0)
break; break;
......
...@@ -99,7 +99,7 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info, ...@@ -99,7 +99,7 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
struct ip_conntrack_tuple t; struct ip_conntrack_tuple t;
struct iphdr *iph = (*pskb)->nh.iph; struct iphdr *iph = (*pskb)->nh.iph;
struct tcphdr *tcph = (void *) iph + iph->ihl * 4; struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
int port; u_int16_t port;
/* "4294967296 65635 " */ /* "4294967296 65635 " */
char buffer[18]; char buffer[18];
......
...@@ -2517,7 +2517,109 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) ...@@ -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); 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] = { 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_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
[RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, },
[RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, }, [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, },
......
...@@ -1044,6 +1044,17 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1044,6 +1044,17 @@ static void ndisc_router_discovery(struct sk_buff *skb)
in6_dev->if_flags |= IF_RA_RCVD; 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); lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); 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