From db0badc58e948b810c7a75cfcc48845e2949ee37 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 18 Aug 2008 13:40:18 +0200 Subject: udf: Fix lock inversion between iprune_mutex and alloc_mutex (v2) A memory allocation inside alloc_mutex must not recurse back into the filesystem itself because that leads to lock inversion between iprune_mutex and alloc_mutex (and thus to deadlocks - see traces below). alloc_mutex is actually needed only to update allocation statistics in the superblock so we can drop it before we start allocating memory for the inode. tar D ffff81015b9c8c90 0 6614 6612 ffff8100d5a21a20 0000000000000086 0000000000000000 00000000ffff0000 ffff81015b9c8c90 ffff81015b8f0cd0 ffff81015b9c8ee0 0000000000000000 0000000000000003 0000000000000000 0000000000000000 0000000000000000 Call Trace: [] __mutex_lock_slowpath+0x64/0x9b [] mutex_lock+0xa/0xb [] shrink_icache_memory+0x38/0x200 [] shrink_slab+0xe3/0x15b [] try_to_free_pages+0x221/0x30d [] isolate_pages_global+0x0/0x31 [] __alloc_pages_internal+0x252/0x3ab [] cache_alloc_refill+0x22e/0x47b [] kmem_cache_alloc+0x3b/0x61 [] cache_alloc_refill+0x2fe/0x47b [] __kmalloc+0x76/0x9c [] :udf:udf_new_inode+0x202/0x2e2 [] :udf:udf_create+0x2f/0x16d [] :udf:udf_lookup+0xa6/0xad ... kswapd0 D ffff81015b9d9270 0 125 2 ffff81015b903c28 0000000000000046 ffffffff8028cbb0 00000000fffffffb ffff81015b9d9270 ffff81015b8f0cd0 ffff81015b9d94c0 000000000271b490 ffffe2000271b458 ffffe2000271b420 ffffe20002728dc8 ffffe20002728d90 Call Trace: [] __set_page_dirty+0xeb/0xf5 [] get_dirty_limits+0x1d/0x22f [] __mutex_lock_slowpath+0x64/0x9b [] mutex_lock+0xa/0xb [] :udf:udf_bitmap_free_blocks+0x47/0x1eb [] :udf:udf_discard_prealloc+0xc6/0x172 [] :udf:udf_clear_inode+0x1e/0x48 [] clear_inode+0x6d/0xc4 [] dispose_list+0x56/0xee [] shrink_icache_memory+0x1d0/0x200 [] shrink_slab+0xe3/0x15b [] kswapd+0x346/0x447 ... Reported-by: Tibor Tajti Reviewed-by: Ingo Oeser Signed-off-by: Jan Kara --- fs/udf/ialloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index eb9cfa23dc3..c4943c8988c 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -111,6 +111,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(sbi->s_lvid_bh); } + mutex_unlock(&sbi->s_alloc_mutex); inode->i_mode = mode; inode->i_uid = current->fsuid; if (dir->i_mode & S_ISGID) { @@ -145,7 +146,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) if (!iinfo->i_ext.i_data) { iput(inode); *err = -ENOMEM; - mutex_unlock(&sbi->s_alloc_mutex); return NULL; } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) @@ -158,7 +158,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) iinfo->i_crtime = current_fs_time(inode->i_sb); insert_inode_hash(inode); mark_inode_dirty(inode); - mutex_unlock(&sbi->s_alloc_mutex); if (DQUOT_ALLOC_INODE(inode)) { DQUOT_DROP(inode); -- cgit v1.2.3 From 97e1cfb08616987878f91a46cefdd7fc5fa3dba1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 18 Aug 2008 13:44:48 +0200 Subject: udf: Fix error paths in udf_new_inode() I case we failed to allocate memory for inode when creating it, we did not properly free block already allocated for this inode. Move memory allocation before the block allocation which fixes this issue (thanks for the idea go to Ingo Oeser ). Also remove a few superfluous initializations already done in udf_alloc_inode(). Reviewed-by: Ingo Oeser Signed-off-by: Jan Kara --- fs/udf/ialloc.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index c4943c8988c..a4f2b3ce45b 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -76,11 +76,24 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) *err = -ENOSPC; iinfo = UDF_I(inode); - iinfo->i_unique = 0; - iinfo->i_lenExtents = 0; - iinfo->i_next_alloc_block = 0; - iinfo->i_next_alloc_goal = 0; - iinfo->i_strat4096 = 0; + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { + iinfo->i_efe = 1; + if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) + sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; + iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct extendedFileEntry), + GFP_KERNEL); + } else { + iinfo->i_efe = 0; + iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - + sizeof(struct fileEntry), + GFP_KERNEL); + } + if (!iinfo->i_ext.i_data) { + iput(inode); + *err = -ENOMEM; + return NULL; + } block = udf_new_block(dir->i_sb, NULL, dinfo->i_location.partitionReferenceNum, @@ -130,24 +143,6 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) iinfo->i_lenEAttr = 0; iinfo->i_lenAlloc = 0; iinfo->i_use = 0; - if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { - iinfo->i_efe = 1; - if (UDF_VERS_USE_EXTENDED_FE > sbi->s_udfrev) - sbi->s_udfrev = UDF_VERS_USE_EXTENDED_FE; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct extendedFileEntry), - GFP_KERNEL); - } else { - iinfo->i_efe = 0; - iinfo->i_ext.i_data = kzalloc(inode->i_sb->s_blocksize - - sizeof(struct fileEntry), - GFP_KERNEL); - } - if (!iinfo->i_ext.i_data) { - iput(inode); - *err = -ENOMEM; - return NULL; - } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) -- cgit v1.2.3 From 04da11bfcf511544ae19e0a7e5f994b3237752ac Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 20 Aug 2008 17:16:34 +0300 Subject: UBIFS: fix zero-length truncations Always allow truncations to zero, even if budgeting thinks there is no space. UBIFS reserves some space for deletions anyway. Otherwise, the following happans: 1. create a file, and write as much as possible there, until ENOSPC 2. truncate the file, which fails with ENOSPC, which is not good. Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 1 - fs/ubifs/file.c | 20 ++++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 5c96f1fb701..2b267c9a180 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) if (err) { if (err != -ENOSPC) return err; - err = 0; budgeted = 0; } diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 4071d1cae29..3d698e2022b 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, int err; struct ubifs_budget_req req; loff_t old_size = inode->i_size, new_size = attr->ia_size; - int offset = new_size & (UBIFS_BLOCK_SIZE - 1); + int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1; struct ubifs_inode *ui = ubifs_inode(inode); dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size); @@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, /* A funny way to budget for truncation node */ req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ; err = ubifs_budget_space(c, &req); - if (err) - return err; + if (err) { + /* + * Treat truncations to zero as deletion and always allow them, + * just like we do for '->unlink()'. + */ + if (new_size || err != -ENOSPC) + return err; + budgeted = 0; + } err = vmtruncate(inode, new_size); if (err) @@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, err = ubifs_jnl_truncate(c, inode, old_size, new_size); mutex_unlock(&ui->ui_mutex); out_budg: - ubifs_release_budget(c, &req); + if (budgeted) + ubifs_release_budget(c, &req); + else { + c->nospace = c->nospace_rp = 0; + smp_wmb(); + } return err; } -- cgit v1.2.3 From 761e29f3bb19b05bea55285dfdf2d28e001a63b8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 20 Aug 2008 16:32:40 +0300 Subject: UBIFS: always read hashed-key nodes under TNC mutex Leaf-nodes that have a hashed key are stored in the leaf-node-cache (LNC) which is protected by the TNC mutex. Consequently, when reading a leaf node with a hashed key (i.e. directory entries, xattr entries) the TNC mutex is always required. Signed-off-by: Adrian Hunter --- fs/ubifs/tnc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index e909f4a9644..4fbc5921688 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1498,7 +1498,6 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, { int found, n, err; struct ubifs_znode *znode; - struct ubifs_zbranch zbr; dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key)); mutex_lock(&c->tnc_mutex); @@ -1522,11 +1521,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, goto out_unlock; } - zbr = znode->zbranch[n]; - mutex_unlock(&c->tnc_mutex); - - err = tnc_read_node_nm(c, &zbr, node); - return err; + err = tnc_read_node_nm(c, &znode->zbranch[n], node); out_unlock: mutex_unlock(&c->tnc_mutex); -- cgit v1.2.3 From 601c0bc46753007be011b513ba4fc50ed8e30aef Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Aug 2008 14:23:35 +0300 Subject: UBIFS: allow for racing between GC and TNC The TNC mutex is unlocked prematurely when reading leaf nodes with non-hashed keys. This is unsafe because the node may be moved by garbage collection and the eraseblock unmapped, although that has never actually happened during stress testing. This patch fixes the flaw by detecting the race and retrying with the TNC mutex locked. Signed-off-by: Adrian Hunter --- fs/ubifs/gc.c | 6 +++ fs/ubifs/misc.h | 17 +++++++++ fs/ubifs/tnc.c | 109 ++++++++++++++++++++++++++++++------------------------- fs/ubifs/ubifs.h | 6 ++- 4 files changed, 87 insertions(+), 51 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index d0f3dac2908..13f1019c859 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) if (err) goto out; + /* Allow for races with TNC */ + c->gced_lnum = lnum; + smp_wmb(); + c->gc_seq += 1; + smp_wmb(); + if (c->gc_lnum == -1) { c->gc_lnum = lnum; err = LEB_RETAINED; diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 87dabf9fe74..87ced4c74a6 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -325,4 +325,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode) current_fs_time(inode->i_sb) : CURRENT_TIME_SEC; } +/** + * ubifs_tnc_lookup - look up a file-system node. + * @c: UBIFS file-system description object + * @key: node key to lookup + * @node: the node is returned here + * + * This function look up and reads node with key @key. The caller has to make + * sure the @node buffer is large enough to fit the node. Returns zero in case + * of success, %-ENOENT if the node was not found, and a negative error code in + * case of failure. + */ +static inline int ubifs_tnc_lookup(struct ubifs_info *c, + const union ubifs_key *key, void *node) +{ + return ubifs_tnc_locate(c, key, node, NULL, NULL); +} + #endif /* __UBIFS_MISC_H__ */ diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 4fbc5921688..7da209ab937 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -506,7 +506,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, if (keys_cmp(c, key, &node_key) != 0) ret = 0; } - if (ret == 0) + if (ret == 0 && c->replaying) dbg_mnt("dangling branch LEB %d:%d len %d, key %s", zbr->lnum, zbr->offs, zbr->len, DBGKEY(key)); return ret; @@ -1382,50 +1382,39 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key, } /** - * ubifs_tnc_lookup - look up a file-system node. + * maybe_leb_gced - determine if a LEB may have been garbage collected. * @c: UBIFS file-system description object - * @key: node key to lookup - * @node: the node is returned here + * @lnum: LEB number + * @gc_seq1: garbage collection sequence number * - * This function look up and reads node with key @key. The caller has to make - * sure the @node buffer is large enough to fit the node. Returns zero in case - * of success, %-ENOENT if the node was not found, and a negative error code in - * case of failure. + * This function determines if @lnum may have been garbage collected since + * sequence number @gc_seq1. If it may have been then %1 is returned, otherwise + * %0 is returned. */ -int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, - void *node) +static int maybe_leb_gced(struct ubifs_info *c, int lnum, int gc_seq1) { - int found, n, err; - struct ubifs_znode *znode; - struct ubifs_zbranch zbr, *zt; - - mutex_lock(&c->tnc_mutex); - found = ubifs_lookup_level0(c, key, &znode, &n); - if (!found) { - err = -ENOENT; - goto out; - } else if (found < 0) { - err = found; - goto out; - } - zt = &znode->zbranch[n]; - if (is_hash_key(c, key)) { - /* - * In this case the leaf node cache gets used, so we pass the - * address of the zbranch and keep the mutex locked - */ - err = tnc_read_node_nm(c, zt, node); - goto out; - } - zbr = znode->zbranch[n]; - mutex_unlock(&c->tnc_mutex); - - err = ubifs_tnc_read_node(c, &zbr, node); - return err; + int gc_seq2, gced_lnum; -out: - mutex_unlock(&c->tnc_mutex); - return err; + gced_lnum = c->gced_lnum; + smp_rmb(); + gc_seq2 = c->gc_seq; + /* Same seq means no GC */ + if (gc_seq1 == gc_seq2) + return 0; + /* Different by more than 1 means we don't know */ + if (gc_seq1 + 1 != gc_seq2) + return 1; + /* + * We have seen the sequence number has increased by 1. Now we need to + * be sure we read the right LEB number, so read it again. + */ + smp_rmb(); + if (gced_lnum != c->gced_lnum) + return 1; + /* Finally we can check lnum */ + if (gced_lnum == lnum) + return 1; + return 0; } /** @@ -1436,16 +1425,19 @@ out: * @lnum: LEB number is returned here * @offs: offset is returned here * - * This function is the same as 'ubifs_tnc_lookup()' but it returns the node - * location also. See 'ubifs_tnc_lookup()'. + * This function look up and reads node with key @key. The caller has to make + * sure the @node buffer is large enough to fit the node. Returns zero in case + * of success, %-ENOENT if the node was not found, and a negative error code in + * case of failure. The node location can be returned in @lnum and @offs. */ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, void *node, int *lnum, int *offs) { - int found, n, err; + int found, n, err, safely = 0, gc_seq1; struct ubifs_znode *znode; struct ubifs_zbranch zbr, *zt; +again: mutex_lock(&c->tnc_mutex); found = ubifs_lookup_level0(c, key, &znode, &n); if (!found) { @@ -1456,24 +1448,43 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, goto out; } zt = &znode->zbranch[n]; + if (lnum) { + *lnum = zt->lnum; + *offs = zt->offs; + } if (is_hash_key(c, key)) { /* * In this case the leaf node cache gets used, so we pass the * address of the zbranch and keep the mutex locked */ - *lnum = zt->lnum; - *offs = zt->offs; err = tnc_read_node_nm(c, zt, node); goto out; } + if (safely) { + err = ubifs_tnc_read_node(c, zt, node); + goto out; + } + /* Drop the TNC mutex prematurely and race with garbage collection */ zbr = znode->zbranch[n]; + gc_seq1 = c->gc_seq; mutex_unlock(&c->tnc_mutex); - *lnum = zbr.lnum; - *offs = zbr.offs; + if (ubifs_get_wbuf(c, zbr.lnum)) { + /* We do not GC journal heads */ + err = ubifs_tnc_read_node(c, &zbr, node); + return err; + } - err = ubifs_tnc_read_node(c, &zbr, node); - return err; + err = fallible_read_node(c, key, &zbr, node); + if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + /* + * The node may have been GC'ed out from under us so try again + * while keeping the TNC mutex locked. + */ + safely = 1; + goto again; + } + return 0; out: mutex_unlock(&c->tnc_mutex); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d7f706f7a30..7828d69ca4f 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1028,6 +1028,8 @@ struct ubifs_mount_opts { * @sbuf: a buffer of LEB size used by GC and replay for scanning * @idx_gc: list of index LEBs that have been garbage collected * @idx_gc_cnt: number of elements on the idx_gc list + * @gc_seq: incremented for every non-index LEB garbage collected + * @gced_lnum: last non-index LEB that was garbage collected * * @infos_list: links all 'ubifs_info' objects * @umount_mutex: serializes shrinker and un-mount @@ -1257,6 +1259,8 @@ struct ubifs_info { void *sbuf; struct list_head idx_gc; int idx_gc_cnt; + volatile int gc_seq; + volatile int gced_lnum; struct list_head infos_list; struct mutex umount_mutex; @@ -1451,8 +1455,6 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c); /* tnc.c */ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key, struct ubifs_znode **zn, int *n); -int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, - void *node); int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, void *node, const struct qstr *nm); int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, -- cgit v1.2.3 From bfad9ceac5d11318c99ae8a0d1e926a380a56edd Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 2 Aug 2008 19:49:40 +0200 Subject: [SCSI] sd: select CRC_T10DIF only when necessary Signed-off-by: Stefan Richter Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index c7f06298bd3..4e0322b1c1e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -63,7 +63,7 @@ comment "SCSI support type (disk, tape, CD-ROM)" config BLK_DEV_SD tristate "SCSI disk support" depends on SCSI - select CRC_T10DIF + select CRC_T10DIF if BLK_DEV_INTEGRITY ---help--- If you want to use SCSI hard disks, Fibre Channel disks, Serial ATA (SATA) or Parallel ATA (PATA) hard disks, -- cgit v1.2.3 From d4538817287e56abc938900886301a5bdfafbfcd Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 21 Aug 2008 13:43:32 +0200 Subject: [SCSI] zfcp: Fix request queue locking The request queue lock can be acquired from softirq context when the SCSI midlayer issues commands. Disable softirqs for this lock when commands are issued from zfcp. Signed-off-by: Christof Schmitt Signed-off-by: Martin Petermann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 56 +++++++++++++++++++++---------------------- drivers/s390/scsi/zfcp_qdio.c | 4 ++-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 19c1ca91387..aad33241a2e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -710,10 +710,10 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) static int zfcp_fsf_sbal_check(struct zfcp_qdio_queue *queue) { - spin_lock(&queue->lock); + spin_lock_bh(&queue->lock); if (atomic_read(&queue->count)) return 1; - spin_unlock(&queue->lock); + spin_unlock_bh(&queue->lock); return 0; } @@ -722,13 +722,13 @@ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) long ret; struct zfcp_qdio_queue *req_q = &adapter->req_q; - spin_unlock(&req_q->lock); + spin_unlock_bh(&req_q->lock); ret = wait_event_interruptible_timeout(adapter->request_wq, zfcp_fsf_sbal_check(req_q), 5 * HZ); if (ret > 0) return 0; - spin_lock(&req_q->lock); + spin_lock_bh(&req_q->lock); return -EIO; } @@ -870,7 +870,7 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter) volatile struct qdio_buffer_element *sbale; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -910,7 +910,7 @@ failed_buf: zfcp_fsf_req_free(req); zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1106,7 +1106,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, struct zfcp_fsf_req *req; int ret = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1148,7 +1148,7 @@ failed_send: if (erp_action) erp_action->fsf_req = NULL; out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return ret; } @@ -1263,7 +1263,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) struct zfcp_adapter *adapter = erp_action->adapter; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (!atomic_read(&adapter->req_q.count)) goto out; req = zfcp_fsf_req_create(adapter, @@ -1295,7 +1295,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1306,7 +1306,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, struct zfcp_fsf_req *req = NULL; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1334,7 +1334,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); @@ -1359,7 +1359,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (!atomic_read(&adapter->req_q.count)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, @@ -1385,7 +1385,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1405,7 +1405,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (!atomic_read(&adapter->req_q.count)) goto out; @@ -1427,7 +1427,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); @@ -1531,7 +1531,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1562,7 +1562,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1603,7 +1603,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1633,7 +1633,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1700,7 +1700,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1731,7 +1731,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1875,7 +1875,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1910,7 +1910,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -1965,7 +1965,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, @@ -1995,7 +1995,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); return retval; } @@ -2417,7 +2417,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, return ERR_PTR(-EINVAL); } - spin_lock(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q.lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -2447,7 +2447,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q.lock); if (!retval) { wait_event(req->completion_wq, diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index d6dbd653fde..69d632d851d 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -423,9 +423,9 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ req_q = &adapter->req_q; - spin_lock(&req_q->lock); + spin_lock_bh(&req_q->lock); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); - spin_unlock(&req_q->lock); + spin_unlock_bh(&req_q->lock); qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); -- cgit v1.2.3 From 47f7bba52b01dd881fbd17b4b50c89ecf186eee2 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 21 Aug 2008 13:43:33 +0200 Subject: [SCSI] zfcp: Correctly query end flag in gpn_ft response When the last port entry in the gpn_ft response is already a known port, the eval function would skip the end flag and try to attach ports with wwpn 0. Fix this by checking the flag first. Signed-off-by: Christof Schmitt Signed-off-by: Martin Petermann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index e984469bb98..27edabe5b20 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -475,7 +475,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) struct zfcp_adapter *adapter = ct->port->adapter; struct zfcp_port *port, *tmp; u32 d_id; - int ret = 0, x; + int ret = 0, x, last = 0; if (ct->status) return -EIO; @@ -492,12 +492,13 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) down(&zfcp_data.config_sema); /* first entry is the header */ - for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES; x++) { + for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) { if (x % (ZFCP_GPN_FT_ENTRIES + 1)) acc++; else acc = sg_virt(++sg); + last = acc->control & 0x80; d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | acc->port_id[2]; @@ -513,8 +514,6 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) ret = PTR_ERR(port); else zfcp_erp_port_reopen(port, 0, 149, NULL); - if (acc->control & 0x80) /* last entry */ - break; } zfcp_erp_wait(adapter); -- cgit v1.2.3 From f48bf7fb00f74d93105ba69522a3f6c9435d6af3 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 21 Aug 2008 13:43:34 +0200 Subject: [SCSI] zfcp: Simplify ccw notify handler The notify handler does not change the list of adapters, it only triggers erp actions to open or shutdown the adapter. We don't need to hold the config semaphore and wait for the erp to complete. This is a prerequisite for a fix in the s390 common i/o code. Signed-off-by: Christof Schmitt Signed-off-by: Martin Petermann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_ccw.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 391dd29749f..51b6a05f4d1 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -152,10 +152,8 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) */ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) { - struct zfcp_adapter *adapter; + struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev); - down(&zfcp_data.config_sema); - adapter = dev_get_drvdata(&ccw_device->dev); switch (event) { case CIO_GONE: dev_warn(&adapter->ccw_device->dev, "device gone\n"); @@ -174,8 +172,6 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) 89, NULL); break; } - zfcp_erp_wait(adapter); - up(&zfcp_data.config_sema); return 1; } -- cgit v1.2.3 From 9528539cc2d506aa232b0d93881ac4d19738752f Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 21 Aug 2008 13:43:35 +0200 Subject: [SCSI] zfcp: Fix reference counter for remote ports Fix the remote port reference counter handling during ELS ADISC commands and find the remote port by WWPN not by D_IDs that could change. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 27edabe5b20..05e6b09c48f 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -39,18 +39,6 @@ struct zfcp_gpn_ft { struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; }; -static struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *adapter, - u32 d_id) -{ - struct zfcp_port *port; - - list_for_each_entry(port, &adapter->port_list_head, list) - if ((port->d_id == d_id) && - !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) - return port; - return NULL; -} - static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, struct fcp_rscn_element *elem) { @@ -341,12 +329,13 @@ void zfcp_test_link(struct zfcp_port *port) zfcp_port_get(port); retval = zfcp_fc_adisc(port); - if (retval == 0 || retval == -EBUSY) + if (retval == 0) return; /* send of ADISC was not possible */ zfcp_port_put(port); - zfcp_erp_port_forced_reopen(port, 0, 65, NULL); + if (retval != -EBUSY) + zfcp_erp_port_forced_reopen(port, 0, 65, NULL); } static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter) @@ -503,9 +492,13 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) acc->port_id[2]; /* skip the adapter's port and known remote ports */ - if (acc->wwpn == fc_host_port_name(adapter->scsi_host) || - zfcp_get_port_by_did(adapter, d_id)) + if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) continue; + port = zfcp_get_port_by_wwpn(adapter, acc->wwpn); + if (port) { + zfcp_port_get(port); + continue; + } port = zfcp_port_enqueue(adapter, acc->wwpn, ZFCP_STATUS_PORT_DID_DID | -- cgit v1.2.3 From 6139308dca9437975125290698cb9306240f525c Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 21 Aug 2008 13:43:36 +0200 Subject: [SCSI] zfcp: channel cannot be detached due to refcount imbalance Due to an imbalance of the nameserver refcounting, channel devices couldn't be take offline anymore after the channel was activated. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 05e6b09c48f..56196c98c07 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -352,7 +352,6 @@ static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter) if (ret) return ret; zfcp_erp_wait(adapter); - zfcp_port_put(adapter->nameserver_port); } return !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->nameserver_port->status); -- cgit v1.2.3 From 025270f0eaa2def673747ed6f77cca41f694f354 Mon Sep 17 00:00:00 2001 From: Hirofumi Nakagawa Date: Thu, 21 Aug 2008 13:43:37 +0200 Subject: [SCSI] zfcp: Remove duplicated unlikely() macros. Some drivers have duplicated unlikely() macros. IS_ERR() already has unlikely() in itself. This patch cleans up such pointless codes although there is no real effect on the kernel's behaviour. Signed-off-by: Hirofumi Nakagawa Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index aad33241a2e..49dbeb754e5 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -877,7 +877,7 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter) req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS, ZFCP_REQ_NO_QTCB, adapter->pool.fsf_req_status_read); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -988,7 +988,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, req_flags, adapter->pool.fsf_req_abort); - if (unlikely(IS_ERR(req))) + if (IS_ERR(req)) goto out; if (unlikely(!(atomic_read(&unit->status) & @@ -1112,7 +1112,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, ZFCP_REQ_AUTO_CLEANUP, pool); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { ret = PTR_ERR(req); goto out; } @@ -1223,7 +1223,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, ZFCP_REQ_AUTO_CLEANUP, NULL); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { ret = PTR_ERR(req); goto out; } @@ -1270,7 +1270,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) FSF_QTCB_EXCHANGE_CONFIG_DATA, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1312,7 +1312,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, 0, NULL); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1365,7 +1365,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1411,7 +1411,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, NULL); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1539,7 +1539,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) FSF_QTCB_OPEN_PORT_WITH_DID, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1610,7 +1610,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1707,7 +1707,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1882,7 +1882,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -1971,7 +1971,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -2228,7 +2228,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = PTR_ERR(req); goto out; } @@ -2351,7 +2351,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); - if (unlikely(IS_ERR(req))) + if (IS_ERR(req)) goto out; req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; @@ -2422,7 +2422,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, goto out; req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL); - if (unlikely(IS_ERR(req))) { + if (IS_ERR(req)) { retval = -EPERM; goto out; } -- cgit v1.2.3 From c7dbb627a2505f42b2e6b3581f3716d73453dd0c Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Tue, 12 Aug 2008 12:11:57 -0700 Subject: [SCSI] scsi_dh: make check_sense return ADD_TO_MLQUEUE Change scsi_dh check_sense functions to return ADD_TO_MLQUEUE to allow retries to occur without restriction of blk_noretry_request check. Signed-off-by: Mike Anderson Acked-by: Chandra Seetharaman Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 12 ++++++------ drivers/scsi/device_handler/scsi_dh_emc.c | 4 ++-- drivers/scsi/device_handler/scsi_dh_rdac.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 994da56fffe..708e475896b 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -425,7 +425,7 @@ static int alua_check_sense(struct scsi_device *sdev, /* * LUN Not Accessible - ALUA state transition */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b) /* * LUN Not Accessible -- Target port in standby state @@ -447,18 +447,18 @@ static int alua_check_sense(struct scsi_device *sdev, /* * Power On, Reset, or Bus Device Reset, just retry. */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) { /* * ALUA state changed */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; } if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) { /* * Implicit ALUA state transition failed */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; } break; } @@ -490,7 +490,7 @@ static int alua_stpg(struct scsi_device *sdev, int state, if (!err) return SCSI_DH_IO; err = alua_check_sense(sdev, &sense_hdr); - if (retry > 0 && err == NEEDS_RETRY) { + if (retry > 0 && err == ADD_TO_MLQUEUE) { retry--; goto retry; } @@ -535,7 +535,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) return SCSI_DH_IO; err = alua_check_sense(sdev, &sense_hdr); - if (err == NEEDS_RETRY) + if (err == ADD_TO_MLQUEUE) goto retry; sdev_printk(KERN_INFO, sdev, "%s: rtpg sense code %02x/%02x/%02x\n", diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index b9d23e9e9a4..ef693e8412e 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -439,7 +439,7 @@ static int clariion_check_sense(struct scsi_device *sdev, * Unit Attention Code. This is the first IO * to the new path, so just retry. */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; break; } @@ -514,7 +514,7 @@ retry: return SCSI_DH_IO; err = clariion_check_sense(sdev, &sshdr); - if (retry > 0 && err == NEEDS_RETRY) { + if (retry > 0 && err == ADD_TO_MLQUEUE) { retry--; goto retry; } diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 2dee69da35c..6e2f130d56d 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -551,7 +551,7 @@ static int rdac_check_sense(struct scsi_device *sdev, * * Just retry and wait. */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; break; case ILLEGAL_REQUEST: if (sense_hdr->asc == 0x94 && sense_hdr->ascq == 0x01) { @@ -568,7 +568,7 @@ static int rdac_check_sense(struct scsi_device *sdev, /* * Power On, Reset, or Bus Device Reset, just retry. */ - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; break; } /* success just means we do not care what scsi-ml does */ -- cgit v1.2.3 From bb0003c1e189d5766b6b39299b08c690c985c4dc Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Tue, 12 Aug 2008 12:11:58 -0700 Subject: [SCSI] make scsi_check_sense HARDWARE_ERROR return ADD_TO_MLQUEUE on retry Change scsi_check_sense HARDWARE_ERROR check to return ADD_TO_MLQUEUE if device->retry_hwerror is set to allow retries to occur without restriction of blk_noretry_request check. Signed-off-by: Mike Anderson Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 880051c89bd..39ce3aba1da 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -391,7 +391,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) case HARDWARE_ERROR: if (scmd->device->retry_hwerror) - return NEEDS_RETRY; + return ADD_TO_MLQUEUE; else return SUCCESS; -- cgit v1.2.3 From 01b291bd66564b4bd826326af6bd0b6d17e99439 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 21 Aug 2008 15:14:14 -0500 Subject: [SCSI] fix check of PQ and PDT bits for WLUNs For IBM z series certain LUNs can no longer be accessed. This is because kernel version 2.6.19 a check was introduced not to create a generic SCSI device for devices that return PQ=1 and PDT=0x1f. For WLUNs (see SAM-3, p. 41ff) generic SCSI devices should be created unconditionally without looking at the PQ bit, so add a check for WLUNs in with this test. Acked-by: Martin Petermann Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 3 ++- include/scsi/scsi.h | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 84b4879cff1..34d0de6cd51 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1080,7 +1080,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * PDT=1Fh none (no FDD connected to the requested logical unit) */ if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) && - (result[0] & 0x1f) == 0x1f) { + (result[0] & 0x1f) == 0x1f && + !scsi_is_wlun(lun)) { SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: peripheral device type" " of 31, no device added\n")); diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 5c40cc537d4..192f8716aa9 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -308,6 +308,20 @@ struct scsi_lun { __u8 scsi_lun[8]; }; +/* + * The Well Known LUNS (SAM-3) in our int representation of a LUN + */ +#define SCSI_W_LUN_BASE 0xc100 +#define SCSI_W_LUN_REPORT_LUNS (SCSI_W_LUN_BASE + 1) +#define SCSI_W_LUN_ACCESS_CONTROL (SCSI_W_LUN_BASE + 2) +#define SCSI_W_LUN_TARGET_LOG_PAGE (SCSI_W_LUN_BASE + 3) + +static inline int scsi_is_wlun(unsigned int lun) +{ + return (lun & 0xff00) == SCSI_W_LUN_BASE; +} + + /* * MESSAGE CODES */ -- cgit v1.2.3 From 8191e1fa8131a422f4bf7b0f2dc1f8543fd17783 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 22 Aug 2008 12:26:40 +0300 Subject: UBIFS: do not update min_idx_lebs in stafs This is bad because the rest of the code should not depend on it, and this may hide bugss, instead of revealing them. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 15409815747..ac0d2e1e73b 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -741,7 +741,6 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) available = ubifs_calc_available(c, min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; - c->min_idx_lebs = min_idx_lebs; spin_unlock(&c->space_lock); if (available > outstanding) -- cgit v1.2.3 From 9e5de3549615818cae9c20a0ee1fd3ad4a747758 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 17:29:43 +0300 Subject: UBIFS: push empty flash hack down We have a hack which forces the amount of flash space to be equivalent to 'c->blocks_cnt' in case of empty FS. This is to make users happy and see '%0' used in 'df' when they mount an empty FS. This hack is not needed in 'ubifs_calc_available()', but it is only needed the caller, in 'ubifs_budg_get_free_space()'. So push it down there. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 24 +++++++++++------------- fs/ubifs/super.c | 2 -- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index ac0d2e1e73b..f6d2eaa7a06 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs) int subtract_lebs; long long available; - /* - * Force the amount available to the total size reported if the used - * space is zero. - */ - if (c->lst.total_used <= UBIFS_INO_NODE_SZ && - c->budg_data_growth + c->budg_dd_growth == 0) { - /* Do the same calculation as for c->block_cnt */ - available = c->main_lebs - 2; - available *= c->leb_size - c->dark_wm; - return available; - } - available = c->main_bytes - c->lst.total_used; /* @@ -739,8 +727,18 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) return 0; } - available = ubifs_calc_available(c, min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; + + /* + * Force the amount available to the total size reported if the used + * space is zero. + */ + if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) { + spin_unlock(&c->space_lock); + return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT; + } + + available = ubifs_calc_available(c, min_idx_lebs); spin_unlock(&c->space_lock); if (available > outstanding) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index f71e6b8822c..1018053519e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -649,8 +649,6 @@ static int init_constants_late(struct ubifs_info *c) * * Subtract the LEB reserved for GC and the LEB which is reserved for * deletions. - * - * Review 'ubifs_calc_available()' if changing this calculation. */ tmp64 = c->main_lebs - 2; tmp64 *= (uint64_t)c->leb_size - c->dark_wm; -- cgit v1.2.3 From 8aabb75017291ba68c09ff5fdb998ef0a1fdaaf9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 16:02:31 +0300 Subject: UBIFS: remove incorrect index space check When we report free space to user-space, we should not report 0 if the amount of empty LEBs is too low, because they would be produced by GC when needed. Thus, just call 'ubifs_calc_available()' straight away which would take 'min_idx_lebs' into account anyway. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index f6d2eaa7a06..9ef630a594c 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -709,24 +709,11 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, */ long long ubifs_budg_get_free_space(struct ubifs_info *c) { - int min_idx_lebs, rsvd_idx_lebs; + int min_idx_lebs; long long available, outstanding, free; - /* Do exactly the same calculations as in 'do_budget_space()' */ spin_lock(&c->space_lock); min_idx_lebs = ubifs_calc_min_idx_lebs(c); - - if (min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; - else - rsvd_idx_lebs = 0; - - if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - - c->lst.taken_empty_lebs) { - spin_unlock(&c->space_lock); - return 0; - } - outstanding = c->budg_data_growth + c->budg_dd_growth; /* -- cgit v1.2.3 From 4b5f2762ec914c9dfd0e9d2377c0574f2ee9a8f9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 16:15:56 +0300 Subject: UBIFS: improve statfs reporting Make free space calculation less pessimistic and more realistic, which in turn improves 'statfs()' reports. Now it lies by 10%-20%, instead of 20%-30% (10% more honest). Results of "freespace" test (120MiB volume, 16KiB LEB size, 512 bytes page size). Before the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 78274560 bytes 74.6 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 18214912 bytes 17.4 MiB, wrote 23.3% more than predicted freespace: was free: 76754944 bytes 73.2 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 19738624 bytes 18.8 MiB, wrote 25.7% more than predicted freespace: was free: 76759040 bytes 73.2 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 19730432 bytes 18.8 MiB, wrote 25.7% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 6977722 bytes 6.7 MiB each time freespace: was free: 72273920 bytes 68.9 MiB, wrote: 88891392 bytes 84.8 MiB, delta: 16617472 bytes 15.8 MiB, wrote 23.0% more than predicted freespace: was free: 66154496 bytes 63.1 MiB, wrote: 81506304 bytes 77.7 MiB, delta: 15351808 bytes 14.6 MiB, wrote 23.2% more than predicted freespace: was free: 58732544 bytes 56.0 MiB, wrote: 72572928 bytes 69.2 MiB, delta: 13840384 bytes 13.2 MiB, wrote 23.6% more than predicted freespace: was free: 51552256 bytes 49.2 MiB, wrote: 63754240 bytes 60.8 MiB, delta: 12201984 bytes 11.6 MiB, wrote 23.7% more than predicted freespace: was free: 44404736 bytes 42.3 MiB, wrote: 54943744 bytes 52.4 MiB, delta: 10539008 bytes 10.1 MiB, wrote 23.7% more than predicted freespace: was free: 37285888 bytes 35.6 MiB, wrote: 46161920 bytes 44.0 MiB, delta: 8876032 bytes 8.5 MiB, wrote 23.8% more than predicted freespace: was free: 30171136 bytes 28.8 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 7213056 bytes 6.9 MiB, wrote 23.9% more than predicted freespace: was free: 23048192 bytes 22.0 MiB, wrote: 28606464 bytes 27.3 MiB, delta: 5558272 bytes 5.3 MiB, wrote 24.1% more than predicted freespace: was free: 15941632 bytes 15.2 MiB, wrote: 19828736 bytes 18.9 MiB, delta: 3887104 bytes 3.7 MiB, wrote 24.4% more than predicted freespace: was free: 8830976 bytes 8.4 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 2232320 bytes 2.1 MiB, wrote 25.3% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 6985541 bytes 6.7 MiB each time freespace: trashing: was free: 76840960 bytes 73.3 MiB, need free: 6985550 bytes 6.7 MiB, files created: 248311, delete 225737 (90.9% of them) freespace: was free: 65228800 bytes 62.2 MiB, wrote: 82530304 bytes 78.7 MiB, delta: 17301504 bytes 16.5 MiB, wrote 26.5% more than predicted freespace: trashing: was free: 74485760 bytes 71.0 MiB, need free: 13971091 bytes 13.3 MiB, files created: 248712, delete 202061 (81.2% of them) freespace: was free: 55025664 bytes 52.5 MiB, wrote: 71925760 bytes 68.6 MiB, delta: 16900096 bytes 16.1 MiB, wrote 30.7% more than predicted freespace: trashing: was free: 75550720 bytes 72.1 MiB, need free: 20956632 bytes 20.0 MiB, files created: 248849, delete 179822 (72.3% of them) freespace: was free: 46669824 bytes 44.5 MiB, wrote: 63197184 bytes 60.3 MiB, delta: 16527360 bytes 15.8 MiB, wrote 35.4% more than predicted freespace: trashing: was free: 76214272 bytes 72.7 MiB, need free: 27942173 bytes 26.6 MiB, files created: 248789, delete 157576 (63.3% of them) freespace: was free: 39129088 bytes 37.3 MiB, wrote: 55164928 bytes 52.6 MiB, delta: 16035840 bytes 15.3 MiB, wrote 41.0% more than predicted freespace: trashing: was free: 77398016 bytes 73.8 MiB, need free: 34927714 bytes 33.3 MiB, files created: 248711, delete 136474 (54.9% of them) freespace: was free: 32325632 bytes 30.8 MiB, wrote: 48234496 bytes 46.0 MiB, delta: 15908864 bytes 15.2 MiB, wrote 49.2% more than predicted freespace: trashing: was free: 75796480 bytes 72.3 MiB, need free: 41913255 bytes 40.0 MiB, files created: 248674, delete 111164 (44.7% of them) freespace: was free: 25079808 bytes 23.9 MiB, wrote: 40775680 bytes 38.9 MiB, delta: 15695872 bytes 15.0 MiB, wrote 62.6% more than predicted freespace: trashing: was free: 78209024 bytes 74.6 MiB, need free: 48898796 bytes 46.6 MiB, files created: 248708, delete 93207 (37.5% of them) freespace: was free: 20582400 bytes 19.6 MiB, wrote: 34844672 bytes 33.2 MiB, delta: 14262272 bytes 13.6 MiB, wrote 69.3% more than predicted freespace: trashing: was free: 77328384 bytes 73.7 MiB, need free: 55884337 bytes 53.3 MiB, files created: 248644, delete 68951 (27.7% of them) freespace: was free: 14368768 bytes 13.7 MiB, wrote: 28278784 bytes 27.0 MiB, delta: 13910016 bytes 13.3 MiB, wrote 96.8% more than predicted freespace: trashing: was free: 77434880 bytes 73.8 MiB, need free: 62869878 bytes 60.0 MiB, files created: 248640, delete 46767 (18.8% of them) freespace: was free: 8286208 bytes 7.9 MiB, wrote: 21811200 bytes 20.8 MiB, delta: 13524992 bytes 12.9 MiB, wrote 163.2% more than predicted freespace: trashing: was free: 77856768 bytes 74.2 MiB, need free: 69855419 bytes 66.6 MiB, files created: 248576, delete 25546 (10.3% of them) freespace: was free: 5570560 bytes 5.3 MiB, wrote: 8187904 bytes 7.8 MiB, delta: 2617344 bytes 2.5 MiB, wrote 47.0% more than predicted freespace: Test 3 finished freespace: finished successfully After the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 85204992 bytes 81.3 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 11284480 bytes 10.8 MiB, wrote 13.2% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 12935168 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 12939264 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 7596218 bytes 7.2 MiB each time freespace: was free: 78675968 bytes 75.0 MiB, wrote: 88903680 bytes 84.8 MiB, delta: 10227712 bytes 9.8 MiB, wrote 13.0% more than predicted freespace: was free: 72015872 bytes 68.7 MiB, wrote: 81514496 bytes 77.7 MiB, delta: 9498624 bytes 9.1 MiB, wrote 13.2% more than predicted freespace: was free: 63938560 bytes 61.0 MiB, wrote: 72589312 bytes 69.2 MiB, delta: 8650752 bytes 8.2 MiB, wrote 13.5% more than predicted freespace: was free: 56127488 bytes 53.5 MiB, wrote: 63762432 bytes 60.8 MiB, delta: 7634944 bytes 7.3 MiB, wrote 13.6% more than predicted freespace: was free: 48336896 bytes 46.1 MiB, wrote: 54935552 bytes 52.4 MiB, delta: 6598656 bytes 6.3 MiB, wrote 13.7% more than predicted freespace: was free: 40587264 bytes 38.7 MiB, wrote: 46157824 bytes 44.0 MiB, delta: 5570560 bytes 5.3 MiB, wrote 13.7% more than predicted freespace: was free: 32841728 bytes 31.3 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 4542464 bytes 4.3 MiB, wrote 13.8% more than predicted freespace: was free: 25100288 bytes 23.9 MiB, wrote: 28618752 bytes 27.3 MiB, delta: 3518464 bytes 3.4 MiB, wrote 14.0% more than predicted freespace: was free: 17342464 bytes 16.5 MiB, wrote: 19841024 bytes 18.9 MiB, delta: 2498560 bytes 2.4 MiB, wrote 14.4% more than predicted freespace: was free: 9605120 bytes 9.2 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 1458176 bytes 1.4 MiB, wrote 15.2% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 7606272 bytes 7.3 MiB each time freespace: trashing: was free: 83668992 bytes 79.8 MiB, need free: 7606272 bytes 7.3 MiB, files created: 248297, delete 225724 (90.9% of them) freespace: was free: 70803456 bytes 67.5 MiB, wrote: 82485248 bytes 78.7 MiB, delta: 11681792 bytes 11.1 MiB, wrote 16.5% more than predicted freespace: trashing: was free: 81080320 bytes 77.3 MiB, need free: 15212544 bytes 14.5 MiB, files created: 248711, delete 202047 (81.2% of them) freespace: was free: 59867136 bytes 57.1 MiB, wrote: 71897088 bytes 68.6 MiB, delta: 12029952 bytes 11.5 MiB, wrote 20.1% more than predicted freespace: trashing: was free: 82243584 bytes 78.4 MiB, need free: 22818816 bytes 21.8 MiB, files created: 248866, delete 179817 (72.3% of them) freespace: was free: 50905088 bytes 48.5 MiB, wrote: 63168512 bytes 60.2 MiB, delta: 12263424 bytes 11.7 MiB, wrote 24.1% more than predicted freespace: trashing: was free: 83402752 bytes 79.5 MiB, need free: 30425088 bytes 29.0 MiB, files created: 248920, delete 158114 (63.5% of them) freespace: was free: 42651648 bytes 40.7 MiB, wrote: 55406592 bytes 52.8 MiB, delta: 12754944 bytes 12.2 MiB, wrote 29.9% more than predicted freespace: trashing: was free: 84402176 bytes 80.5 MiB, need free: 38031360 bytes 36.3 MiB, files created: 248709, delete 136641 (54.9% of them) freespace: was free: 35233792 bytes 33.6 MiB, wrote: 48250880 bytes 46.0 MiB, delta: 13017088 bytes 12.4 MiB, wrote 36.9% more than predicted freespace: trashing: was free: 82530304 bytes 78.7 MiB, need free: 45637632 bytes 43.5 MiB, files created: 248778, delete 111208 (44.7% of them) freespace: was free: 27287552 bytes 26.0 MiB, wrote: 40267776 bytes 38.4 MiB, delta: 12980224 bytes 12.4 MiB, wrote 47.6% more than predicted freespace: trashing: was free: 85114880 bytes 81.2 MiB, need free: 53243904 bytes 50.8 MiB, files created: 248508, delete 93052 (37.4% of them) freespace: was free: 22437888 bytes 21.4 MiB, wrote: 35328000 bytes 33.7 MiB, delta: 12890112 bytes 12.3 MiB, wrote 57.4% more than predicted freespace: trashing: was free: 84103168 bytes 80.2 MiB, need free: 60850176 bytes 58.0 MiB, files created: 248637, delete 68743 (27.6% of them) freespace: was free: 15536128 bytes 14.8 MiB, wrote: 28319744 bytes 27.0 MiB, delta: 12783616 bytes 12.2 MiB, wrote 82.3% more than predicted freespace: trashing: was free: 84357120 bytes 80.4 MiB, need free: 68456448 bytes 65.3 MiB, files created: 248567, delete 46852 (18.8% of them) freespace: was free: 9015296 bytes 8.6 MiB, wrote: 22044672 bytes 21.0 MiB, delta: 13029376 bytes 12.4 MiB, wrote 144.5% more than predicted freespace: trashing: was free: 84942848 bytes 81.0 MiB, need free: 76062720 bytes 72.5 MiB, files created: 248636, delete 25993 (10.5% of them) freespace: was free: 6086656 bytes 5.8 MiB, wrote: 8331264 bytes 7.9 MiB, delta: 2244608 bytes 2.1 MiB, wrote 36.9% more than predicted freespace: Test 3 finished freespace: finished successfully Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/ubifs/misc.h | 32 -------------------------------- fs/ubifs/ubifs.h | 1 + 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 9ef630a594c..7851480a6ce 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -701,6 +701,51 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, ubifs_release_budget(c, &req); } +/** + * ubifs_reported_space - calculate reported free space. + * @c: the UBIFS file-system description object + * @free: amount of free space + * + * This function calculates amount of free space which will be reported to + * user-space. User-space application tend to expect that if the file-system + * (e.g., via the 'statfs()' call) reports that it has N bytes available, they + * are able to write a file of size N. UBIFS attaches node headers to each data + * node and it has to write indexind nodes as well. This introduces additional + * overhead, and UBIFS it has to report sligtly less free space to meet the + * above expectetion. + * + * This function assumes free space is made up of uncompressed data nodes and + * full index nodes (one per data node, tripled because we always allow enough + * space to write the index thrice). + * + * Note, the calculation is pessimistic, which means that most of the time + * UBIFS reports less space than it actually has. + */ +long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) +{ + int divisor, factor; + + /* + * Reported space size is @free * X, where X is UBIFS block size + * divided by UBIFS block size + all overhead one data block + * introduces. The overhead is the node header + indexing overhead. + * + * Indexing overhead is calculations are based on the following + * formula: I = N/(f - 1) + 1, where I - number of indexing nodes, N - + * number of data nodes, f - fanout. Because effective UBIFS fanout is + * twice as less than maximum fanout, we assume that each data node + * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes. + * Note, the multiplier 3 is because UBIFS reseves thrice as more space + * for the index. + */ + factor = UBIFS_BLOCK_SIZE; + divisor = UBIFS_MAX_DATA_NODE_SZ; + divisor += (c->max_idx_node_sz * 3) / ((c->fanout >> 1) - 1); + free *= factor; + do_div(free, divisor); + return free; +} + /** * ubifs_budg_get_free_space - return amount of free space. * @c: UBIFS file-system description object diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 87ced4c74a6..4c12a9215d7 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -283,38 +283,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c, return (void *)((struct ubifs_branch *)idx->branches)->key; } -/** - * ubifs_reported_space - calculate reported free space. - * @c: the UBIFS file-system description object - * @free: amount of free space - * - * This function calculates amount of free space which will be reported to - * user-space. User-space application tend to expect that if the file-system - * (e.g., via the 'statfs()' call) reports that it has N bytes available, they - * are able to write a file of size N. UBIFS attaches node headers to each data - * node and it has to write indexind nodes as well. This introduces additional - * overhead, and UBIFS it has to report sligtly less free space to meet the - * above expectetion. - * - * This function assumes free space is made up of uncompressed data nodes and - * full index nodes (one per data node, doubled because we always allow enough - * space to write the index twice). - * - * Note, the calculation is pessimistic, which means that most of the time - * UBIFS reports less space than it actually has. - */ -static inline long long ubifs_reported_space(const struct ubifs_info *c, - uint64_t free) -{ - int divisor, factor; - - divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3); - factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ; - do_div(free, divisor); - - return free * factor; -} - /** * ubifs_current_time - round current time to time granularity. * @inode: inode diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 7828d69ca4f..681d46e1628 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1441,6 +1441,7 @@ void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, long long ubifs_budg_get_free_space(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); +long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs); /* find.c */ -- cgit v1.2.3 From ad507653a39e0d27404291e5d813683265388a20 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:32:57 +0300 Subject: UBIFS: fix assertion The assertion was incorrect, because it did not take into account free space. This patch also amends the comments correspondingly, and cleans them up a little. Signed-off-by: Artem Bityutskiy --- fs/ubifs/find.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index adee7b5ddea..9fc55ae7b03 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, * dirty index heap, and it falls-back to LPT scanning if the heaps are empty * or do not have an LEB which satisfies the @min_space criteria. * - * Note: - * o LEBs which have less than dead watermark of dirty space are never picked - * by this function; - * - * Returns zero and the LEB properties of - * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a - * negative error code in case of other failures. The returned LEB is marked as - * "taken". + * Note, LEBs which have less than dead watermark of free + dirty space are + * never picked by this function. * * The additional @pick_free argument controls if this function has to return a * free or freeable LEB if one is present. For example, GC must to set it to %1, @@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, * * In addition @pick_free is set to %2 by the recovery process in order to * recover gc_lnum in which case an index LEB must not be returned. + * + * This function returns zero and the LEB properties of found dirty LEB in case + * of success, %-ENOSPC if no dirty LEB was found and a negative error code in + * case of other failures. The returned LEB is marked as "taken". */ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, int min_space, int pick_free) @@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, lp = idx_lp; if (lp) { - ubifs_assert(lp->dirty >= c->dead_wm); + ubifs_assert(lp->free + lp->dirty >= c->dead_wm); goto found; } -- cgit v1.2.3 From 131130b9a1e6e523c64b34137b14f88ae1382a6a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:34:45 +0300 Subject: UBIFS: add forgotten gc_idx_lebs component We add this component at other similar places, but not in this one. Signed-off-by: Artem Bityutskiy --- fs/ubifs/find.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 9fc55ae7b03..e045c8b5542 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -243,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, int lebs, rsvd_idx_lebs = 0; spin_lock(&c->space_lock); - lebs = c->lst.empty_lebs; + lebs = c->lst.empty_lebs + c->idx_gc_cnt; lebs += c->freeable_cnt - c->lst.taken_empty_lebs; /* -- cgit v1.2.3 From 9bbb5726efb64e2cfed42f6eec07db80cd87e63b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 22 Aug 2008 18:23:22 +0300 Subject: UBIFS: introduce LEB overhead This is a preparational patch for the following statfs() report fix. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 6 ++++++ fs/ubifs/ubifs.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1018053519e..be23fd3cfd8 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -530,6 +530,12 @@ static int init_constants_early(struct ubifs_info *c) c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); + /* + * Calculate how many bytes would be wasted at the end of LEB if it was + * fully filled with data nodes of maximum size. This is used in + * calculations when reporting free space. + */ + c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ; return 0; } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 681d46e1628..57e58541de2 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -995,6 +995,9 @@ struct ubifs_mount_opts { * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary * @max_inode_sz: maximum possible inode size in bytes * @max_znode_sz: size of znode in bytes + * + * @leb_overhead: how many bytes are wasted in an LEB when it is filled with + * data nodes of maximum size - used in free space reporting * @dead_wm: LEB dead space watermark * @dark_wm: LEB dark space watermark * @block_cnt: count of 4KiB blocks on the FS @@ -1226,6 +1229,8 @@ struct ubifs_info { int max_idx_node_sz; long long max_inode_sz; int max_znode_sz; + + int leb_overhead; int dead_wm; int dark_wm; int block_cnt; -- cgit v1.2.3 From 7dad181bbe58b8fe9e170da28bcd5f6ec9addd6d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:58:19 +0300 Subject: UBIFS: improve statfs reporting even more Since free space we report in statfs is file size which should fit to the FS - change the way we calculate free space and use leb_overhead instead of dark_wm in calculations. Results of "freespace" test (120MiB volume, 16KiB LEB size, 512 bytes page size). Before the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 85204992 bytes 81.3 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 11284480 bytes 10.8 MiB, wrote 13.2% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 12935168 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 12939264 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 7596218 bytes 7.2 MiB each time freespace: was free: 78675968 bytes 75.0 MiB, wrote: 88903680 bytes 84.8 MiB, delta: 10227712 bytes 9.8 MiB, wrote 13.0% more than predicted freespace: was free: 72015872 bytes 68.7 MiB, wrote: 81514496 bytes 77.7 MiB, delta: 9498624 bytes 9.1 MiB, wrote 13.2% more than predicted freespace: was free: 63938560 bytes 61.0 MiB, wrote: 72589312 bytes 69.2 MiB, delta: 8650752 bytes 8.2 MiB, wrote 13.5% more than predicted freespace: was free: 56127488 bytes 53.5 MiB, wrote: 63762432 bytes 60.8 MiB, delta: 7634944 bytes 7.3 MiB, wrote 13.6% more than predicted freespace: was free: 48336896 bytes 46.1 MiB, wrote: 54935552 bytes 52.4 MiB, delta: 6598656 bytes 6.3 MiB, wrote 13.7% more than predicted freespace: was free: 40587264 bytes 38.7 MiB, wrote: 46157824 bytes 44.0 MiB, delta: 5570560 bytes 5.3 MiB, wrote 13.7% more than predicted freespace: was free: 32841728 bytes 31.3 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 4542464 bytes 4.3 MiB, wrote 13.8% more than predicted freespace: was free: 25100288 bytes 23.9 MiB, wrote: 28618752 bytes 27.3 MiB, delta: 3518464 bytes 3.4 MiB, wrote 14.0% more than predicted freespace: was free: 17342464 bytes 16.5 MiB, wrote: 19841024 bytes 18.9 MiB, delta: 2498560 bytes 2.4 MiB, wrote 14.4% more than predicted freespace: was free: 9605120 bytes 9.2 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 1458176 bytes 1.4 MiB, wrote 15.2% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 7606272 bytes 7.3 MiB each time freespace: trashing: was free: 83668992 bytes 79.8 MiB, need free: 7606272 bytes 7.3 MiB, files created: 248297, delete 225724 (90.9% of them) freespace: was free: 70803456 bytes 67.5 MiB, wrote: 82485248 bytes 78.7 MiB, delta: 11681792 bytes 11.1 MiB, wrote 16.5% more than predicted freespace: trashing: was free: 81080320 bytes 77.3 MiB, need free: 15212544 bytes 14.5 MiB, files created: 248711, delete 202047 (81.2% of them) freespace: was free: 59867136 bytes 57.1 MiB, wrote: 71897088 bytes 68.6 MiB, delta: 12029952 bytes 11.5 MiB, wrote 20.1% more than predicted freespace: trashing: was free: 82243584 bytes 78.4 MiB, need free: 22818816 bytes 21.8 MiB, files created: 248866, delete 179817 (72.3% of them) freespace: was free: 50905088 bytes 48.5 MiB, wrote: 63168512 bytes 60.2 MiB, delta: 12263424 bytes 11.7 MiB, wrote 24.1% more than predicted freespace: trashing: was free: 83402752 bytes 79.5 MiB, need free: 30425088 bytes 29.0 MiB, files created: 248920, delete 158114 (63.5% of them) freespace: was free: 42651648 bytes 40.7 MiB, wrote: 55406592 bytes 52.8 MiB, delta: 12754944 bytes 12.2 MiB, wrote 29.9% more than predicted freespace: trashing: was free: 84402176 bytes 80.5 MiB, need free: 38031360 bytes 36.3 MiB, files created: 248709, delete 136641 (54.9% of them) freespace: was free: 35233792 bytes 33.6 MiB, wrote: 48250880 bytes 46.0 MiB, delta: 13017088 bytes 12.4 MiB, wrote 36.9% more than predicted freespace: trashing: was free: 82530304 bytes 78.7 MiB, need free: 45637632 bytes 43.5 MiB, files created: 248778, delete 111208 (44.7% of them) freespace: was free: 27287552 bytes 26.0 MiB, wrote: 40267776 bytes 38.4 MiB, delta: 12980224 bytes 12.4 MiB, wrote 47.6% more than predicted freespace: trashing: was free: 85114880 bytes 81.2 MiB, need free: 53243904 bytes 50.8 MiB, files created: 248508, delete 93052 (37.4% of them) freespace: was free: 22437888 bytes 21.4 MiB, wrote: 35328000 bytes 33.7 MiB, delta: 12890112 bytes 12.3 MiB, wrote 57.4% more than predicted freespace: trashing: was free: 84103168 bytes 80.2 MiB, need free: 60850176 bytes 58.0 MiB, files created: 248637, delete 68743 (27.6% of them) freespace: was free: 15536128 bytes 14.8 MiB, wrote: 28319744 bytes 27.0 MiB, delta: 12783616 bytes 12.2 MiB, wrote 82.3% more than predicted freespace: trashing: was free: 84357120 bytes 80.4 MiB, need free: 68456448 bytes 65.3 MiB, files created: 248567, delete 46852 (18.8% of them) freespace: was free: 9015296 bytes 8.6 MiB, wrote: 22044672 bytes 21.0 MiB, delta: 13029376 bytes 12.4 MiB, wrote 144.5% more than predicted freespace: trashing: was free: 84942848 bytes 81.0 MiB, need free: 76062720 bytes 72.5 MiB, files created: 248636, delete 25993 (10.5% of them) freespace: was free: 6086656 bytes 5.8 MiB, wrote: 8331264 bytes 7.9 MiB, delta: 2244608 bytes 2.1 MiB, wrote 36.9% more than predicted freespace: Test 3 finished freespace: finished successfully After the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 94048256 bytes 89.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 2441216 bytes 2.3 MiB, wrote 2.6% more than predicted freespace: was free: 92246016 bytes 88.0 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 4247552 bytes 4.1 MiB, wrote 4.6% more than predicted freespace: was free: 92254208 bytes 88.0 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 4235264 bytes 4.0 MiB, wrote 4.6% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 8386001 bytes 8.0 MiB each time freespace: was free: 86605824 bytes 82.6 MiB, wrote: 88252416 bytes 84.2 MiB, delta: 1646592 bytes 1.6 MiB, wrote 1.9% more than predicted freespace: was free: 78667776 bytes 75.0 MiB, wrote: 80715776 bytes 77.0 MiB, delta: 2048000 bytes 2.0 MiB, wrote 2.6% more than predicted freespace: was free: 69615616 bytes 66.4 MiB, wrote: 71630848 bytes 68.3 MiB, delta: 2015232 bytes 1.9 MiB, wrote 2.9% more than predicted freespace: was free: 61018112 bytes 58.2 MiB, wrote: 62783488 bytes 59.9 MiB, delta: 1765376 bytes 1.7 MiB, wrote 2.9% more than predicted freespace: was free: 52424704 bytes 50.0 MiB, wrote: 53968896 bytes 51.5 MiB, delta: 1544192 bytes 1.5 MiB, wrote 2.9% more than predicted freespace: was free: 43880448 bytes 41.8 MiB, wrote: 45199360 bytes 43.1 MiB, delta: 1318912 bytes 1.3 MiB, wrote 3.0% more than predicted freespace: was free: 35332096 bytes 33.7 MiB, wrote: 36425728 bytes 34.7 MiB, delta: 1093632 bytes 1.0 MiB, wrote 3.1% more than predicted freespace: was free: 26771456 bytes 25.5 MiB, wrote: 27643904 bytes 26.4 MiB, delta: 872448 bytes 852.0 KiB, wrote 3.3% more than predicted freespace: was free: 18231296 bytes 17.4 MiB, wrote: 18878464 bytes 18.0 MiB, delta: 647168 bytes 632.0 KiB, wrote 3.5% more than predicted freespace: was free: 9674752 bytes 9.2 MiB, wrote: 10088448 bytes 9.6 MiB, delta: 413696 bytes 404.0 KiB, wrote 4.3% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 8397544 bytes 8.0 MiB each time freespace: trashing: was free: 92372992 bytes 88.1 MiB, need free: 8397552 bytes 8.0 MiB, files created: 248296, delete 225723 (90.9% of them) freespace: was free: 71909376 bytes 68.6 MiB, wrote: 82472960 bytes 78.7 MiB, delta: 10563584 bytes 10.1 MiB, wrote 14.7% more than predicted freespace: trashing: was free: 88989696 bytes 84.9 MiB, need free: 16795096 bytes 16.0 MiB, files created: 248794, delete 201838 (81.1% of them) freespace: was free: 60354560 bytes 57.6 MiB, wrote: 71782400 bytes 68.5 MiB, delta: 11427840 bytes 10.9 MiB, wrote 18.9% more than predicted freespace: trashing: was free: 90304512 bytes 86.1 MiB, need free: 25192640 bytes 24.0 MiB, files created: 248733, delete 179342 (72.1% of them) freespace: was free: 51187712 bytes 48.8 MiB, wrote: 62943232 bytes 60.0 MiB, delta: 11755520 bytes 11.2 MiB, wrote 23.0% more than predicted freespace: trashing: was free: 91209728 bytes 87.0 MiB, need free: 33590184 bytes 32.0 MiB, files created: 248779, delete 157160 (63.2% of them) freespace: was free: 42704896 bytes 40.7 MiB, wrote: 55050240 bytes 52.5 MiB, delta: 12345344 bytes 11.8 MiB, wrote 28.9% more than predicted freespace: trashing: was free: 92700672 bytes 88.4 MiB, need free: 41987728 bytes 40.0 MiB, files created: 248848, delete 136135 (54.7% of them) freespace: was free: 35250176 bytes 33.6 MiB, wrote: 48115712 bytes 45.9 MiB, delta: 12865536 bytes 12.3 MiB, wrote 36.5% more than predicted freespace: trashing: was free: 93986816 bytes 89.6 MiB, need free: 50385272 bytes 48.1 MiB, files created: 248723, delete 115385 (46.4% of them) freespace: was free: 29995008 bytes 28.6 MiB, wrote: 41582592 bytes 39.7 MiB, delta: 11587584 bytes 11.1 MiB, wrote 38.6% more than predicted freespace: trashing: was free: 91881472 bytes 87.6 MiB, need free: 58782816 bytes 56.1 MiB, files created: 248645, delete 89569 (36.0% of them) freespace: was free: 22511616 bytes 21.5 MiB, wrote: 34705408 bytes 33.1 MiB, delta: 12193792 bytes 11.6 MiB, wrote 54.2% more than predicted freespace: trashing: was free: 91774976 bytes 87.5 MiB, need free: 67180360 bytes 64.1 MiB, files created: 248580, delete 66616 (26.8% of them) freespace: was free: 16908288 bytes 16.1 MiB, wrote: 26898432 bytes 25.7 MiB, delta: 9990144 bytes 9.5 MiB, wrote 59.1% more than predicted freespace: trashing: was free: 92450816 bytes 88.2 MiB, need free: 75577904 bytes 72.1 MiB, files created: 248654, delete 45381 (18.3% of them) freespace: was free: 10170368 bytes 9.7 MiB, wrote: 19111936 bytes 18.2 MiB, delta: 8941568 bytes 8.5 MiB, wrote 87.9% more than predicted freespace: trashing: was free: 93282304 bytes 89.0 MiB, need free: 83975448 bytes 80.1 MiB, files created: 248513, delete 24794 (10.0% of them) freespace: was free: 3911680 bytes 3.7 MiB, wrote: 7872512 bytes 7.5 MiB, delta: 3960832 bytes 3.8 MiB, wrote 101.3% more than predicted freespace: Test 3 finished freespace: finished successfully Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 38 ++++++++++++++++++++++++++++++++++---- fs/ubifs/super.c | 10 +++++----- fs/ubifs/ubifs.h | 2 +- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 7851480a6ce..101d278c591 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -747,14 +747,24 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) } /** - * ubifs_budg_get_free_space - return amount of free space. + * ubifs_get_free_space - return amount of free space. * @c: UBIFS file-system description object * - * This function returns amount of free space on the file-system. + * This function calculates amount of free space to report to user-space. + * + * Because UBIFS may introduce substantial overhead (the index, node headers, + * alighment, wastage at the end of eraseblocks, etc), it cannot report real + * amount of free flash space it has (well, because not all dirty space is + * reclamable, UBIFS does not actually know the real amount). If UBIFS did so, + * it would bread user expectetion about what free space is. Users seem to + * accustomed to assume that if the file-system reports N bytes of free space, + * they would be able to fit a file of N bytes to the FS. This almost works for + * traditional file-systems, because they have way less overhead than UBIFS. + * So, to keep users happy, UBIFS tries to take the overhead into account. */ -long long ubifs_budg_get_free_space(struct ubifs_info *c) +long long ubifs_get_free_space(struct ubifs_info *c) { - int min_idx_lebs; + int min_idx_lebs, rsvd_idx_lebs, lebs; long long available, outstanding, free; spin_lock(&c->space_lock); @@ -771,6 +781,26 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) } available = ubifs_calc_available(c, min_idx_lebs); + + /* + * When reporting free space to user-space, UBIFS guarantees that it is + * possible to write a file of free space size. This means that for + * empty LEBs we may use more precise calculations than + * 'ubifs_calc_available()' is using. Namely, we know that in empty + * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm. + * Thus, amend the available space. + * + * Note, the calculations below are similar to what we have in + * 'do_budget_space()', so refer there for comments. + */ + if (min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; + else + rsvd_idx_lebs = 0; + lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - + c->lst.taken_empty_lebs; + lebs -= rsvd_idx_lebs; + available += lebs * (c->dark_wm - c->leb_overhead); spin_unlock(&c->space_lock); if (available > outstanding) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index be23fd3cfd8..1207bd51ead 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -371,7 +371,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) struct ubifs_info *c = dentry->d_sb->s_fs_info; unsigned long long free; - free = ubifs_budg_get_free_space(c); + free = ubifs_get_free_space(c); dbg_gen("free space %lld bytes (%lld blocks)", free, free >> UBIFS_BLOCK_SHIFT); @@ -653,11 +653,11 @@ static int init_constants_late(struct ubifs_info *c) * internally because it does not make much sense for UBIFS, but it is * necessary to report something for the 'statfs()' call. * - * Subtract the LEB reserved for GC and the LEB which is reserved for - * deletions. + * Subtract the LEB reserved for GC, the LEB which is reserved for + * deletions, and assume only one journal head is available. */ - tmp64 = c->main_lebs - 2; - tmp64 *= (uint64_t)c->leb_size - c->dark_wm; + tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1; + tmp64 *= (uint64_t)c->leb_size - c->leb_overhead; tmp64 = ubifs_reported_space(c, tmp64); c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 57e58541de2..17c620b93ee 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1443,7 +1443,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); -long long ubifs_budg_get_free_space(struct ubifs_info *c); +long long ubifs_get_free_space(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); -- cgit v1.2.3 From b3385c278d3c32aec68d4900b35bc07df1b2240c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 31 Aug 2008 17:13:18 +0300 Subject: UBIFS: fill f_fsid UBIFS stores 16-bit UUID in the superblock, and it is a good idea to return part of it in 'f_fsid' filed of kstatfs structure. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1207bd51ead..0dee4042c6c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -386,6 +386,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = 0; buf->f_ffree = 0; buf->f_namelen = UBIFS_MAX_NLEN; + memcpy(&buf->f_fsid, c->uuid, sizeof(__kernel_fsid_t)); return 0; } -- cgit v1.2.3 From a9b0623357d2faa49a0f862154ba36c42c4bad2b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 2 Sep 2008 10:19:29 +0200 Subject: pcm037: add rts/cts support for serial port We have rts/cts pins on the first serial port on the pcm037. Enable it. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/pcm037.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 0a152ed15a8..df8582a6231 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -54,7 +54,7 @@ static struct platform_device pcm037_flash = { }; static struct imxuart_platform_data uart_pdata = { - .flags = 0, + .flags = IMXUART_HAVE_RTSCTS, }; static struct platform_device *devices[] __initdata = { -- cgit v1.2.3 From c45e7d7be891fe94e13d0e7aeee3e0e4ee7118f4 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Tue, 2 Sep 2008 10:19:29 +0200 Subject: i.MX serial: fix init failure Adds extra "out" label to probe function after calling .init form platform data. Because .init can return error number caused by gpio request fail. Signed-off-by: Darius Augulis Signed-off-by: Sascha Hauer --- drivers/serial/imx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 6a29f9330a7..20189c447e9 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1133,13 +1133,19 @@ static int serial_imx_probe(struct platform_device *pdev) if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) sport->have_rtscts = 1; - if (pdata->init) - pdata->init(pdev); + if (pdata->init) { + ret = pdata->init(pdev); + if (ret) + goto clkput; + } uart_add_one_port(&imx_reg, &sport->port); platform_set_drvdata(pdev, &sport->port); return 0; +clkput: + clk_put(sport->clk); + clk_disable(sport->clk); unmap: iounmap(sport->port.membase); free: -- cgit v1.2.3 From 4411805b13d4b8c31870b276c2730d585b062db7 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 28 Jul 2008 12:10:34 +0200 Subject: imx serial: set RXD mux bit on i.MX27 and i.MX31 RX in i.MX27 and i.MX31 UART lines does not work unless the "RXD Muxed Input Select" bit is set on i.MX27 and i.MX31 processors. This patch sets the missing RXD mux bit in the UCR3 register. Signed-off-by: Marc Kleine-Budde Signed-off-by: Sascha Hauer --- drivers/serial/imx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 20189c447e9..312653e2f71 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -127,8 +127,13 @@ #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ -#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ -#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#ifdef CONFIG_ARCH_IMX +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz, only on mx1 */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz, only on mx1 */ +#endif +#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 +#define UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */ +#endif #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ #define UCR3_BPEN (1<<0) /* Preset registers enable */ #define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ @@ -598,6 +603,12 @@ static int imx_startup(struct uart_port *port) temp |= (UCR2_RXEN | UCR2_TXEN); writel(temp, sport->port.membase + UCR2); +#if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 + temp = readl(sport->port.membase + UCR3); + temp |= UCR3_RXDMUXSEL; + writel(temp, sport->port.membase + UCR3); +#endif + /* * Enable modem status interrupts */ -- cgit v1.2.3 From 9fbe604456c5ae21768f1c98379e1b81c72adcd3 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 28 Jul 2008 21:26:01 +0200 Subject: imx serial: fix rts handling for non imx1 based hardware The interrupt handler for muxed interrupts (imx2/imx3) was calling the rts handling subroutine if the RTSS bit was set. (Which indicates the status of the RTS line), leading to an interrupt flood on RTS bit low. This patch fixes the problem by looking at the RTSD bit instead, indicating a change in the RTS line. Signed-off-by: Marc Kleine-Budde Signed-off-by: Sascha Hauer --- drivers/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 312653e2f71..3f90f1bbbbc 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -450,7 +450,7 @@ static irqreturn_t imx_int(int irq, void *dev_id) readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) imx_txint(irq, dev_id); - if (sts & USR1_RTSS) + if (sts & USR1_RTSD) imx_rtsint(irq, dev_id); return IRQ_HANDLED; -- cgit v1.2.3 From c9257433f2eaf8803a1f3d3be5d984232db41ffe Mon Sep 17 00:00:00 2001 From: Vladimir Sokolovsky Date: Tue, 2 Sep 2008 13:38:29 -0700 Subject: mlx4_core: Set RAE and init mtt_sz field in FRMR MPT entries Set the RAE (remote access enable) bit and correctly initialize the MTT size in MPT entries being set up for fast register memory regions. Otherwise the callers can't enable remote access and in fact can't fast register at all (since the HCA will think no MTT entries are allocated). Signed-off-by: Vladimir Sokolovsky Signed-off-by: Roland Dreier --- drivers/net/mlx4/mr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 62071d9c4a5..644adf074a3 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -67,7 +67,8 @@ struct mlx4_mpt_entry { #define MLX4_MPT_FLAG_PHYSICAL (1 << 9) #define MLX4_MPT_FLAG_REGION (1 << 8) -#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 26) +#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27) +#define MLX4_MPT_PD_FLAG_RAE (1 << 28) #define MLX4_MPT_PD_FLAG_EN_INV (3 << 24) #define MLX4_MTT_FLAG_PRESENT 1 @@ -348,7 +349,10 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) { /* fast register MR in free state */ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE); - mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG); + mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG | + MLX4_MPT_PD_FLAG_RAE); + mpt_entry->mtt_sz = cpu_to_be32((1 << mr->mtt.order) * + MLX4_MTT_ENTRY_PER_SEG); } else { mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS); } -- cgit v1.2.3 From 7c7cbadf7341a0792879c67d6e3020f040d6cd7f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 14:16:42 +0300 Subject: UBIFS: amend f_fsid David Woodhouse suggested to be consistent with other FSes and xor the beginning and the end of the UUID. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 0dee4042c6c..7562464ac83 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -370,6 +370,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct ubifs_info *c = dentry->d_sb->s_fs_info; unsigned long long free; + __le32 *uuid = (__le32 *)c->uuid; free = ubifs_get_free_space(c); dbg_gen("free space %lld bytes (%lld blocks)", @@ -386,8 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = 0; buf->f_ffree = 0; buf->f_namelen = UBIFS_MAX_NLEN; - memcpy(&buf->f_fsid, c->uuid, sizeof(__kernel_fsid_t)); - + buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); + buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); return 0; } -- cgit v1.2.3 From b98738412372d6bcba1548b6b439f49023e25a34 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 05:59:16 +0200 Subject: mv643xx_eth: fix 'netdev_priv(dev) == dev->priv' assumption Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 0a18b9e96da..deee66dcd0a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1277,7 +1277,7 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, uint64_t *data) { - struct mv643xx_eth_private *mp = dev->priv; + struct mv643xx_eth_private *mp = netdev_priv(dev); int i; mib_counters_update(mp); -- cgit v1.2.3 From 3a499481c167977368a7e7cae8ea1ff2a99518a0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 07:19:48 +0200 Subject: mv643xx_eth: fix receive buffer DMA unmapping When tearing down a DMA mapping for a receive buffer, we should pass dma_unmap_single() the exact same address that dma_map_single() gave us when we originally set up the mapping. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index deee66dcd0a..ad2ae937443 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -559,7 +559,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) spin_unlock_irqrestore(&mp->lock, flags); - dma_unmap_single(NULL, rx_desc->buf_ptr + 2, + dma_unmap_single(NULL, rx_desc->buf_ptr, rx_desc->buf_size, DMA_FROM_DEVICE); rxq->rx_desc_count--; rx++; -- cgit v1.2.3 From 2a1867a76fc13499521af1f0dbcf08ddb3ef78ba Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 23 Aug 2008 23:43:38 +0200 Subject: mv643xx_eth: get rid of IRQF_SAMPLE_RANDOM Using IRQF_SAMPLE_RANDOM for the mv643xx_eth interrupt handler significantly increases interrupt processing overhead, so get rid of it. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index ad2ae937443..8c812c3d1b7 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2004,8 +2004,7 @@ static int mv643xx_eth_open(struct net_device *dev) rdl(mp, INT_CAUSE_EXT(mp->port_num)); err = request_irq(dev->irq, mv643xx_eth_irq, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, - dev->name, dev); + IRQF_SHARED, dev->name, dev); if (err) { dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n"); return -EAGAIN; -- cgit v1.2.3 From 9da7874575468ad3b126d1b9197b6ae387950bb4 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 23 Aug 2008 23:45:28 +0200 Subject: mv643xx_eth: get rid of modulo operations Get rid of the modulo operations that are currently used for computing successive TX/RX descriptor ring indexes. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 8c812c3d1b7..2f6cec4e849 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -497,8 +497,10 @@ static void rxq_refill(struct rx_queue *rxq) skb_reserve(skb, dma_get_cache_alignment() - unaligned); rxq->rx_desc_count++; - rx = rxq->rx_used_desc; - rxq->rx_used_desc = (rx + 1) % rxq->rx_ring_size; + + rx = rxq->rx_used_desc++; + if (rxq->rx_used_desc == rxq->rx_ring_size) + rxq->rx_used_desc = 0; rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data, skb_size, DMA_FROM_DEVICE); @@ -555,7 +557,9 @@ static int rxq_process(struct rx_queue *rxq, int budget) skb = rxq->rx_skb[rxq->rx_curr_desc]; rxq->rx_skb[rxq->rx_curr_desc] = NULL; - rxq->rx_curr_desc = (rxq->rx_curr_desc + 1) % rxq->rx_ring_size; + rxq->rx_curr_desc++; + if (rxq->rx_curr_desc == rxq->rx_ring_size) + rxq->rx_curr_desc = 0; spin_unlock_irqrestore(&mp->lock, flags); @@ -684,8 +688,9 @@ static int txq_alloc_desc_index(struct tx_queue *txq) BUG_ON(txq->tx_desc_count >= txq->tx_ring_size); - tx_desc_curr = txq->tx_curr_desc; - txq->tx_curr_desc = (tx_desc_curr + 1) % txq->tx_ring_size; + tx_desc_curr = txq->tx_curr_desc++; + if (txq->tx_curr_desc == txq->tx_ring_size) + txq->tx_curr_desc = 0; BUG_ON(txq->tx_curr_desc == txq->tx_used_desc); @@ -1515,7 +1520,12 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) rx_desc = (struct rx_desc *)rxq->rx_desc_area; for (i = 0; i < rxq->rx_ring_size; i++) { - int nexti = (i + 1) % rxq->rx_ring_size; + int nexti; + + nexti = i + 1; + if (nexti == rxq->rx_ring_size) + nexti = 0; + rx_desc[i].next_desc_ptr = rxq->rx_desc_dma + nexti * sizeof(struct rx_desc); } @@ -1617,7 +1627,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) tx_desc = (struct tx_desc *)txq->tx_desc_area; for (i = 0; i < txq->tx_ring_size; i++) { struct tx_desc *txd = tx_desc + i; - int nexti = (i + 1) % txq->tx_ring_size; + int nexti; + + nexti = i + 1; + if (nexti == txq->tx_ring_size) + nexti = 0; txd->cmd_sts = 0; txd->next_desc_ptr = txq->tx_desc_dma + @@ -1663,7 +1677,9 @@ static void txq_reclaim(struct tx_queue *txq, int force) desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA; } - txq->tx_used_desc = (tx_index + 1) % txq->tx_ring_size; + txq->tx_used_desc = tx_index + 1; + if (txq->tx_used_desc == txq->tx_ring_size) + txq->tx_used_desc = 0; txq->tx_desc_count--; addr = desc->buf_ptr; -- cgit v1.2.3 From 2b3ba0e3ea3aa9383d38cf95fabd24ca35483784 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 05:41:09 +0200 Subject: mv643xx_eth: switch ->phy_lock from a spinlock to a mutex Since commit 81600eea98789da09a32de69ca9d3be8b9503c54 ("mv643xx_eth: use auto phy polling for configuring (R)(G)MII interface"), mv643xx_eth no longer does SMI accesses from interrupt context. The only other callers that do SMI accesses all do them from process context, which means we can switch the PHY lock from a spinlock to a mutex, and get rid of the extra locking in some ethtool methods. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2f6cec4e849..2d434017a67 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -251,7 +251,7 @@ struct mv643xx_eth_shared_private { /* * Protects access to SMI_REG, which is shared between ports. */ - spinlock_t phy_lock; + struct mutex phy_lock; /* * Per-port MBUS window access register value. @@ -988,11 +988,10 @@ static void smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr, unsigned int reg, unsigned int *value) { void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; - unsigned long flags; int i; /* the SMI register is a shared resource */ - spin_lock_irqsave(&mp->shared_smi->phy_lock, flags); + mutex_lock(&mp->shared_smi->phy_lock); /* wait for the SMI register to become available */ for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { @@ -1016,7 +1015,7 @@ static void smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr, *value = readl(smi_reg) & 0xffff; out: - spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags); + mutex_unlock(&mp->shared_smi->phy_lock); } static void smi_reg_write(struct mv643xx_eth_private *mp, @@ -1024,11 +1023,10 @@ static void smi_reg_write(struct mv643xx_eth_private *mp, unsigned int reg, unsigned int value) { void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; - unsigned long flags; int i; /* the SMI register is a shared resource */ - spin_lock_irqsave(&mp->shared_smi->phy_lock, flags); + mutex_lock(&mp->shared_smi->phy_lock); /* wait for the SMI register to become available */ for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { @@ -1042,7 +1040,7 @@ static void smi_reg_write(struct mv643xx_eth_private *mp, writel(SMI_OPCODE_WRITE | (reg << 21) | (addr << 16) | (value & 0xffff), smi_reg); out: - spin_unlock_irqrestore(&mp->shared_smi->phy_lock, flags); + mutex_unlock(&mp->shared_smi->phy_lock); } @@ -1161,9 +1159,7 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd * struct mv643xx_eth_private *mp = netdev_priv(dev); int err; - spin_lock_irq(&mp->lock); err = mii_ethtool_gset(&mp->mii, cmd); - spin_unlock_irq(&mp->lock); /* * The MAC does not support 1000baseT_Half. @@ -1211,18 +1207,13 @@ static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethto static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct mv643xx_eth_private *mp = netdev_priv(dev); - int err; /* * The MAC does not support 1000baseT_Half. */ cmd->advertising &= ~ADVERTISED_1000baseT_Half; - spin_lock_irq(&mp->lock); - err = mii_ethtool_sset(&mp->mii, cmd); - spin_unlock_irq(&mp->lock); - - return err; + return mii_ethtool_sset(&mp->mii, cmd); } static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) @@ -2324,7 +2315,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (msp->base == NULL) goto out_free; - spin_lock_init(&msp->phy_lock); + mutex_init(&msp->phy_lock); /* * (Re-)program MBUS remapping windows if we are asked to. -- cgit v1.2.3 From 45c5d3bc1eae7a1d91b12dbee6443109337ec8c3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 04:42:59 +0200 Subject: mv643xx_eth: use the SMI done interrupt to wait for SMI access completion If the platform code has passed us the IRQ number of the mv643xx_eth top-level error interrupt, use the error interrupt to wait for SMI access completion instead of polling the SMI busy bit, since SMI bus accesses can take up to tens of milliseconds. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 191 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 57 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2d434017a67..b41860dc5b5 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -72,6 +72,13 @@ static char mv643xx_eth_driver_version[] = "1.3"; */ #define PHY_ADDR 0x0000 #define SMI_REG 0x0004 +#define SMI_BUSY 0x10000000 +#define SMI_READ_VALID 0x08000000 +#define SMI_OPCODE_READ 0x04000000 +#define SMI_OPCODE_WRITE 0x00000000 +#define ERR_INT_CAUSE 0x0080 +#define ERR_INT_SMI_DONE 0x00000010 +#define ERR_INT_MASK 0x0084 #define WINDOW_BASE(w) (0x0200 + ((w) << 3)) #define WINDOW_SIZE(w) (0x0204 + ((w) << 3)) #define WINDOW_REMAP_HIGH(w) (0x0280 + ((w) << 2)) @@ -253,6 +260,15 @@ struct mv643xx_eth_shared_private { */ struct mutex phy_lock; + /* + * If we have access to the error interrupt pin (which is + * somewhat misnamed as it not only reflects internal errors + * but also reflects SMI completion), use that to wait for + * SMI access completion instead of polling the SMI busy bit. + */ + int err_interrupt; + wait_queue_head_t smi_busy_wait; + /* * Per-port MBUS window access register value. */ @@ -979,68 +995,103 @@ static void txq_set_wrr(struct tx_queue *txq, int weight) /* mii management interface *************************************************/ -#define SMI_BUSY 0x10000000 -#define SMI_READ_VALID 0x08000000 -#define SMI_OPCODE_READ 0x04000000 -#define SMI_OPCODE_WRITE 0x00000000 +static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id) +{ + struct mv643xx_eth_shared_private *msp = dev_id; -static void smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr, - unsigned int reg, unsigned int *value) + if (readl(msp->base + ERR_INT_CAUSE) & ERR_INT_SMI_DONE) { + writel(~ERR_INT_SMI_DONE, msp->base + ERR_INT_CAUSE); + wake_up(&msp->smi_busy_wait); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int smi_is_done(struct mv643xx_eth_shared_private *msp) { - void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; - int i; + return !(readl(msp->base + SMI_REG) & SMI_BUSY); +} - /* the SMI register is a shared resource */ - mutex_lock(&mp->shared_smi->phy_lock); +static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) +{ + if (msp->err_interrupt == NO_IRQ) { + int i; - /* wait for the SMI register to become available */ - for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { - if (i == 1000) { - printk("%s: PHY busy timeout\n", mp->dev->name); - goto out; + for (i = 0; !smi_is_done(msp); i++) { + if (i == 10) + return -ETIMEDOUT; + msleep(10); } - udelay(10); + + return 0; + } + + if (!wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp), + msecs_to_jiffies(100))) + return -ETIMEDOUT; + + return 0; +} + +static int smi_reg_read(struct mv643xx_eth_private *mp, + unsigned int addr, unsigned int reg) +{ + struct mv643xx_eth_shared_private *msp = mp->shared_smi; + void __iomem *smi_reg = msp->base + SMI_REG; + int ret; + + mutex_lock(&msp->phy_lock); + + if (smi_wait_ready(msp)) { + printk("%s: SMI bus busy timeout\n", mp->dev->name); + ret = -ETIMEDOUT; + goto out; } writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); - /* now wait for the data to be valid */ - for (i = 0; !(readl(smi_reg) & SMI_READ_VALID); i++) { - if (i == 1000) { - printk("%s: PHY read timeout\n", mp->dev->name); - goto out; - } - udelay(10); + if (smi_wait_ready(msp)) { + printk("%s: SMI bus busy timeout\n", mp->dev->name); + ret = -ETIMEDOUT; + goto out; } - *value = readl(smi_reg) & 0xffff; + ret = readl(smi_reg); + if (!(ret & SMI_READ_VALID)) { + printk("%s: SMI bus read not valid\n", mp->dev->name); + ret = -ENODEV; + goto out; + } + + ret &= 0xffff; + out: - mutex_unlock(&mp->shared_smi->phy_lock); + mutex_unlock(&msp->phy_lock); + + return ret; } -static void smi_reg_write(struct mv643xx_eth_private *mp, - unsigned int addr, - unsigned int reg, unsigned int value) +static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, + unsigned int reg, unsigned int value) { - void __iomem *smi_reg = mp->shared_smi->base + SMI_REG; - int i; + struct mv643xx_eth_shared_private *msp = mp->shared_smi; + void __iomem *smi_reg = msp->base + SMI_REG; - /* the SMI register is a shared resource */ - mutex_lock(&mp->shared_smi->phy_lock); + mutex_lock(&msp->phy_lock); - /* wait for the SMI register to become available */ - for (i = 0; readl(smi_reg) & SMI_BUSY; i++) { - if (i == 1000) { - printk("%s: PHY busy timeout\n", mp->dev->name); - goto out; - } - udelay(10); + if (smi_wait_ready(msp)) { + printk("%s: SMI bus busy timeout\n", mp->dev->name); + mutex_unlock(&msp->phy_lock); + return -ETIMEDOUT; } writel(SMI_OPCODE_WRITE | (reg << 21) | (addr << 16) | (value & 0xffff), smi_reg); -out: - mutex_unlock(&mp->shared_smi->phy_lock); + + mutex_unlock(&msp->phy_lock); + + return 0; } @@ -1877,16 +1928,19 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) static void phy_reset(struct mv643xx_eth_private *mp) { - unsigned int data; + int data; + + data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + if (data < 0) + return; - smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data); data |= BMCR_RESET; - smi_reg_write(mp, mp->phy_addr, MII_BMCR, data); + if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data) < 0) + return; do { - udelay(1); - smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data); - } while (data & BMCR_RESET); + data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + } while (data >= 0 && data & BMCR_RESET); } static void port_start(struct mv643xx_eth_private *mp) @@ -2214,11 +2268,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg) { struct mv643xx_eth_private *mp = netdev_priv(dev); - int val; - - smi_reg_read(mp, addr, reg, &val); - - return val; + return smi_reg_read(mp, addr, reg); } static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val) @@ -2317,6 +2367,24 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) mutex_init(&msp->phy_lock); + msp->err_interrupt = NO_IRQ; + init_waitqueue_head(&msp->smi_busy_wait); + + /* + * Check whether the error interrupt is hooked up. + */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res != NULL) { + int err; + + err = request_irq(res->start, mv643xx_eth_err_irq, + IRQF_SHARED, "mv643xx_eth", msp); + if (!err) { + writel(ERR_INT_SMI_DONE, msp->base + ERR_INT_MASK); + msp->err_interrupt = res->start; + } + } + /* * (Re-)program MBUS remapping windows if we are asked to. */ @@ -2343,6 +2411,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) { struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); + if (msp->err_interrupt != NO_IRQ) + free_irq(msp->err_interrupt, msp); iounmap(msp->base); kfree(msp); @@ -2431,13 +2501,20 @@ static void set_params(struct mv643xx_eth_private *mp, static int phy_detect(struct mv643xx_eth_private *mp) { - unsigned int data; - unsigned int data2; + int data; + int data2; + + data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + if (data < 0) + return -ENODEV; + + if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE) < 0) + return -ENODEV; - smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data); - smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE); + data2 = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + if (data2 < 0) + return -ENODEV; - smi_reg_read(mp, mp->phy_addr, MII_BMCR, &data2); if (((data ^ data2) & BMCR_ANENABLE) == 0) return -ENODEV; -- cgit v1.2.3 From 78fff83b0347d72e996cef883f09c3e5b8544f73 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 01:03:57 +0200 Subject: mv643xx_eth: make napi unconditional Make napi unconditional on the receive side, so that we can get rid of all the locking and local interrupt disabling in the receive path. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b41860dc5b5..2b7e76d9ac0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -58,7 +58,6 @@ static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.3"; #define MV643XX_ETH_CHECKSUM_OFFLOAD_TX -#define MV643XX_ETH_NAPI #define MV643XX_ETH_TX_FAST_REFILL #ifdef MV643XX_ETH_CHECKSUM_OFFLOAD_TX @@ -616,7 +615,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) if (cmd_sts & ERROR_SUMMARY) stats->rx_errors++; - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); } else { /* * The -4 is for the CRC in the trailer of the @@ -630,11 +629,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) (cmd_sts & 0x0007fff8) >> 3); } skb->protocol = eth_type_trans(skb, mp->dev); -#ifdef MV643XX_ETH_NAPI netif_receive_skb(skb); -#else - netif_rx(skb); -#endif } mp->dev->last_rx = jiffies; @@ -645,7 +640,6 @@ static int rxq_process(struct rx_queue *rxq, int budget) return rx; } -#ifdef MV643XX_ETH_NAPI static int mv643xx_eth_poll(struct napi_struct *napi, int budget) { struct mv643xx_eth_private *mp; @@ -681,7 +675,6 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) return rx; } -#endif /* tx ***********************************************************************/ @@ -1856,7 +1849,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) /* * RxBuffer or RxError set for any of the 8 queues? */ -#ifdef MV643XX_ETH_NAPI if (int_cause & INT_RX) { wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_RX)); wrl(mp, INT_MASK(mp->port_num), 0x00000000); @@ -1864,15 +1856,6 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) netif_rx_schedule(dev, &mp->napi); } -#else - if (int_cause & INT_RX) { - int i; - - for (i = 7; i >= 0; i--) - if (mp->rxq_mask & (1 << i)) - rxq_process(mp->rxq + i, INT_MAX); - } -#endif /* * TxBuffer or TxError set for any of the 8 queues? @@ -2101,9 +2084,7 @@ static int mv643xx_eth_open(struct net_device *dev) } } -#ifdef MV643XX_ETH_NAPI napi_enable(&mp->napi); -#endif netif_carrier_off(dev); netif_stop_queue(dev); @@ -2167,9 +2148,8 @@ static int mv643xx_eth_stop(struct net_device *dev) wrl(mp, INT_MASK(mp->port_num), 0x00000000); rdl(mp, INT_MASK(mp->port_num)); -#ifdef MV643XX_ETH_NAPI napi_disable(&mp->napi); -#endif + netif_carrier_off(dev); netif_stop_queue(dev); @@ -2632,9 +2612,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->port_num = pd->port_number; mp->dev = dev; -#ifdef MV643XX_ETH_NAPI + netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 64); -#endif set_params(mp, pd); @@ -2700,10 +2679,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) if (dev->features & NETIF_F_IP_CSUM) dev_printk(KERN_NOTICE, &dev->dev, "tx checksum offload\n"); -#ifdef MV643XX_ETH_NAPI - dev_printk(KERN_NOTICE, &dev->dev, "napi enabled\n"); -#endif - if (mp->tx_desc_sram_size > 0) dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n"); -- cgit v1.2.3 From 2257e05c170561bb1168ee50205ae920008c37fb Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 04:33:36 +0200 Subject: mv643xx_eth: get rid of receive-side locking By having the receive out-of-memory handling timer schedule the napi poll handler and then doing oom processing from the napi poll handler, all code that touches receive state moves to napi context, letting us get rid of all explicit locking in the receive paths since the only mutual exclusion we need anymore at that point is protection against reentering ourselves, which is provided by napi synchronisation. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 132 ++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 64 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2b7e76d9ac0..3831a8bffbd 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -329,8 +329,6 @@ struct rx_queue { dma_addr_t rx_desc_dma; int rx_desc_area_size; struct sk_buff **rx_skb; - - struct timer_list rx_oom; }; struct tx_queue { @@ -372,6 +370,7 @@ struct mv643xx_eth_private { u8 rxq_mask; int rxq_primary; struct napi_struct napi; + struct timer_list rx_oom; struct rx_queue rxq[8]; /* @@ -473,44 +472,43 @@ static void __txq_maybe_wake(struct tx_queue *txq) /* rx ***********************************************************************/ static void txq_reclaim(struct tx_queue *txq, int force); -static void rxq_refill(struct rx_queue *rxq) +static int rxq_refill(struct rx_queue *rxq, int budget, int *oom) { - struct mv643xx_eth_private *mp = rxq_to_mp(rxq); - unsigned long flags; + int skb_size; + int refilled; - spin_lock_irqsave(&mp->lock, flags); + /* + * Reserve 2+14 bytes for an ethernet header (the hardware + * automatically prepends 2 bytes of dummy data to each + * received packet), 16 bytes for up to four VLAN tags, and + * 4 bytes for the trailing FCS -- 36 bytes total. + */ + skb_size = rxq_to_mp(rxq)->dev->mtu + 36; + + /* + * Make sure that the skb size is a multiple of 8 bytes, as + * the lower three bits of the receive descriptor's buffer + * size field are ignored by the hardware. + */ + skb_size = (skb_size + 7) & ~7; - while (rxq->rx_desc_count < rxq->rx_ring_size) { - int skb_size; + refilled = 0; + while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { struct sk_buff *skb; int unaligned; int rx; - /* - * Reserve 2+14 bytes for an ethernet header (the - * hardware automatically prepends 2 bytes of dummy - * data to each received packet), 16 bytes for up to - * four VLAN tags, and 4 bytes for the trailing FCS - * -- 36 bytes total. - */ - skb_size = mp->dev->mtu + 36; - - /* - * Make sure that the skb size is a multiple of 8 - * bytes, as the lower three bits of the receive - * descriptor's buffer size field are ignored by - * the hardware. - */ - skb_size = (skb_size + 7) & ~7; - skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1); - if (skb == NULL) + if (skb == NULL) { + *oom = 1; break; + } unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); if (unaligned) skb_reserve(skb, dma_get_cache_alignment() - unaligned); + refilled++; rxq->rx_desc_count++; rx = rxq->rx_used_desc++; @@ -534,15 +532,7 @@ static void rxq_refill(struct rx_queue *rxq) skb_reserve(skb, 2); } - if (rxq->rx_desc_count != rxq->rx_ring_size) - mod_timer(&rxq->rx_oom, jiffies + (HZ / 10)); - - spin_unlock_irqrestore(&mp->lock, flags); -} - -static inline void rxq_refill_timer_wrapper(unsigned long data) -{ - rxq_refill((struct rx_queue *)data); + return refilled; } static int rxq_process(struct rx_queue *rxq, int budget) @@ -556,17 +546,12 @@ static int rxq_process(struct rx_queue *rxq, int budget) struct rx_desc *rx_desc; unsigned int cmd_sts; struct sk_buff *skb; - unsigned long flags; - - spin_lock_irqsave(&mp->lock, flags); rx_desc = &rxq->rx_desc_area[rxq->rx_curr_desc]; cmd_sts = rx_desc->cmd_sts; - if (cmd_sts & BUFFER_OWNED_BY_DMA) { - spin_unlock_irqrestore(&mp->lock, flags); + if (cmd_sts & BUFFER_OWNED_BY_DMA) break; - } rmb(); skb = rxq->rx_skb[rxq->rx_curr_desc]; @@ -576,8 +561,6 @@ static int rxq_process(struct rx_queue *rxq, int budget) if (rxq->rx_curr_desc == rxq->rx_ring_size) rxq->rx_curr_desc = 0; - spin_unlock_irqrestore(&mp->lock, flags); - dma_unmap_single(NULL, rx_desc->buf_ptr, rx_desc->buf_size, DMA_FROM_DEVICE); rxq->rx_desc_count--; @@ -635,15 +618,14 @@ static int rxq_process(struct rx_queue *rxq, int budget) mp->dev->last_rx = jiffies; } - rxq_refill(rxq); - return rx; } static int mv643xx_eth_poll(struct napi_struct *napi, int budget) { struct mv643xx_eth_private *mp; - int rx; + int work_done; + int oom; int i; mp = container_of(napi, struct mv643xx_eth_private, napi); @@ -663,17 +645,32 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) } #endif - rx = 0; - for (i = 7; rx < budget && i >= 0; i--) - if (mp->rxq_mask & (1 << i)) - rx += rxq_process(mp->rxq + i, budget - rx); + work_done = 0; + oom = 0; + for (i = 7; work_done < budget && i >= 0; i--) { + if (mp->rxq_mask & (1 << i)) { + struct rx_queue *rxq = mp->rxq + i; - if (rx < budget) { + work_done += rxq_process(rxq, budget - work_done); + work_done += rxq_refill(rxq, budget - work_done, &oom); + } + } + + if (work_done < budget) { + if (oom) + mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); netif_rx_complete(mp->dev, napi); wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); } - return rx; + return work_done; +} + +static inline void oom_timer_wrapper(unsigned long data) +{ + struct mv643xx_eth_private *mp = (void *)data; + + napi_schedule(&mp->napi); } @@ -1565,10 +1562,6 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) nexti * sizeof(struct rx_desc); } - init_timer(&rxq->rx_oom); - rxq->rx_oom.data = (unsigned long)rxq; - rxq->rx_oom.function = rxq_refill_timer_wrapper; - return 0; @@ -1591,8 +1584,6 @@ static void rxq_deinit(struct rx_queue *rxq) rxq_disable(rxq); - del_timer_sync(&rxq->rx_oom); - for (i = 0; i < rxq->rx_ring_size; i++) { if (rxq->rx_skb[i]) { dev_kfree_skb(rxq->rx_skb[i]); @@ -1854,7 +1845,7 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) wrl(mp, INT_MASK(mp->port_num), 0x00000000); rdl(mp, INT_MASK(mp->port_num)); - netif_rx_schedule(dev, &mp->napi); + napi_schedule(&mp->napi); } /* @@ -2041,6 +2032,7 @@ static int mv643xx_eth_open(struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); int err; + int oom; int i; wrl(mp, INT_CAUSE(mp->port_num), 0); @@ -2056,6 +2048,9 @@ static int mv643xx_eth_open(struct net_device *dev) init_mac_tables(mp); + napi_enable(&mp->napi); + + oom = 0; for (i = 0; i < 8; i++) { if ((mp->rxq_mask & (1 << i)) == 0) continue; @@ -2068,7 +2063,12 @@ static int mv643xx_eth_open(struct net_device *dev) goto out; } - rxq_refill(mp->rxq + i); + rxq_refill(mp->rxq + i, INT_MAX, &oom); + } + + if (oom) { + mp->rx_oom.expires = jiffies + (HZ / 10); + add_timer(&mp->rx_oom); } for (i = 0; i < 8; i++) { @@ -2084,8 +2084,6 @@ static int mv643xx_eth_open(struct net_device *dev) } } - napi_enable(&mp->napi); - netif_carrier_off(dev); netif_stop_queue(dev); @@ -2150,6 +2148,8 @@ static int mv643xx_eth_stop(struct net_device *dev) napi_disable(&mp->napi); + del_timer_sync(&mp->rx_oom); + netif_carrier_off(dev); netif_stop_queue(dev); @@ -2613,8 +2613,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->dev = dev; - netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 64); - set_params(mp, pd); spin_lock_init(&mp->lock); @@ -2633,6 +2631,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev) } init_pscr(mp, pd->speed, pd->duplex); + netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 128); + + init_timer(&mp->rx_oom); + mp->rx_oom.data = (unsigned long)mp; + mp->rx_oom.function = oom_timer_wrapper; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); BUG_ON(!res); -- cgit v1.2.3 From 17cd0a59f9c34164c4f3bfe404894f5285bac112 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 05:33:55 +0200 Subject: mv643xx_eth: get rid of compile-time configurable transmit checksumming Get rid of the mv643xx_eth-internal MV643XX_ETH_CHECKSUM_OFFLOAD_TX compile-time option. Using transmit checksumming is the sane default, and anyone wanting to disable it should use ethtool(8) instead of recompiling their kernels. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 3831a8bffbd..53cfd01b405 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -57,15 +57,8 @@ static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.3"; -#define MV643XX_ETH_CHECKSUM_OFFLOAD_TX #define MV643XX_ETH_TX_FAST_REFILL -#ifdef MV643XX_ETH_CHECKSUM_OFFLOAD_TX -#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) -#else -#define MAX_DESCS_PER_SKB 1 -#endif - /* * Registers shared between all ports. */ @@ -464,7 +457,7 @@ static void __txq_maybe_wake(struct tx_queue *txq) */ BUG_ON(txq->index != mp->txq_primary); - if (txq->tx_ring_size - txq->tx_desc_count >= MAX_DESCS_PER_SKB) + if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) netif_wake_queue(mp->dev); } @@ -855,7 +848,7 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) txq = mp->txq + mp->txq_primary; - if (txq->tx_ring_size - txq->tx_desc_count < MAX_DESCS_PER_SKB) { + if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { spin_unlock_irqrestore(&mp->lock, flags); if (txq->index == mp->txq_primary && net_ratelimit()) dev_printk(KERN_ERR, &dev->dev, @@ -873,7 +866,7 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) int entries_left; entries_left = txq->tx_ring_size - txq->tx_desc_count; - if (entries_left < MAX_DESCS_PER_SKB) + if (entries_left < MAX_SKB_FRAGS + 1) netif_stop_queue(dev); } @@ -2656,14 +2649,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev->watchdog_timeo = 2 * HZ; dev->base_addr = 0; -#ifdef MV643XX_ETH_CHECKSUM_OFFLOAD_TX - /* - * Zero copy can only work if we use Discovery II memory. Else, we will - * have to map the buffers to ISA memory which is only 16 MB - */ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM; -#endif SET_NETDEV_DEV(dev, &pdev->dev); @@ -2677,12 +2664,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %s\n", mp->port_num, print_mac(mac, dev->dev_addr)); - if (dev->features & NETIF_F_SG) - dev_printk(KERN_NOTICE, &dev->dev, "scatter/gather enabled\n"); - - if (dev->features & NETIF_F_IP_CSUM) - dev_printk(KERN_NOTICE, &dev->dev, "tx checksum offload\n"); - if (mp->tx_desc_sram_size > 0) dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n"); -- cgit v1.2.3 From f7981c1c67b53abb4a7d8a501e68585b9826179a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 10:23:22 +0200 Subject: mv643xx_eth: require contiguous receive and transmit queue numbering Simplify receive and transmit queue handling by requiring the set of queue numbers to be contiguous starting from zero. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 123 ++++++++++++++++---------------------------- include/linux/mv643xx_eth.h | 6 +-- 2 files changed, 47 insertions(+), 82 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 53cfd01b405..c41541d8710 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -360,8 +360,7 @@ struct mv643xx_eth_private { int default_rx_ring_size; unsigned long rx_desc_sram_addr; int rx_desc_sram_size; - u8 rxq_mask; - int rxq_primary; + int rxq_count; struct napi_struct napi; struct timer_list rx_oom; struct rx_queue rxq[8]; @@ -372,8 +371,7 @@ struct mv643xx_eth_private { int default_tx_ring_size; unsigned long tx_desc_sram_addr; int tx_desc_sram_size; - u8 txq_mask; - int txq_primary; + int txq_count; struct tx_queue txq[8]; #ifdef MV643XX_ETH_TX_FAST_REFILL int tx_clean_threshold; @@ -455,7 +453,7 @@ static void __txq_maybe_wake(struct tx_queue *txq) * netif_{stop,wake}_queue() flow control only applies to * the primary queue. */ - BUG_ON(txq->index != mp->txq_primary); + BUG_ON(txq->index != 0); if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) netif_wake_queue(mp->dev); @@ -626,13 +624,12 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) #ifdef MV643XX_ETH_TX_FAST_REFILL if (++mp->tx_clean_threshold > 5) { mp->tx_clean_threshold = 0; - for (i = 0; i < 8; i++) - if (mp->txq_mask & (1 << i)) - txq_reclaim(mp->txq + i, 0); + for (i = 0; i < mp->txq_count; i++) + txq_reclaim(mp->txq + i, 0); if (netif_carrier_ok(mp->dev)) { spin_lock_irq(&mp->lock); - __txq_maybe_wake(mp->txq + mp->txq_primary); + __txq_maybe_wake(mp->txq); spin_unlock_irq(&mp->lock); } } @@ -640,13 +637,11 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) work_done = 0; oom = 0; - for (i = 7; work_done < budget && i >= 0; i--) { - if (mp->rxq_mask & (1 << i)) { - struct rx_queue *rxq = mp->rxq + i; + for (i = mp->rxq_count - 1; work_done < budget && i >= 0; i--) { + struct rx_queue *rxq = mp->rxq + i; - work_done += rxq_process(rxq, budget - work_done); - work_done += rxq_refill(rxq, budget - work_done, &oom); - } + work_done += rxq_process(rxq, budget - work_done); + work_done += rxq_refill(rxq, budget - work_done, &oom); } if (work_done < budget) { @@ -846,11 +841,11 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&mp->lock, flags); - txq = mp->txq + mp->txq_primary; + txq = mp->txq; if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { spin_unlock_irqrestore(&mp->lock, flags); - if (txq->index == mp->txq_primary && net_ratelimit()) + if (txq->index == 0 && net_ratelimit()) dev_printk(KERN_ERR, &dev->dev, "primary tx queue full?!\n"); kfree_skb(skb); @@ -862,7 +857,7 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) stats->tx_packets++; dev->trans_start = jiffies; - if (txq->index == mp->txq_primary) { + if (txq->index == 0) { int entries_left; entries_left = txq->tx_ring_size - txq->tx_desc_count; @@ -1517,7 +1512,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) size = rxq->rx_ring_size * sizeof(struct rx_desc); - if (index == mp->rxq_primary && size <= mp->rx_desc_sram_size) { + if (index == 0 && size <= mp->rx_desc_sram_size) { rxq->rx_desc_area = ioremap(mp->rx_desc_sram_addr, mp->rx_desc_sram_size); rxq->rx_desc_dma = mp->rx_desc_sram_addr; @@ -1559,7 +1554,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) out_free: - if (index == mp->rxq_primary && size <= mp->rx_desc_sram_size) + if (index == 0 && size <= mp->rx_desc_sram_size) iounmap(rxq->rx_desc_area); else dma_free_coherent(NULL, size, @@ -1590,7 +1585,7 @@ static void rxq_deinit(struct rx_queue *rxq) rxq->rx_desc_count); } - if (rxq->index == mp->rxq_primary && + if (rxq->index == 0 && rxq->rx_desc_area_size <= mp->rx_desc_sram_size) iounmap(rxq->rx_desc_area); else @@ -1617,7 +1612,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) size = txq->tx_ring_size * sizeof(struct tx_desc); - if (index == mp->txq_primary && size <= mp->tx_desc_sram_size) { + if (index == 0 && size <= mp->tx_desc_sram_size) { txq->tx_desc_area = ioremap(mp->tx_desc_sram_addr, mp->tx_desc_sram_size); txq->tx_desc_dma = mp->tx_desc_sram_addr; @@ -1661,7 +1656,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) out_free: - if (index == mp->txq_primary && size <= mp->tx_desc_sram_size) + if (index == 0 && size <= mp->tx_desc_sram_size) iounmap(txq->tx_desc_area); else dma_free_coherent(NULL, size, @@ -1738,7 +1733,7 @@ static void txq_deinit(struct tx_queue *txq) BUG_ON(txq->tx_used_desc != txq->tx_curr_desc); - if (txq->index == mp->txq_primary && + if (txq->index == 0 && txq->tx_desc_area_size <= mp->tx_desc_sram_size) iounmap(txq->tx_desc_area); else @@ -1768,13 +1763,11 @@ static void handle_link_event(struct mv643xx_eth_private *mp) netif_carrier_off(dev); netif_stop_queue(dev); - for (i = 0; i < 8; i++) { + for (i = 0; i < mp->txq_count; i++) { struct tx_queue *txq = mp->txq + i; - if (mp->txq_mask & (1 << i)) { - txq_reclaim(txq, 1); - txq_reset_hw_ptr(txq); - } + txq_reclaim(txq, 1); + txq_reset_hw_ptr(txq); } } return; @@ -1847,9 +1840,8 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) if (int_cause_ext & INT_EXT_TX) { int i; - for (i = 0; i < 8; i++) - if (mp->txq_mask & (1 << i)) - txq_reclaim(mp->txq + i, 0); + for (i = 0; i < mp->txq_count; i++) + txq_reclaim(mp->txq + i, 0); /* * Enough space again in the primary TX queue for a @@ -1857,7 +1849,7 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) */ if (netif_carrier_ok(dev)) { spin_lock(&mp->lock); - __txq_maybe_wake(mp->txq + mp->txq_primary); + __txq_maybe_wake(mp->txq); spin_unlock(&mp->lock); } } @@ -1945,12 +1937,9 @@ static void port_start(struct mv643xx_eth_private *mp) * Configure TX path and queues. */ tx_set_rate(mp, 1000000000, 16777216); - for (i = 0; i < 8; i++) { + for (i = 0; i < mp->txq_count; i++) { struct tx_queue *txq = mp->txq + i; - if ((mp->txq_mask & (1 << i)) == 0) - continue; - txq_reset_hw_ptr(txq); txq_set_rate(txq, 1000000000, 16777216); txq_set_fixed_prio_mode(txq); @@ -1975,14 +1964,11 @@ static void port_start(struct mv643xx_eth_private *mp) /* * Enable the receive queues. */ - for (i = 0; i < 8; i++) { + for (i = 0; i < mp->rxq_count; i++) { struct rx_queue *rxq = mp->rxq + i; int off = RXQ_CURRENT_DESC_PTR(mp->port_num, i); u32 addr; - if ((mp->rxq_mask & (1 << i)) == 0) - continue; - addr = (u32)rxq->rx_desc_dma; addr += rxq->rx_curr_desc * sizeof(struct rx_desc); wrl(mp, off, addr); @@ -2044,15 +2030,11 @@ static int mv643xx_eth_open(struct net_device *dev) napi_enable(&mp->napi); oom = 0; - for (i = 0; i < 8; i++) { - if ((mp->rxq_mask & (1 << i)) == 0) - continue; - + for (i = 0; i < mp->rxq_count; i++) { err = rxq_init(mp, i); if (err) { while (--i >= 0) - if (mp->rxq_mask & (1 << i)) - rxq_deinit(mp->rxq + i); + rxq_deinit(mp->rxq + i); goto out; } @@ -2064,15 +2046,11 @@ static int mv643xx_eth_open(struct net_device *dev) add_timer(&mp->rx_oom); } - for (i = 0; i < 8; i++) { - if ((mp->txq_mask & (1 << i)) == 0) - continue; - + for (i = 0; i < mp->txq_count; i++) { err = txq_init(mp, i); if (err) { while (--i >= 0) - if (mp->txq_mask & (1 << i)) - txq_deinit(mp->txq + i); + txq_deinit(mp->txq + i); goto out_free; } } @@ -2094,9 +2072,8 @@ static int mv643xx_eth_open(struct net_device *dev) out_free: - for (i = 0; i < 8; i++) - if (mp->rxq_mask & (1 << i)) - rxq_deinit(mp->rxq + i); + for (i = 0; i < mp->rxq_count; i++) + rxq_deinit(mp->rxq + i); out: free_irq(dev->irq, dev); @@ -2108,12 +2085,10 @@ static void port_reset(struct mv643xx_eth_private *mp) unsigned int data; int i; - for (i = 0; i < 8; i++) { - if (mp->rxq_mask & (1 << i)) - rxq_disable(mp->rxq + i); - if (mp->txq_mask & (1 << i)) - txq_disable(mp->txq + i); - } + for (i = 0; i < mp->rxq_count; i++) + rxq_disable(mp->rxq + i); + for (i = 0; i < mp->txq_count; i++) + txq_disable(mp->txq + i); while (1) { u32 ps = rdl(mp, PORT_STATUS(mp->port_num)); @@ -2151,12 +2126,10 @@ static int mv643xx_eth_stop(struct net_device *dev) port_reset(mp); mib_counters_update(mp); - for (i = 0; i < 8; i++) { - if (mp->rxq_mask & (1 << i)) - rxq_deinit(mp->rxq + i); - if (mp->txq_mask & (1 << i)) - txq_deinit(mp->txq + i); - } + for (i = 0; i < mp->rxq_count; i++) + rxq_deinit(mp->rxq + i); + for (i = 0; i < mp->txq_count; i++) + txq_deinit(mp->txq + i); return 0; } @@ -2211,7 +2184,7 @@ static void tx_timeout_task(struct work_struct *ugly) port_reset(mp); port_start(mp); - __txq_maybe_wake(mp->txq + mp->txq_primary); + __txq_maybe_wake(mp->txq); } } @@ -2453,11 +2426,7 @@ static void set_params(struct mv643xx_eth_private *mp, mp->rx_desc_sram_addr = pd->rx_sram_addr; mp->rx_desc_sram_size = pd->rx_sram_size; - if (pd->rx_queue_mask) - mp->rxq_mask = pd->rx_queue_mask; - else - mp->rxq_mask = 0x01; - mp->rxq_primary = fls(mp->rxq_mask) - 1; + mp->rxq_count = pd->rx_queue_count ? : 1; mp->default_tx_ring_size = DEFAULT_TX_QUEUE_SIZE; if (pd->tx_queue_size) @@ -2465,11 +2434,7 @@ static void set_params(struct mv643xx_eth_private *mp, mp->tx_desc_sram_addr = pd->tx_sram_addr; mp->tx_desc_sram_size = pd->tx_sram_size; - if (pd->tx_queue_mask) - mp->txq_mask = pd->tx_queue_mask; - else - mp->txq_mask = 0x01; - mp->txq_primary = fls(mp->txq_mask) - 1; + mp->txq_count = pd->tx_queue_count ? : 1; } static int phy_detect(struct mv643xx_eth_private *mp) diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 12078577aef..eb78b00edcd 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -49,10 +49,10 @@ struct mv643xx_eth_platform_data { int duplex; /* - * Which RX/TX queues to use. + * How many RX/TX queues to use. */ - int rx_queue_mask; - int tx_queue_mask; + int rx_queue_count; + int tx_queue_count; /* * Override default RX/TX queue sizes if nonzero. -- cgit v1.2.3 From fc0eb9f226d8ecc8e3b563bf808bd6d61a6153a1 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 12:56:56 +0200 Subject: mv643xx_eth: smi sharing is a per-unit property, not a per-port one Which top-level unit's SMI interface to use should be a property of the top-level unit, not of the individual ports. This patch moves the ->shared_smi pointer from the per-port platform data to the global platform data. Signed-off-by: Lennert Buytenhek --- arch/arm/mach-mv78xx0/common.c | 6 +++--- drivers/net/mv643xx_eth.c | 19 +++++++++++-------- include/linux/mv643xx_eth.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 953a26c469c..5842d3bb02b 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -330,6 +330,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge01_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge01_shared_resources[] = { @@ -370,7 +371,6 @@ static struct platform_device mv78xx0_ge01 = { void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge01_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge01.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge01_shared); @@ -384,6 +384,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge10_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge10_shared_resources[] = { @@ -424,7 +425,6 @@ static struct platform_device mv78xx0_ge10 = { void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge10_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge10.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge10_shared); @@ -438,6 +438,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data) struct mv643xx_eth_shared_platform_data mv78xx0_ge11_shared_data = { .t_clk = 0, .dram = &mv78xx0_mbus_dram_info, + .shared_smi = &mv78xx0_ge00_shared, }; static struct resource mv78xx0_ge11_shared_resources[] = { @@ -478,7 +479,6 @@ static struct platform_device mv78xx0_ge11 = { void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data) { eth_data->shared = &mv78xx0_ge11_shared; - eth_data->shared_smi = &mv78xx0_ge00_shared; mv78xx0_ge11.dev.platform_data = eth_data; platform_device_register(&mv78xx0_ge11_shared); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index c41541d8710..6d3da78b7ad 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -247,6 +247,11 @@ struct mv643xx_eth_shared_private { */ void __iomem *base; + /* + * Points at the right SMI instance to use. + */ + struct mv643xx_eth_shared_private *smi; + /* * Protects access to SMI_REG, which is shared between ports. */ @@ -345,7 +350,6 @@ struct mv643xx_eth_private { struct net_device *dev; - struct mv643xx_eth_shared_private *shared_smi; int phy_addr; spinlock_t lock; @@ -1015,7 +1019,7 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) static int smi_reg_read(struct mv643xx_eth_private *mp, unsigned int addr, unsigned int reg) { - struct mv643xx_eth_shared_private *msp = mp->shared_smi; + struct mv643xx_eth_shared_private *msp = mp->shared->smi; void __iomem *smi_reg = msp->base + SMI_REG; int ret; @@ -1053,7 +1057,7 @@ out: static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, unsigned int reg, unsigned int value) { - struct mv643xx_eth_shared_private *msp = mp->shared_smi; + struct mv643xx_eth_shared_private *msp = mp->shared->smi; void __iomem *smi_reg = msp->base + SMI_REG; mutex_lock(&msp->phy_lock); @@ -2311,6 +2315,10 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (msp->base == NULL) goto out_free; + msp->smi = msp; + if (pd != NULL && pd->shared_smi != NULL) + msp->smi = platform_get_drvdata(pd->shared_smi); + mutex_init(&msp->phy_lock); msp->err_interrupt = NO_IRQ; @@ -2405,13 +2413,8 @@ static void set_params(struct mv643xx_eth_private *mp, uc_addr_get(mp, dev->dev_addr); if (pd->phy_addr == -1) { - mp->shared_smi = NULL; mp->phy_addr = -1; } else { - mp->shared_smi = mp->shared; - if (pd->shared_smi != NULL) - mp->shared_smi = platform_get_drvdata(pd->shared_smi); - if (pd->force_phy_addr || pd->phy_addr) { mp->phy_addr = pd->phy_addr & 0x3f; phy_addr_set(mp, mp->phy_addr); diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index eb78b00edcd..12339eb6570 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -17,6 +17,7 @@ struct mv643xx_eth_shared_platform_data { struct mbus_dram_target_info *dram; + struct platform_device *shared_smi; unsigned int t_clk; }; @@ -30,7 +31,6 @@ struct mv643xx_eth_platform_data { /* * Whether a PHY is present, and if yes, at which address. */ - struct platform_device *shared_smi; int force_phy_addr; int phy_addr; -- cgit v1.2.3 From ac840605f3b1d9b99e1e6629a54994f8e003ff91 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 14:06:47 +0200 Subject: mv643xx_eth: remove force_phy_addr field Currently, there are two different fields in the mv643xx_eth_platform_data struct that together describe the PHY address -- one field (phy_addr) has the address of the PHY, but if that address is zero, a second field (force_phy_addr) needs to be set to distinguish the actual address zero from a zero due to not having filled in the PHY address explicitly (which should mean 'use the default PHY address'). If we are a bit smarter about the encoding of the phy_addr field, we can avoid the need for a second field -- this patch does that. Signed-off-by: Lennert Buytenhek --- arch/arm/mach-kirkwood/db88f6281-bp-setup.c | 2 +- arch/arm/mach-kirkwood/rd88f6192-nas-setup.c | 2 +- arch/arm/mach-kirkwood/rd88f6281-setup.c | 2 +- arch/arm/mach-loki/lb88rc8480-setup.c | 2 +- arch/arm/mach-mv78xx0/db78x00-bp-setup.c | 8 ++++---- arch/arm/mach-orion5x/db88f5281-setup.c | 2 +- arch/arm/mach-orion5x/dns323-setup.c | 2 +- arch/arm/mach-orion5x/kurobox_pro-setup.c | 2 +- arch/arm/mach-orion5x/mss2-setup.c | 2 +- arch/arm/mach-orion5x/mv2120-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 2 +- arch/arm/mach-orion5x/rd88f5182-setup.c | 2 +- arch/arm/mach-orion5x/ts78xx-setup.c | 3 +-- arch/arm/mach-orion5x/tsx09-common.c | 2 +- arch/arm/mach-orion5x/wnr854t-setup.c | 2 +- arch/arm/mach-orion5x/wrt350n-v2-setup.c | 2 +- arch/powerpc/sysdev/mv64x60_dev.c | 6 ++---- drivers/net/mv643xx_eth.c | 4 ++-- include/linux/mv643xx_eth.h | 5 ++++- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index 610fb24d8ae..cd317795f35 100644 --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -25,7 +25,7 @@ #include "common.h" static struct mv643xx_eth_platform_data db88f6281_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data db88f6281_sata_data = { diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c index a3012d44597..b1d1a87a682 100644 --- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c @@ -30,7 +30,7 @@ #define RD88F6192_GPIO_USB_VBUS 10 static struct mv643xx_eth_platform_data rd88f6192_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data rd88f6192_sata_data = { diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index d96487a0f18..b6416615c0b 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -69,7 +69,7 @@ static struct platform_device rd88f6281_nand_flash = { }; static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c index 2cc9ac9b488..85f9c1296aa 100644 --- a/arch/arm/mach-loki/lb88rc8480-setup.c +++ b/arch/arm/mach-loki/lb88rc8480-setup.c @@ -67,7 +67,7 @@ static struct platform_device lb88rc8480_boot_flash = { }; static struct mv643xx_eth_platform_data lb88rc8480_ge0_data = { - .phy_addr = 1, + .phy_addr = MV643XX_ETH_PHY_ADDR(1), .mac_addr = { 0x00, 0x50, 0x43, 0x11, 0x22, 0x33 }, }; diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c index a2d0c978360..49f434c39eb 100644 --- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c +++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c @@ -19,19 +19,19 @@ #include "common.h" static struct mv643xx_eth_platform_data db78x00_ge00_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv643xx_eth_platform_data db78x00_ge01_data = { - .phy_addr = 9, + .phy_addr = MV643XX_ETH_PHY_ADDR(9), }; static struct mv643xx_eth_platform_data db78x00_ge10_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, }; static struct mv643xx_eth_platform_data db78x00_ge11_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, }; static struct mv_sata_platform_data db78x00_sata_data = { diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index ff13e9060b1..d318bea2af9 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -285,7 +285,7 @@ subsys_initcall(db88f5281_pci_init); * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data db88f5281_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index b38c65ccfb1..3e66098340a 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -79,7 +79,7 @@ subsys_initcall(dns323_pci_init); */ static struct mv643xx_eth_platform_data dns323_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /**************************************************************************** diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index e321ec33183..610f2a6297f 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -161,7 +161,7 @@ subsys_initcall(kurobox_pro_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c index 53ff1893b88..68acca98e63 100644 --- a/arch/arm/mach-orion5x/mss2-setup.c +++ b/arch/arm/mach-orion5x/mss2-setup.c @@ -109,7 +109,7 @@ subsys_initcall(mss2_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data mss2_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index 978d4d59939..97c9ccb2ac6 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -39,7 +39,7 @@ * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data mv2120_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static struct mv_sata_platform_data mv2120_sata_data = { diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index e72fe1e065e..500cdadaf09 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -88,7 +88,7 @@ static struct orion5x_mpp_mode rd88f5181l_fxo_mpp_modes[] __initdata = { }; static struct mv643xx_eth_platform_data rd88f5181l_fxo_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index a1fe3257320..ebde8141649 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -89,7 +89,7 @@ static struct orion5x_mpp_mode rd88f5181l_ge_mpp_modes[] __initdata = { }; static struct mv643xx_eth_platform_data rd88f5181l_ge_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index 4c3bcd76ac8..a04f9e4b633 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -221,7 +221,7 @@ subsys_initcall(rd88f5182_pci_init); ****************************************************************************/ static struct mv643xx_eth_platform_data rd88f5182_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index ae0a5dccd2a..1368e9fd1a0 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -103,8 +103,7 @@ static struct platform_device ts78xx_nor_boot_flash = { * Ethernet ****************************************************************************/ static struct mv643xx_eth_platform_data ts78xx_eth_data = { - .phy_addr = 0, - .force_phy_addr = 1, + .phy_addr = MV643XX_ETH_PHY_ADDR(0), }; /***************************************************************************** diff --git a/arch/arm/mach-orion5x/tsx09-common.c b/arch/arm/mach-orion5x/tsx09-common.c index 83feac3147a..19cde24fbfd 100644 --- a/arch/arm/mach-orion5x/tsx09-common.c +++ b/arch/arm/mach-orion5x/tsx09-common.c @@ -48,7 +48,7 @@ void qnap_tsx09_power_off(void) ****************************************************************************/ struct mv643xx_eth_platform_data qnap_tsx09_eth_data = { - .phy_addr = 8, + .phy_addr = MV643XX_ETH_PHY_ADDR(8), }; static int __init qnap_tsx09_parse_hex_nibble(char n) diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c index b6bc43e07ee..7ddc22c2bb5 100644 --- a/arch/arm/mach-orion5x/wnr854t-setup.c +++ b/arch/arm/mach-orion5x/wnr854t-setup.c @@ -92,7 +92,7 @@ static struct platform_device wnr854t_nor_flash = { }; static struct mv643xx_eth_platform_data wnr854t_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index b10da17b3fb..9a4fd525646 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -100,7 +100,7 @@ static struct platform_device wrt350n_v2_nor_flash = { }; static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = { - .phy_addr = -1, + .phy_addr = MV643XX_ETH_PHY_NONE, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 32e0ad0ebea..b6bd775d2e2 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -293,10 +293,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id, return -ENODEV; prop = of_get_property(phy, "reg", NULL); - if (prop) { - pdata.force_phy_addr = 1; - pdata.phy_addr = *prop; - } + if (prop) + pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop); of_node_put(phy); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 6d3da78b7ad..b4850cf2a8c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2412,10 +2412,10 @@ static void set_params(struct mv643xx_eth_private *mp, else uc_addr_get(mp, dev->dev_addr); - if (pd->phy_addr == -1) { + if (pd->phy_addr == MV643XX_ETH_PHY_NONE) { mp->phy_addr = -1; } else { - if (pd->force_phy_addr || pd->phy_addr) { + if (pd->phy_addr != MV643XX_ETH_PHY_ADDR_DEFAULT) { mp->phy_addr = pd->phy_addr & 0x3f; phy_addr_set(mp, mp->phy_addr); } else { diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 12339eb6570..cbbbe9bfeca 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -21,6 +21,10 @@ struct mv643xx_eth_shared_platform_data { unsigned int t_clk; }; +#define MV643XX_ETH_PHY_ADDR_DEFAULT 0 +#define MV643XX_ETH_PHY_ADDR(x) (0x80 | (x)) +#define MV643XX_ETH_PHY_NONE 0xff + struct mv643xx_eth_platform_data { /* * Pointer back to our parent instance, and our port number. @@ -31,7 +35,6 @@ struct mv643xx_eth_platform_data { /* * Whether a PHY is present, and if yes, at which address. */ - int force_phy_addr; int phy_addr; /* -- cgit v1.2.3 From 4fdeca3f4e7e35f6c19e87617c23fbb59dfb1a63 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 05:39:13 +0200 Subject: mv643xx_eth: get rid of netif_{stop,wake}_queue() calls on link down/up There is no need to call netif_{stop,wake}_queue() when the link goes down/up, as the networking already takes care of this internally. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b4850cf2a8c..bd3ca470916 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -631,11 +631,9 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) for (i = 0; i < mp->txq_count; i++) txq_reclaim(mp->txq + i, 0); - if (netif_carrier_ok(mp->dev)) { - spin_lock_irq(&mp->lock); - __txq_maybe_wake(mp->txq); - spin_unlock_irq(&mp->lock); - } + spin_lock_irq(&mp->lock); + __txq_maybe_wake(mp->txq); + spin_unlock_irq(&mp->lock); } #endif @@ -1765,7 +1763,6 @@ static void handle_link_event(struct mv643xx_eth_private *mp) printk(KERN_INFO "%s: link down\n", dev->name); netif_carrier_off(dev); - netif_stop_queue(dev); for (i = 0; i < mp->txq_count; i++) { struct tx_queue *txq = mp->txq + i; @@ -1799,10 +1796,8 @@ static void handle_link_event(struct mv643xx_eth_private *mp) speed, duplex ? "full" : "half", fc ? "en" : "dis"); - if (!netif_carrier_ok(dev)) { + if (!netif_carrier_ok(dev)) netif_carrier_on(dev); - netif_wake_queue(dev); - } } static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) @@ -1851,11 +1846,9 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) * Enough space again in the primary TX queue for a * full packet? */ - if (netif_carrier_ok(dev)) { - spin_lock(&mp->lock); - __txq_maybe_wake(mp->txq); - spin_unlock(&mp->lock); - } + spin_lock(&mp->lock); + __txq_maybe_wake(mp->txq); + spin_unlock(&mp->lock); } /* @@ -2060,7 +2053,6 @@ static int mv643xx_eth_open(struct net_device *dev) } netif_carrier_off(dev); - netif_stop_queue(dev); port_start(mp); @@ -2123,7 +2115,6 @@ static int mv643xx_eth_stop(struct net_device *dev) del_timer_sync(&mp->rx_oom); netif_carrier_off(dev); - netif_stop_queue(dev); free_irq(dev->irq, dev); @@ -2184,11 +2175,9 @@ static void tx_timeout_task(struct work_struct *ugly) mp = container_of(ugly, struct mv643xx_eth_private, tx_timeout_task); if (netif_running(mp->dev)) { netif_stop_queue(mp->dev); - port_reset(mp); port_start(mp); - - __txq_maybe_wake(mp->txq); + netif_wake_queue(mp->dev); } } -- cgit v1.2.3 From befefe2177d4bca07a64a2410333388c063a6f7d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 06:10:04 +0200 Subject: mv643xx_eth: delete unused and uninteresting interrupt source mask bits Delete a couple of unused and uninteresting interrupt source mask bits: - The receive resource underrun interrupt sources are uninteresting because if we are in out-of-memory mode, we are already dealing with the issue, and we don't need the hardware to remind us again that we are out of memory. - The LINK and PHY interrupt sources can be coalesced into one define, since we always use them together. - The transmit resource underrun interrupt source can be disabled since we never activate the head descriptor of a paged skb until the fragments are all activated, so transmit underrun during a packet should never happen. - The INT_EXT_TX_0 define is never used. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index bd3ca470916..e592fac8706 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -105,14 +105,11 @@ static char mv643xx_eth_driver_version[] = "1.3"; #define INT_CAUSE(p) (0x0460 + ((p) << 10)) #define INT_TX_END_0 0x00080000 #define INT_TX_END 0x07f80000 -#define INT_RX 0x0007fbfc +#define INT_RX 0x000003fc #define INT_EXT 0x00000002 #define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10)) -#define INT_EXT_LINK 0x00100000 -#define INT_EXT_PHY 0x00010000 -#define INT_EXT_TX_ERROR_0 0x00000100 -#define INT_EXT_TX_0 0x00000001 -#define INT_EXT_TX 0x0000ffff +#define INT_EXT_LINK_PHY 0x00110000 +#define INT_EXT_TX 0x000000ff #define INT_MASK(p) (0x0468 + ((p) << 10)) #define INT_MASK_EXT(p) (0x046c + ((p) << 10)) #define TX_FIFO_URGENT_THRESHOLD(p) (0x0474 + ((p) << 10)) @@ -1815,11 +1812,11 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) int_cause_ext = 0; if (int_cause & INT_EXT) { int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num)) - & (INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX); + & (INT_EXT_LINK_PHY | INT_EXT_TX); wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); } - if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) + if (int_cause_ext & INT_EXT_LINK_PHY) handle_link_event(mp); /* @@ -2059,9 +2056,7 @@ static int mv643xx_eth_open(struct net_device *dev) set_rx_coal(mp, 0); set_tx_coal(mp, 0); - wrl(mp, INT_MASK_EXT(mp->port_num), - INT_EXT_LINK | INT_EXT_PHY | INT_EXT_TX); - + wrl(mp, INT_MASK_EXT(mp->port_num), INT_EXT_LINK_PHY | INT_EXT_TX); wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); return 0; -- cgit v1.2.3 From e5ef1de198c7bf2ca10de82add06536ed6165f8b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 06:26:23 +0200 Subject: mv643xx_eth: transmit multiqueue support As all the infrastructure for multiple transmit queues already exists in the driver, this patch is entirely trivial. The individual transmit queues are still serialised by the driver's per-port private spinlock, but that will disappear (i.e. be replaced by the per-subqueue ->_xmit_lock) in a subsequent patch. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e592fac8706..1ceed879861 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -449,15 +449,10 @@ static void txq_disable(struct tx_queue *txq) static void __txq_maybe_wake(struct tx_queue *txq) { struct mv643xx_eth_private *mp = txq_to_mp(txq); - - /* - * netif_{stop,wake}_queue() flow control only applies to - * the primary queue. - */ - BUG_ON(txq->index != 0); + struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) - netif_wake_queue(mp->dev); + netif_tx_wake_queue(nq); } @@ -827,8 +822,11 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; + int queue; struct tx_queue *txq; + struct netdev_queue *nq; unsigned long flags; + int entries_left; if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { stats->tx_dropped++; @@ -838,15 +836,16 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - spin_lock_irqsave(&mp->lock, flags); + queue = skb_get_queue_mapping(skb); + txq = mp->txq + queue; + nq = netdev_get_tx_queue(dev, queue); - txq = mp->txq; + spin_lock_irqsave(&mp->lock, flags); if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { spin_unlock_irqrestore(&mp->lock, flags); - if (txq->index == 0 && net_ratelimit()) - dev_printk(KERN_ERR, &dev->dev, - "primary tx queue full?!\n"); + if (net_ratelimit()) + dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n"); kfree_skb(skb); return NETDEV_TX_OK; } @@ -856,13 +855,9 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) stats->tx_packets++; dev->trans_start = jiffies; - if (txq->index == 0) { - int entries_left; - - entries_left = txq->tx_ring_size - txq->tx_desc_count; - if (entries_left < MAX_SKB_FRAGS + 1) - netif_stop_queue(dev); - } + entries_left = txq->tx_ring_size - txq->tx_desc_count; + if (entries_left < MAX_SKB_FRAGS + 1) + netif_tx_stop_queue(nq); spin_unlock_irqrestore(&mp->lock, flags); @@ -2169,10 +2164,10 @@ static void tx_timeout_task(struct work_struct *ugly) mp = container_of(ugly, struct mv643xx_eth_private, tx_timeout_task); if (netif_running(mp->dev)) { - netif_stop_queue(mp->dev); + netif_tx_stop_all_queues(mp->dev); port_reset(mp); port_start(mp); - netif_wake_queue(mp->dev); + netif_tx_wake_all_queues(mp->dev); } } @@ -2546,7 +2541,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) return -ENODEV; } - dev = alloc_etherdev(sizeof(struct mv643xx_eth_private)); + dev = alloc_etherdev_mq(sizeof(struct mv643xx_eth_private), 8); if (!dev) return -ENOMEM; @@ -2559,6 +2554,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->dev = dev; set_params(mp, pd); + dev->real_num_tx_queues = mp->txq_count; spin_lock_init(&mp->lock); -- cgit v1.2.3 From f171d4d769c8ccac6675892960e37f6485837fae Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 16:17:14 +0300 Subject: UBIFS: fix division by zero If fanout is 3, we have division by zero in 'ubifs_read_superblock()': divide error: 0000 [#1] PREEMPT SMP Pid: 28744, comm: mount Not tainted (2.6.27-rc4-ubifs-2.6 #23) EIP: 0060:[] EFLAGS: 00010202 CPU: 0 EIP is at ubifs_reported_space+0x2d/0x69 [ubifs] EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000000 ESI: 00000000 EDI: f0ae64b0 EBP: f1f9fcf4 ESP: f1f9fce0 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 101d278c591..73db464cd08 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -723,24 +723,25 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, */ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) { - int divisor, factor; + int divisor, factor, f; /* * Reported space size is @free * X, where X is UBIFS block size * divided by UBIFS block size + all overhead one data block * introduces. The overhead is the node header + indexing overhead. * - * Indexing overhead is calculations are based on the following - * formula: I = N/(f - 1) + 1, where I - number of indexing nodes, N - - * number of data nodes, f - fanout. Because effective UBIFS fanout is - * twice as less than maximum fanout, we assume that each data node + * Indexing overhead calculations are based on the following formula: + * I = N/(f - 1) + 1, where I - number of indexing nodes, N - number + * of data nodes, f - fanout. Because effective UBIFS fanout is twice + * as less than maximum fanout, we assume that each data node * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes. * Note, the multiplier 3 is because UBIFS reseves thrice as more space * for the index. */ + f = c->fanout > 3 ? c->fanout >> 1 : 2; factor = UBIFS_BLOCK_SIZE; divisor = UBIFS_MAX_DATA_NODE_SZ; - divisor += (c->max_idx_node_sz * 3) / ((c->fanout >> 1) - 1); + divisor += (c->max_idx_node_sz * 3) / (f - 1); free *= factor; do_div(free, divisor); return free; -- cgit v1.2.3 From a5cb562d6977d9d7989c346b7b153cef31ec0228 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 18:26:47 +0300 Subject: UBIFS: make minimum fanout 3 UBIFS does not really work correctly when fanout is 2, because of the way we manage the indexing tree. It may just become a list and UBIFS screws up. Signed-off-by: Artem Bityutskiy --- fs/ubifs/ubifs-media.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index bd2121f3426..a9ecbd9af20 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h @@ -87,7 +87,7 @@ #define UBIFS_SK_LEN 8 /* Minimum index tree fanout */ -#define UBIFS_MIN_FANOUT 2 +#define UBIFS_MIN_FANOUT 3 /* Maximum number of levels in UBIFS indexing B-tree */ #define UBIFS_MAX_LEVELS 512 -- cgit v1.2.3 From 4a911b1efe219fa3c8af697be0054c72e13bdae4 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Thu, 4 Sep 2008 23:05:45 +0200 Subject: [MIPS] IP22: Fix detection of second HPC3 on Challenge S The second HPC3 could be found only on Guiness systems (Challenge-S), but not on fullhouse (Indigo2) systems. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip22/ip22-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c index 60141235ec4..52486c4d2b0 100644 --- a/arch/mips/sgi-ip22/ip22-platform.c +++ b/arch/mips/sgi-ip22/ip22-platform.c @@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void) return res; /* Second HPC is missing? */ - if (!ip22_is_fullhouse() || + if (ip22_is_fullhouse() || get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1])) return 0; -- cgit v1.2.3 From 0253398ca1df7e1d2bfbb452175c964a0862482c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 8 Sep 2008 09:54:49 -0700 Subject: xen: fix 2.6.27-rc5 xen balloon driver warnings Set the class so it doesn't clash with the normal memory class. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar =================================================================== --- drivers/xen/balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d4427cb8697..2e15da5459c 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -60,7 +60,7 @@ #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) -#define BALLOON_CLASS_NAME "memory" +#define BALLOON_CLASS_NAME "xen_memory" struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ -- cgit v1.2.3 From 5c89468c12899b84886cb47eec93f0c88e0f896a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 8 Sep 2008 19:44:17 +0200 Subject: udf: add llseek method UDF currently doesn't set a llseek method for regular files, which means it will fall back to default_llseek. This means no one can seek beyond 2 Gigabytes on udf, and that there's not protection vs the i_size updates from writers. Signed-off-by: Christoph Hellwig Signed-off-by: Jan Kara --- fs/udf/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/udf/file.c b/fs/udf/file.c index 0ed6e146a0d..eb91f3b7032 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -211,6 +211,7 @@ const struct file_operations udf_file_operations = { .release = udf_release_file, .fsync = udf_fsync_file, .splice_read = generic_file_splice_read, + .llseek = generic_file_llseek, }; const struct inode_operations udf_file_inode_operations = { -- cgit v1.2.3 From 14469a8dd23677921db5e7354a602c98d9c6300f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Sep 2008 09:30:14 -0700 Subject: x86: disable static NOPLs on 32 bits On 32-bit, at least the generic nops are fairly reasonable, but the default nops for 64-bit really look pretty sad, and the P6 nops really do look better. So I would suggest perhaps moving the static P6 nop selection into the CONFIG_X86_64 thing. The alternative is to just get rid of that static nop selection, and just have two cases: 32-bit and 64-bit, and just pick obviously safe cases for them. Signed-off-by: H. Peter Anvin --- arch/x86/Kconfig.cpu | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2c518fbc52e..b225219c448 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -382,14 +382,17 @@ config X86_OOSTORE # P6_NOPs are a relatively minor optimization that require a family >= # 6 processor, except that it is broken on certain VIA chips. # Furthermore, AMD chips prefer a totally different sequence of NOPs -# (which work on all CPUs). As a result, disallow these if we're -# compiling X86_GENERIC but not X86_64 (these NOPs do work on all -# x86-64 capable chips); the list of processors in the right-hand clause -# are the cores that benefit from this optimization. +# (which work on all CPUs). In addition, it looks like Virtual PC +# does not understand them. +# +# As a result, disallow these if we're not compiling for X86_64 (these +# NOPs do work on all x86-64 capable chips); the list of processors in +# the right-hand clause are the cores that benefit from this optimization. # config X86_P6_NOP def_bool y - depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC) + depends on X86_64 + depends on (MCORE2 || MPENTIUM4 || MPSC) config X86_TSC def_bool y -- cgit v1.2.3 From 2eb2f77900d62796934bcd43c4089e444cf1179e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 Sep 2008 17:21:07 -0700 Subject: sparc64: Disable timer interrupts in fixup_irqs(). When a CPU is offlined, we leave the timer interrupts disabled because fixup_irqs() does not explicitly take care of that case. Fix this by invoking tick_ops->disable_irq(). Based upon analysis done by Paul E. McKenney. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 9b6689d9d57..23963882bc1 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -792,6 +792,8 @@ void fixup_irqs(void) } spin_unlock_irqrestore(&irq_desc[irq].lock, flags); } + + tick_ops->disable_irq(); } #endif -- cgit v1.2.3 From 3d6e48f43340343d97839eadb1ab7b6a3ea98797 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 9 Sep 2008 12:38:56 +0200 Subject: [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit mode When running a 31-bit ptrace, on either an s390 or s390x kernel, reads and writes into a padding area in struct user_regs_struct32 will result in a kernel panic. This is also known as CVE-2008-1514. Test case available here: http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/user-area-padding.c?cvsroot=systemtap Steps to reproduce: 1) wget the above 2) gcc -o user-area-padding-31bit user-area-padding.c -Wall -ggdb2 -D_GNU_SOURCE -m31 3) ./user-area-padding-31bit Test status ----------- Without patch, both s390 and s390x kernels panic. With patch, the test case, as well as the gdb testsuite, pass without incident, padding area reads returning zero, writes ignored. Nb: original version returned -EINVAL on write attempts, which broke the gdb test and made the test case slightly unhappy, Jan Kratochvil suggested the change to return 0 on write attempts. Signed-off-by: Jarod Wilson Tested-by: Jan Kratochvil Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_ptrace.h | 1 + arch/s390/kernel/ptrace.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h index cde81fa64f8..a2be3a978d5 100644 --- a/arch/s390/kernel/compat_ptrace.h +++ b/arch/s390/kernel/compat_ptrace.h @@ -42,6 +42,7 @@ struct user_regs_struct32 u32 gprs[NUM_GPRS]; u32 acrs[NUM_ACRS]; u32 orig_gpr2; + /* nb: there's a 4-byte hole here */ s390_fp_regs fp_regs; /* * These per registers are in here so that gdb can modify them diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 2815bfe348a..c8b08289eb8 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) */ tmp = (addr_t) task_pt_regs(child)->orig_gpr2; + } else if (addr < (addr_t) &dummy->regs.fp_regs) { + /* + * prevent reads of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + tmp = 0; + } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) */ task_pt_regs(child)->orig_gpr2 = data; + } else if (addr < (addr_t) &dummy->regs.fp_regs) { + /* + * prevent writes of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + return 0; + } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) */ tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4); + } else if (addr < (addr_t) &dummy32->regs.fp_regs) { + /* + * prevent reads of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + tmp = 0; + } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child, */ *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp; + } else if (addr < (addr_t) &dummy32->regs.fp_regs) { + /* + * prevent writess of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + return 0; + } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure -- cgit v1.2.3 From a2164b8174f13b7315c3f45c0b48dec619285096 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 9 Sep 2008 12:38:57 +0200 Subject: [S390] cio: Correct cleanup on error. Fix cleanup on error in chp_new() and init_channel_subsystem() (must not call kfree() on structures that had been registered). Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chp.c | 7 ++++--- drivers/s390/cio/css.c | 32 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index db00b059173..f1216cf6fa8 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid) ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); if (ret) { device_unregister(&chp->dev); - goto out_free; + goto out; } mutex_lock(&channel_subsystems[chpid.cssid]->mutex); if (channel_subsystems[chpid.cssid]->cm_enabled) { @@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid) sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); device_unregister(&chp->dev); mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); - goto out_free; + goto out; } } channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); - return ret; + goto out; out_free: kfree(chp); +out: return ret; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 51489eff6b0..1261e1a9e8c 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev) css = to_css(dev); mutex_destroy(&css->mutex); + if (css->pseudo_subchannel) { + /* Implies that it has been generated but never registered. */ + css_subchannel_release(&css->pseudo_subchannel->dev); + css->pseudo_subchannel = NULL; + } kfree(css); } @@ -785,11 +790,15 @@ init_channel_subsystem (void) } channel_subsystems[i] = css; ret = setup_css(i); - if (ret) - goto out_free; + if (ret) { + kfree(channel_subsystems[i]); + goto out_unregister; + } ret = device_register(&css->device); - if (ret) - goto out_free_all; + if (ret) { + put_device(&css->device); + goto out_unregister; + } if (css_chsc_characteristics.secm) { ret = device_create_file(&css->device, &dev_attr_cm_enable); @@ -802,7 +811,7 @@ init_channel_subsystem (void) } ret = register_reboot_notifier(&css_reboot_notifier); if (ret) - goto out_pseudo; + goto out_unregister; css_init_done = 1; /* Enable default isc for I/O subchannels. */ @@ -810,18 +819,12 @@ init_channel_subsystem (void) for_each_subchannel(__init_channel_subsystem, NULL); return 0; -out_pseudo: - device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev); out_file: - device_remove_file(&channel_subsystems[i]->device, - &dev_attr_cm_enable); + if (css_chsc_characteristics.secm) + device_remove_file(&channel_subsystems[i]->device, + &dev_attr_cm_enable); out_device: device_unregister(&channel_subsystems[i]->device); -out_free_all: - kfree(channel_subsystems[i]->pseudo_subchannel->lock); - kfree(channel_subsystems[i]->pseudo_subchannel); -out_free: - kfree(channel_subsystems[i]); out_unregister: while (i > 0) { struct channel_subsystem *css; @@ -829,6 +832,7 @@ out_unregister: i--; css = channel_subsystems[i]; device_unregister(&css->pseudo_subchannel->dev); + css->pseudo_subchannel = NULL; if (css_chsc_characteristics.secm) device_remove_file(&css->device, &dev_attr_cm_enable); -- cgit v1.2.3 From c91ebe496120e05301465fff31094bfecf798e9f Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 9 Sep 2008 12:38:58 +0200 Subject: [S390] cio: handle ssch() return codes correctly. ssch() has two classes of return codes: - condition codes (0-3) which need to be translated to Linux error codes - Linux error codes (-EIO on exceptions) which should be passed to the caller (instead of erronously being handled like condition code 3) Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 33bff8fec7d..5954b905e3c 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ case 1: /* status pending */ case 2: /* busy */ return -EBUSY; - default: /* device/path not operational */ + case 3: /* device/path not operational */ return cio_start_handle_notoper(sch, lpm); + default: + return ccode; } } -- cgit v1.2.3 From b301ea8c81b13123761772f344faf606c76ba174 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 9 Sep 2008 12:38:59 +0200 Subject: [S390] cio: allow offline processing for disconnected devices When disconnected ccw devices are removed, the device has to be set offline, otherwise there will be side effects including a reference count imbalance. This patch modifies ccw_device_offline to work for devices in disconnecte/not operational state. ccw_device_offline is called by cio for devices which are online during device removal. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 550508df952..84cc9ea346d 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev) { struct subchannel *sch; + /* Allow ccw_device_offline while disconnected. */ + if (cdev->private->state == DEV_STATE_DISCONNECTED || + cdev->private->state == DEV_STATE_NOT_OPER) { + cdev->private->flags.donotify = 0; + ccw_device_done(cdev, DEV_STATE_NOT_OPER); + return 0; + } if (ccw_device_is_orphan(cdev)) { ccw_device_done(cdev, DEV_STATE_OFFLINE); return 0; -- cgit v1.2.3 From cbda1ba898647aeb4ee770b803c922f595e97731 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 7 Sep 2008 16:35:26 +0100 Subject: PCI/iommu: blacklist DMAR on Intel G31/G33 chipsets Some BIOSes (the Intel DG33BU, for example) wrongly claim to have DMAR when they don't. Avoid the resulting crashes when it doesn't work as expected. Signed-off-by: David Woodhouse Acked-by: Ingo Molnar Signed-off-by: Jesse Barnes --- drivers/pci/intel-iommu.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 8d0e60ac849..c3edcdc08e7 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2348,11 +2348,34 @@ static void __init iommu_exit_mempool(void) } +static int blacklist_iommu(const struct dmi_system_id *id) +{ + printk(KERN_INFO "%s detected; disabling IOMMU\n", + id->ident); + dmar_disabled = 1; + return 0; +} + +static struct dmi_system_id __initdata intel_iommu_dmi_table[] = { + { /* Some DG33BU BIOS revisions advertised non-existent VT-d */ + .callback = blacklist_iommu, + .ident = "Intel DG33BU", + { DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "DG33BU"), + } + }, + { } +}; + + void __init detect_intel_iommu(void) { if (swiotlb || no_iommu || iommu_detected || dmar_disabled) return; if (early_dmar_detect()) { + dmi_check_system(intel_iommu_dmi_table); + if (dmar_disabled) + return; iommu_detected = 1; } } -- cgit v1.2.3 From 4ca8a7726fb0e8094fdb56f2ae2d69fcf9254eae Mon Sep 17 00:00:00 2001 From: Johann Felix Soden Date: Fri, 22 Aug 2008 20:46:59 +0200 Subject: PCI: Fix printk warnings in probe.c The cleaned up resource code in probe.c introduced some warnings: drivers/pci/probe.c: In function 'pci_read_bridge_bases': drivers/pci/probe.c:386: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'resource_size_t' drivers/pci/probe.c:386: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'resource_size_t' drivers/pci/probe.c:398: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'resource_size_t' drivers/pci/probe.c:398: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'resource_size_t' drivers/pci/probe.c:434: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'resource_size_t' drivers/pci/probe.c:434: warning: format '%llx' expects type 'long long unsigned int', but argument 5 has type 'resource_size_t' So fix them up. Signed-off-by: Johann Felix Soden Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cce2f4cb1fb..0ad936765b2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -383,7 +383,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->start = base; if (!res->end) res->end = limit + 0xfff; - printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), res->start, res->end); + printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", + pci_name(dev), (unsigned long long) res->start, + (unsigned long long) res->end); } res = child->resource[1]; @@ -395,7 +397,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; - printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), res->start, res->end); + printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), + (unsigned long long) res->start, (unsigned long long) res->end); } res = child->resource[2]; @@ -431,7 +434,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->start = base; res->end = limit + 0xfffff; - printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64)?"64":"32",res->start, res->end); + printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", + pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32", + (unsigned long long) res->start, (unsigned long long) res->end); } } -- cgit v1.2.3 From 53bc88701be91e7f631ad31418b32392aa952e9b Mon Sep 17 00:00:00 2001 From: Johann Felix Soden Date: Fri, 22 Aug 2008 20:25:10 +0200 Subject: PCI: Fix printk warnings in setup-bus.c Again, the cleaned up code introduced some resource warnings: drivers/pci/setup-bus.c: In function 'pci_bus_dump_res': drivers/pci/setup-bus.c:542: warning: format '%llx' expects type 'long long unsigned int', but argument 5 has type 'resource_size_t' drivers/pci/setup-bus.c:542: warning: format '%llx' expects type 'long long unsigned int', but argument 6 has type 'resource_size_t' Fix those up too. Signed-off-by: Johann Felix Soden Signed-off-by: Jesse Barnes --- drivers/pci/setup-bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 82634a2f1b1..c6ea4e97e8b 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -539,7 +539,11 @@ static void pci_bus_dump_res(struct pci_bus *bus) if (!res) continue; - printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", bus->number, i, (res->flags & IORESOURCE_IO)? "io port":"mmio", res->start, res->end); + printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", + bus->number, i, + (res->flags & IORESOURCE_IO) ? "io port" : "mmio", + (unsigned long long) res->start, + (unsigned long long) res->end); } } -- cgit v1.2.3 From 48902025af4da44dbbc0231061e542d6d40e712e Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Fri, 5 Sep 2008 14:05:03 -0700 Subject: PCI Hotplug: fakephp: fix deadlock... again Commit fe99740cac117f208707488c03f3789cf4904957 (construct one fakephp slot per PCI slot) introduced a regression, causing a deadlock when removing a PCI device. We also never actually removed the device from the PCI core. So we: - remove the device from the PCI core - do not directly call remove_slot() to prevent deadlock Yu Zhao reported and diagnosed this defect. Signed-off-by: Alex Chiang Acked-by: Yu Zhao Cc: Matthew Wilcox Cc: Kristen Carlson Accardi Signed-off-by: Andrew Morton Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/fakephp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 40337a06c18..146ca9cd156 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -320,15 +320,15 @@ static int disable_slot(struct hotplug_slot *slot) return -ENODEV; } + /* remove the device from the pci core */ + pci_remove_bus_device(dev); + /* queue work item to blow away this sysfs entry and other * parts. */ INIT_WORK(&dslot->remove_work, remove_slot_worker); queue_work(dummyphp_wq, &dslot->remove_work); - /* blow away this sysfs entry and other parts. */ - remove_slot(dslot); - pci_dev_put(dev); } return 0; -- cgit v1.2.3 From adaae7215e5130e5ce1ac3ee390e5a23101b09b2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Sep 2008 20:02:01 +0200 Subject: update Documentation/filesystems/Locking for 2.6.27 changes In the 2.6.27 circle ->fasync lost the BKL, and the last remaining ->open variant that takes the BKL is also gone. ->get_sb and ->kill_sb didn't have BKL forever, so updated the entries while we're at that. Signed-off-by: Christoph Hellwig Signed-off-by: Linus Torvalds --- Documentation/filesystems/Locking | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 680fb566b92..8362860e21a 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -144,8 +144,8 @@ prototypes: void (*kill_sb) (struct super_block *); locking rules: may block BKL -get_sb yes yes -kill_sb yes yes +get_sb yes no +kill_sb yes no ->get_sb() returns error or 0 with locked superblock attached to the vfsmount (exclusive on ->s_umount). @@ -409,12 +409,12 @@ ioctl: yes (see below) unlocked_ioctl: no (see below) compat_ioctl: no mmap: no -open: maybe (see below) +open: no flush: no release: no fsync: no (see below) aio_fsync: no -fasync: yes (see below) +fasync: no lock: yes readv: no writev: no @@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode semaphore. Note some filesystems (i.e. remote ones) provide no protection for i_size so you will need to use the BKL. -->open() locking is in-transit: big lock partially moved into the methods. -The only exception is ->open() in the instances of file_operations that never -end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices -(chrdev_open() takes lock before replacing ->f_op and calling the secondary -method. As soon as we fix the handling of module reference counters all -instances of ->open() will be called without the BKL. - Note: ext2_release() was *the* source of contention on fs-intensive loads and dropping BKL on ->release() helps to get rid of that (we still grab BKL for cases when we close a file that had been opened r/w, but that -- cgit v1.2.3 From 7ae115b4f50d3c5824f1a15e572b5de9d1b06d35 Mon Sep 17 00:00:00 2001 From: Chris Snook Date: Tue, 9 Sep 2008 03:26:57 -0400 Subject: MAINTAINERS: add Atheros maintainer for atlx Jie Yang at Atheros is getting more directly involved with upstream work on the atl* drivers. This patch changes the ATL1 entry to ATLX (atl2 support posted to netdev today) and adds him as a maintainer. Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b3e92fbe336..186be3ba506 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -750,11 +750,13 @@ P: Ville Syrjala M: syrjala@sci.fi S: Maintained -ATL1 ETHERNET DRIVER +ATLX ETHERNET DRIVERS P: Jay Cliburn M: jcliburn@gmail.com P: Chris Snook M: csnook@redhat.com +P: Jie Yang +M: jie.yang@atheros.com L: atl1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net -- cgit v1.2.3 From deac93df26b20cf8438339b5935b5f5643bc30c9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 3 Sep 2008 20:43:36 -0500 Subject: lib: Correct printk %pF to work on all architectures It was introduced by "vsprintf: add support for '%pS' and '%pF' pointer formats" in commit 0fe1ef24f7bd0020f29ffe287dfdb9ead33ca0b2. However, the current way its coded doesn't work on parisc64. For two reasons: 1) parisc isn't in the #ifdef and 2) parisc has a different format for function descriptors Make dereference_function_descriptor() more accommodating by allowing architecture overrides. I put the three overrides (for parisc64, ppc64 and ia64) in arch/kernel/module.c because that's where the kernel internal linker which knows how to deal with function descriptors sits. Signed-off-by: James Bottomley Acked-by: Benjamin Herrenschmidt Acked-by: Tony Luck Acked-by: Kyle McMartin Signed-off-by: Linus Torvalds --- arch/ia64/include/asm/sections.h | 3 +++ arch/ia64/kernel/module.c | 12 ++++++++++++ arch/parisc/kernel/module.c | 14 ++++++++++++++ arch/powerpc/include/asm/sections.h | 3 +++ arch/powerpc/kernel/module_64.c | 13 ++++++++++++- include/asm-generic/sections.h | 6 ++++++ include/asm-parisc/sections.h | 5 +++++ lib/vsprintf.c | 11 +---------- 8 files changed, 56 insertions(+), 11 deletions(-) diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h index 7286e4a9fe8..a7acad2bc2f 100644 --- a/arch/ia64/include/asm/sections.h +++ b/arch/ia64/include/asm/sections.h @@ -21,5 +21,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b extern char __start_unwind[], __end_unwind[]; extern char __start_ivt_text[], __end_ivt_text[]; +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); + #endif /* _ASM_IA64_SECTIONS_H */ diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 29aad349e0c..545626f66a4 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -31,9 +31,11 @@ #include #include #include +#include #include #include +#include #include #define ARCH_MODULE_DEBUG 0 @@ -941,3 +943,13 @@ module_arch_cleanup (struct module *mod) if (mod->arch.core_unw_table) unw_remove_unwind_table(mod->arch.core_unw_table); } + +void *dereference_function_descriptor(void *ptr) +{ + struct fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->ip, p)) + ptr = p; + return ptr; +} diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index fdacdd4341c..44138c3e6ea 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -47,7 +47,9 @@ #include #include #include +#include +#include #include #if 0 @@ -860,3 +862,15 @@ void module_arch_cleanup(struct module *mod) deregister_unwind_table(mod); module_bug_cleanup(mod); } + +#ifdef CONFIG_64BIT +void *dereference_function_descriptor(void *ptr) +{ + Elf64_Fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->addr, p)) + ptr = p; + return ptr; +} +#endif diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 916018e425c..7710e9e6660 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -16,6 +16,9 @@ static inline int in_kernel_text(unsigned long addr) return 0; } +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); + #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ee6a2982d56..ad79de272ff 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -21,8 +21,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -451,3 +452,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; } + +void *dereference_function_descriptor(void *ptr) +{ + struct ppc64_opd_entry *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->funcaddr, p)) + ptr = p; + return ptr; +} diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 8feeae1f236..79a7ff925bf 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -14,4 +14,10 @@ extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; +/* function descriptor handling (if any). Override + * in asm/sections.h */ +#ifndef dereference_function_descriptor +#define dereference_function_descriptor(p) (p) +#endif + #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h index fdd43ec42ec..9d13c3507ad 100644 --- a/include/asm-parisc/sections.h +++ b/include/asm-parisc/sections.h @@ -4,4 +4,9 @@ /* nothing to see, move along */ #include +#ifdef CONFIG_64BIT +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); +#endif + #endif diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d8d1d114224..c399bc1093c 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -27,6 +27,7 @@ #include /* for PAGE_SIZE */ #include +#include /* for dereference_function_descriptor() */ /* Works only for digits and letters, but small and fast */ #define TOLOWER(x) ((x) | 0x20) @@ -513,16 +514,6 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio return buf; } -static inline void *dereference_function_descriptor(void *ptr) -{ -#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) - void *p; - if (!probe_kernel_address(ptr, p)) - ptr = p; -#endif - return ptr; -} - static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) { unsigned long value = (unsigned long) ptr; -- cgit v1.2.3 From d6be118a97ce51ca84035270f91c2bccecbfac5f Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 9 Sep 2008 09:56:08 -0400 Subject: x86: fix memmap=exactmap boot argument When using kdump modifying the e820 map is yielding strange results. For example starting with BIOS-provided physical RAM map: BIOS-e820: 0000000000000100 - 0000000000093400 (usable) BIOS-e820: 0000000000093400 - 00000000000a0000 (reserved) BIOS-e820: 0000000000100000 - 000000003fee0000 (usable) BIOS-e820: 000000003fee0000 - 000000003fef3000 (ACPI data) BIOS-e820: 000000003fef3000 - 000000003ff80000 (ACPI NVS) BIOS-e820: 000000003ff80000 - 0000000040000000 (reserved) BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved) BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved) BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) BIOS-e820: 00000000ff000000 - 0000000100000000 (reserved) and booting with args memmap=exactmap memmap=640K@0K memmap=5228K@16384K memmap=125188K@22252K memmap=76K#1047424K memmap=564K#1047500K resulted in: user-defined physical RAM map: user: 0000000000000000 - 0000000000093400 (usable) user: 0000000000093400 - 00000000000a0000 (reserved) user: 0000000000100000 - 000000003fee0000 (usable) user: 000000003fee0000 - 000000003fef3000 (ACPI data) user: 000000003fef3000 - 000000003ff80000 (ACPI NVS) user: 000000003ff80000 - 0000000040000000 (reserved) user: 00000000e0000000 - 00000000f0000000 (reserved) user: 00000000fec00000 - 00000000fec10000 (reserved) user: 00000000fee00000 - 00000000fee01000 (reserved) user: 00000000ff000000 - 0000000100000000 (reserved) But should have resulted in: user-defined physical RAM map: user: 0000000000000000 - 00000000000a0000 (usable) user: 0000000001000000 - 000000000151b000 (usable) user: 00000000015bb000 - 0000000008ffc000 (usable) user: 000000003fee0000 - 000000003ff80000 (ACPI data) This is happening because of an improper usage of strcmp() in the e820 parsing code. The strcmp() always returns !0 and never resets the value for e820.nr_map and returns an incorrect user-defined map. This patch fixes the problem. Signed-off-by: Prarit Bhargava Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 9af89078f7b..66e48aa2dd1 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p) if (!p) return -EINVAL; - if (!strcmp(p, "exactmap")) { + if (!strncmp(p, "exactmap", 8)) { #ifdef CONFIG_CRASH_DUMP /* * If we are doing a crash dump, we still need to know -- cgit v1.2.3 From 61c22c34c6f80a8e89cff5ff717627c54cc14fd4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 9 Sep 2008 21:38:57 +0200 Subject: clockevents: remove WARN_ON which was used to gather information The issue of the endless reprogramming loop due to a too small min_delta_ns was fixed with the previous updates of the clock events code, but we had no information about the spread of this problem. I added a WARN_ON to get automated information via kerneloops.org and to get some direct reports, which allowed me to analyse the affected machines. The WARN_ON has served its purpose and would be annoying for a release kernel. Remove it and just keep the information about the increase of the min_delta_ns value. Signed-off-by: Thomas Gleixner --- kernel/time/tick-oneshot.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 2e35501e61d..2e8de678e76 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c @@ -43,19 +43,17 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, * and emit a warning. */ if (++i > 2) { - printk(KERN_WARNING "CE: __tick_program_event of %s is " - "stuck %llx %llx\n", dev->name ? dev->name : "?", - now.tv64, expires.tv64); - printk(KERN_WARNING - "CE: increasing min_delta_ns %ld to %ld nsec\n", - dev->min_delta_ns, dev->min_delta_ns << 1); - WARN_ON(1); - - /* Double the min. delta and try again */ + /* Increase the min. delta and try again */ if (!dev->min_delta_ns) dev->min_delta_ns = 5000; else - dev->min_delta_ns <<= 1; + dev->min_delta_ns += dev->min_delta_ns >> 1; + + printk(KERN_WARNING + "CE: %s increasing min_delta_ns to %lu nsec\n", + dev->name ? dev->name : "?", + dev->min_delta_ns << 1); + i = 0; } -- cgit v1.2.3 From e75b986af7881ed8d8ccb1ed154045ed17cfebd0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 9 Sep 2008 21:38:57 +0200 Subject: clockevents: remove WARN_ON which was used to gather information The issue of the endless reprogramming loop due to a too small min_delta_ns was fixed with the previous updates of the clock events code, but we had no information about the spread of this problem. I added a WARN_ON to get automated information via kerneloops.org and to get some direct reports, which allowed me to analyse the affected machines. The WARN_ON has served its purpose and would be annoying for a release kernel. Remove it and just keep the information about the increase of the min_delta_ns value. Signed-off-by: Thomas Gleixner --- kernel/time/tick-oneshot.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 2e35501e61d..2e8de678e76 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c @@ -43,19 +43,17 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, * and emit a warning. */ if (++i > 2) { - printk(KERN_WARNING "CE: __tick_program_event of %s is " - "stuck %llx %llx\n", dev->name ? dev->name : "?", - now.tv64, expires.tv64); - printk(KERN_WARNING - "CE: increasing min_delta_ns %ld to %ld nsec\n", - dev->min_delta_ns, dev->min_delta_ns << 1); - WARN_ON(1); - - /* Double the min. delta and try again */ + /* Increase the min. delta and try again */ if (!dev->min_delta_ns) dev->min_delta_ns = 5000; else - dev->min_delta_ns <<= 1; + dev->min_delta_ns += dev->min_delta_ns >> 1; + + printk(KERN_WARNING + "CE: %s increasing min_delta_ns to %lu nsec\n", + dev->name ? dev->name : "?", + dev->min_delta_ns << 1); + i = 0; } -- cgit v1.2.3 From adee14b2e1557d0a8559f29681732d05a89dfc35 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 9 Sep 2008 16:27:49 -0700 Subject: Linux 2.6.27-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f448e0082eb..4ff83ea36c1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Rotary Wombat # *DOCUMENTATION* -- cgit v1.2.3 From 0e116227a01580acf47437adba3afadf21b6bd5f Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 3 Sep 2008 01:57:14 +0800 Subject: ocfs2: Fix a bug in direct IO read. ocfs2 will become read-only if we try to read the bytes which pass the end of i_size. This can be easily reproduced by following steps: 1. mkfs a ocfs2 volume with bs=4k cs=4k and nosparse. 2. create a small file(say less than 100 bytes) and we will create the file which is allocated 1 cluster. 3. read 8196 bytes from the kernel using O_DIRECT which exceeds the limit. 4. The ocfs2 volume becomes read-only and dmesg shows: OCFS2: ERROR (device sda13): ocfs2_direct_IO_get_blocks: Inode 66010 has a hole at block 1 File system is now read-only due to the potential of on-disk corruption. Please run fsck.ocfs2 once the file system is unmounted. So suppress the ERROR message. Signed-off-by: Tao Ma Signed-off-by: Mark Fasheh --- fs/ocfs2/aops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 506c24fb507..a53da146627 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -594,7 +594,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, goto bail; } - if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)) && !p_blkno) { + if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)) && !p_blkno && create) { ocfs2_error(inode->i_sb, "Inode %llu has a hole at block %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, -- cgit v1.2.3 From f461a1d80c865e5ec4d24107adbab8b010b60e32 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 10 Sep 2008 13:57:43 +0200 Subject: arch/x86/kernel/kdebugfs.c: introduce missing kfree Error handling code following a kmalloc should free the allocated data. Note that at the point of the change, node has not yet been stored in d, so it is not affected by the existing cleanup code. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,l; position p1,p2; expression *ptr != NULL; @@ ( if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S ) <... when != x when != if (...) { <+...x...+> } x->f = E ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Ingo Molnar --- arch/x86/kernel/kdebugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index f2d43bc7551..ff7d3b0124f 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -139,6 +139,7 @@ static int __init create_setup_data_nodes(struct dentry *parent) if (PageHighMem(pg)) { data = ioremap_cache(pa_data, sizeof(*data)); if (!data) { + kfree(node); error = -ENXIO; goto err_dir; } -- cgit v1.2.3 From 4611a771fc8e5ad77d27f25268846abb425101a0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 9 Sep 2008 17:56:47 -0500 Subject: [IA64] fix compile failure with non modular builds Broke the non modular builds by moving an essential function into modules.c. Fix this by moving it out again and into asm/sections.h as an inline. To do this, the definitions of struct fdesc and struct got_val have been lifted out of modules.c and put in asm/elf.h where they belong. Signed-off-by: James Bottomley Signed-off-by: Tony Luck --- arch/ia64/include/asm/elf.h | 15 +++++++++++++++ arch/ia64/include/asm/sections.h | 13 ++++++++++++- arch/ia64/kernel/module.c | 21 --------------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h index 5e0c1a6bce8..2acb6b6543c 100644 --- a/arch/ia64/include/asm/elf.h +++ b/arch/ia64/include/asm/elf.h @@ -266,4 +266,19 @@ do { \ } \ } while (0) +/* + * format for entries in the Global Offset Table + */ +struct got_entry { + uint64_t val; +}; + +/* + * Layout of the Function Descriptor + */ +struct fdesc { + uint64_t ip; + uint64_t gp; +}; + #endif /* _ASM_IA64_ELF_H */ diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h index a7acad2bc2f..f6679989103 100644 --- a/arch/ia64/include/asm/sections.h +++ b/arch/ia64/include/asm/sections.h @@ -6,6 +6,8 @@ * David Mosberger-Tang */ +#include +#include #include extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[]; @@ -22,7 +24,16 @@ extern char __start_unwind[], __end_unwind[]; extern char __start_ivt_text[], __end_ivt_text[]; #undef dereference_function_descriptor -void *dereference_function_descriptor(void *); +static inline void *dereference_function_descriptor(void *ptr) +{ + struct fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->ip, p)) + ptr = p; + return ptr; +} + #endif /* _ASM_IA64_SECTIONS_H */ diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 545626f66a4..aaa7d901521 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -31,11 +31,9 @@ #include #include #include -#include #include #include -#include #include #define ARCH_MODULE_DEBUG 0 @@ -137,15 +135,6 @@ static const char *reloc_name[256] = { #undef N -struct got_entry { - uint64_t val; -}; - -struct fdesc { - uint64_t ip; - uint64_t gp; -}; - /* Opaque struct for insns, to protect against derefs. */ struct insn; @@ -943,13 +932,3 @@ module_arch_cleanup (struct module *mod) if (mod->arch.core_unw_table) unw_remove_unwind_table(mod->arch.core_unw_table); } - -void *dereference_function_descriptor(void *ptr) -{ - struct fdesc *desc = ptr; - void *p; - - if (!probe_kernel_address(&desc->ip, p)) - ptr = p; - return ptr; -} -- cgit v1.2.3 From 47633cf0d60bde5581d039ac1283ef4377a6e782 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 9 Sep 2008 10:34:44 -0500 Subject: [IA64] fix up bte.h bte.h expects a #define of L1_CACHE_MASK which is currently only in bte.c. This small patch gets bte.h to include cleanly and makes BTE_UNALIGNED_COPY not report errors. Signed-off-by: Robin Holt Signed-off-by: Tony Luck --- arch/ia64/include/asm/sn/bte.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/ia64/include/asm/sn/bte.h b/arch/ia64/include/asm/sn/bte.h index a0d214f4311..5efecf06c9a 100644 --- a/arch/ia64/include/asm/sn/bte.h +++ b/arch/ia64/include/asm/sn/bte.h @@ -223,10 +223,11 @@ extern void bte_error_handler(unsigned long); * until the transfer is complete. In order to get the asynch * version of bte_copy, you must perform this check yourself. */ -#define BTE_UNALIGNED_COPY(src, dest, len, mode) \ - (((len & L1_CACHE_MASK) || (src & L1_CACHE_MASK) || \ - (dest & L1_CACHE_MASK)) ? \ - bte_unaligned_copy(src, dest, len, mode) : \ +#define BTE_UNALIGNED_COPY(src, dest, len, mode) \ + (((len & (L1_CACHE_BYTES - 1)) || \ + (src & (L1_CACHE_BYTES - 1)) || \ + (dest & (L1_CACHE_BYTES - 1))) ? \ + bte_unaligned_copy(src, dest, len, mode) : \ bte_copy(src, dest, len, mode, NULL)) -- cgit v1.2.3 From 6bf6a1a49377c32a02939ec835553703994f3e41 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 10 Sep 2008 13:57:19 +0200 Subject: [IA64] arch/ia64/sn/pci/tioca_provider.c: introduce missing kfree Error handling code following a kmalloc should free the allocated data. Signed-off-by: Julia Lawall Signed-off-by: Tony Luck --- arch/ia64/sn/pci/tioca_provider.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 529462c0157..79165122501 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -420,8 +420,10 @@ tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) entry = find_next_zero_bit(map, mapsize, last_entry); } - if (entry > mapsize) + if (entry > mapsize) { + kfree(ca_dmamap); goto map_return; + } for (i = 0; i < entries; i++) set_bit(entry + i, map); -- cgit v1.2.3 From a5827f40afafc864f57a1c44915f0bfaf3d94f53 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 28 Aug 2008 01:05:26 +0300 Subject: PCI: fix pciehp_free_irq() This patch fixes an obvious bug (loop was never entered) caused by commit 820943b6fc4781621dee52ba026106758a727dd3 (pciehp: cleanup pcie_poll_cmd). Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Acked-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index ab31f5ba665..9d934ddee95 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -258,7 +258,7 @@ static int pcie_poll_cmd(struct controller *ctrl) return 1; } } - while (timeout > 1000) { + while (timeout > 0) { msleep(10); timeout -= 10; if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) { -- cgit v1.2.3 From e7b140365b86aaf94374214c6f4e6decbee2eb0a Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 31 Aug 2008 11:06:30 -0700 Subject: [IA64] prevent ia64 from invoking irq handlers on offline CPUs Make ia64 refrain from clearing a given to-be-offlined CPU's bit in the cpu_online_mask until it has processed pending irqs. This change prevents other CPUs from being blindsided by an apparently offline CPU nevertheless changing globally visible state. Also remove the existing redundant cpu_clear(cpu, cpu_online_map). Signed-off-by: Paul E. McKenney Signed-off-by: Tony Luck --- arch/ia64/kernel/smpboot.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index bcea81e432f..d8f05e504fb 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -741,16 +741,14 @@ int __cpu_disable(void) return -EBUSY; } - cpu_clear(cpu, cpu_online_map); - if (migrate_platform_irqs(cpu)) { cpu_set(cpu, cpu_online_map); return (-EBUSY); } remove_siblinginfo(cpu); - cpu_clear(cpu, cpu_online_map); fixup_irqs(); + cpu_clear(cpu, cpu_online_map); local_flush_tlb_all(); cpu_clear(cpu, cpu_callin_map); return 0; -- cgit v1.2.3 From 62ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2 Mon Sep 17 00:00:00 2001 From: Masoud Sharbiani Date: Wed, 10 Sep 2008 22:22:34 +0200 Subject: ide: Fix pointer arithmetic in hpt3xx driver code (3rd try) git commit 74811f355f4f69a187fa74892dcf2a684b84ce99 causes crash at module load (or boot) time on my machine with a hpt374 controller. The reason for this is that for initializing second controller which sets (hwif->dev == host->dev[1]) to true (1), adds 1 to a void ptr, which advances it by one byte instead of advancing it by sizeof(hpt_info) bytes. Because of this, all initialization functions get corrupted data in info variable which causes a crash at boot time. This patch fixes that and makes my machine boot again. The card itself is a HPT374 raid conroller: Here is the lspci -v output: 03:06.0 RAID bus controller: HighPoint Technologies, Inc. HPT374 (rev 07) Subsystem: HighPoint Technologies, Inc. Unknown device 0001 Flags: bus master, 66MHz, medium devsel, latency 120, IRQ 28 I/O ports at 8000 [size=8] I/O ports at 7800 [size=4] I/O ports at 7400 [size=8] I/O ports at 7000 [size=4] I/O ports at 6800 [size=256] Expansion ROM at fe8e0000 [disabled] [size=128K] Capabilities: [60] Power Management version 2 03:06.1 RAID bus controller: HighPoint Technologies, Inc. HPT374 (rev 07) Subsystem: HighPoint Technologies, Inc. Unknown device 0001 Flags: bus master, 66MHz, medium devsel, latency 120, IRQ 28 I/O ports at 9800 [size=8] I/O ports at 9400 [size=4] I/O ports at 9000 [size=8] I/O ports at 8800 [size=4] I/O ports at 8400 [size=256] Capabilities: [60] Power Management version 2 Signed-off-by: Masoud Sharbiani Cc: Sergei Shtylyov Cc: Andrew Morton [bart: use dev_get_drvdata() per Sergei's suggestion] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index eb107eef0db..c37ab174381 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -613,6 +613,14 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) return 0; } +static struct hpt_info *hpt3xx_get_info(struct device *dev) +{ + struct ide_host *host = dev_get_drvdata(dev); + struct hpt_info *info = (struct hpt_info *)host->host_priv; + + return dev == host->dev[1] ? info + 1 : info; +} + /* * The Marvell bridge chips used on the HighPoint SATA cards do not seem * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... @@ -621,9 +629,7 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) static u8 hpt3xx_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); u8 mask = hwif->ultra_mask; switch (info->chip_type) { @@ -662,9 +668,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) static u8 hpt3xx_mdma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); switch (info->chip_type) { case HPT372 : @@ -700,8 +704,7 @@ static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) { ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); struct hpt_timings *t = info->timings; u8 itr_addr = 0x40 + (drive->dn * 4); u32 old_itr = 0; @@ -744,8 +747,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); if (drive->quirk_list) { if (info->chip_type >= HPT370) { @@ -973,8 +975,7 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev) { unsigned long io_base = pci_resource_start(dev, 4); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(&dev->dev); const char *name = DRV_NAME; u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ u8 chip_type; @@ -1217,8 +1218,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev) static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); u8 chip_type = info->chip_type; u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; @@ -1262,8 +1262,7 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - struct ide_host *host = pci_get_drvdata(dev); - struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); int serialize = HPT_SERIALIZE_IO; u8 chip_type = info->chip_type; u8 new_mcr, old_mcr = 0; -- cgit v1.2.3 From 46dfa040f6c26f416a0979a7cd5a2d81f08121d5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 10 Sep 2008 22:22:34 +0200 Subject: add deprecated ide-scsi to feature-removal-schedule.txt Signed-off-by: FUJITA Tomonori Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/feature-removal-schedule.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index eb1a47b9742..83c88cae1ed 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -322,3 +322,11 @@ Why: Accounting can now be enabled/disabled without kernel recompilation. controlled by a kernel/module/sysfs/sysctl parameter. Who: Krzysztof Piotr Oledzki +--------------------------- + +What: ide-scsi (BLK_DEV_IDESCSI) +When: 2.6.29 +Why: The 2.6 kernel supports direct writing to ide CD drives, which + eliminates the need for ide-scsi. The new method is more + efficient in every way. +Who: FUJITA Tomonori -- cgit v1.2.3 From 36223a399f639b13b7a454349565934e6d3e2db0 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Wed, 10 Sep 2008 21:07:55 +0100 Subject: swiotlb: fix back-off path when memory allocation fails This fixes a SWIOTLB oops With SWIOTLB being enabled and straight-forward page allocation failure [1], the swiotlb_alloc_coherent fall-back path hits an issue [2], resulting in my webcam failing to work. At the time of oops, RDI is clearly a pointer to a structure which has arrived as NULL, leading to the typo in swiotlb_map_single's callsite arguments. Correctly passing the device structure [3] addresses the issue and gets my webcam working again (the allocation failure still occuring). --- [1] skype: page allocation failure. order:3, mode:0x1 Pid: 5895, comm: skype Not tainted 2.6.27-rc6-235c-debug #1 Call Trace: [] __alloc_pages_internal+0x4a0/0x5d0 [] alloc_pages_current+0xad/0x110 [] __get_free_pages+0x1d/0x60 [] swiotlb_alloc_coherent+0x49/0x180 [] dma_alloc_coherent+0x281/0x310 [] hcd_buffer_alloc+0x50/0x90 [] usb_buffer_alloc+0x2d/0x40 [] uvc_alloc_urb_buffers+0x53/0xf0 [uvcvideo] [] uvc_init_video+0x158/0x3e0 [uvcvideo] [] uvc_video_enable+0x37/0x80 [uvcvideo] [] uvc_v4l2_do_ioctl+0x723/0x1260 [uvcvideo] [] ? trace_hardirqs_off_caller+0x21/0xc0 [] ? trace_hardirqs_off_caller+0x21/0xc0 [] video_usercopy+0x19f/0x390 [videodev] [] ? uvc_v4l2_do_ioctl+0x0/0x1260 [uvcvideo] [] ? put_lock_stats+0xe/0x30 [] uvc_v4l2_ioctl+0x4d/0x80 [uvcvideo] [] native_ioctl+0x83/0x90 [compat_ioctl32] [] v4l_compat_ioctl32+0x2be/0x1da4 [compat_ioctl32] [] ? do_page_fault+0x3d1/0xae0 [] ? trace_hardirqs_on+0xd/0x10 [] ? trace_hardirqs_on_caller+0x149/0x1b0 [] ? trace_hardirqs_on+0xd/0x10 [] compat_sys_ioctl+0x8a/0x3c0 [] ? trace_hardirqs_off_thunk+0x3a/0x3c [] sysenter_dispatch+0x7/0x2c [] ? trace_hardirqs_on_thunk+0x3a/0x3f Mem-Info: Node 0 DMA per-cpu: CPU 0: hi: 0, btch: 1 usd: 0 CPU 1: hi: 0, btch: 1 usd: 0 Node 0 DMA32 per-cpu: CPU 0: hi: 186, btch: 31 usd: 3 CPU 1: hi: 186, btch: 31 usd: 0 Node 0 Normal per-cpu: CPU 0: hi: 186, btch: 31 usd: 23 CPU 1: hi: 186, btch: 31 usd: 179 Active:78545 inactive:48683 dirty:31 writeback:0 unstable:2 free:830202 slab:17516 mapped:17473 pagetables:3496 bounce:0 Node 0 DMA free:36kB min:28kB low:32kB high:40kB active:0kB inactive:0kB present:15156kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 3207 3956 3956 Node 0 DMA32 free:3197192kB min:6512kB low:8140kB high:9768kB active:0kB inactive:0kB present:3284896kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 0 748 748 Node 0 Normal free:123580kB min:1516kB low:1892kB high:2272kB active:314180kB inactive:194732kB present:766464kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 0 0 0 Node 0 DMA: 1*4kB 0*8kB 0*16kB 1*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 36kB Node 0 DMA32: 4*4kB 3*8kB 2*16kB 3*32kB 4*64kB 5*128kB 3*256kB 5*512kB 4*1024kB 5*2048kB 776*4096kB = 3197224kB Node 0 Normal: 14*4kB 14*8kB 8*16kB 6*32kB 1*64kB 3*128kB 3*256kB 2*512kB 4*1024kB 1*2048kB 28*4096kB = 123560kB 64847 total pagecache pages 0 pages in swap cache Swap cache stats: add 0, delete 0, find 0/0 Free swap = 502752kB Total swap = 502752kB 1048576 pages RAM 52120 pages reserved 71967 pages shared 143004 pages non-shared --- [2] BUG: unable to handle kernel NULL pointer dereference at 00000000000002c8 IP: [] map_single+0x1c/0x280 PGD 10e54e067 PUD 10e595067 PMD 0 Oops: 0000 [1] PREEMPT SMP DEBUG_PAGEALLOC CPU 0 Modules linked in: kvm_intel kvm microcode uvcvideo compat_ioctl32 videodev v4l1_compat shpchp pci_hotplug Pid: 5895, comm: skype Not tainted 2.6.27-rc6-235c-debug #1 RIP: 0010:[] [] map_single+0x1c/0x280 RSP: 0018:ffff88010e78d988 EFLAGS: 00210296 RAX: 0000780000000000 RBX: 0000000000000000 RCX: 0000000000000002 RDX: 0000000000005000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88010e78d9e8 R08: 0000000000000000 R09: 0000000000000001 R10: ffff88010e78d698 R11: 0000000000000001 R12: 0000000000000002 R13: 0000000000000000 R14: 0000000000005000 R15: ffff88012f1c9968 FS: 0000000000000000(0000) GS:ffffffff80a6cdc0(0063) knlGS:00000000f6355b90 CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 CR2: 00000000000002c8 CR3: 000000010e57d000 CR4: 00000000000026e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process skype (pid: 5895, threadinfo ffff88010e78c000, task ffff88012b9cc460) Stack: 0000000200000000 0000000000005000 0000000000000000 0000000000000000 00000000000017b8 0000000000000000 ffff88010e78d9c8 0000000000000000 0000000000000002 0000000000000000 0000000000005000 ffff88012f1c9968 Call Trace: [] swiotlb_map_single_attrs+0x60/0xf0 [] swiotlb_map_single+0xc/0x10 [] swiotlb_alloc_coherent+0xfe/0x180 [] dma_alloc_coherent+0x281/0x310 [] hcd_buffer_alloc+0x50/0x90 [] usb_buffer_alloc+0x2d/0x40 [] uvc_alloc_urb_buffers+0x53/0xf0 [uvcvideo] [] uvc_init_video+0x158/0x3e0 [uvcvideo] [] uvc_video_enable+0x37/0x80 [uvcvideo] [] uvc_v4l2_do_ioctl+0x723/0x1260 [uvcvideo] [] ? trace_hardirqs_off_caller+0x21/0xc0 [] ? trace_hardirqs_off_caller+0x21/0xc0 [] video_usercopy+0x19f/0x390 [videodev] [] ? uvc_v4l2_do_ioctl+0x0/0x1260 [uvcvideo] [] ? put_lock_stats+0xe/0x30 [] uvc_v4l2_ioctl+0x4d/0x80 [uvcvideo] [] native_ioctl+0x83/0x90 [compat_ioctl32] [] v4l_compat_ioctl32+0x2be/0x1da4 [compat_ioctl32] [] ? do_page_fault+0x3d1/0xae0 [] ? trace_hardirqs_on+0xd/0x10 [] ? trace_hardirqs_on_caller+0x149/0x1b0 [] ? trace_hardirqs_on+0xd/0x10 [] compat_sys_ioctl+0x8a/0x3c0 [] ? trace_hardirqs_off_thunk+0x3a/0x3c [] sysenter_dispatch+0x7/0x2c [] ? trace_hardirqs_on_thunk+0x3a/0x3f Code: 45 31 c0 48 89 e5 e8 a4 ff ff ff c9 c3 66 90 55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83 ec 38 48 89 75 b0 48 89 55 a8 89 4d a4 <48> 8b 87 c8 02 00 00 48 85 c0 0f 84 1c 02 00 00 48 8b 58 08 48 RIP [] map_single+0x1c/0x280 RSP CR2: 00000000000002c8 ---[ end trace 5d15baeeb7025a0e ]--- --- [3] ffffffff8046c830 : map_single(): /store/kernel/linux/lib/swiotlb.c:291 ffffffff8046c830: 55 push %rbp ffffffff8046c831: 48 89 e5 mov %rsp,%rbp ffffffff8046c834: 41 57 push %r15 ffffffff8046c836: 41 56 push %r14 ffffffff8046c838: 41 55 push %r13 ffffffff8046c83a: 41 54 push %r12 ffffffff8046c83c: 53 push %rbx ffffffff8046c83d: 48 83 ec 38 sub $0x38,%rsp ffffffff8046c841: 48 89 75 b0 mov %rsi,-0x50(%rbp) ffffffff8046c845: 48 89 55 a8 mov %rdx,-0x58(%rbp) ffffffff8046c849: 89 4d a4 mov %ecx,-0x5c(%rbp) dma_get_seg_boundary(): /store/kernel/linux/include/linux/dma-mapping.h:80 ffffffff8046c84c: 48 8b 87 c8 02 00 00 mov 0x2c8(%rdi),%rax <---- --- [4] Signed-off-by: Daniel J Blueman Signed-off-by: Linus Torvalds --- lib/swiotlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 977edbdbc1d..8826fdf0f18 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -491,7 +491,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, * the lowest available address range. */ dma_addr_t handle; - handle = swiotlb_map_single(NULL, NULL, size, DMA_FROM_DEVICE); + handle = swiotlb_map_single(hwdev, NULL, size, DMA_FROM_DEVICE); if (swiotlb_dma_mapping_error(hwdev, handle)) return NULL; -- cgit v1.2.3 From ebfb2c63405f2410897674f14e41c031c9302909 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 14:08:27 -0700 Subject: sparc64: Fix interrupt register calculations on Psycho and Sabre. Use the IMAP offset calculation for OBIO devices as documented in the programmer's manual. Which is "0x10000 + ((ino & 0x1f) << 3)" Signed-off-by: David S. Miller --- arch/sparc64/kernel/prom.c | 104 +++------------------------------------------ 1 file changed, 6 insertions(+), 98 deletions(-) diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 3c048ac4e63..7151513f156 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -156,55 +156,11 @@ static unsigned long psycho_pcislot_imap_offset(unsigned long ino) return PSYCHO_IMAP_B_SLOT0 + (slot * 8); } -#define PSYCHO_IMAP_SCSI 0x1000UL -#define PSYCHO_IMAP_ETH 0x1008UL -#define PSYCHO_IMAP_BPP 0x1010UL -#define PSYCHO_IMAP_AU_REC 0x1018UL -#define PSYCHO_IMAP_AU_PLAY 0x1020UL -#define PSYCHO_IMAP_PFAIL 0x1028UL -#define PSYCHO_IMAP_KMS 0x1030UL -#define PSYCHO_IMAP_FLPY 0x1038UL -#define PSYCHO_IMAP_SHW 0x1040UL -#define PSYCHO_IMAP_KBD 0x1048UL -#define PSYCHO_IMAP_MS 0x1050UL -#define PSYCHO_IMAP_SER 0x1058UL -#define PSYCHO_IMAP_TIM0 0x1060UL -#define PSYCHO_IMAP_TIM1 0x1068UL -#define PSYCHO_IMAP_UE 0x1070UL -#define PSYCHO_IMAP_CE 0x1078UL -#define PSYCHO_IMAP_A_ERR 0x1080UL -#define PSYCHO_IMAP_B_ERR 0x1088UL -#define PSYCHO_IMAP_PMGMT 0x1090UL -#define PSYCHO_IMAP_GFX 0x1098UL -#define PSYCHO_IMAP_EUPA 0x10a0UL - -static unsigned long __psycho_onboard_imap_off[] = { -/*0x20*/ PSYCHO_IMAP_SCSI, -/*0x21*/ PSYCHO_IMAP_ETH, -/*0x22*/ PSYCHO_IMAP_BPP, -/*0x23*/ PSYCHO_IMAP_AU_REC, -/*0x24*/ PSYCHO_IMAP_AU_PLAY, -/*0x25*/ PSYCHO_IMAP_PFAIL, -/*0x26*/ PSYCHO_IMAP_KMS, -/*0x27*/ PSYCHO_IMAP_FLPY, -/*0x28*/ PSYCHO_IMAP_SHW, -/*0x29*/ PSYCHO_IMAP_KBD, -/*0x2a*/ PSYCHO_IMAP_MS, -/*0x2b*/ PSYCHO_IMAP_SER, -/*0x2c*/ PSYCHO_IMAP_TIM0, -/*0x2d*/ PSYCHO_IMAP_TIM1, -/*0x2e*/ PSYCHO_IMAP_UE, -/*0x2f*/ PSYCHO_IMAP_CE, -/*0x30*/ PSYCHO_IMAP_A_ERR, -/*0x31*/ PSYCHO_IMAP_B_ERR, -/*0x32*/ PSYCHO_IMAP_PMGMT, -/*0x33*/ PSYCHO_IMAP_GFX, -/*0x34*/ PSYCHO_IMAP_EUPA, -}; +#define PSYCHO_OBIO_IMAP_BASE 0x1000UL + #define PSYCHO_ONBOARD_IRQ_BASE 0x20 -#define PSYCHO_ONBOARD_IRQ_LAST 0x34 #define psycho_onboard_imap_offset(__ino) \ - __psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE] + (PSYCHO_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3)) #define PSYCHO_ICLR_A_SLOT0 0x1400UL #define PSYCHO_ICLR_SCSI 0x1800UL @@ -228,10 +184,6 @@ static unsigned int psycho_irq_build(struct device_node *dp, imap_off = psycho_pcislot_imap_offset(ino); } else { /* Onboard device */ - if (ino > PSYCHO_ONBOARD_IRQ_LAST) { - prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino); - prom_halt(); - } imap_off = psycho_onboard_imap_offset(ino); } @@ -318,23 +270,6 @@ static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) #define SABRE_IMAP_A_SLOT0 0x0c00UL #define SABRE_IMAP_B_SLOT0 0x0c20UL -#define SABRE_IMAP_SCSI 0x1000UL -#define SABRE_IMAP_ETH 0x1008UL -#define SABRE_IMAP_BPP 0x1010UL -#define SABRE_IMAP_AU_REC 0x1018UL -#define SABRE_IMAP_AU_PLAY 0x1020UL -#define SABRE_IMAP_PFAIL 0x1028UL -#define SABRE_IMAP_KMS 0x1030UL -#define SABRE_IMAP_FLPY 0x1038UL -#define SABRE_IMAP_SHW 0x1040UL -#define SABRE_IMAP_KBD 0x1048UL -#define SABRE_IMAP_MS 0x1050UL -#define SABRE_IMAP_SER 0x1058UL -#define SABRE_IMAP_UE 0x1070UL -#define SABRE_IMAP_CE 0x1078UL -#define SABRE_IMAP_PCIERR 0x1080UL -#define SABRE_IMAP_GFX 0x1098UL -#define SABRE_IMAP_EUPA 0x10a0UL #define SABRE_ICLR_A_SLOT0 0x1400UL #define SABRE_ICLR_B_SLOT0 0x1480UL #define SABRE_ICLR_SCSI 0x1800UL @@ -364,33 +299,10 @@ static unsigned long sabre_pcislot_imap_offset(unsigned long ino) return SABRE_IMAP_B_SLOT0 + (slot * 8); } -static unsigned long __sabre_onboard_imap_off[] = { -/*0x20*/ SABRE_IMAP_SCSI, -/*0x21*/ SABRE_IMAP_ETH, -/*0x22*/ SABRE_IMAP_BPP, -/*0x23*/ SABRE_IMAP_AU_REC, -/*0x24*/ SABRE_IMAP_AU_PLAY, -/*0x25*/ SABRE_IMAP_PFAIL, -/*0x26*/ SABRE_IMAP_KMS, -/*0x27*/ SABRE_IMAP_FLPY, -/*0x28*/ SABRE_IMAP_SHW, -/*0x29*/ SABRE_IMAP_KBD, -/*0x2a*/ SABRE_IMAP_MS, -/*0x2b*/ SABRE_IMAP_SER, -/*0x2c*/ 0 /* reserved */, -/*0x2d*/ 0 /* reserved */, -/*0x2e*/ SABRE_IMAP_UE, -/*0x2f*/ SABRE_IMAP_CE, -/*0x30*/ SABRE_IMAP_PCIERR, -/*0x31*/ 0 /* reserved */, -/*0x32*/ 0 /* reserved */, -/*0x33*/ SABRE_IMAP_GFX, -/*0x34*/ SABRE_IMAP_EUPA, -}; -#define SABRE_ONBOARD_IRQ_BASE 0x20 -#define SABRE_ONBOARD_IRQ_LAST 0x30 +#define SABRE_OBIO_IMAP_BASE 0x1000UL +#define SABRE_ONBOARD_IRQ_BASE 0x20 #define sabre_onboard_imap_offset(__ino) \ - __sabre_onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE] + (SABRE_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3)) #define sabre_iclr_offset(ino) \ ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ @@ -453,10 +365,6 @@ static unsigned int sabre_irq_build(struct device_node *dp, imap_off = sabre_pcislot_imap_offset(ino); } else { /* onboard device */ - if (ino > SABRE_ONBOARD_IRQ_LAST) { - prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino); - prom_halt(); - } imap_off = sabre_onboard_imap_offset(ino); } -- cgit v1.2.3 From 5368f69c8b155d6e82dfc622d817c882689e9cd9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 10 Sep 2008 22:15:18 +0200 Subject: VIDEO_SH_MOBILE_CEU should depend on HAS_DMA commit 0d3244d6439c8c31d2a29efd587c7aca9042c8aa ("V4L/DVB (8342): sh_mobile_ceu_camera: Add SuperH Mobile CEU driver V3") introduced VIDEO_SH_MOBILE_CEU, which selects VIDEOBUF_DMA_CONTIG. This circumvents the dependency on HAS_DMA of VIDEOBUF_DMA_CONTIG. Add a dependency on HAS_DMA to VIDEO_SH_MOBILE_CEU to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Paul Mundt Acked-by: Magnus Damm Signed-off-by: Linus Torvalds --- drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ecbfa1b39b7..3e9e0dcd217 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -968,7 +968,7 @@ config VIDEO_PXA27x config VIDEO_SH_MOBILE_CEU tristate "SuperH Mobile CEU Interface driver" - depends on VIDEO_DEV + depends on VIDEO_DEV && HAS_DMA select SOC_CAMERA select VIDEOBUF_DMA_CONTIG ---help--- -- cgit v1.2.3 From 9e7222c83560186686319f2892f43fc557baed2d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 10 Sep 2008 22:15:19 +0200 Subject: m68k: Update defconfigs for 2.6.27-rc6 Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Torvalds --- arch/m68k/configs/amiga_defconfig | 53 ++++++++++++++++++------------ arch/m68k/configs/apollo_defconfig | 53 ++++++++++++++++++------------ arch/m68k/configs/atari_defconfig | 60 +++++++++++++++++++--------------- arch/m68k/configs/bvme6000_defconfig | 52 ++++++++++++++++++------------ arch/m68k/configs/hp300_defconfig | 52 ++++++++++++++++++------------ arch/m68k/configs/mac_defconfig | 53 ++++++++++++++++++------------ arch/m68k/configs/multi_defconfig | 62 +++++++++++++++++++++--------------- arch/m68k/configs/mvme147_defconfig | 52 ++++++++++++++++++------------ arch/m68k/configs/mvme16x_defconfig | 52 ++++++++++++++++++------------ arch/m68k/configs/q40_defconfig | 53 ++++++++++++++++++------------ arch/m68k/configs/sun3_defconfig | 54 ++++++++++++++++++------------- arch/m68k/configs/sun3x_defconfig | 52 ++++++++++++++++++------------ 12 files changed, 390 insertions(+), 258 deletions(-) diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 8e2a0f5faf5..8bd61a640fc 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:00 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -166,10 +172,6 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_ZORRO_NAMES=y - -# -# Networking -# CONFIG_NET=y # @@ -183,6 +185,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -413,6 +416,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -432,7 +436,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -460,6 +466,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -470,6 +477,7 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set @@ -489,8 +497,6 @@ CONFIG_BLK_DEV_GAYLE=y CONFIG_BLK_DEV_IDEDOUBLER=y CONFIG_BLK_DEV_BUDDHA=y # CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -556,6 +562,7 @@ CONFIG_A2091_SCSI=y CONFIG_GVP11_SCSI=y CONFIG_SCSI_A4000T=y CONFIG_SCSI_ZORRO7XX=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -564,7 +571,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -573,13 +580,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -722,6 +725,7 @@ CONFIG_INPUT_M68K_BEEP=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -757,6 +761,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -768,8 +773,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -844,10 +851,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# CONFIG_SOUND=m CONFIG_DMASOUND_PAULA=m CONFIG_DMASOUND=m @@ -861,6 +864,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set @@ -899,6 +903,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -958,6 +963,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -980,7 +986,6 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -989,7 +994,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -1054,6 +1058,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1113,6 +1119,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1154,6 +1164,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index e2d511e2a1d..c41b854c028 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:01 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -161,10 +167,6 @@ CONFIG_HEARTBEAT=y CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -178,6 +180,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -411,6 +414,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -430,7 +434,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -448,6 +454,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -499,6 +506,7 @@ CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -507,7 +515,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -516,13 +524,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -532,7 +536,6 @@ CONFIG_VETH=m # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y # CONFIG_MII is not set -CONFIG_APOLLO_ELPLUS=y # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set @@ -627,6 +630,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -657,6 +661,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -668,8 +673,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -738,10 +745,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -753,6 +756,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -789,6 +793,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -848,6 +853,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -860,18 +866,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -880,7 +885,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -944,6 +948,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1003,6 +1009,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1044,6 +1054,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 6e20d656ada..654c5acb9e8 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:02 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -162,10 +168,6 @@ CONFIG_HEARTBEAT=y CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -179,6 +181,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -409,6 +412,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -428,7 +432,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -452,6 +458,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -462,6 +469,7 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set @@ -479,8 +487,6 @@ CONFIG_IDE_PROC_FS=y # CONFIG_BLK_DEV_PLATFORM is not set CONFIG_BLK_DEV_FALCON_IDE=y # CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -530,6 +536,7 @@ CONFIG_ISCSI_TCP=m CONFIG_ATARI_SCSI=y # CONFIG_ATARI_SCSI_TOSHIBA_DELAY is not set # CONFIG_ATARI_SCSI_RESET_BOOT is not set +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -538,7 +545,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -547,13 +554,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -666,6 +669,7 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -700,6 +704,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -711,8 +716,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -782,10 +789,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# CONFIG_SOUND=m CONFIG_DMASOUND_ATARI=m CONFIG_DMASOUND=m @@ -799,6 +802,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set @@ -806,11 +810,8 @@ CONFIG_HIDRAW=y # Character devices # CONFIG_ATARI_MFPSER=m -CONFIG_ATARI_SCC=y -CONFIG_ATARI_SCC_DMA=y CONFIG_ATARI_MIDI=m CONFIG_ATARI_DSP56K=m -# CONFIG_SERIAL_CONSOLE is not set # # File systems @@ -820,8 +821,10 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +CONFIG_EXT4DEV_FS=y +# CONFIG_EXT4DEV_FS_XATTR is not set CONFIG_JBD=y +CONFIG_JBD2=y CONFIG_REISERFS_FS=m # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set @@ -840,6 +843,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -899,6 +903,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -920,7 +925,6 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m -CONFIG_SUNRPC_BIND34=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -929,7 +933,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -994,6 +997,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1053,6 +1058,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1094,6 +1103,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index a0a9b30bb50..2e44af0fe54 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:03 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -163,10 +169,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -180,6 +182,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -413,6 +416,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -432,7 +436,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -450,6 +456,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -503,6 +510,7 @@ CONFIG_ISCSI_TCP=m CONFIG_53C700_BE_BUS=y # CONFIG_SCSI_DEBUG is not set CONFIG_BVME6000_SCSI=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -511,7 +519,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -520,13 +528,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -631,6 +635,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -661,6 +666,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -672,8 +678,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -708,10 +716,6 @@ CONFIG_SSB_POSSIBLE=y # Console display driver support # CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -723,6 +727,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -759,6 +764,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -818,6 +824,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -830,18 +837,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -850,7 +856,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -915,6 +920,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -974,6 +981,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1015,6 +1026,7 @@ CONFIG_BITREVERSE=m # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=m # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 6778041de26..3570fc89b08 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:04 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -162,10 +168,6 @@ CONFIG_HEARTBEAT=y CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -179,6 +181,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -412,6 +415,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -431,7 +435,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -449,6 +455,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -500,6 +507,7 @@ CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -508,7 +516,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -517,13 +525,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -636,6 +640,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -666,6 +671,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -677,8 +683,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -747,10 +755,6 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -762,6 +766,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -796,6 +801,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -855,6 +861,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -867,18 +874,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -887,7 +893,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -951,6 +956,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1010,6 +1017,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1051,6 +1062,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 7cd37574034..db6e8822594 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:06 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -163,10 +169,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -180,6 +182,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -413,6 +416,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -432,7 +436,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -450,6 +456,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -460,6 +467,7 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set @@ -477,8 +485,6 @@ CONFIG_IDE_PROC_FS=y # CONFIG_BLK_DEV_PLATFORM is not set CONFIG_BLK_DEV_MAC_IDE=y # CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -527,6 +533,7 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set CONFIG_MAC_SCSI=y CONFIG_SCSI_MAC_ESP=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -535,7 +542,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -544,9 +551,6 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_MACINTOSH_DRIVERS=y @@ -559,7 +563,6 @@ CONFIG_ADB_CUDA=y CONFIG_INPUT_ADBHID=y CONFIG_MAC_EMUMOUSEBTN=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -670,6 +673,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -700,6 +704,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -711,8 +716,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -784,10 +791,6 @@ CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y CONFIG_LOGO_MAC_CLUT224=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -799,6 +802,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -836,6 +840,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -895,6 +900,7 @@ CONFIG_HFSPLUS_FS=y CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -917,7 +923,6 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -926,7 +931,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -991,6 +995,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1050,6 +1056,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1091,6 +1101,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 0747fa3984d..1a806102b99 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:07 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -173,10 +179,6 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_ZORRO_NAMES=y - -# -# Networking -# CONFIG_NET=y # @@ -190,6 +192,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -427,6 +430,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -446,7 +450,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -476,6 +482,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -486,6 +493,7 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set @@ -508,8 +516,6 @@ CONFIG_BLK_DEV_FALCON_IDE=y CONFIG_BLK_DEV_MAC_IDE=y CONFIG_BLK_DEV_Q40IDE=y # CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -584,6 +590,7 @@ CONFIG_MVME147_SCSI=y CONFIG_MVME16x_SCSI=y CONFIG_BVME6000_SCSI=y CONFIG_SUN3X_ESP=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -592,7 +599,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -601,9 +608,6 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_MACINTOSH_DRIVERS=y @@ -616,7 +620,6 @@ CONFIG_ADB_CUDA=y CONFIG_INPUT_ADBHID=y CONFIG_MAC_EMUMOUSEBTN=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -632,7 +635,6 @@ CONFIG_A2065=m CONFIG_HYDRA=m CONFIG_ZORRO8390=m CONFIG_APNE=m -CONFIG_APOLLO_ELPLUS=y CONFIG_MAC8390=y CONFIG_MAC89x0=m CONFIG_MACSONIC=m @@ -791,6 +793,7 @@ CONFIG_SERIO_LIBPS2=y # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -827,6 +830,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -838,8 +842,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -923,10 +929,6 @@ CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y CONFIG_LOGO_MAC_CLUT224=y - -# -# Sound -# CONFIG_SOUND=m CONFIG_DMASOUND_ATARI=m CONFIG_DMASOUND_PAULA=m @@ -942,6 +944,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set @@ -949,8 +952,6 @@ CONFIG_HIDRAW=y # Character devices # CONFIG_ATARI_MFPSER=m -CONFIG_ATARI_SCC=y -CONFIG_ATARI_SCC_DMA=y CONFIG_ATARI_MIDI=m CONFIG_ATARI_DSP56K=m CONFIG_AMIGA_BUILTIN_SERIAL=y @@ -972,8 +973,10 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +CONFIG_EXT4DEV_FS=y +# CONFIG_EXT4DEV_FS_XATTR is not set CONFIG_JBD=y +CONFIG_JBD2=y CONFIG_REISERFS_FS=m # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set @@ -992,6 +995,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -1051,6 +1055,7 @@ CONFIG_HFSPLUS_FS=y CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -1063,18 +1068,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -1083,7 +1087,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -1152,6 +1155,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1211,6 +1216,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1252,6 +1261,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index e7a8246840b..cacb5aef6a3 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:08 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -163,10 +169,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -180,6 +182,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -413,6 +416,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -432,7 +436,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -450,6 +456,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -502,6 +509,7 @@ CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set CONFIG_MVME147_SCSI=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -510,7 +518,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -519,13 +527,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -630,6 +634,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -660,6 +665,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -671,8 +677,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -707,10 +715,6 @@ CONFIG_SSB_POSSIBLE=y # Console display driver support # CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -722,6 +726,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -758,6 +763,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -817,6 +823,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -829,18 +836,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -849,7 +855,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -914,6 +919,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -973,6 +980,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1014,6 +1025,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index ab536eb172b..a183e25e348 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:09 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -163,10 +169,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -180,6 +182,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -413,6 +416,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -432,7 +436,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -450,6 +456,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -503,6 +510,7 @@ CONFIG_ISCSI_TCP=m CONFIG_53C700_BE_BUS=y # CONFIG_SCSI_DEBUG is not set CONFIG_MVME16x_SCSI=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -511,7 +519,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -520,13 +528,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -631,6 +635,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -661,6 +666,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -672,8 +678,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -708,10 +716,6 @@ CONFIG_SSB_POSSIBLE=y # Console display driver support # CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -723,6 +727,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -760,6 +765,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -819,6 +825,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -831,18 +838,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -851,7 +857,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -916,6 +921,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -975,6 +982,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1016,6 +1027,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index e05be687b50..72eaff0776b 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:10 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -163,10 +169,6 @@ CONFIG_ISA=y CONFIG_GENERIC_ISA_DMA=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -180,6 +182,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -410,6 +413,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -429,7 +433,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -448,6 +454,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -458,6 +465,7 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives # +CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set @@ -475,8 +483,6 @@ CONFIG_IDE_PROC_FS=y # CONFIG_BLK_DEV_PLATFORM is not set CONFIG_BLK_DEV_Q40IDE=y # CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -536,6 +542,7 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -544,7 +551,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -553,13 +560,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -680,6 +683,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -711,6 +715,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -722,8 +727,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -792,10 +799,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# CONFIG_SOUND=m CONFIG_DMASOUND_Q40=m CONFIG_DMASOUND=m @@ -809,6 +812,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -843,6 +847,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -902,6 +907,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -924,7 +930,6 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -933,7 +938,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -997,6 +1001,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1056,6 +1062,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1097,6 +1107,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 296340d2b31..cb62b96d766 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:11 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -149,10 +155,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -166,6 +168,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -399,6 +402,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -418,7 +422,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -436,6 +442,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -488,6 +495,7 @@ CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set CONFIG_SUN3_SCSI=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -496,7 +504,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -505,13 +513,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -527,7 +531,6 @@ CONFIG_SUN3_82586=y # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_B44 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -617,6 +620,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -647,19 +651,20 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -727,10 +732,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -776,6 +777,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -835,6 +837,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -847,18 +850,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -867,7 +869,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -932,6 +933,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -991,6 +994,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1032,6 +1039,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 8d3a416c92b..04b4363a705 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Wed May 28 22:47:35 2008 +# Linux kernel version: 2.6.27-rc6 +# Wed Sep 10 09:02:12 2008 # CONFIG_M68K=y CONFIG_MMU=y @@ -52,7 +52,6 @@ CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y @@ -75,10 +74,16 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set # CONFIG_MARKERS is not set # CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -95,6 +100,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -160,10 +166,6 @@ CONFIG_BINFMT_MISC=m CONFIG_PROC_HARDWARE=y CONFIG_ZONE_DMA=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# Networking -# CONFIG_NET=y # @@ -177,6 +179,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y # CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y @@ -410,6 +413,7 @@ CONFIG_NET_CLS_ROUTE=y # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set # CONFIG_MAC80211 is not set CONFIG_IEEE80211=m # CONFIG_IEEE80211_DEBUG is not set @@ -429,7 +433,9 @@ CONFIG_IEEE80211_CRYPT_TKIP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set CONFIG_CONNECTOR=m # CONFIG_MTD is not set @@ -447,6 +453,7 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -499,6 +506,7 @@ CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_DEBUG is not set CONFIG_SUN3X_ESP=y +# CONFIG_SCSI_DH is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -507,7 +515,7 @@ CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set CONFIG_MD_RAID456=m CONFIG_MD_RAID5_RESHAPE=y -CONFIG_MD_MULTIPATH=m +# CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m # CONFIG_DM_DEBUG is not set @@ -516,13 +524,9 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_EMC=m -CONFIG_DM_MULTIPATH_RDAC=m -CONFIG_DM_MULTIPATH_HP=m # CONFIG_DM_DELAY is not set CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set CONFIG_MACVLAN=m @@ -627,6 +631,7 @@ CONFIG_SERIO_LIBPS2=m # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y @@ -657,6 +662,7 @@ CONFIG_GEN_RTC_X=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -668,8 +674,10 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -737,10 +745,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=m @@ -752,6 +756,7 @@ CONFIG_HIDRAW=y # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -786,6 +791,7 @@ CONFIG_XFS_FS=m CONFIG_OCFS2_FS=m CONFIG_OCFS2_FS_O2CB=m CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +# CONFIG_OCFS2_FS_STATS is not set # CONFIG_OCFS2_DEBUG_MASKLOG is not set # CONFIG_OCFS2_DEBUG_FS is not set CONFIG_DNOTIFY=y @@ -845,6 +851,7 @@ CONFIG_HFSPLUS_FS=m CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set CONFIG_HPFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -857,18 +864,17 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set -CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BIND34=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -877,7 +883,6 @@ CONFIG_SMB_NLS_REMOTE="cp437" # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -942,6 +947,8 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # @@ -1001,6 +1008,10 @@ CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m @@ -1042,6 +1053,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_NEXT_BIT is not set CONFIG_CRC_CCITT=m CONFIG_CRC16=m +CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set -- cgit v1.2.3 From bdba4d6b77fcc76f206986d7cc55f1feb20301f8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 23:38:51 -0700 Subject: sparc32: Fix function signature of of_bus_sbus_get_flags(). This doesn't match the function pointer type it gets assigned to. Luckily, this was harmless. Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index c481d45f97b..f58c537446a 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -241,7 +241,7 @@ static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) return of_bus_default_map(addr, range, na, ns, pna); } -static unsigned int of_bus_sbus_get_flags(const u32 *addr) +static unsigned long of_bus_sbus_get_flags(const u32 *addr, unsigned long flags) { return IORESOURCE_MEM; } -- cgit v1.2.3 From baf25731e54d06eb13dc4eda78c6dc7da4ce84e8 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Tue, 9 Sep 2008 11:26:33 +0800 Subject: sched: fix 2.6.27-rc5 couldn't boot on tulsa machine randomly On my tulsa x86-64 machine, kernel 2.6.25-rc5 couldn't boot randomly. Basically, function __enable_runtime forgets to reset rt_rq->rt_throttled to 0. When every cpu is up, per-cpu migration_thread is created and it runs very fast, sometimes to mark the corresponding rt_rq->rt_throttled to 1 very quickly. After all cpus are up, with below calling chain: sched_init_smp => arch_init_sched_domains => build_sched_domains => ... => cpu_attach_domain => rq_attach_root => set_rq_online => ... => _enable_runtime _enable_runtime is called against every rt_rq again, so rt_rq->rt_time is reset to 0, but rt_rq->rt_throttled might be still 1. Later on function do_sched_rt_period_timer couldn't reset it, and all RT tasks couldn't be scheduled to run on that cpu. here is RT task migration_thread which is woken up when a task is migrated to another cpu. Below patch fixes it against 2.6.27-rc5. Signed-off-by: Zhang Yanmin Signed-off-by: Ingo Molnar --- kernel/sched_rt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 552310798da..1113157b205 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -350,6 +350,7 @@ static void __enable_runtime(struct rq *rq) spin_lock(&rt_rq->rt_runtime_lock); rt_rq->rt_runtime = rt_b->rt_runtime; rt_rq->rt_time = 0; + rt_rq->rt_throttled = 0; spin_unlock(&rt_rq->rt_runtime_lock); spin_unlock(&rt_b->rt_runtime_lock); } -- cgit v1.2.3 From ec5d498991e87c74730509508b25c3959192b7e7 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 10 Sep 2008 17:00:19 -0700 Subject: sched: fix deadlock in setting scheduler parameter to zero Andrei Gusev wrote: > I played witch scheduler settings. After doing something like: > echo -n 1000000 >sched_rt_period_us > > command is locked. I found in kernel.log: > > Sep 11 00:39:34 zaratustra > Sep 11 00:39:34 zaratustra Pid: 4495, comm: bash Tainted: G W > (2.6.26.3 #12) > Sep 11 00:39:34 zaratustra EIP: 0060:[] EFLAGS: 00210246 CPU: 0 > Sep 11 00:39:34 zaratustra EIP is at div64_u64+0x57/0x80 > Sep 11 00:39:34 zaratustra EAX: 0000389f EBX: 00000000 ECX: 00000000 > EDX: 00000000 > Sep 11 00:39:34 zaratustra ESI: d9800000 EDI: d9800000 EBP: 0000389f > ESP: ea7a6edc > Sep 11 00:39:34 zaratustra DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 > Sep 11 00:39:34 zaratustra Process bash (pid: 4495, ti=ea7a6000 > task=ea744000 task.ti=ea7a6000) > Sep 11 00:39:34 zaratustra Stack: 00000000 000003e8 d9800000 0000389f > c0119042 00000000 00000000 00000001 > Sep 11 00:39:34 zaratustra 00000000 00000000 ea7a6f54 00010000 00000000 > c04d2e80 00000001 000e7ef0 > Sep 11 00:39:34 zaratustra c01191a3 00000000 00000000 ea7a6fa0 00000001 > ffffffff c04d2e80 ea5b2480 > Sep 11 00:39:34 zaratustra Call Trace: > Sep 11 00:39:34 zaratustra [] __rt_schedulable+0x52/0x130 > Sep 11 00:39:34 zaratustra [] sched_rt_handler+0x83/0x120 > Sep 11 00:39:34 zaratustra [] proc_sys_call_handler+0xb6/0xd0 > Sep 11 00:39:34 zaratustra [] proc_sys_write+0x0/0x20 > Sep 11 00:39:34 zaratustra [] proc_sys_write+0x19/0x20 > Sep 11 00:39:34 zaratustra [] vfs_write+0xa8/0x140 > Sep 11 00:39:34 zaratustra [] sys_write+0x41/0x80 > Sep 11 00:39:34 zaratustra [] sysenter_past_esp+0x6a/0x91 > Sep 11 00:39:34 zaratustra ======================= > Sep 11 00:39:34 zaratustra Code: c8 41 0f ad f3 d3 ee f6 c1 20 0f 45 de > 31 f6 0f ad ef d3 ed f6 c1 20 0f 45 fd 0f 45 ee 31 c9 39 eb 89 fe 89 ea > 77 08 89 e8 31 d2 f3 89 c1 89 f0 8b 7c 24 08 f7 f3 8b 74 24 04 89 > ca 8b 1c 24 > Sep 11 00:39:34 zaratustra EIP: [] div64_u64+0x57/0x80 SS:ESP > 0068:ea7a6edc > Sep 11 00:39:34 zaratustra ---[ end trace 4eaa2a86a8e2da22 ]--- fix the boundary condition. sysctl_sched_rt_period=0 makes exception at to_ratio(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Ingo Molnar --- kernel/sched.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index cc1f81b50b8..98890807375 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8909,6 +8909,9 @@ static int sched_rt_global_constraints(void) u64 rt_runtime, rt_period; int ret = 0; + if (sysctl_sched_rt_period <= 0) + return -EINVAL; + rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period); rt_runtime = tg->rt_bandwidth.rt_runtime; @@ -8925,6 +8928,9 @@ static int sched_rt_global_constraints(void) unsigned long flags; int i; + if (sysctl_sched_rt_period <= 0) + return -EINVAL; + spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags); for_each_possible_cpu(i) { struct rt_rq *rt_rq = &cpu_rq(i)->rt; -- cgit v1.2.3 From 44874f84918e37b64bec6df1587e5fe2fdf6ab62 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 27 Aug 2008 14:18:43 +0200 Subject: KVM: SVM: fix random segfaults with NPT enabled This patch introduces a guest TLB flush on every NPF exit in KVM. This fixes random segfaults and #UD exceptions in the guest seen under some workloads (e.g. long running compile workloads or tbench). A kernbench run with and without that fix showed that it has a slowdown lower than 0.5% Cc: stable@kernel.org Signed-off-by: Joerg Roedel Signed-off-by: Alexander Graf Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index e2ee264740c..d1106cddab0 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -62,6 +62,7 @@ static int npt = 1; module_param(npt, int, S_IRUGO); static void kvm_reput_irq(struct vcpu_svm *svm); +static void svm_flush_tlb(struct kvm_vcpu *vcpu); static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) { @@ -1027,6 +1028,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) KVMTRACE_3D(TDP_FAULT, &svm->vcpu, error_code, (u32)fault_address, (u32)(fault_address >> 32), handler); + /* + * FIXME: Tis shouldn't be necessary here, but there is a flush + * missing in the MMU code. Until we find this bug, flush the + * complete TLB here on an NPF + */ + if (npt_enabled) + svm_flush_tlb(&svm->vcpu); if (event_injection) kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address); -- cgit v1.2.3 From e5eab0cede4b1ffaca4ad857d840127622038e55 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 9 Sep 2008 19:11:51 +0200 Subject: KVM: SVM: fix guest global tlb flushes with NPT Accesses to CR4 are intercepted even with Nested Paging enabled. But the code does not check if the guest wants to do a global TLB flush. So this flush gets lost. This patch adds the check and the flush to svm_set_cr4. Signed-off-by: Joerg Roedel Signed-off-by: Avi Kivity --- arch/x86/kvm/svm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index d1106cddab0..8233b86c778 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -879,6 +879,10 @@ set: static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) { unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE; + unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4; + + if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE)) + force_new_asid(vcpu); vcpu->arch.cr4 = cr4; if (!npt_enabled) -- cgit v1.2.3 From 534e38b447df47f129a6d3ec3af6705c1e3f651e Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 8 Sep 2008 15:12:30 +0800 Subject: KVM: VMX: Always return old for clear_flush_young() when using EPT As well as discard fake accessed bit and dirty bit of EPT. Signed-off-by: Sheng Yang Signed-off-by: Avi Kivity --- arch/x86/kvm/mmu.c | 4 ++++ arch/x86/kvm/vmx.c | 3 +-- arch/x86/kvm/vmx.h | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 0bfe2bd305e..3da2508eb22 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -711,6 +711,10 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp) u64 *spte; int young = 0; + /* always return old for EPT */ + if (!shadow_accessed_mask) + return 0; + spte = rmap_next(kvm, rmapp, NULL); while (spte) { int _young; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 2a69773e3b2..7041cc52b56 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3301,8 +3301,7 @@ static int __init vmx_init(void) kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK | VMX_EPT_WRITABLE_MASK | VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT); - kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK, - VMX_EPT_FAKE_DIRTY_MASK, 0ull, + kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull, VMX_EPT_EXECUTABLE_MASK); kvm_enable_tdp(); } else diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 425a13436b3..23e8373507a 100644 --- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h @@ -370,8 +370,6 @@ enum vmcs_field { #define VMX_EPT_READABLE_MASK 0x1ull #define VMX_EPT_WRITABLE_MASK 0x2ull #define VMX_EPT_EXECUTABLE_MASK 0x4ull -#define VMX_EPT_FAKE_ACCESSED_MASK (1ull << 62) -#define VMX_EPT_FAKE_DIRTY_MASK (1ull << 63) #define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul -- cgit v1.2.3 From f1926ce63b996b42772b39e4b47bb4ef4ba748b4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 11 Sep 2008 11:09:49 +0200 Subject: clocksource, acpi_pm.c: fix check for monotonicity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actually check the monotonicity of the ACPI PMTMR ten times, only delay for 0.9 miliseconds at most, and bail out early if some problem is determined. Reported-by: Jochen Voß Signed-off-by: Dominik Brodowski Signed-off-by: Ingo Molnar --- drivers/clocksource/acpi_pm.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 4eee533f3f4..71d2ac4e3f4 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -178,11 +178,13 @@ static int verify_pmtmr_rate(void) /* Number of monotonicity checks to perform during initialization */ #define ACPI_PM_MONOTONICITY_CHECKS 10 +/* Number of reads we try to get two different values */ +#define ACPI_PM_READ_CHECKS 10000 static int __init init_acpi_pm_clocksource(void) { cycle_t value1, value2; - unsigned int i, j, good = 0; + unsigned int i, j = 0; if (!pmtmr_ioport) return -ENODEV; @@ -192,29 +194,26 @@ static int __init init_acpi_pm_clocksource(void) /* "verify" this timing source: */ for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { + udelay(100 * j); value1 = clocksource_acpi_pm.read(); - for (i = 0; i < 10000; i++) { + for (i = 0; i < ACPI_PM_READ_CHECKS; i++) { value2 = clocksource_acpi_pm.read(); if (value2 == value1) continue; if (value2 > value1) - good++; break; if ((value2 < value1) && ((value2) < 0xFFF)) - good++; break; printk(KERN_INFO "PM-Timer had inconsistent results:" " 0x%#llx, 0x%#llx - aborting.\n", value1, value2); return -EINVAL; } - udelay(300 * i); - } - - if (good != ACPI_PM_MONOTONICITY_CHECKS) { - printk(KERN_INFO "PM-Timer failed consistency check " - " (0x%#llx) - aborting.\n", value1); - return -ENODEV; + if (i == ACPI_PM_READ_CHECKS) { + printk(KERN_INFO "PM-Timer failed consistency check " + " (0x%#llx) - aborting.\n", value1); + return -ENODEV; + } } if (verify_pmtmr_rate() != 0) -- cgit v1.2.3 From 7736c09c6cf9521f2413d78856a66f4a37046e84 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Sep 2008 10:16:22 +0100 Subject: [ARM] OMAP: Fix MMC device data OMAPs MMC device data was passing the wrong structure via the platform device. Moreover, a missing function means that both sx1_defconfig and omap_h2_1610_defconfig builds failed with undefined reference to `omap_set_mmc_info' errors. Fix this by updating the MMC support from the omapzoom tree. Signed-off-by: Russell King --- arch/arm/plat-omap/devices.c | 123 ++++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 187e3d8bfdf..bc1cf30c83e 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -194,25 +195,38 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ + defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) -#ifdef CONFIG_ARCH_OMAP24XX +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #define OMAP_MMC1_BASE 0x4809c000 -#define OMAP_MMC1_INT INT_24XX_MMC_IRQ +#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x1fc) +#define OMAP_MMC1_INT INT_24XX_MMC_IRQ + +#define OMAP_MMC2_BASE 0x480b4000 +#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x1fc) +#define OMAP_MMC2_INT INT_24XX_MMC2_IRQ + #else + #define OMAP_MMC1_BASE 0xfffb7800 +#define OMAP_MMC1_END (OMAP_MMC1_BASE + 0x7f) #define OMAP_MMC1_INT INT_MMC -#endif + #define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ +#define OMAP_MMC2_END (OMAP_MMC2_BASE + 0x7f) +#define OMAP_MMC2_INT INT_1610_MMC2 -static struct omap_mmc_conf mmc1_conf; +#endif + +static struct omap_mmc_platform_data mmc1_data; static u64 mmc1_dmamask = 0xffffffff; static struct resource mmc1_resources[] = { { .start = OMAP_MMC1_BASE, - .end = OMAP_MMC1_BASE + 0x7f, + .end = OMAP_MMC1_END, .flags = IORESOURCE_MEM, }, { @@ -226,26 +240,27 @@ static struct platform_device mmc_omap_device1 = { .id = 1, .dev = { .dma_mask = &mmc1_dmamask, - .platform_data = &mmc1_conf, + .platform_data = &mmc1_data, }, .num_resources = ARRAY_SIZE(mmc1_resources), .resource = mmc1_resources, }; -#ifdef CONFIG_ARCH_OMAP16XX +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ + defined(CONFIG_ARCH_OMAP34XX) -static struct omap_mmc_conf mmc2_conf; +static struct omap_mmc_platform_data mmc2_data; static u64 mmc2_dmamask = 0xffffffff; static struct resource mmc2_resources[] = { { .start = OMAP_MMC2_BASE, - .end = OMAP_MMC2_BASE + 0x7f, + .end = OMAP_MMC2_END, .flags = IORESOURCE_MEM, }, { - .start = INT_1610_MMC2, + .start = OMAP_MMC2_INT, .flags = IORESOURCE_IRQ, }, }; @@ -255,26 +270,19 @@ static struct platform_device mmc_omap_device2 = { .id = 2, .dev = { .dma_mask = &mmc2_dmamask, - .platform_data = &mmc2_conf, + .platform_data = &mmc2_data, }, .num_resources = ARRAY_SIZE(mmc2_resources), .resource = mmc2_resources, }; #endif -static void __init omap_init_mmc(void) +static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf) { - const struct omap_mmc_config *mmc_conf; - const struct omap_mmc_conf *mmc; - - /* NOTE: assumes MMC was never (wrongly) enabled */ - mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); - if (!mmc_conf) + if (cpu_is_omap2430() || cpu_is_omap34xx()) return; - /* block 1 is always available and has just one pinout option */ - mmc = &mmc_conf->mmc[0]; - if (mmc->enabled) { + if (mmc_conf->mmc[0].enabled) { if (cpu_is_omap24xx()) { omap_cfg_reg(H18_24XX_MMC_CMD); omap_cfg_reg(H15_24XX_MMC_CLKI); @@ -292,7 +300,7 @@ static void __init omap_init_mmc(void) omap_cfg_reg(P20_1710_MMC_DATDIR0); } } - if (mmc->wire4) { + if (mmc_conf->mmc[0].wire4) { if (cpu_is_omap24xx()) { omap_cfg_reg(H14_24XX_MMC_DAT1); omap_cfg_reg(E19_24XX_MMC_DAT2); @@ -303,25 +311,35 @@ static void __init omap_init_mmc(void) } else { omap_cfg_reg(MMC_DAT1); /* NOTE: DAT2 can be on W10 (here) or M15 */ - if (!mmc->nomux) + if (!mmc_conf->mmc[0].nomux) omap_cfg_reg(MMC_DAT2); omap_cfg_reg(MMC_DAT3); } } - mmc1_conf = *mmc; - (void) platform_device_register(&mmc_omap_device1); +#if defined(CONFIG_ARCH_OMAP2420) + if (mmc_conf->mmc[0].internal_clock) { + /* + * Use internal loop-back in MMC/SDIO + * Module Input Clock selection + */ + if (cpu_is_omap24xx()) { + u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + v |= (1 << 24); /* not used in 243x */ + omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); + } + } +#endif } #ifdef CONFIG_ARCH_OMAP16XX /* block 2 is on newer chips, and has many pinout options */ - mmc = &mmc_conf->mmc[1]; - if (mmc->enabled) { - if (!mmc->nomux) { + if (mmc_conf->mmc[1].enabled) { + if (!mmc_conf->mmc[1].nomux) { omap_cfg_reg(Y8_1610_MMC2_CMD); omap_cfg_reg(Y10_1610_MMC2_CLK); omap_cfg_reg(R18_1610_MMC2_CLKIN); omap_cfg_reg(W8_1610_MMC2_DAT0); - if (mmc->wire4) { + if (mmc_conf->mmc[1].wire4) { omap_cfg_reg(V8_1610_MMC2_DAT1); omap_cfg_reg(W15_1610_MMC2_DAT2); omap_cfg_reg(R10_1610_MMC2_DAT3); @@ -337,14 +355,55 @@ static void __init omap_init_mmc(void) if (cpu_is_omap1710()) omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), MOD_CONF_CTRL_1); - mmc2_conf = *mmc; + } +#endif +} + +static void __init omap_init_mmc(void) +{ + const struct omap_mmc_config *mmc_conf; + + /* NOTE: assumes MMC was never (wrongly) enabled */ + mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); + if (!mmc_conf) + return; + + omap_init_mmc_conf(mmc_conf); + + if (mmc_conf->mmc[0].enabled) { + mmc1_data.conf = mmc_conf->mmc[0]; + (void) platform_device_register(&mmc_omap_device1); + } + +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ + defined(CONFIG_ARCH_OMAP34XX) + if (mmc_conf->mmc[1].enabled) { + mmc2_data.conf = mmc_conf->mmc[1]; (void) platform_device_register(&mmc_omap_device2); } #endif - return; } + +void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) +{ + switch (host) { + case 1: + mmc1_data = *info; + break; +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430) || \ + defined(CONFIG_ARCH_OMAP34XX) + case 2: + mmc2_data = *info; + break; +#endif + default: + BUG(); + } +} + #else static inline void omap_init_mmc(void) {} +void omap_set_mmc_info(int host, const struct omap_mmc_platform_data *info) {} #endif /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 2dc75d3c3b49c64fd26b4832a7efb75546cb3fc5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 11 Sep 2008 14:20:23 +0200 Subject: block: disable sysfs parts of the disk command filter We still have life time issues with the sysfs command filter kobject, so disable it for 2.6.27 release. We can revisit this and make it work properly for 2.6.28, for 2.6.27 release it's too risky. Signed-off-by: Jens Axboe --- block/cmd-filter.c | 2 ++ drivers/ide/ide-cd.c | 2 -- drivers/scsi/sd.c | 2 -- drivers/scsi/sr.c | 2 -- include/linux/blkdev.h | 2 -- 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/block/cmd-filter.c b/block/cmd-filter.c index 228b6447e89..79c14996ac1 100644 --- a/block/cmd-filter.c +++ b/block/cmd-filter.c @@ -49,6 +49,7 @@ int blk_verify_command(struct blk_cmd_filter *filter, } EXPORT_SYMBOL(blk_verify_command); +#if 0 /* and now, the sysfs stuff */ static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page, int rw) @@ -233,3 +234,4 @@ void blk_unregister_filter(struct gendisk *disk) kobject_put(disk->holder_dir->parent); } EXPORT_SYMBOL(blk_unregister_filter); +#endif diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f1489999cf9..49a8c589e34 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1933,7 +1933,6 @@ static void ide_cd_remove(ide_drive_t *drive) ide_proc_unregister_driver(drive, info->driver); - blk_unregister_filter(info->disk); del_gendisk(info->disk); ide_cd_put(info); @@ -2159,7 +2158,6 @@ static int ide_cd_probe(ide_drive_t *drive) g->fops = &idecd_ops; g->flags |= GENHD_FL_REMOVABLE; add_disk(g); - blk_register_filter(g); return 0; out_free_cd: diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2a2bc89aba8..e5e7d785645 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1875,7 +1875,6 @@ static int sd_probe(struct device *dev) dev_set_drvdata(dev, sdkp); add_disk(gd); - blk_register_filter(gd); sd_dif_config_host(sdkp); sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", @@ -1909,7 +1908,6 @@ static int sd_remove(struct device *dev) struct scsi_disk *sdkp = dev_get_drvdata(dev); device_del(&sdkp->dev); - blk_unregister_filter(sdkp->disk); del_gendisk(sdkp->disk); sd_shutdown(dev); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 3292965bfd8..27f5bfd1def 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -656,7 +656,6 @@ static int sr_probe(struct device *dev) dev_set_drvdata(dev, cd); disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); - blk_register_filter(disk); sdev_printk(KERN_DEBUG, sdev, "Attached scsi CD-ROM %s\n", cd->cdi.name); @@ -895,7 +894,6 @@ static int sr_remove(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); - blk_unregister_filter(cd->disk); del_gendisk(cd->disk); mutex_lock(&sr_ref_mutex); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 44710d7e7bf..53ea933cf60 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -843,8 +843,6 @@ extern int blkdev_issue_flush(struct block_device *, sector_t *); */ extern int blk_verify_command(struct blk_cmd_filter *filter, unsigned char *cmd, int has_write_perm); -extern int blk_register_filter(struct gendisk *disk); -extern void blk_unregister_filter(struct gendisk *disk); extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter); #define MAX_PHYS_SEGMENTS 128 -- cgit v1.2.3 From 50bed2e2862a8f3a4f7d683d0d27292e71ef18b9 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 11 Sep 2008 18:35:39 +0200 Subject: sg: disable interrupts inside sg_copy_buffer The callers of sg_copy_buffer must disable interrupts before calling it (since it uses kmap_atomic). Some callers use it on interrupt-disabled code but some need to take the trouble to disable interrupts just for this. No wonder they forget about it and we hit a bug like: http://bugzilla.kernel.org/show_bug.cgi?id=11529 James said that it might be better to disable interrupts inside the function rather than risk the callers getting it wrong. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- lib/scatterlist.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 876ba6d5b67..8d2688ff135 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -422,9 +422,12 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, { unsigned int offset = 0; struct sg_mapping_iter miter; + unsigned long flags; sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC); + local_irq_save(flags); + while (sg_miter_next(&miter) && offset < buflen) { unsigned int len; @@ -442,6 +445,7 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, sg_miter_stop(&miter); + local_irq_restore(flags); return offset; } -- cgit v1.2.3 From d1c6d2e547148c5aa0c0a4ff6aac82f7c6da1d8b Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 11 Sep 2008 17:18:56 +0100 Subject: MN10300: Change the fault handler to check in_atomic() not in_interrupt() Change the MN10300 fault handler to make it check in_atomic() rather than in_interrupt() as commit 6edaf68a87d17570790fd55f0c451a29ec1d6703 did for other architectures: Author: Peter Zijlstra Date: Wed Dec 6 20:32:18 2006 -0800 [PATCH] mm: arch do_page_fault() vs in_atomic() In light of the recent pagefault and filemap_copy_from_user work I've gone through all the arch pagefault handlers to make sure the inc_preempt_count() 'feature' works as expected. Several sections of code (including the new filemap_copy_from_user) rely on the fact that faults do not take locks under increased preempt count. Signed-off-by: David Howells Acked-by: Peter Zijlstra Signed-off-by: Linus Torvalds --- arch/mn10300/mm/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 78f092ca031..33cf25025da 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c @@ -174,7 +174,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code, * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); -- cgit v1.2.3 From 7c6a329e444725f24c02192ac493d8a7cd9fa638 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 12 Sep 2008 03:11:54 +0200 Subject: [Bluetooth] Fix regression from using default link policy To speed up the Simple Pairing connection setup, the support for the default link policy has been enabled. This is in contrast to settings the link policy on every connection setup. Using the default link policy is the preferred way since there is no need to dynamically change it for every connection. For backward compatibility reason and to support old userspace the HCISETLINKPOL ioctl has been switched over to using hci_request() to issue the HCI command for setting the default link policy instead of just storing it in the HCI device structure. However the hci_request() can only be issued when the device is brought up. If used on a device that is registered, but still down it will timeout and fail. This is problematic since the command is put on the TX queue and the Bluetooth core tries to submit it to hardware that is not ready yet. The timeout for these requests is 10 seconds and this causes a significant regression when setting up a new device. The userspace can perfectly handle a failure of the HCISETLINKPOL ioctl and will re-submit it later, but the 10 seconds delay causes a problem. So in case hci_request() is called on a device that is still down, just fail it with ENETDOWN to indicate what happens. Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f5b21cb9369..278a3ace14f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -164,6 +164,9 @@ static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev * { int ret; + if (!test_bit(HCI_UP, &hdev->flags)) + return -ENETDOWN; + /* Serialize all requests */ hci_req_lock(hdev); ret = __hci_request(hdev, req, opt, timeout); -- cgit v1.2.3 From 1045b03e07d85f3545118510a587035536030c1c Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Thu, 11 Sep 2008 19:05:29 -0700 Subject: netlink: fix overrun in attribute iteration kmemcheck reported this: kmemcheck: Caught 16-bit read from uninitialized memory (f6c1ba30) 0500110001508abf050010000500000002017300140000006f72672e66726565 i i i i i i i i i i i i i u u u u u u u u u u u u u u u u u u u ^ Pid: 3462, comm: wpa_supplicant Not tainted (2.6.27-rc3-00054-g6397ab9-dirty #13) EIP: 0060:[] EFLAGS: 00010296 CPU: 0 EIP is at nla_parse+0x5a/0xf0 EAX: 00000008 EBX: fffffffd ECX: c06f16c0 EDX: 00000005 ESI: 00000010 EDI: f6c1ba30 EBP: f6367c6c ESP: c0a11e88 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 CR0: 8005003b CR2: f781cc84 CR3: 3632f000 CR4: 000006d0 DR0: c0ead9bc DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff4ff0 DR7: 00000400 [] rtnl_setlink+0x63/0x130 [] rtnetlink_rcv_msg+0x165/0x200 [] netlink_rcv_skb+0x76/0xa0 [] rtnetlink_rcv+0x1e/0x30 [] netlink_unicast+0x281/0x290 [] netlink_sendmsg+0x1b9/0x2b0 [] sock_sendmsg+0xd2/0x100 [] sys_sendto+0xa5/0xd0 [] sys_send+0x36/0x40 [] sys_socketcall+0x1e6/0x2c0 [] sysenter_do_call+0x12/0x3f [] 0xffffffff This is the line in nla_ok(): /** * nla_ok - check if the netlink attribute fits into the remaining bytes * @nla: netlink attribute * @remaining: number of bytes remaining in attribute stream */ static inline int nla_ok(const struct nlattr *nla, int remaining) { return remaining >= sizeof(*nla) && nla->nla_len >= sizeof(*nla) && nla->nla_len <= remaining; } It turns out that remaining can become negative due to alignment in nla_next(). But GCC promotes "remaining" to unsigned in the test against sizeof(*nla) above. Therefore the test succeeds, and the nla_for_each_attr() may access memory outside the received buffer. A short example illustrating this point is here: #include main(void) { printf("%d\n", -1 >= sizeof(int)); } ...which prints "1". This patch adds a cast in front of the sizeof so that GCC will make a signed comparison and fix the illegal memory dereference. With the patch applied, there is no kmemcheck report. Signed-off-by: Vegard Nossum Acked-by: Thomas Graf Signed-off-by: David S. Miller --- include/net/netlink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 18024b8cecb..208fe5a3854 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -702,7 +702,7 @@ static inline int nla_len(const struct nlattr *nla) */ static inline int nla_ok(const struct nlattr *nla, int remaining) { - return remaining >= sizeof(*nla) && + return remaining >= (int) sizeof(*nla) && nla->nla_len >= sizeof(*nla) && nla->nla_len <= remaining; } -- cgit v1.2.3 From 0ad5bce7409d681a5655c66e64bb0eb740b89c1f Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 11 Sep 2008 16:42:00 -0700 Subject: x86: fix possible x86_64 and EFI regression Russ Anderson reported a boot crash with EFI and latest mainline: BIOS-e820: 00000000fffa0000 - 00000000fffac000 (reserved) Pid: 0, comm: swapper Not tainted 2.6.27-rc5-00100-gec0c15a-dirty #5 Call Trace: [] early_idt_handler+0x55/0x69 [] __memcpy+0x12/0xa4 [] efi_init+0xce/0x932 [] setup_early_serial8250_console+0x2d/0x36a [] __insert_resource+0x18/0xc8 [] setup_arch+0x3a7/0x632 [] start_kernel+0x91/0x367 [] x86_64_start_kernel+0xe3/0xe7 [] x86_64_start_kernel+0x0/0xe7 RIP 0x10 Such a crash is possible if the CPU in this system is a 64-bit processor which doesn't support NX (ie, old Intel P4 -based64-bit processors). Certainly, if we support such processors, then we should start with _PAGE_NX initially clear in __supported_pte_flags, and then set it once we've established that the processor does indeed support NX. That will prevent early_ioremap - or anything else - from trying to set it. The simple fix is to simply call check_efer() earlier. Reported-by: Russ Anderson Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 362d4e7f2d3..9838f2539df 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -670,6 +670,10 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); +#ifdef CONFIG_X86_64 + check_efer(); +#endif + #if defined(CONFIG_VMI) && defined(CONFIG_X86_32) /* * Must be before kernel pagetables are setup @@ -738,7 +742,6 @@ void __init setup_arch(char **cmdline_p) #else num_physpages = max_pfn; - check_efer(); /* How many end-of-memory variables you have, grandma! */ /* need this before calling reserve_initrd */ -- cgit v1.2.3 From 80a56ab626c70468be92e74cf3d288ffaed23fdb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 15:13:15 -0700 Subject: sparc64: Fix PCI error interrupt registry on PSYCHO. We need to pass IRQF_SHARED, otherwise we get things like: IRQ handler type mismatch for IRQ 33 current handler: PSYCHO_UE Call Trace: [000000000048394c] request_irq+0xac/0x120 [00000000007c5f6c] psycho_scan_bus+0x98/0x158 [00000000007c2bc0] pcibios_init+0xdc/0x12c [0000000000426a5c] do_one_initcall+0x1c/0x160 [00000000007c0180] kernel_init+0x9c/0xfc [0000000000427050] kernel_thread+0x30/0x60 [00000000006ae1d0] rest_init+0x10/0x60 on e3500 and similar systems. On a single board, the UE interrupts of two Psycho nodes are funneled through the same interrupt, from of_debug=3 dump: /pci@b,4000: direct translate 2ee --> 21 ... /pci@b,2000: direct translate 2ee --> 21 Decimal "33" mentioned above is the hex "21" mentioned here. Thanks to Meelis Roos for dumps and testing. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index ef5fe29202c..e205ade69cf 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -744,16 +744,16 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) * the second will just error out since we do not pass in * IRQF_SHARED. */ - err = request_irq(op->irqs[1], psycho_ue_intr, 0, + err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO_UE", pbm); - err = request_irq(op->irqs[2], psycho_ce_intr, 0, + err = request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO_CE", pbm); /* This one, however, ought not to fail. We can just warn * about it since the system can still operate properly even * if this fails. */ - err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, + err = request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, "PSYCHO_PCIERR", pbm); if (err) printk(KERN_WARNING "%s: Could not register PCIERR, " -- cgit v1.2.3 From 7d4ee289d139d27b619c08c9809e7b1088c100aa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 15:01:31 -0700 Subject: sparc: Fix user_regset 'n' field values. As noticed by Russell King, we were not setting this properly to the number of entries, but rather the total size. This results in the core dumping code allocating waayyyy too much memory. Signed-off-by: David S. Miller --- arch/sparc/kernel/ptrace.c | 4 ++-- arch/sparc64/kernel/ptrace.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 20699c70141..8ce6285a06d 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -288,7 +288,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 38 * sizeof(u32), + .n = 38, .size = sizeof(u32), .align = sizeof(u32), .get = genregs32_get, .set = genregs32_set }, @@ -304,7 +304,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 99 * sizeof(u32), + .n = 99, .size = sizeof(u32), .align = sizeof(u32), .get = fpregs32_get, .set = fpregs32_set }, diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index bd578cc4856..10306e476e3 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -443,7 +443,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 36 * sizeof(u64), + .n = 36, .size = sizeof(u64), .align = sizeof(u64), .get = genregs64_get, .set = genregs64_set }, @@ -455,7 +455,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 35 * sizeof(u64), + .n = 35, .size = sizeof(u64), .align = sizeof(u64), .get = fpregs64_get, .set = fpregs64_set }, @@ -801,7 +801,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 38 * sizeof(u32), + .n = 38, .size = sizeof(u32), .align = sizeof(u32), .get = genregs32_get, .set = genregs32_set }, @@ -817,7 +817,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 99 * sizeof(u32), + .n = 99, .size = sizeof(u32), .align = sizeof(u32), .get = fpregs32_get, .set = fpregs32_set }, -- cgit v1.2.3 From cff502a38394fd33693f6233e03fca363dfa956d Mon Sep 17 00:00:00 2001 From: Santwona Behera Date: Fri, 12 Sep 2008 16:04:26 -0700 Subject: niu: panic on reset The reset_task function in the niu driver does not reset the tx and rx buffers properly. This leads to panic on reset. This patch is a modified implementation of the previously posted fix. Signed-off-by: Santwona Behera Signed-off-by: David S. Miller --- drivers/net/niu.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index e4765b713ab..e3be81eba8a 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -5984,6 +5984,56 @@ static void niu_netif_start(struct niu *np) niu_enable_interrupts(np, 1); } +static void niu_reset_buffers(struct niu *np) +{ + int i, j, k, err; + + if (np->rx_rings) { + for (i = 0; i < np->num_rx_rings; i++) { + struct rx_ring_info *rp = &np->rx_rings[i]; + + for (j = 0, k = 0; j < MAX_RBR_RING_SIZE; j++) { + struct page *page; + + page = rp->rxhash[j]; + while (page) { + struct page *next = + (struct page *) page->mapping; + u64 base = page->index; + base = base >> RBR_DESCR_ADDR_SHIFT; + rp->rbr[k++] = cpu_to_le32(base); + page = next; + } + } + for (; k < MAX_RBR_RING_SIZE; k++) { + err = niu_rbr_add_page(np, rp, GFP_ATOMIC, k); + if (unlikely(err)) + break; + } + + rp->rbr_index = rp->rbr_table_size - 1; + rp->rcr_index = 0; + rp->rbr_pending = 0; + rp->rbr_refill_pending = 0; + } + } + if (np->tx_rings) { + for (i = 0; i < np->num_tx_rings; i++) { + struct tx_ring_info *rp = &np->tx_rings[i]; + + for (j = 0; j < MAX_TX_RING_SIZE; j++) { + if (rp->tx_buffs[j].skb) + (void) release_tx_packet(np, rp, j); + } + + rp->pending = MAX_TX_RING_SIZE; + rp->prod = 0; + rp->cons = 0; + rp->wrap_bit = 0; + } + } +} + static void niu_reset_task(struct work_struct *work) { struct niu *np = container_of(work, struct niu, reset_task); @@ -6006,6 +6056,12 @@ static void niu_reset_task(struct work_struct *work) niu_stop_hw(np); + spin_unlock_irqrestore(&np->lock, flags); + + niu_reset_buffers(np); + + spin_lock_irqsave(&np->lock, flags); + err = niu_init_hw(np); if (!err) { np->timer.expires = jiffies + HZ; -- cgit v1.2.3 From 395a125c6237802b19bf22b41017c99ff57f1024 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 9 Sep 2008 12:27:52 -0700 Subject: PCI: re-add debug prints for unmodified BARs Print out for device BAR values before the kernel tries to update them. Also make related output use KERN_DEBUG. Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/probe.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 0ad936765b2..36698e57b97 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -304,6 +304,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } else { res->start = l64; res->end = l64 + sz64; + printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n", + pci_name(dev), pos, (unsigned long long)res->start, + (unsigned long long)res->end); } } else { sz = pci_size(l, sz, mask); @@ -313,6 +316,9 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, res->start = l; res->end = l + sz; + printk(KERN_DEBUG "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev), + pos, (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio", + (unsigned long long)res->start, (unsigned long long)res->end); } out: @@ -383,7 +389,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->start = base; if (!res->end) res->end = limit + 0xfff; - printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", + printk(KERN_DEBUG "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), (unsigned long long) res->start, (unsigned long long) res->end); } @@ -397,8 +403,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; - printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), - (unsigned long long) res->start, (unsigned long long) res->end); + printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", + pci_name(dev), (unsigned long long) res->start, + (unsigned long long) res->end); } res = child->resource[2]; @@ -434,7 +441,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->start = base; res->end = limit + 0xfffff; - printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", + printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32", (unsigned long long) res->start, (unsigned long long) res->end); } -- cgit v1.2.3 From 048feec5548c0582ee96148c61b87cccbcb5f9be Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 11 Sep 2008 22:19:45 -0700 Subject: [SCSI] qla2xxx: Defer enablement of RISC interrupts until ISP initialization completes. Josip Rodin noted (http://article.gmane.org/gmane.linux.ports.sparc/10152) the driver oopsing during registration of an rport to the FC-transport layer with a backtrace indicating a dereferencing of an shost->shost_data equal to NULL. David Miller identified a small window in driver logic where this could happen: > Look at how the driver registers the IRQ handler before the host has > been registered with the SCSI layer. > > That leads to a window of time where the shost hasn't been setup > fully, yet ISRs can come in and trigger DPC thread events, such as > loop resyncs, which expect the transport area to be setup. > > But it won't be setup, because scsi_add_host() hasn't finished yet. > > Note that in Josip's crash log, we don't even see the > > qla_printk(KERN_INFO, ha, "\n" > " QLogic Fibre Channel HBA Driver: %s\n" > " QLogic %s - %s\n" > " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", > ... > > message yet. > > Which means that the crash occurs between qla2x00_request_irqs() > and printing that message. Close this window by enabling RISC interrupts after the host has been registered with the SCSI midlayer. Reported-by: Josip Rodin Cc: Stable Tree Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 1 - drivers/scsi/qla2xxx/qla_os.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 45a3b93eed5..bf41887cdd6 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1834,7 +1834,6 @@ clear_risc_ints: WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); } spin_unlock_irq(&ha->hardware_lock); - ha->isp_ops->enable_intrs(ha); fail: return ret; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 26afe44265c..6d0f0e5f282 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1740,6 +1740,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto probe_failed; + ha->isp_ops->enable_intrs(ha); + scsi_scan_host(host); qla2x00_alloc_sysfs_attr(ha); -- cgit v1.2.3 From 632480ea6548ae66e89a49ef037fd593c7a52418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Schindele?= Date: Mon, 8 Sep 2008 22:06:29 +0100 Subject: [ARM] 5245/1: Fix warning about unused return value in drivers/pcmcia Fix warning when compiling "drivers/pcmcia/soc-common.c" The return value of the function "device_create_file" was not used / assigned. Signed-off-by: Jrgen Schindele Signed-off-by: Russell King --- drivers/pcmcia/soc_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index c48f3f69bda..da397215322 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -748,7 +748,9 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops add_timer(&skt->poll_timer); - device_create_file(&skt->socket.dev, &dev_attr_status); + ret = device_create_file(&skt->socket.dev, &dev_attr_status); + if (ret) + goto out_err_8; } dev_set_drvdata(dev, sinfo); @@ -758,6 +760,8 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops do { skt = &sinfo->skt[i]; + device_remove_file(&skt->socket.dev, &dev_attr_status); + out_err_8: del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); -- cgit v1.2.3 From 7bdb22c9d4b4f526b81770cd719d2f5dddf0373d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 10 Sep 2008 10:30:37 +0100 Subject: [ARM] 5246/1: tosa: add proper clock alias for tc6393xb clock Add clock alias for clock that is used by tc6393xb device on tosa. As that chip plays pretty major part in tosa life and is currently disabled, this is 2.4.27 material. Signed-off-by: Dmitry Baryshkov Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 5dab30eafdd..33da99fa1cc 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -50,6 +50,7 @@ #include #include "generic.h" +#include "clock.h" #include "devices.h" static unsigned long tosa_pin_config[] = { @@ -792,6 +793,8 @@ static void __init tosa_init(void) pxa_set_i2c_info(NULL); platform_scoop_config = &tosa_pcmcia_config; + clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL); + platform_add_devices(devices, ARRAY_SIZE(devices)); } -- cgit v1.2.3 From c33de47bce74e0c890f9f830a7641371524edbc1 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 11 Sep 2008 01:28:51 +0100 Subject: [ARM] 5247/1: tosa: SW_EAR_IN support Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 33da99fa1cc..9f3ef9eb32e 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -522,6 +522,14 @@ static struct gpio_keys_button tosa_gpio_keys[] = { .wakeup = 1, .active_low = 1, }, + { + .type = EV_SW, + .code = SW_HEADPHONE_INSERT, + .gpio = TOSA_GPIO_EAR_IN, + .desc = "HeadPhone insert", + .active_low = 1, + .debounce_interval = 300, + }, }; static struct gpio_keys_platform_data tosa_gpio_keys_platform_data = { -- cgit v1.2.3 From 88c381bf09d7b3f2c2e8749150087aff2c434be4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 13 Sep 2008 21:23:06 +0100 Subject: [ARM] Fix PCI_DMA_BUS_IS_PHYS for ARM PCI_DMA_BUS_IS_PHYS was defined to be zero, which meant we ignored the DMA mask for IDE and SCSI transfers. This is wrong - we have no DMA translation hardware. We want to obey DMA masks so that the block layer performs bouncing itself. Reported-by: Mikael Pettersson Signed-off-by: Russell King --- arch/arm/include/asm/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 721c03d53f4..918d0cbbf06 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -30,7 +30,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) * The networking and block device layers use this boolean for bounce * buffer decisions. */ -#define PCI_DMA_BUS_IS_PHYS (0) +#define PCI_DMA_BUS_IS_PHYS (1) /* * Whether pci_unmap_{single,page} is a nop depends upon the -- cgit v1.2.3 From da3ceb2288d0b50373b69d57a81c34fdd7cd11aa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 8 Sep 2008 09:31:39 -0700 Subject: ata: duplicate variable sparse warning drivers/ata/ata_piix.c:1502:7: warning: symbol 'rc' shadows an earlier one Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index b1d08a8f500..e6b4606e36b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1499,7 +1499,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, * off. */ if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) { - int rc = piix_disable_ahci(pdev); + rc = piix_disable_ahci(pdev); if (rc) return rc; } -- cgit v1.2.3 From 99580664aa83ca04bb52988d504a4195b41833b0 Mon Sep 17 00:00:00 2001 From: Bob Stewart Date: Thu, 11 Sep 2008 11:50:03 +0200 Subject: sata_inic162x: enable LED blinking Enable LED blinking. Signed-off-by: Bob Stewart Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_inic162x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 3ead02fe379..5032c32fa50 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -96,6 +96,7 @@ enum { PORT_SCR = 0x20, /* HOST_CTL bits */ + HCTL_LEDEN = (1 << 3), /* enable LED operation */ HCTL_IRQOFF = (1 << 8), /* global IRQ off */ HCTL_FTHD0 = (1 << 10), /* fifo threshold 0 */ HCTL_FTHD1 = (1 << 11), /* fifo threshold 1*/ @@ -540,7 +541,7 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc) void __iomem *port_base = inic_port_base(ap); /* fire up the ADMA engine */ - writew(HCTL_FTHD0, port_base + HOST_CTL); + writew(HCTL_FTHD0 | HCTL_LEDEN, port_base + HOST_CTL); writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL); writeb(0, port_base + PORT_CPB_PTQFIFO); -- cgit v1.2.3 From 97b697a11b07e2ebfa69c488132596cc5eb24119 Mon Sep 17 00:00:00 2001 From: Taisuke Yamada Date: Sat, 13 Sep 2008 16:46:15 -0400 Subject: [libata] LBA28/LBA48 off-by-one bug in ata.h I recently bought 3 HGST P7K500-series 500GB SATA drives and had trouble accessing the block right on the LBA28-LBA48 border. Here's how it fails (same for all 3 drives): # dd if=/dev/sdc bs=512 count=1 skip=268435455 > /dev/null dd: reading `/dev/sdc': Input/output error 0+0 records in 0+0 records out 0 bytes (0 B) copied, 0.288033 seconds, 0.0 kB/s # dmesg ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0 ata1.00: BMDMA stat 0x25 ata1.00: cmd c8/00:08:f8:ff:ff/00:00:00:00:00/ef tag 0 dma 4096 in res 51/04:08:f8:ff:ff/00:00:00:00:00/ef Emask 0x1 (device error) ata1.00: status: { DRDY ERR } ata1.00: error: { ABRT } ata1.00: configured for UDMA/33 ata1: EH complete ... After some investigations, it turned out this seems to be caused by misinterpretation of the ATA specification on LBA28 access. Following part is the code in question: === include/linux/ata.h === static inline int lba_28_ok(u64 block, u32 n_block) { /* check the ending block number */ return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); } HGST drive (sometimes) fails with LBA28 access of {block = 0xfffffff, n_block = 1}, and this behavior seems to be comformant. Other drives, including other HGST drives are not that strict, through. >From the ATA specification: (http://www.t13.org/Documents/UploadedDocuments/project/d1410r3b-ATA-ATAPI-6.pdf) 8.15.29 Word (61:60): Total number of user addressable sectors This field contains a value that is one greater than the total number of user addressable sectors (see 6.2). The maximum value that shall be placed in this field is 0FFFFFFFh. So the driver shouldn't use the value of 0xfffffff for LBA28 request as this exceeds maximum user addressable sector. The logical maximum value for LBA28 is 0xffffffe. The obvious fix is to cut "- 1" part, and the patch attached just do that. I've been using the patched kernel for about a month now, and the same fix is also floating on the net for some time. So I believe this fix works reliably. Just FYI, many Windows/Intel platform users also seems to be struck by this, and HGST has issued a note pointing to Intel ICH8/9 driver. "28-bit LBA command is being used to access LBAs 29-bits in length" http://www.hitachigst.com/hddt/knowtree.nsf/cffe836ed7c12018862565b000530c74/b531b8bce8745fb78825740f00580e23 Also, *BSDs seems to have similar fix included sometime around ~2004, through I have not checked out exact portion of the code. Signed-off-by: Taisuke Yamada Signed-off-by: Jeff Garzik --- include/linux/ata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/ata.h b/include/linux/ata.h index 1ce19c1ef0e..8a12d718c16 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -745,7 +745,7 @@ static inline int ata_ok(u8 status) static inline int lba_28_ok(u64 block, u32 n_block) { /* check the ending block number */ - return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); + return ((block + n_block) < ((u64)1 << 28)) && (n_block <= 256); } static inline int lba_48_ok(u64 block, u32 n_block) -- cgit v1.2.3 From 665020c35e89a9e0643e21561e4f8f967f4f2c4b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 13 Sep 2008 02:33:06 -0700 Subject: proc: more debugging for "already registered" case Print parent directory name as well. The aim is to catch non-creation of parent directory when proc_mkdir will return NULL and all subsequent registrations go directly in /proc instead of intended directory. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton [ Fixed insane printk string while at it. - Linus ] Signed-off-by: Linus Torvalds --- fs/proc/generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index bca0f81eb68..7821589a17d 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -547,8 +547,8 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp for (tmp = dir->subdir; tmp; tmp = tmp->next) if (strcmp(tmp->name, dp->name) == 0) { - printk(KERN_WARNING "proc_dir_entry '%s' already " - "registered\n", dp->name); + printk(KERN_WARNING "proc_dir_entry '%s/%s' already registered\n", + dir->name, dp->name); dump_stack(); break; } -- cgit v1.2.3 From dea420ce0e2973e8ef1fd11fde6804c8d03a82ad Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Sat, 13 Sep 2008 02:33:07 -0700 Subject: include/linux/ioport.h: add missing macro argument for devm_release_* family akpm: these have no callers at this time, but they shall soon, so let's get them right. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Hiroshi DOYU Cc: Tony Lindgren Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/ioport.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 8d3b7a9afd1..350033e8f4e 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -159,9 +159,9 @@ extern struct resource * __devm_request_region(struct device *dev, struct resource *parent, resource_size_t start, resource_size_t n, const char *name); -#define devm_release_region(start,n) \ +#define devm_release_region(dev, start, n) \ __devm_release_region(dev, &ioport_resource, (start), (n)) -#define devm_release_mem_region(start,n) \ +#define devm_release_mem_region(dev, start, n) \ __devm_release_region(dev, &iomem_resource, (start), (n)) extern void __devm_release_region(struct device *dev, struct resource *parent, -- cgit v1.2.3 From 4e74339af6a59c061cf02f1ac497766bca1de19a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Sat, 13 Sep 2008 02:33:08 -0700 Subject: cpuset: avoid changing cpuset's cpus when -errno returned After the patch: commit 0b2f630a28d53b5a2082a5275bc3334b10373508 Author: Miao Xie Date: Fri Jul 25 01:47:21 2008 -0700 cpusets: restructure the function update_cpumask() and update_nodemask() It might happen that 'echo 0 > /cpuset/sub/cpus' returned failure but 'cpus' has been changed, because cpus was changed before calling heap_init() which may return -ENOMEM. This patch restores the orginal behavior. Signed-off-by: Li Zefan Acked-by: Paul Menage Cc: Paul Jackson Cc: Miao Xie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index f227bc17269..827cd9adccb 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -843,37 +843,25 @@ static void cpuset_change_cpumask(struct task_struct *tsk, /** * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed + * @heap: if NULL, defer allocating heap memory to cgroup_scan_tasks() * * Called with cgroup_mutex held * * The cgroup_scan_tasks() function will scan all the tasks in a cgroup, * calling callback functions for each. * - * Return 0 if successful, -errno if not. + * No return value. It's guaranteed that cgroup_scan_tasks() always returns 0 + * if @heap != NULL. */ -static int update_tasks_cpumask(struct cpuset *cs) +static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap) { struct cgroup_scanner scan; - struct ptr_heap heap; - int retval; - - /* - * cgroup_scan_tasks() will initialize heap->gt for us. - * heap_init() is still needed here for we should not change - * cs->cpus_allowed when heap_init() fails. - */ - retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); - if (retval) - return retval; scan.cg = cs->css.cgroup; scan.test_task = cpuset_test_cpumask; scan.process_task = cpuset_change_cpumask; - scan.heap = &heap; - retval = cgroup_scan_tasks(&scan); - - heap_free(&heap); - return retval; + scan.heap = heap; + cgroup_scan_tasks(&scan); } /** @@ -883,6 +871,7 @@ static int update_tasks_cpumask(struct cpuset *cs) */ static int update_cpumask(struct cpuset *cs, const char *buf) { + struct ptr_heap heap; struct cpuset trialcs; int retval; int is_load_balanced; @@ -917,6 +906,10 @@ static int update_cpumask(struct cpuset *cs, const char *buf) if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) return 0; + retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); + if (retval) + return retval; + is_load_balanced = is_sched_load_balance(&trialcs); mutex_lock(&callback_mutex); @@ -927,9 +920,9 @@ static int update_cpumask(struct cpuset *cs, const char *buf) * Scan tasks in the cpuset, and update the cpumasks of any * that need an update. */ - retval = update_tasks_cpumask(cs); - if (retval < 0) - return retval; + update_tasks_cpumask(cs, &heap); + + heap_free(&heap); if (is_load_balanced) async_rebuild_sched_domains(); @@ -1965,7 +1958,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root) nodes_empty(cp->mems_allowed)) remove_tasks_in_empty_cpuset(cp); else { - update_tasks_cpumask(cp); + update_tasks_cpumask(cp, NULL); update_tasks_nodemask(cp, &oldmems); } } -- cgit v1.2.3 From 024994310e10cd7632f43b6873558820308c1af1 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Sat, 13 Sep 2008 02:33:09 -0700 Subject: cpuset: hotplug documentation fix If all the cpus in a cpuset are offlined, the tasks in it will be moved to the nearest ancestor with non-empty cpus. Signed-off-by: Li Zefan Acked-by: Paul Jackson Cc: Paul Menage Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cpusets.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt index 1f5a924d1e5..47e568a9370 100644 --- a/Documentation/cpusets.txt +++ b/Documentation/cpusets.txt @@ -635,14 +635,16 @@ prior 'mems' setting, will not be moved. There is an exception to the above. If hotplug functionality is used to remove all the CPUs that are currently assigned to a cpuset, -then the kernel will automatically update the cpus_allowed of all -tasks attached to CPUs in that cpuset to allow all CPUs. When memory -hotplug functionality for removing Memory Nodes is available, a -similar exception is expected to apply there as well. In general, -the kernel prefers to violate cpuset placement, over starving a task -that has had all its allowed CPUs or Memory Nodes taken offline. User -code should reconfigure cpusets to only refer to online CPUs and Memory -Nodes when using hotplug to add or remove such resources. +then all the tasks in that cpuset will be moved to the nearest ancestor +with non-empty cpus. But the moving of some (or all) tasks might fail if +cpuset is bound with another cgroup subsystem which has some restrictions +on task attaching. In this failing case, those tasks will stay +in the original cpuset, and the kernel will automatically update +their cpus_allowed to allow all online CPUs. When memory hotplug +functionality for removing Memory Nodes is available, a similar exception +is expected to apply there as well. In general, the kernel prefers to +violate cpuset placement, over starving a task that has had all +its allowed CPUs or Memory Nodes taken offline. There is a second exception to the above. GFP_ATOMIC requests are kernel internal allocations that must be satisfied, immediately. -- cgit v1.2.3 From b261dfea48e81636516f4fa653667097638a8a62 Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Sat, 13 Sep 2008 02:33:10 -0700 Subject: coredump_filter: add description of bit 4 There is no description of bit 4 of coredump_filter in the documentation. This patch adds it. Signed-off-by: Hidehiro Kawai Cc: Roland McGrath Cc: Mel Gorman Acked-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/proc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 394eb2cc1c3..f566ad9bcb7 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -2413,6 +2413,8 @@ The following 4 memory types are supported: - (bit 1) anonymous shared memory - (bit 2) file-backed private memory - (bit 3) file-backed shared memory + - (bit 4) ELF header pages in file-backed private memory areas (it is + effective only if the bit 2 is cleared) Note that MMIO pages such as frame buffer are never dumped and vDSO pages are always dumped regardless of the bitmask status. -- cgit v1.2.3 From 1558182f651798164418abf53f76786da0ea4a6f Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sat, 13 Sep 2008 02:33:12 -0700 Subject: bfs: fix Lockdep warning This fixes: ============================================= [ INFO: possible recursive locking detected ] 2.6.27-rc5-00283-g70bb089 #68 --------------------------------------------- touch/6855 is trying to acquire lock: (&info->bfs_lock){--..}, at: [] bfs_delete_inode+0x9e/0x18c but task is already holding lock: (&info->bfs_lock){--..}, at: [] bfs_create+0x45/0x187 other info that might help us debug this: 2 locks held by touch/6855: #0: (&type->i_mutex_dir_key#5){--..}, at: [] do_filp_open+0x10b/0x62f #1: (&info->bfs_lock){--..}, at: [] bfs_create+0x45/0x187 stack backtrace: Pid: 6855, comm: touch Not tainted 2.6.27-rc5-00283-g70bb089 #68 [] validate_chain+0x458/0x9f4 [] ? trace_hardirqs_off+0xb/0xd [] __lock_acquire+0x666/0x6e0 [] lock_acquire+0x5b/0x77 [] ? bfs_delete_inode+0x9e/0x18c [] mutex_lock_nested+0xbc/0x234 [] ? bfs_delete_inode+0x9e/0x18c [] ? bfs_delete_inode+0x9e/0x18c [] bfs_delete_inode+0x9e/0x18c [] ? bfs_delete_inode+0x0/0x18c [] generic_delete_inode+0x94/0xfe [] generic_drop_inode+0x12/0x12f [] iput+0x4b/0x4e [] bfs_create+0x163/0x187 [] vfs_create+0xa6/0x114 [] do_filp_open+0x1ad/0x62f [] ? native_sched_clock+0x82/0x96 [] ? _spin_unlock+0x27/0x3c [] ? alloc_fd+0xbf/0xc9 [] ? sub_preempt_count+0x9d/0xab [] ? alloc_fd+0xbf/0xc9 [] do_sys_open+0x42/0xb8 [] ? trace_hardirqs_on_thunk+0xc/0x10 [] sys_open+0x1e/0x26 [] sysenter_do_call+0x12/0x31 ======================= The problem is that we don't unlock the bfs->lock mutex before calling iput (we do in the other cases). Signed-off-by: Eric Sesterhenn Cc: Tigran Aivazian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 87ee5ccee34..ed8feb052df 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -125,8 +125,8 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode, inode->i_ino); if (err) { inode_dec_link_count(inode); - iput(inode); mutex_unlock(&info->bfs_lock); + iput(inode); return err; } mutex_unlock(&info->bfs_lock); -- cgit v1.2.3 From d7a3e4959c28bccc25dd33315809ffcf40f7493e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sat, 13 Sep 2008 02:33:13 -0700 Subject: mm: ifdef Quicklists in /proc/meminfo A "Quicklists: 0 kB" line has just started appearing in /proc/meminfo, but most architectures (including x86) don't have them configured, so #ifdef it, like the highmem lines. And those architectures which do have quicklists configured are using them for page tables: so let's place it next to PageTables. Signed-off-by: Hugh Dickins Acked-by: Christoph Lameter Acked-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/proc_misc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 00f10a2dcf1..29e20c6b1f7 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -183,6 +183,9 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "SReclaimable: %8lu kB\n" "SUnreclaim: %8lu kB\n" "PageTables: %8lu kB\n" +#ifdef CONFIG_QUICKLIST + "Quicklists: %8lu kB\n" +#endif "NFS_Unstable: %8lu kB\n" "Bounce: %8lu kB\n" "WritebackTmp: %8lu kB\n" @@ -190,8 +193,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "Committed_AS: %8lu kB\n" "VmallocTotal: %8lu kB\n" "VmallocUsed: %8lu kB\n" - "VmallocChunk: %8lu kB\n" - "Quicklists: %8lu kB\n", + "VmallocChunk: %8lu kB\n", K(i.totalram), K(i.freeram), K(i.bufferram), @@ -216,6 +218,9 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(global_page_state(NR_SLAB_RECLAIMABLE)), K(global_page_state(NR_SLAB_UNRECLAIMABLE)), K(global_page_state(NR_PAGETABLE)), +#ifdef CONFIG_QUICKLIST + K(quicklist_total_size()), +#endif K(global_page_state(NR_UNSTABLE_NFS)), K(global_page_state(NR_BOUNCE)), K(global_page_state(NR_WRITEBACK_TEMP)), @@ -223,8 +228,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(committed), (unsigned long)VMALLOC_TOTAL >> 10, vmi.used >> 10, - vmi.largest_chunk >> 10, - K(quicklist_total_size()) + vmi.largest_chunk >> 10 ); len += hugetlb_report_meminfo(page + len); -- cgit v1.2.3 From 53604dbe1371c3c4458c2d741adbd8cfd8fe8e79 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sat, 13 Sep 2008 02:33:14 -0700 Subject: spi_mpc83xx: fix clockrate calculation for low speed Commit a61f5345 (spi_mpc83xx clockrate fixes) broke clockrate calculation for low speeds. SPMODE_DIV16 should be set if the divider is higher than 64, not only if the divider gets clipped to 1024. Furthermore, the clipping check was off by a factor 16 as well. Signed-off-by: Peter Korsgaard Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_mpc83xx.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 070c6219e2d..ab7ee445d8b 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -267,16 +267,13 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) cs->hw_mode |= SPMODE_LEN(bits_per_word); if ((mpc83xx_spi->spibrg / hz) > 64) { + cs->hw_mode |= SPMODE_DIV16; pm = mpc83xx_spi->spibrg / (hz * 64); if (pm > 16) { - cs->hw_mode |= SPMODE_DIV16; - pm /= 16; - if (pm > 16) { - dev_err(&spi->dev, "Requested speed is too " - "low: %d Hz. Will use %d Hz instead.\n", - hz, mpc83xx_spi->spibrg / 1024); - pm = 16; - } + dev_err(&spi->dev, "Requested speed is too " + "low: %d Hz. Will use %d Hz instead.\n", + hz, mpc83xx_spi->spibrg / 1024); + pm = 16; } } else pm = mpc83xx_spi->spibrg / (hz * 4); -- cgit v1.2.3 From aa77d96ba94326db4f50d2aa36602824dd03286a Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Sat, 13 Sep 2008 02:33:15 -0700 Subject: spi_mpc83xx: reject invalid transfer sizes Error out on transfer length != multiple of bytes per word with -EINVAL. Fixes a buffer overrun crash if length < bytes per word. Signed-off-by: Peter Korsgaard Acked-by: Joakim Tjernlund Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_mpc83xx.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index ab7ee445d8b..ac0e3e4b3c5 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -312,11 +312,20 @@ static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) if (t->bits_per_word) bits_per_word = t->bits_per_word; len = t->len; - if (bits_per_word > 8) + if (bits_per_word > 8) { + /* invalid length? */ + if (len & 1) + return -EINVAL; len /= 2; - if (bits_per_word > 16) + } + if (bits_per_word > 16) { + /* invalid length? */ + if (len & 1) + return -EINVAL; len /= 2; + } mpc83xx_spi->count = len; + INIT_COMPLETION(mpc83xx_spi->done); /* enable rx ints */ -- cgit v1.2.3 From 8423597d676615f3dd2d9ab36f59f147086b90b8 Mon Sep 17 00:00:00 2001 From: Ned Forrester Date: Sat, 13 Sep 2008 02:33:17 -0700 Subject: pxa2xx_spi: chipselect bugfixes Fixes several chipselect bugs in the pxa2xx_spi driver. These bugs are in all versions of this driver and prevent using it with chips like m25p16 flash. 1. The spi_transfer.cs_change flag is handled too early: before spi_transfer.delay_usecs applies, thus making the delay ineffective at holding chip select. 2. spi_transfer.delay_usecs is ignored on the last transfer of a message (likewise not holding chipselect long enough). 3. If spi_transfer.cs_change is set on the last transfer, the chip select is always disabled, instead of the intended meaning: optionally holding chip select enabled for the next message. Those first three bugs were fixed with a relocation of delays and chip select de-assertions. 4. If a message has the cs_change flag set on the last transfer, and had the chip select stayed enabled as requested (see 3, above), it would not have been disabled if the next message is for a different chip. Fixed by dropping chip select regardless of cs_change at end of a message, if there is no next message or if the next message is for a different chip. This patch should apply to all kernels back to and including 2.6.20; it was test patched against 2.6.20. An additional patch would be required for older kernels, but those versions are very buggy anyway. Signed-off-by: Ned Forrester Cc: Vernon Sauder Cc: Eric Miao Signed-off-by: David Brownell Cc: [2.6.25.x, 2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 59 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 34c7c987568..a7b9070e1b4 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -144,7 +144,6 @@ struct driver_data { size_t tx_map_len; u8 n_bytes; u32 dma_width; - int cs_change; int (*write)(struct driver_data *drv_data); int (*read)(struct driver_data *drv_data); irqreturn_t (*transfer_handler)(struct driver_data *drv_data); @@ -406,8 +405,45 @@ static void giveback(struct driver_data *drv_data) struct spi_transfer, transfer_list); + /* Delay if requested before any change in chip select */ + if (last_transfer->delay_usecs) + udelay(last_transfer->delay_usecs); + + /* Drop chip select UNLESS cs_change is true or we are returning + * a message with an error, or next message is for another chip + */ if (!last_transfer->cs_change) drv_data->cs_control(PXA2XX_CS_DEASSERT); + else { + struct spi_message *next_msg; + + /* Holding of cs was hinted, but we need to make sure + * the next message is for the same chip. Don't waste + * time with the following tests unless this was hinted. + * + * We cannot postpone this until pump_messages, because + * after calling msg->complete (below) the driver that + * sent the current message could be unloaded, which + * could invalidate the cs_control() callback... + */ + + /* get a pointer to the next message, if any */ + spin_lock_irqsave(&drv_data->lock, flags); + if (list_empty(&drv_data->queue)) + next_msg = NULL; + else + next_msg = list_entry(drv_data->queue.next, + struct spi_message, queue); + spin_unlock_irqrestore(&drv_data->lock, flags); + + /* see if the next and current messages point + * to the same chip + */ + if (next_msg && next_msg->spi != msg->spi) + next_msg = NULL; + if (!next_msg || msg->state == ERROR_STATE) + drv_data->cs_control(PXA2XX_CS_DEASSERT); + } msg->state = NULL; if (msg->complete) @@ -490,10 +526,9 @@ static void dma_transfer_complete(struct driver_data *drv_data) msg->actual_length += drv_data->len - (drv_data->rx_end - drv_data->rx); - /* Release chip select if requested, transfer delays are - * handled in pump_transfers */ - if (drv_data->cs_change) - drv_data->cs_control(PXA2XX_CS_DEASSERT); + /* Transfer delays and chip select release are + * handled in pump_transfers or giveback + */ /* Move to next transfer */ msg->state = next_transfer(drv_data); @@ -602,10 +637,9 @@ static void int_transfer_complete(struct driver_data *drv_data) drv_data->cur_msg->actual_length += drv_data->len - (drv_data->rx_end - drv_data->rx); - /* Release chip select if requested, transfer delays are - * handled in pump_transfers */ - if (drv_data->cs_change) - drv_data->cs_control(PXA2XX_CS_DEASSERT); + /* Transfer delays and chip select release are + * handled in pump_transfers or giveback + */ /* Move to next transfer */ drv_data->cur_msg->state = next_transfer(drv_data); @@ -840,13 +874,17 @@ static void pump_transfers(unsigned long data) return; } - /* Delay if requested at end of transfer*/ + /* Delay if requested at end of transfer before CS change */ if (message->state == RUNNING_STATE) { previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); if (previous->delay_usecs) udelay(previous->delay_usecs); + + /* Drop chip select only if cs_change is requested */ + if (previous->cs_change) + drv_data->cs_control(PXA2XX_CS_DEASSERT); } /* Check transfer length */ @@ -878,7 +916,6 @@ static void pump_transfers(unsigned long data) drv_data->len = transfer->len & DCMD_LENGTH; drv_data->write = drv_data->tx ? chip->write : null_writer; drv_data->read = drv_data->rx ? chip->read : null_reader; - drv_data->cs_change = transfer->cs_change; /* Change speed and bit per word on a per transfer */ cr0 = chip->cr0; -- cgit v1.2.3 From 7e96445533ac3f4f7964646a202ff3620602fab4 Mon Sep 17 00:00:00 2001 From: Ned Forrester Date: Sat, 13 Sep 2008 02:33:18 -0700 Subject: pxa2xx_spi: dma bugfixes Fixes two DMA bugs in the pxa2xx_spi driver. The first bug is in all versions of this driver; the second was introduced in the 2.6.20 kernel, and prevents using the driver with chips like m25p16 flash (which can issue large DMA reads). 1. Zero length transfers are permitted for use to insert timing, but pxa2xx_spi.c will fail if this is requested in DMA mode. Fixed by using programmed I/O (PIO) mode for such transfers. 2. Transfers larger than 8191 are not permitted in DMA mode. A test for length rejects all large transfers regardless of DMA or PIO mode. Worked around by rejecting only large transfers with DMA mapped buffers, and forcing all other transfers larger than 8191 to use PIO mode. A rate limited warning is issued for DMA transfers forced to PIO mode. This patch should apply to all kernels back to and including 2.6.20; it was test patched against 2.6.20. An additional patch would be required for older kernels, but those versions are very buggy anyway. Signed-off-by: Ned Forrester Cc: Vernon Sauder Cc: Eric Miao Signed-off-by: David Brownell Cc: [2.6.25.x, 2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 57 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index a7b9070e1b4..0e53354c1cf 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -47,9 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi"); #define MAX_BUSES 3 -#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) -#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) -#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) +#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) +#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) +#define IS_DMA_ALIGNED(x) (((x) & 0x07) == 0) +#define MAX_DMA_LEN 8191 /* * for testing SSCR1 changes that require SSP restart, basically @@ -887,14 +888,27 @@ static void pump_transfers(unsigned long data) drv_data->cs_control(PXA2XX_CS_DEASSERT); } - /* Check transfer length */ - if (transfer->len > 8191) - { - dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer " - "length greater than 8191\n"); - message->status = -EINVAL; - giveback(drv_data); - return; + /* Check for transfers that need multiple DMA segments */ + if (transfer->len > MAX_DMA_LEN && chip->enable_dma) { + + /* reject already-mapped transfers; PIO won't always work */ + if (message->is_dma_mapped + || transfer->rx_dma || transfer->tx_dma) { + dev_err(&drv_data->pdev->dev, + "pump_transfers: mapped transfer length " + "of %lu is greater than %d\n", + transfer->len, MAX_DMA_LEN); + message->status = -EINVAL; + giveback(drv_data); + return; + } + + /* warn ... we force this to PIO mode */ + if (printk_ratelimit()) + dev_warn(&message->spi->dev, "pump_transfers: " + "DMA disabled for transfer length %ld " + "greater than %d\n", + (long)drv_data->len, MAX_DMA_LEN); } /* Setup the transfer state based on the type of transfer */ @@ -962,7 +976,7 @@ static void pump_transfers(unsigned long data) &dma_thresh)) if (printk_ratelimit()) dev_warn(&message->spi->dev, - "pump_transfer: " + "pump_transfers: " "DMA burst size reduced to " "match bits_per_word\n"); } @@ -976,8 +990,23 @@ static void pump_transfers(unsigned long data) message->state = RUNNING_STATE; - /* Try to map dma buffer and do a dma transfer if successful */ - if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) { + /* Try to map dma buffer and do a dma transfer if successful, but + * only if the length is non-zero and less than MAX_DMA_LEN. + * + * Zero-length non-descriptor DMA is illegal on PXA2xx; force use + * of PIO instead. Care is needed above because the transfer may + * have have been passed with buffers that are already dma mapped. + * A zero-length transfer in PIO mode will not try to write/read + * to/from the buffers + * + * REVISIT large transfers are exactly where we most want to be + * using DMA. If this happens much, split those transfers into + * multiple DMA segments rather than forcing PIO. + */ + drv_data->dma_mapped = 0; + if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN) + drv_data->dma_mapped = map_dma_buffers(drv_data); + if (drv_data->dma_mapped) { /* Ensure we have the correct interrupt handler */ drv_data->transfer_handler = dma_transfer; -- cgit v1.2.3 From 5bead2a0680687b9576d57c177988e8aa082b922 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Sat, 13 Sep 2008 02:33:19 -0700 Subject: mm: mark the correct zone as full when scanning zonelists The iterator for_each_zone_zonelist() uses a struct zoneref *z cursor when scanning zonelists to keep track of where in the zonelist it is. The zoneref that is returned corresponds to the the next zone that is to be scanned, not the current one. It was intended to be treated as an opaque list. When the page allocator is scanning a zonelist, it marks elements in the zonelist corresponding to zones that are temporarily full. As the zonelist is being updated, it uses the cursor here; if (NUMA_BUILD) zlc_mark_zone_full(zonelist, z); This is intended to prevent rescanning in the near future but the zoneref cursor does not correspond to the zone that has been found to be full. This is an easy misunderstanding to make so this patch corrects the problem by changing zoneref cursor to be the current zone being scanned instead of the next one. Signed-off-by: Mel Gorman Cc: Andy Whitcroft Cc: KAMEZAWA Hiroyuki Cc: [2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 12 ++++++------ mm/mmzone.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 443bc7cd8c6..428328a05fa 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -751,8 +751,9 @@ static inline int zonelist_node_idx(struct zoneref *zoneref) * * This function returns the next zone at or below a given zone index that is * within the allowed nodemask using a cursor as the starting point for the - * search. The zoneref returned is a cursor that is used as the next starting - * point for future calls to next_zones_zonelist(). + * search. The zoneref returned is a cursor that represents the current zone + * being examined. It should be advanced by one before calling + * next_zones_zonelist again. */ struct zoneref *next_zones_zonelist(struct zoneref *z, enum zone_type highest_zoneidx, @@ -768,9 +769,8 @@ struct zoneref *next_zones_zonelist(struct zoneref *z, * * This function returns the first zone at or below a given zone index that is * within the allowed nodemask. The zoneref returned is a cursor that can be - * used to iterate the zonelist with next_zones_zonelist. The cursor should - * not be used by the caller as it does not match the value of the zone - * returned. + * used to iterate the zonelist with next_zones_zonelist by advancing it by + * one before calling. */ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist, enum zone_type highest_zoneidx, @@ -795,7 +795,7 @@ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist, #define for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \ for (z = first_zones_zonelist(zlist, highidx, nodemask, &zone); \ zone; \ - z = next_zones_zonelist(z, highidx, nodemask, &zone)) \ + z = next_zones_zonelist(++z, highidx, nodemask, &zone)) \ /** * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index diff --git a/mm/mmzone.c b/mm/mmzone.c index 486ed595ee6..16ce8b955dc 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -69,6 +69,6 @@ struct zoneref *next_zones_zonelist(struct zoneref *z, (z->zone && !zref_in_nodemask(z, nodes))) z++; - *zone = zonelist_zone(z++); + *zone = zonelist_zone(z); return z; } -- cgit v1.2.3 From 9f986a8cdf94a5855201cf67db6ffdf926bc4cd9 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 13 Sep 2008 02:33:20 -0700 Subject: Documentation/ABI: /sys/class/gpio Provide summary ABI docs about the /sys/class/gpio files. Signed-off-by: David Brownell Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-gpio | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-gpio diff --git a/Documentation/ABI/testing/sysfs-gpio b/Documentation/ABI/testing/sysfs-gpio new file mode 100644 index 00000000000..8aab8092ad3 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-gpio @@ -0,0 +1,26 @@ +What: /sys/class/gpio/ +Date: July 2008 +KernelVersion: 2.6.27 +Contact: David Brownell +Description: + + As a Kconfig option, individual GPIO signals may be accessed from + userspace. GPIOs are only made available to userspace by an explicit + "export" operation. If a given GPIO is not claimed for use by + kernel code, it may be exported by userspace (and unexported later). + Kernel code may export it for complete or partial access. + + GPIOs are identified as they are inside the kernel, using integers in + the range 0..INT_MAX. See Documentation/gpio.txt for more information. + + /sys/class/gpio + /export ... asks the kernel to export a GPIO to userspace + /unexport ... to return a GPIO to the kernel + /gpioN ... for each exported GPIO #N + /value ... always readable, writes fail for input GPIOs + /direction ... r/w as: in, out (default low); write: high, low + /gpiochipN ... for each gpiochip; #N is its first GPIO + /base ... (r/o) same as N + /label ... (r/o) descriptive, not necessarily unique + /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) + -- cgit v1.2.3 From ecc9a04de66e7b2d40d539cc39d5798bc46553e9 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 13 Sep 2008 02:33:21 -0700 Subject: MAINTAINERS: fix USB VIDEO CLASS mail list address It should be linux-uvc-devel@lists.berlios.de. Signed-off-by: Ming Lei Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 186be3ba506..0a613cb926c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4365,7 +4365,7 @@ S: Maintained USB VIDEO CLASS P: Laurent Pinchart M: laurent.pinchart@skynet.be -L: linx-uvc-devel@berlios.de +L: linux-uvc-devel@lists.berlios.de L: video4linux-list@redhat.com W: http://linux-uvc.berlios.de S: Maintained -- cgit v1.2.3 From 8275d102f8dbaa4f437f6b03b00d85bfb4e16025 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Sat, 13 Sep 2008 02:33:22 -0700 Subject: ia64: fix panic during `modprobe -r xpc' If you are on ia64 and you modprobe xpc then modprobe -r xpc, you immediately get a panic. xpc depends on xp which depends on gru for a symbol. That symbol is only used when we are running on UV hardware. Currently, the GRU driver detects we are not on UV hardware and does no initializing. It does not do the same check when unloading. As a result, the gru driver attempts to tear down stuff that was not setup. This is a simple two-line workaround to get us through this release. Once 2.6.28 is opened, we need to rework the symbols that xp is depending on from gru so the gru driver can properly fail to load when hardware is not available. Signed-off-by: Robin Holt Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-gru/grufile.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index 23c91f5f6b6..d61cee796ef 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c @@ -445,6 +445,9 @@ static void __exit gru_exit(void) int order = get_order(sizeof(struct gru_state) * GRU_CHIPLETS_PER_BLADE); + if (!IS_UV()) + return; + for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++) free_irq(IRQ_GRU + i, NULL); -- cgit v1.2.3 From 3aa04f1b07352be89960bddca4db0d5d8c09510c Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Sat, 13 Sep 2008 02:33:23 -0700 Subject: atmel_lcdfb: disable LCD and DMA engines when suspending When suspending the system with atmel_lcdfb enabled, I sometimes see this: atmel_lcdfb atmel_lcdfb.0: FIFO underflow 0x10 Which can be explained by the fact that we're not stopping the LCD controller and its DMA engine when suspending, we're just gating the clocks to them. There's another potential issue which may be harder to trigger but much more nasty: If we gate the clocks at _just_ the right moment, e.g. when the DMA engine is doing a bus transaction, we may cause the DMA engine to violate the system bus protocol and cause a lockup. Avoid these issues by shutting down the LCD controller before entering suspend (and restarting it when resuming). This prevents the underrun from happening in the first place, and prevents whatever nastiness is happening when the bus clock stops in the middle of a DMA transfer. Signed-off-by: Haavard Skinnemoen Acked-by: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/atmel_lcdfb.c | 84 ++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5a24c6411d3..75dac578104 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -208,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) return value; } +static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo) +{ + /* Turn off the LCD controller and the DMA controller */ + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, + sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + + /* Wait for the LCDC core to become idle */ + while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) + msleep(10); + + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); +} + +static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo) +{ + atmel_lcdfb_stop_nowait(sinfo); + + /* Wait for DMA engine to become idle... */ + while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) + msleep(10); +} + +static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo) +{ + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); + lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, + (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) + | ATMEL_LCDC_PWR); +} + static void atmel_lcdfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var) { @@ -420,26 +450,8 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) { might_sleep(); - /* LCD power off */ - lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); - - /* wait for the LCDC core to become idle */ - while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) - msleep(10); - - /* DMA disable */ - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); - - /* wait for DMA engine to become idle */ - while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) - msleep(10); - - /* LCD power on */ - lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, - (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); - - /* DMA enable */ - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); + atmel_lcdfb_stop(sinfo); + atmel_lcdfb_start(sinfo); } /** @@ -471,14 +483,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) info->var.xres, info->var.yres, info->var.xres_virtual, info->var.yres_virtual); - /* Turn off the LCD controller and the DMA controller */ - lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); - - /* Wait for the LCDC core to become idle */ - while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) - msleep(10); - - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); + atmel_lcdfb_stop_nowait(sinfo); if (info->var.bits_per_pixel == 1) info->fix.visual = FB_VISUAL_MONO01; @@ -583,13 +588,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) msleep(10); - dev_dbg(info->device, " * re-enable DMA engine\n"); - /* ...and enable it with updated configuration */ - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); - - dev_dbg(info->device, " * re-enable LCDC core\n"); - lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, - (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); + atmel_lcdfb_start(sinfo); dev_dbg(info->device, " * DONE\n"); @@ -1032,11 +1031,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) struct fb_info *info = platform_get_drvdata(pdev); struct atmel_lcdfb_info *sinfo = info->par; + /* + * We don't want to handle interrupts while the clock is + * stopped. It may take forever. + */ + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); + sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); if (sinfo->atmel_lcdfb_power_control) sinfo->atmel_lcdfb_power_control(0); + + atmel_lcdfb_stop(sinfo); atmel_lcdfb_stop_clock(sinfo); + return 0; } @@ -1046,9 +1054,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) struct atmel_lcdfb_info *sinfo = info->par; atmel_lcdfb_start_clock(sinfo); + atmel_lcdfb_start(sinfo); if (sinfo->atmel_lcdfb_power_control) sinfo->atmel_lcdfb_power_control(1); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); + + /* Enable FIFO & DMA errors */ + lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI + | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); + return 0; } -- cgit v1.2.3 From 42cde4309b8f2671610be049352df2f8716e8809 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 13 Sep 2008 02:33:24 -0700 Subject: spi_s3c24xx: fix section warning Fix the section mismatch warning generated by the incorrect naming of s3c24xx_spidrv which should be s3c24xx_spi_driver: WARNING: drivers/spi/spi_s3c24xx.o(.data+0x4): Section mismatch in reference from the variable s3c24xx_spidrv to the (unknown reference) .exit.text:(unknown) Signed-off-by: Ben Dooks Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_s3c24xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 98abc73c1a1..3eb414b84a9 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -430,7 +430,7 @@ static int s3c24xx_spi_resume(struct platform_device *pdev) #endif MODULE_ALIAS("platform:s3c2410-spi"); -static struct platform_driver s3c24xx_spidrv = { +static struct platform_driver s3c24xx_spi_driver = { .remove = __exit_p(s3c24xx_spi_remove), .suspend = s3c24xx_spi_suspend, .resume = s3c24xx_spi_resume, @@ -442,12 +442,12 @@ static struct platform_driver s3c24xx_spidrv = { static int __init s3c24xx_spi_init(void) { - return platform_driver_probe(&s3c24xx_spidrv, s3c24xx_spi_probe); + return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe); } static void __exit s3c24xx_spi_exit(void) { - platform_driver_unregister(&s3c24xx_spidrv); + platform_driver_unregister(&s3c24xx_spi_driver); } module_init(s3c24xx_spi_init); -- cgit v1.2.3 From 8d99f83b9478768d3a8d7d1bcd9bd182c75a0447 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 13 Sep 2008 02:33:25 -0700 Subject: rescan_partitions(): make device capacity errors non-fatal Herton Krzesinski reports that the error-checking changes in 04ebd4aee52b06a2c38127d9208546e5b96f3a19 ("block/ioctl.c and fs/partition/check.c: check value returned by add_partition") cause his buggy USB camera to no longer mount. "The camera is an Olympus X-840. The original issue comes from the camera itself: its format program creates a partition with an off by one error". Buggy devices happen. It is better for the kernel to warn and to proceed with the mount. Reported-by: Herton Ronaldo Krzesinski Cc: Abdel Benamrouche Cc: Jens Axboe Cc: Alan Stern Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/check.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 7d6b34e201d..ecc3330972e 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -499,9 +499,9 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (!size) continue; if (from + size > get_capacity(disk)) { - printk(KERN_ERR " %s: p%d exceeds device capacity\n", + printk(KERN_WARNING + "%s: p%d exceeds device capacity\n", disk->disk_name, p); - continue; } res = add_partition(disk, p, from, size, state->parts[p].flags); if (res) { -- cgit v1.2.3 From 8e82f8c34b1759ae0d80fe96101746ec51fb1ba4 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Sat, 13 Sep 2008 02:33:26 -0700 Subject: memstick: fix MSProHG 8-bit interface mode support - 8-bit interface mode never worked properly. The only adapter I have which supports the 8b mode (the Jmicron) had some problems with its clock wiring and they discovered it only now. We also discovered that ProHG media is more sensitive to the ordering of initialization commands. - Make the driver fall back to highest supported mode instead of always falling back to serial. The driver will attempt the switch to 8b mode for any new MSPro card, but not all of them support it. Previously, these new cards ended up in serial mode, which is not the best idea (they work fine with 4b, after all). - Edit some macros for better conformance to Sony documentation Signed-off-by: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/core/memstick.c | 10 ++-- drivers/memstick/core/mspro_block.c | 33 ++++++++++--- drivers/memstick/host/jmb38x_ms.c | 39 ++++++++++----- include/linux/memstick.h | 97 +++++++++++++++++++------------------ 4 files changed, 106 insertions(+), 73 deletions(-) diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index a38005008a2..cea46906408 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -185,7 +185,7 @@ static void memstick_free(struct device *dev) } static struct class memstick_host_class = { - .name = "memstick_host", + .name = "memstick_host", .dev_release = memstick_free }; @@ -264,7 +264,7 @@ EXPORT_SYMBOL(memstick_new_req); * @sg - TPC argument */ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, - struct scatterlist *sg) + const struct scatterlist *sg) { mrq->tpc = tpc; if (tpc & 8) @@ -294,7 +294,7 @@ EXPORT_SYMBOL(memstick_init_req_sg); * user supplied buffer. */ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, - void *buf, size_t length) + const void *buf, size_t length) { mrq->tpc = tpc; if (tpc & 8) @@ -439,7 +439,7 @@ static void memstick_check(struct work_struct *work) if (!host->card) { if (memstick_power_on(host)) goto out_power_off; - } else + } else if (host->card->stop) host->card->stop(host->card); card = memstick_alloc_card(host); @@ -458,7 +458,7 @@ static void memstick_check(struct work_struct *work) || !(host->card->check(host->card))) { device_unregister(&host->card->dev); host->card = NULL; - } else + } else if (host->card->start) host->card->start(host->card); } diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 44b1817f2f2..d2d2318dafa 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -30,6 +30,8 @@ module_param(major, int, 0644); #define MSPRO_BLOCK_SIGNATURE 0xa5c3 #define MSPRO_BLOCK_MAX_ATTRIBUTES 41 +#define MSPRO_BLOCK_PART_SHIFT 3 + enum { MSPRO_BLOCK_ID_SYSINFO = 0x10, MSPRO_BLOCK_ID_MODELNAME = 0x15, @@ -195,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) static int mspro_block_disk_release(struct gendisk *disk) { struct mspro_block_data *msb = disk->private_data; - int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT; + int disk_id = disk->first_minor >> MSPRO_BLOCK_PART_SHIFT; mutex_lock(&mspro_block_disk_lock); @@ -877,6 +879,7 @@ static int mspro_block_switch_interface(struct memstick_dev *card) struct mspro_block_data *msb = memstick_get_drvdata(card); int rc = 0; +try_again: if (msb->caps & MEMSTICK_CAP_PAR4) rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4); else @@ -930,6 +933,18 @@ static int mspro_block_switch_interface(struct memstick_dev *card) rc = memstick_set_rw_addr(card); if (!rc) rc = mspro_block_set_interface(card, msb->system); + + if (!rc) { + msleep(150); + rc = mspro_block_wait_for_ced(card); + if (rc) + return rc; + + if (msb->caps & MEMSTICK_CAP_PAR8) { + msb->caps &= ~MEMSTICK_CAP_PAR8; + goto try_again; + } + } } return rc; } @@ -1117,14 +1132,16 @@ static int mspro_block_init_card(struct memstick_dev *card) return -EIO; msb->caps = host->caps; - rc = mspro_block_switch_interface(card); + + msleep(150); + rc = mspro_block_wait_for_ced(card); if (rc) return rc; - msleep(200); - rc = mspro_block_wait_for_ced(card); + rc = mspro_block_switch_interface(card); if (rc) return rc; + dev_dbg(&card->dev, "card activated\n"); if (msb->system != MEMSTICK_SYS_SERIAL) msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; @@ -1192,12 +1209,12 @@ static int mspro_block_init_disk(struct memstick_dev *card) if (rc) return rc; - if ((disk_id << MEMSTICK_PART_SHIFT) > 255) { + if ((disk_id << MSPRO_BLOCK_PART_SHIFT) > 255) { rc = -ENOSPC; goto out_release_id; } - msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT); + msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT); if (!msb->disk) { rc = -ENOMEM; goto out_release_id; @@ -1220,7 +1237,7 @@ static int mspro_block_init_disk(struct memstick_dev *card) MSPRO_BLOCK_MAX_PAGES * msb->page_size); msb->disk->major = major; - msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT; + msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT; msb->disk->fops = &ms_block_bdops; msb->usage_count = 1; msb->disk->private_data = msb; @@ -1416,7 +1433,7 @@ out_unlock: static struct memstick_device_id mspro_block_id_tbl[] = { {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO, - MEMSTICK_CLASS_GENERIC_DUO}, + MEMSTICK_CLASS_DUO}, {} }; diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 3485c63d20b..2fb95a5b72e 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -81,6 +81,8 @@ struct jmb38x_ms { #define TPC_CODE_SZ_MASK 0x00000700 #define TPC_DATA_SZ_MASK 0x00000007 +#define HOST_CONTROL_TDELAY_EN 0x00040000 +#define HOST_CONTROL_HW_OC_P 0x00010000 #define HOST_CONTROL_RESET_REQ 0x00008000 #define HOST_CONTROL_REI 0x00004000 #define HOST_CONTROL_LED 0x00000400 @@ -88,6 +90,7 @@ struct jmb38x_ms { #define HOST_CONTROL_RESET 0x00000100 #define HOST_CONTROL_POWER_EN 0x00000080 #define HOST_CONTROL_CLOCK_EN 0x00000040 +#define HOST_CONTROL_REO 0x00000008 #define HOST_CONTROL_IF_SHIFT 4 #define HOST_CONTROL_IF_SERIAL 0x0 @@ -133,11 +136,15 @@ struct jmb38x_ms { #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 #define CLOCK_CONTROL_40MHZ 0x00000001 -#define CLOCK_CONTROL_50MHZ 0x00000002 +#define CLOCK_CONTROL_50MHZ 0x0000000a #define CLOCK_CONTROL_60MHZ 0x00000008 #define CLOCK_CONTROL_62_5MHZ 0x0000000c #define CLOCK_CONTROL_OFF 0x00000000 +#define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 +#define PCI_CTL_CLOCK_DLY_MASK_A 0x00000f00 +#define PCI_CTL_CLOCK_DLY_MASK_B 0x0000f000 + enum { CMD_READY = 0x01, FIFO_READY = 0x02, @@ -367,8 +374,7 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) return host->req->error; } - dev_dbg(&msh->dev, "control %08x\n", - readl(host->addr + HOST_CONTROL)); + dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL)); dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS)); dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS)); @@ -637,7 +643,7 @@ static int jmb38x_ms_reset(struct jmb38x_ms_host *host) ndelay(20); } dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); - return -EIO; + /* return -EIO; */ reset_next: writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN @@ -680,7 +686,9 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, host_ctl = 7; host_ctl |= HOST_CONTROL_POWER_EN - | HOST_CONTROL_CLOCK_EN; + | HOST_CONTROL_CLOCK_EN + | HOST_CONTROL_HW_OC_P + | HOST_CONTROL_TDELAY_EN; writel(host_ctl, host->addr + HOST_CONTROL); writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 @@ -704,33 +712,40 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, break; case MEMSTICK_INTERFACE: host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); + pci_read_config_dword(host->chip->pdev, + PCI_CTL_CLOCK_DLY_ADDR, + &clock_delay); + clock_delay &= host->id ? ~PCI_CTL_CLOCK_DLY_MASK_B + : ~PCI_CTL_CLOCK_DLY_MASK_A; if (value == MEMSTICK_SERIAL) { host_ctl &= ~HOST_CONTROL_FAST_CLK; + host_ctl &= ~HOST_CONTROL_REO; host_ctl |= HOST_CONTROL_IF_SERIAL << HOST_CONTROL_IF_SHIFT; host_ctl |= HOST_CONTROL_REI; clock_ctl = CLOCK_CONTROL_40MHZ; - clock_delay = 0; } else if (value == MEMSTICK_PAR4) { - host_ctl |= HOST_CONTROL_FAST_CLK; + host_ctl |= HOST_CONTROL_FAST_CLK | HOST_CONTROL_REO; host_ctl |= HOST_CONTROL_IF_PAR4 << HOST_CONTROL_IF_SHIFT; host_ctl &= ~HOST_CONTROL_REI; clock_ctl = CLOCK_CONTROL_40MHZ; - clock_delay = 4; + clock_delay |= host->id ? (4 << 12) : (4 << 8); } else if (value == MEMSTICK_PAR8) { host_ctl |= HOST_CONTROL_FAST_CLK; host_ctl |= HOST_CONTROL_IF_PAR8 << HOST_CONTROL_IF_SHIFT; - host_ctl &= ~HOST_CONTROL_REI; - clock_ctl = CLOCK_CONTROL_60MHZ; - clock_delay = 0; + host_ctl &= ~(HOST_CONTROL_REI | HOST_CONTROL_REO); + clock_ctl = CLOCK_CONTROL_50MHZ; } else return -EINVAL; + writel(host_ctl, host->addr + HOST_CONTROL); writel(clock_ctl, host->addr + CLOCK_CONTROL); - writel(clock_delay, host->addr + CLOCK_DELAY); + pci_write_config_dword(host->chip->pdev, + PCI_CTL_CLOCK_DLY_ADDR, + clock_delay); break; }; return 0; diff --git a/include/linux/memstick.h b/include/linux/memstick.h index a9f998a3f48..d0c37e68223 100644 --- a/include/linux/memstick.h +++ b/include/linux/memstick.h @@ -21,30 +21,30 @@ struct ms_status_register { unsigned char reserved; unsigned char interrupt; -#define MEMSTICK_INT_CMDNAK 0x0001 -#define MEMSTICK_INT_IOREQ 0x0008 -#define MEMSTICK_INT_IOBREQ 0x0010 -#define MEMSTICK_INT_BREQ 0x0020 -#define MEMSTICK_INT_ERR 0x0040 -#define MEMSTICK_INT_CED 0x0080 +#define MEMSTICK_INT_CMDNAK 0x01 +#define MEMSTICK_INT_IOREQ 0x08 +#define MEMSTICK_INT_IOBREQ 0x10 +#define MEMSTICK_INT_BREQ 0x20 +#define MEMSTICK_INT_ERR 0x40 +#define MEMSTICK_INT_CED 0x80 unsigned char status0; -#define MEMSTICK_STATUS0_WP 0x0001 -#define MEMSTICK_STATUS0_SL 0x0002 -#define MEMSTICK_STATUS0_BF 0x0010 -#define MEMSTICK_STATUS0_BE 0x0020 -#define MEMSTICK_STATUS0_FB0 0x0040 -#define MEMSTICK_STATUS0_MB 0x0080 +#define MEMSTICK_STATUS0_WP 0x01 +#define MEMSTICK_STATUS0_SL 0x02 +#define MEMSTICK_STATUS0_BF 0x10 +#define MEMSTICK_STATUS0_BE 0x20 +#define MEMSTICK_STATUS0_FB0 0x40 +#define MEMSTICK_STATUS0_MB 0x80 unsigned char status1; -#define MEMSTICK_STATUS1_UCFG 0x0001 -#define MEMSTICK_STATUS1_FGER 0x0002 -#define MEMSTICK_STATUS1_UCEX 0x0004 -#define MEMSTICK_STATUS1_EXER 0x0008 -#define MEMSTICK_STATUS1_UCDT 0x0010 -#define MEMSTICK_STATUS1_DTER 0x0020 -#define MEMSTICK_STATUS1_FBI 0x0040 -#define MEMSTICK_STATUS1_MB 0x0080 +#define MEMSTICK_STATUS1_UCFG 0x01 +#define MEMSTICK_STATUS1_FGER 0x02 +#define MEMSTICK_STATUS1_UCEX 0x04 +#define MEMSTICK_STATUS1_EXER 0x08 +#define MEMSTICK_STATUS1_UCDT 0x10 +#define MEMSTICK_STATUS1_DTER 0x20 +#define MEMSTICK_STATUS1_FB1 0x40 +#define MEMSTICK_STATUS1_MB 0x80 } __attribute__((packed)); struct ms_id_register { @@ -56,32 +56,32 @@ struct ms_id_register { struct ms_param_register { unsigned char system; -#define MEMSTICK_SYS_ATEN 0xc0 -#define MEMSTICK_SYS_BAMD 0x80 #define MEMSTICK_SYS_PAM 0x08 +#define MEMSTICK_SYS_BAMD 0x80 unsigned char block_address_msb; unsigned short block_address; unsigned char cp; -#define MEMSTICK_CP_BLOCK 0x0000 -#define MEMSTICK_CP_PAGE 0x0020 -#define MEMSTICK_CP_EXTRA 0x0040 -#define MEMSTICK_CP_OVERWRITE 0x0080 +#define MEMSTICK_CP_BLOCK 0x00 +#define MEMSTICK_CP_PAGE 0x20 +#define MEMSTICK_CP_EXTRA 0x40 +#define MEMSTICK_CP_OVERWRITE 0x80 unsigned char page_address; } __attribute__((packed)); struct ms_extra_data_register { unsigned char overwrite_flag; -#define MEMSTICK_OVERWRITE_UPDATA 0x0010 -#define MEMSTICK_OVERWRITE_PAGE 0x0060 -#define MEMSTICK_OVERWRITE_BLOCK 0x0080 +#define MEMSTICK_OVERWRITE_UDST 0x10 +#define MEMSTICK_OVERWRITE_PGST1 0x20 +#define MEMSTICK_OVERWRITE_PGST0 0x40 +#define MEMSTICK_OVERWRITE_BKST 0x80 unsigned char management_flag; -#define MEMSTICK_MANAGEMENT_SYSTEM 0x0004 -#define MEMSTICK_MANAGEMENT_TRANS_TABLE 0x0008 -#define MEMSTICK_MANAGEMENT_COPY 0x0010 -#define MEMSTICK_MANAGEMENT_ACCESS 0x0020 +#define MEMSTICK_MANAGEMENT_SYSFLG 0x04 +#define MEMSTICK_MANAGEMENT_ATFLG 0x08 +#define MEMSTICK_MANAGEMENT_SCMS1 0x10 +#define MEMSTICK_MANAGEMENT_SCMS0 0x20 unsigned short logical_address; } __attribute__((packed)); @@ -96,9 +96,9 @@ struct ms_register { struct mspro_param_register { unsigned char system; -#define MEMSTICK_SYS_SERIAL 0x80 #define MEMSTICK_SYS_PAR4 0x00 #define MEMSTICK_SYS_PAR8 0x40 +#define MEMSTICK_SYS_SERIAL 0x80 unsigned short data_count; unsigned int data_address; @@ -147,7 +147,7 @@ struct ms_register_addr { unsigned char w_length; } __attribute__((packed)); -enum { +enum memstick_tpc { MS_TPC_READ_MG_STATUS = 0x01, MS_TPC_READ_LONG_DATA = 0x02, MS_TPC_READ_SHORT_DATA = 0x03, @@ -167,7 +167,7 @@ enum { MS_TPC_SET_CMD = 0x0e }; -enum { +enum memstick_command { MS_CMD_BLOCK_END = 0x33, MS_CMD_RESET = 0x3c, MS_CMD_BLOCK_WRITE = 0x55, @@ -201,8 +201,6 @@ enum { /*** Driver structures and functions ***/ -#define MEMSTICK_PART_SHIFT 3 - enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE }; #define MEMSTICK_POWER_OFF 0 @@ -215,24 +213,27 @@ enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE }; struct memstick_host; struct memstick_driver; +struct memstick_device_id { + unsigned char match_flags; #define MEMSTICK_MATCH_ALL 0x01 + unsigned char type; #define MEMSTICK_TYPE_LEGACY 0xff #define MEMSTICK_TYPE_DUO 0x00 #define MEMSTICK_TYPE_PRO 0x01 + unsigned char category; #define MEMSTICK_CATEGORY_STORAGE 0xff #define MEMSTICK_CATEGORY_STORAGE_DUO 0x00 +#define MEMSTICK_CATEGORY_IO 0x01 +#define MEMSTICK_CATEGORY_IO_PRO 0x10 -#define MEMSTICK_CLASS_GENERIC 0xff -#define MEMSTICK_CLASS_GENERIC_DUO 0x00 - - -struct memstick_device_id { - unsigned char match_flags; - unsigned char type; - unsigned char category; unsigned char class; +#define MEMSTICK_CLASS_FLASH 0xff +#define MEMSTICK_CLASS_DUO 0x00 +#define MEMSTICK_CLASS_ROM 0x01 +#define MEMSTICK_CLASS_RO 0x02 +#define MEMSTICK_CLASS_WP 0x03 }; struct memstick_request { @@ -319,9 +320,9 @@ void memstick_suspend_host(struct memstick_host *host); void memstick_resume_host(struct memstick_host *host); void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, - struct scatterlist *sg); + const struct scatterlist *sg); void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, - void *buf, size_t length); + const void *buf, size_t length); int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq); void memstick_new_req(struct memstick_host *host); -- cgit v1.2.3 From 212387055902b65f79463d1934033255aa6b99e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 13 Sep 2008 22:29:31 +0200 Subject: =?UTF-8?q?Add=20Uwe=20Kleine-K=C3=B6nig=20to=20.mailmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a few commits that misencoded my name (or used "oe" instead of "ö"). So add a correct version to .mailmap. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Torvalds --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 726084286d3..dfab12f809e 100644 --- a/.mailmap +++ b/.mailmap @@ -96,4 +96,6 @@ Tejun Heo Thomas Graf Tony Luck Tsuneo Yoshioka +Uwe Kleine-König +Uwe Kleine-König Valdis Kletnieks -- cgit v1.2.3 From 1fa38c586e92cce4ce06bfc08ad3134b8445170b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 08:09:10 +0200 Subject: mv643xx_eth: move all work to the napi poll handler Move link status handling, transmit reclaim and TX_END handling from the interrupt handler to the napi poll handler. This allows switching ->lock over to a non-IRQ-safe lock and removes all explicit interrupt disabling from the driver. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 521 ++++++++++++++++++++++++---------------------- 1 file changed, 275 insertions(+), 246 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 1ceed879861..3db422b6666 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -57,7 +57,6 @@ static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.3"; -#define MV643XX_ETH_TX_FAST_REFILL /* * Registers shared between all ports. @@ -103,7 +102,6 @@ static char mv643xx_eth_driver_version[] = "1.3"; #define TX_BW_MTU(p) (0x0458 + ((p) << 10)) #define TX_BW_BURST(p) (0x045c + ((p) << 10)) #define INT_CAUSE(p) (0x0460 + ((p) << 10)) -#define INT_TX_END_0 0x00080000 #define INT_TX_END 0x07f80000 #define INT_RX 0x000003fc #define INT_EXT 0x00000002 @@ -355,6 +353,14 @@ struct mv643xx_eth_private { struct work_struct tx_timeout_task; struct mii_if_info mii; + struct napi_struct napi; + u8 work_link; + u8 work_tx; + u8 work_tx_end; + u8 work_rx; + u8 work_rx_refill; + u8 work_rx_oom; + /* * RX state. */ @@ -362,7 +368,6 @@ struct mv643xx_eth_private { unsigned long rx_desc_sram_addr; int rx_desc_sram_size; int rxq_count; - struct napi_struct napi; struct timer_list rx_oom; struct rx_queue rxq[8]; @@ -374,9 +379,6 @@ struct mv643xx_eth_private { int tx_desc_sram_size; int txq_count; struct tx_queue txq[8]; -#ifdef MV643XX_ETH_TX_FAST_REFILL - int tx_clean_threshold; -#endif }; @@ -446,82 +448,19 @@ static void txq_disable(struct tx_queue *txq) udelay(10); } -static void __txq_maybe_wake(struct tx_queue *txq) +static void txq_maybe_wake(struct tx_queue *txq) { struct mv643xx_eth_private *mp = txq_to_mp(txq); struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); + spin_lock(&mp->lock); if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) netif_tx_wake_queue(nq); + spin_unlock(&mp->lock); } -/* rx ***********************************************************************/ -static void txq_reclaim(struct tx_queue *txq, int force); - -static int rxq_refill(struct rx_queue *rxq, int budget, int *oom) -{ - int skb_size; - int refilled; - - /* - * Reserve 2+14 bytes for an ethernet header (the hardware - * automatically prepends 2 bytes of dummy data to each - * received packet), 16 bytes for up to four VLAN tags, and - * 4 bytes for the trailing FCS -- 36 bytes total. - */ - skb_size = rxq_to_mp(rxq)->dev->mtu + 36; - - /* - * Make sure that the skb size is a multiple of 8 bytes, as - * the lower three bits of the receive descriptor's buffer - * size field are ignored by the hardware. - */ - skb_size = (skb_size + 7) & ~7; - - refilled = 0; - while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { - struct sk_buff *skb; - int unaligned; - int rx; - - skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1); - if (skb == NULL) { - *oom = 1; - break; - } - - unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); - if (unaligned) - skb_reserve(skb, dma_get_cache_alignment() - unaligned); - - refilled++; - rxq->rx_desc_count++; - - rx = rxq->rx_used_desc++; - if (rxq->rx_used_desc == rxq->rx_ring_size) - rxq->rx_used_desc = 0; - - rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data, - skb_size, DMA_FROM_DEVICE); - rxq->rx_desc_area[rx].buf_size = skb_size; - rxq->rx_skb[rx] = skb; - wmb(); - rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA | - RX_ENABLE_INTERRUPT; - wmb(); - - /* - * The hardware automatically prepends 2 bytes of - * dummy data to each received packet, so that the - * IP header ends up 16-byte aligned. - */ - skb_reserve(skb, 2); - } - - return refilled; -} - +/* rx napi ******************************************************************/ static int rxq_process(struct rx_queue *rxq, int budget) { struct mv643xx_eth_private *mp = rxq_to_mp(rxq); @@ -553,6 +492,8 @@ static int rxq_process(struct rx_queue *rxq, int budget) rxq->rx_desc_count--; rx++; + mp->work_rx_refill |= 1 << rxq->index; + /* * Update statistics. * @@ -605,54 +546,78 @@ static int rxq_process(struct rx_queue *rxq, int budget) mp->dev->last_rx = jiffies; } + if (rx < budget) + mp->work_rx &= ~(1 << rxq->index); + return rx; } -static int mv643xx_eth_poll(struct napi_struct *napi, int budget) +static int rxq_refill(struct rx_queue *rxq, int budget) { - struct mv643xx_eth_private *mp; - int work_done; - int oom; - int i; + struct mv643xx_eth_private *mp = rxq_to_mp(rxq); + int skb_size; + int refilled; - mp = container_of(napi, struct mv643xx_eth_private, napi); + /* + * Reserve 2+14 bytes for an ethernet header (the hardware + * automatically prepends 2 bytes of dummy data to each + * received packet), 16 bytes for up to four VLAN tags, and + * 4 bytes for the trailing FCS -- 36 bytes total. + */ + skb_size = rxq_to_mp(rxq)->dev->mtu + 36; -#ifdef MV643XX_ETH_TX_FAST_REFILL - if (++mp->tx_clean_threshold > 5) { - mp->tx_clean_threshold = 0; - for (i = 0; i < mp->txq_count; i++) - txq_reclaim(mp->txq + i, 0); + /* + * Make sure that the skb size is a multiple of 8 bytes, as + * the lower three bits of the receive descriptor's buffer + * size field are ignored by the hardware. + */ + skb_size = (skb_size + 7) & ~7; - spin_lock_irq(&mp->lock); - __txq_maybe_wake(mp->txq); - spin_unlock_irq(&mp->lock); - } -#endif + refilled = 0; + while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { + struct sk_buff *skb; + int unaligned; + int rx; - work_done = 0; - oom = 0; - for (i = mp->rxq_count - 1; work_done < budget && i >= 0; i--) { - struct rx_queue *rxq = mp->rxq + i; + skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1); + if (skb == NULL) { + mp->work_rx_oom |= 1 << rxq->index; + goto oom; + } - work_done += rxq_process(rxq, budget - work_done); - work_done += rxq_refill(rxq, budget - work_done, &oom); - } + unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); + if (unaligned) + skb_reserve(skb, dma_get_cache_alignment() - unaligned); - if (work_done < budget) { - if (oom) - mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); - netif_rx_complete(mp->dev, napi); - wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); - } + refilled++; + rxq->rx_desc_count++; - return work_done; -} + rx = rxq->rx_used_desc++; + if (rxq->rx_used_desc == rxq->rx_ring_size) + rxq->rx_used_desc = 0; -static inline void oom_timer_wrapper(unsigned long data) -{ - struct mv643xx_eth_private *mp = (void *)data; + rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data, + skb_size, DMA_FROM_DEVICE); + rxq->rx_desc_area[rx].buf_size = skb_size; + rxq->rx_skb[rx] = skb; + wmb(); + rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA | + RX_ENABLE_INTERRUPT; + wmb(); - napi_schedule(&mp->napi); + /* + * The hardware automatically prepends 2 bytes of + * dummy data to each received packet, so that the + * IP header ends up 16-byte aligned. + */ + skb_reserve(skb, 2); + } + + if (refilled < budget) + mp->work_rx_refill &= ~(1 << rxq->index); + +oom: + return refilled; } @@ -807,9 +772,8 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) wmb(); desc->cmd_sts = cmd_sts; - /* clear TX_END interrupt status */ - wrl(mp, INT_CAUSE(mp->port_num), ~(INT_TX_END_0 << txq->index)); - rdl(mp, INT_CAUSE(mp->port_num)); + /* clear TX_END status */ + mp->work_tx_end &= ~(1 << txq->index); /* ensure all descriptors are written before poking hardware */ wmb(); @@ -825,7 +789,6 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) int queue; struct tx_queue *txq; struct netdev_queue *nq; - unsigned long flags; int entries_left; if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { @@ -840,10 +803,10 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) txq = mp->txq + queue; nq = netdev_get_tx_queue(dev, queue); - spin_lock_irqsave(&mp->lock, flags); + spin_lock(&mp->lock); if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { - spin_unlock_irqrestore(&mp->lock, flags); + spin_unlock(&mp->lock); if (net_ratelimit()) dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n"); kfree_skb(skb); @@ -859,12 +822,105 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) if (entries_left < MAX_SKB_FRAGS + 1) netif_tx_stop_queue(nq); - spin_unlock_irqrestore(&mp->lock, flags); + spin_unlock(&mp->lock); return NETDEV_TX_OK; } +/* tx napi ******************************************************************/ +static void txq_kick(struct tx_queue *txq) +{ + struct mv643xx_eth_private *mp = txq_to_mp(txq); + u32 hw_desc_ptr; + u32 expected_ptr; + + spin_lock(&mp->lock); + + if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index)) + goto out; + + hw_desc_ptr = rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, txq->index)); + expected_ptr = (u32)txq->tx_desc_dma + + txq->tx_curr_desc * sizeof(struct tx_desc); + + if (hw_desc_ptr != expected_ptr) + txq_enable(txq); + +out: + spin_unlock(&mp->lock); + + mp->work_tx_end &= ~(1 << txq->index); +} + +static int txq_reclaim(struct tx_queue *txq, int budget, int force) +{ + struct mv643xx_eth_private *mp = txq_to_mp(txq); + int reclaimed; + + spin_lock(&mp->lock); + + reclaimed = 0; + while (reclaimed < budget && txq->tx_desc_count > 0) { + int tx_index; + struct tx_desc *desc; + u32 cmd_sts; + struct sk_buff *skb; + dma_addr_t addr; + int count; + + tx_index = txq->tx_used_desc; + desc = &txq->tx_desc_area[tx_index]; + cmd_sts = desc->cmd_sts; + + if (cmd_sts & BUFFER_OWNED_BY_DMA) { + if (!force) + break; + desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA; + } + + txq->tx_used_desc = tx_index + 1; + if (txq->tx_used_desc == txq->tx_ring_size) + txq->tx_used_desc = 0; + + reclaimed++; + txq->tx_desc_count--; + + addr = desc->buf_ptr; + count = desc->byte_cnt; + skb = txq->tx_skb[tx_index]; + txq->tx_skb[tx_index] = NULL; + + if (cmd_sts & ERROR_SUMMARY) { + dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n"); + mp->dev->stats.tx_errors++; + } + + /* + * Drop mp->lock while we free the skb. + */ + spin_unlock(&mp->lock); + + if (cmd_sts & TX_FIRST_DESC) + dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); + else + dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE); + + if (skb) + dev_kfree_skb(skb); + + spin_lock(&mp->lock); + } + + if (reclaimed < budget) + mp->work_tx &= ~(1 << txq->index); + + spin_unlock(&mp->lock); + + return reclaimed; +} + + /* tx rate control **********************************************************/ /* * Set total maximum TX rate (shared by all TX queues for this port) @@ -1648,7 +1704,6 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) return 0; - out_free: if (index == 0 && size <= mp->tx_desc_sram_size) iounmap(txq->tx_desc_area); @@ -1661,84 +1716,74 @@ out: return -ENOMEM; } -static void txq_reclaim(struct tx_queue *txq, int force) +static void txq_deinit(struct tx_queue *txq) { struct mv643xx_eth_private *mp = txq_to_mp(txq); - unsigned long flags; - spin_lock_irqsave(&mp->lock, flags); - while (txq->tx_desc_count > 0) { - int tx_index; - struct tx_desc *desc; - u32 cmd_sts; - struct sk_buff *skb; - dma_addr_t addr; - int count; + txq_disable(txq); + txq_reclaim(txq, txq->tx_ring_size, 1); - tx_index = txq->tx_used_desc; - desc = &txq->tx_desc_area[tx_index]; - cmd_sts = desc->cmd_sts; + BUG_ON(txq->tx_used_desc != txq->tx_curr_desc); - if (cmd_sts & BUFFER_OWNED_BY_DMA) { - if (!force) - break; - desc->cmd_sts = cmd_sts & ~BUFFER_OWNED_BY_DMA; - } + if (txq->index == 0 && + txq->tx_desc_area_size <= mp->tx_desc_sram_size) + iounmap(txq->tx_desc_area); + else + dma_free_coherent(NULL, txq->tx_desc_area_size, + txq->tx_desc_area, txq->tx_desc_dma); - txq->tx_used_desc = tx_index + 1; - if (txq->tx_used_desc == txq->tx_ring_size) - txq->tx_used_desc = 0; - txq->tx_desc_count--; + kfree(txq->tx_skb); +} - addr = desc->buf_ptr; - count = desc->byte_cnt; - skb = txq->tx_skb[tx_index]; - txq->tx_skb[tx_index] = NULL; - if (cmd_sts & ERROR_SUMMARY) { - dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n"); - mp->dev->stats.tx_errors++; - } +/* netdev ops and related ***************************************************/ +static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp) +{ + u32 int_cause; + u32 int_cause_ext; - /* - * Drop mp->lock while we free the skb. - */ - spin_unlock_irqrestore(&mp->lock, flags); + int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & + (INT_TX_END | INT_RX | INT_EXT); + if (int_cause == 0) + return 0; - if (cmd_sts & TX_FIRST_DESC) - dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); - else - dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE); + int_cause_ext = 0; + if (int_cause & INT_EXT) + int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num)); - if (skb) - dev_kfree_skb_irq(skb); + int_cause &= INT_TX_END | INT_RX; + if (int_cause) { + wrl(mp, INT_CAUSE(mp->port_num), ~int_cause); + mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & + ~(rdl(mp, TXQ_COMMAND(mp->port_num)) & 0xff); + mp->work_rx |= (int_cause & INT_RX) >> 2; + } - spin_lock_irqsave(&mp->lock, flags); + int_cause_ext &= INT_EXT_LINK_PHY | INT_EXT_TX; + if (int_cause_ext) { + wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); + if (int_cause_ext & INT_EXT_LINK_PHY) + mp->work_link = 1; + mp->work_tx |= int_cause_ext & INT_EXT_TX; } - spin_unlock_irqrestore(&mp->lock, flags); + + return 1; } -static void txq_deinit(struct tx_queue *txq) +static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) { - struct mv643xx_eth_private *mp = txq_to_mp(txq); - - txq_disable(txq); - txq_reclaim(txq, 1); + struct net_device *dev = (struct net_device *)dev_id; + struct mv643xx_eth_private *mp = netdev_priv(dev); - BUG_ON(txq->tx_used_desc != txq->tx_curr_desc); + if (unlikely(!mv643xx_eth_collect_events(mp))) + return IRQ_NONE; - if (txq->index == 0 && - txq->tx_desc_area_size <= mp->tx_desc_sram_size) - iounmap(txq->tx_desc_area); - else - dma_free_coherent(NULL, txq->tx_desc_area_size, - txq->tx_desc_area, txq->tx_desc_dma); + wrl(mp, INT_MASK(mp->port_num), 0); + napi_schedule(&mp->napi); - kfree(txq->tx_skb); + return IRQ_HANDLED; } - -/* netdev ops and related ***************************************************/ static void handle_link_event(struct mv643xx_eth_private *mp) { struct net_device *dev = mp->dev; @@ -1759,7 +1804,7 @@ static void handle_link_event(struct mv643xx_eth_private *mp) for (i = 0; i < mp->txq_count; i++) { struct tx_queue *txq = mp->txq + i; - txq_reclaim(txq, 1); + txq_reclaim(txq, txq->tx_ring_size, 1); txq_reset_hw_ptr(txq); } } @@ -1792,86 +1837,72 @@ static void handle_link_event(struct mv643xx_eth_private *mp) netif_carrier_on(dev); } -static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) +static int mv643xx_eth_poll(struct napi_struct *napi, int budget) { - struct net_device *dev = (struct net_device *)dev_id; - struct mv643xx_eth_private *mp = netdev_priv(dev); - u32 int_cause; - u32 int_cause_ext; + struct mv643xx_eth_private *mp; + int work_done; - int_cause = rdl(mp, INT_CAUSE(mp->port_num)) & - (INT_TX_END | INT_RX | INT_EXT); - if (int_cause == 0) - return IRQ_NONE; + mp = container_of(napi, struct mv643xx_eth_private, napi); - int_cause_ext = 0; - if (int_cause & INT_EXT) { - int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num)) - & (INT_EXT_LINK_PHY | INT_EXT_TX); - wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext); - } + mp->work_rx_refill |= mp->work_rx_oom; + mp->work_rx_oom = 0; - if (int_cause_ext & INT_EXT_LINK_PHY) - handle_link_event(mp); + work_done = 0; + while (work_done < budget) { + u8 queue_mask; + int queue; + int work_tbd; + + if (mp->work_link) { + mp->work_link = 0; + handle_link_event(mp); + continue; + } - /* - * RxBuffer or RxError set for any of the 8 queues? - */ - if (int_cause & INT_RX) { - wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_RX)); - wrl(mp, INT_MASK(mp->port_num), 0x00000000); - rdl(mp, INT_MASK(mp->port_num)); + queue_mask = mp->work_tx | mp->work_tx_end | + mp->work_rx | mp->work_rx_refill; + if (!queue_mask) { + if (mv643xx_eth_collect_events(mp)) + continue; + break; + } - napi_schedule(&mp->napi); + queue = fls(queue_mask) - 1; + queue_mask = 1 << queue; + + work_tbd = budget - work_done; + if (work_tbd > 16) + work_tbd = 16; + + if (mp->work_tx_end & queue_mask) { + txq_kick(mp->txq + queue); + } else if (mp->work_tx & queue_mask) { + work_done += txq_reclaim(mp->txq + queue, work_tbd, 0); + txq_maybe_wake(mp->txq + queue); + } else if (mp->work_rx & queue_mask) { + work_done += rxq_process(mp->rxq + queue, work_tbd); + } else if (mp->work_rx_refill & queue_mask) { + work_done += rxq_refill(mp->rxq + queue, work_tbd); + } else { + BUG(); + } } - /* - * TxBuffer or TxError set for any of the 8 queues? - */ - if (int_cause_ext & INT_EXT_TX) { - int i; - - for (i = 0; i < mp->txq_count; i++) - txq_reclaim(mp->txq + i, 0); - - /* - * Enough space again in the primary TX queue for a - * full packet? - */ - spin_lock(&mp->lock); - __txq_maybe_wake(mp->txq); - spin_unlock(&mp->lock); + if (work_done < budget) { + if (mp->work_rx_oom) + mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); + napi_complete(napi); + wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); } - /* - * Any TxEnd interrupts? - */ - if (int_cause & INT_TX_END) { - int i; - - wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_TX_END)); - - spin_lock(&mp->lock); - for (i = 0; i < 8; i++) { - struct tx_queue *txq = mp->txq + i; - u32 hw_desc_ptr; - u32 expected_ptr; - - if ((int_cause & (INT_TX_END_0 << i)) == 0) - continue; - - hw_desc_ptr = - rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, i)); - expected_ptr = (u32)txq->tx_desc_dma + - txq->tx_curr_desc * sizeof(struct tx_desc); + return work_done; +} - if (hw_desc_ptr != expected_ptr) - txq_enable(txq); - } - spin_unlock(&mp->lock); - } +static inline void oom_timer_wrapper(unsigned long data) +{ + struct mv643xx_eth_private *mp = (void *)data; - return IRQ_HANDLED; + napi_schedule(&mp->napi); } static void phy_reset(struct mv643xx_eth_private *mp) @@ -2000,7 +2031,6 @@ static int mv643xx_eth_open(struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); int err; - int oom; int i; wrl(mp, INT_CAUSE(mp->port_num), 0); @@ -2018,7 +2048,6 @@ static int mv643xx_eth_open(struct net_device *dev) napi_enable(&mp->napi); - oom = 0; for (i = 0; i < mp->rxq_count; i++) { err = rxq_init(mp, i); if (err) { @@ -2027,10 +2056,10 @@ static int mv643xx_eth_open(struct net_device *dev) goto out; } - rxq_refill(mp->rxq + i, INT_MAX, &oom); + rxq_refill(mp->rxq + i, INT_MAX); } - if (oom) { + if (mp->work_rx_oom) { mp->rx_oom.expires = jiffies + (HZ / 10); add_timer(&mp->rx_oom); } -- cgit v1.2.3 From 8fd89211bf8e8e60415c66e5546c1478f5e8bc2b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 08:26:28 +0200 Subject: mv643xx_eth: switch to netif tx queue lock, get rid of private spinlock Since our ->hard_start_xmit() method is already called under spinlock protection (the netif tx queue lock), we can simply make that lock cover the private transmit state (descriptor ring indexes et al.) as well, which avoids having to use a private lock to protect that state. Since this was the last user of the driver-private spinlock, it can be killed off. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 85 ++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 3db422b6666..d653b5a19e7 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -337,6 +337,10 @@ struct tx_queue { dma_addr_t tx_desc_dma; int tx_desc_area_size; struct sk_buff **tx_skb; + + unsigned long tx_packets; + unsigned long tx_bytes; + unsigned long tx_dropped; }; struct mv643xx_eth_private { @@ -347,8 +351,6 @@ struct mv643xx_eth_private { int phy_addr; - spinlock_t lock; - struct mib_counters mib_counters; struct work_struct tx_timeout_task; struct mii_if_info mii; @@ -453,10 +455,12 @@ static void txq_maybe_wake(struct tx_queue *txq) struct mv643xx_eth_private *mp = txq_to_mp(txq); struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); - spin_lock(&mp->lock); - if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) - netif_tx_wake_queue(nq); - spin_unlock(&mp->lock); + if (netif_tx_queue_stopped(nq)) { + __netif_tx_lock(nq, smp_processor_id()); + if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) + netif_tx_wake_queue(nq); + __netif_tx_unlock(nq); + } } @@ -785,28 +789,24 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; int queue; struct tx_queue *txq; struct netdev_queue *nq; int entries_left; + queue = skb_get_queue_mapping(skb); + txq = mp->txq + queue; + nq = netdev_get_tx_queue(dev, queue); + if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { - stats->tx_dropped++; + txq->tx_dropped++; dev_printk(KERN_DEBUG, &dev->dev, "failed to linearize skb with tiny " "unaligned fragment\n"); return NETDEV_TX_BUSY; } - queue = skb_get_queue_mapping(skb); - txq = mp->txq + queue; - nq = netdev_get_tx_queue(dev, queue); - - spin_lock(&mp->lock); - if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { - spin_unlock(&mp->lock); if (net_ratelimit()) dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n"); kfree_skb(skb); @@ -814,16 +814,14 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) } txq_submit_skb(txq, skb); - stats->tx_bytes += skb->len; - stats->tx_packets++; + txq->tx_bytes += skb->len; + txq->tx_packets++; dev->trans_start = jiffies; entries_left = txq->tx_ring_size - txq->tx_desc_count; if (entries_left < MAX_SKB_FRAGS + 1) netif_tx_stop_queue(nq); - spin_unlock(&mp->lock); - return NETDEV_TX_OK; } @@ -832,10 +830,11 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) static void txq_kick(struct tx_queue *txq) { struct mv643xx_eth_private *mp = txq_to_mp(txq); + struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); u32 hw_desc_ptr; u32 expected_ptr; - spin_lock(&mp->lock); + __netif_tx_lock(nq, smp_processor_id()); if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index)) goto out; @@ -848,7 +847,7 @@ static void txq_kick(struct tx_queue *txq) txq_enable(txq); out: - spin_unlock(&mp->lock); + __netif_tx_unlock(nq); mp->work_tx_end &= ~(1 << txq->index); } @@ -856,9 +855,10 @@ out: static int txq_reclaim(struct tx_queue *txq, int budget, int force) { struct mv643xx_eth_private *mp = txq_to_mp(txq); + struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); int reclaimed; - spin_lock(&mp->lock); + __netif_tx_lock(nq, smp_processor_id()); reclaimed = 0; while (reclaimed < budget && txq->tx_desc_count > 0) { @@ -897,9 +897,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) } /* - * Drop mp->lock while we free the skb. + * Drop tx queue lock while we free the skb. */ - spin_unlock(&mp->lock); + __netif_tx_unlock(nq); if (cmd_sts & TX_FIRST_DESC) dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); @@ -909,14 +909,14 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) if (skb) dev_kfree_skb(skb); - spin_lock(&mp->lock); + __netif_tx_lock(nq, smp_processor_id()); } + __netif_tx_unlock(nq); + if (reclaimed < budget) mp->work_tx &= ~(1 << txq->index); - spin_unlock(&mp->lock); - return reclaimed; } @@ -1123,7 +1123,31 @@ static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, } -/* mib counters *************************************************************/ +/* statistics ***************************************************************/ +static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) +{ + struct mv643xx_eth_private *mp = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + unsigned long tx_packets = 0; + unsigned long tx_bytes = 0; + unsigned long tx_dropped = 0; + int i; + + for (i = 0; i < mp->txq_count; i++) { + struct tx_queue *txq = mp->txq + i; + + tx_packets += txq->tx_packets; + tx_bytes += txq->tx_bytes; + tx_dropped += txq->tx_dropped; + } + + stats->tx_packets = tx_packets; + stats->tx_bytes = tx_bytes; + stats->tx_dropped = tx_dropped; + + return stats; +} + static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) { return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); @@ -1355,6 +1379,7 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, struct mv643xx_eth_private *mp = netdev_priv(dev); int i; + mv643xx_eth_get_stats(dev); mib_counters_update(mp); for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { @@ -2138,6 +2163,7 @@ static int mv643xx_eth_stop(struct net_device *dev) free_irq(dev->irq, dev); port_reset(mp); + mv643xx_eth_get_stats(dev); mib_counters_update(mp); for (i = 0; i < mp->rxq_count; i++) @@ -2585,8 +2611,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) set_params(mp, pd); dev->real_num_tx_queues = mp->txq_count; - spin_lock_init(&mp->lock); - mib_counters_clear(mp); INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); @@ -2612,6 +2636,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) BUG_ON(!res); dev->irq = res->start; + dev->get_stats = mv643xx_eth_get_stats; dev->hard_start_xmit = mv643xx_eth_xmit; dev->open = mv643xx_eth_open; dev->stop = mv643xx_eth_stop; -- cgit v1.2.3 From a418950c1378c4a3722baecdbe98df78ea23f231 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 13 Sep 2008 04:16:15 +0200 Subject: mv643xx_eth: avoid dropping tx lock during transmit reclaim By moving DMA unmapping during transmit reclaim back under the netif tx lock, we avoid the situation where we read the DMA address and buffer length from the descriptor under the lock and then not do anything with that data after dropping the lock on platforms where the DMA unmapping routines are all NOPs (which is the case on all ARM platforms that mv643xx_eth is used on at least). This saves two uncached reads, which makes a small but measurable performance difference in routing benchmarks. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index d653b5a19e7..7410eca8782 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -866,8 +866,6 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) struct tx_desc *desc; u32 cmd_sts; struct sk_buff *skb; - dma_addr_t addr; - int count; tx_index = txq->tx_used_desc; desc = &txq->tx_desc_area[tx_index]; @@ -886,8 +884,6 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) reclaimed++; txq->tx_desc_count--; - addr = desc->buf_ptr; - count = desc->byte_cnt; skb = txq->tx_skb[tx_index]; txq->tx_skb[tx_index] = NULL; @@ -896,20 +892,16 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) mp->dev->stats.tx_errors++; } - /* - * Drop tx queue lock while we free the skb. - */ - __netif_tx_unlock(nq); - - if (cmd_sts & TX_FIRST_DESC) - dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); - else - dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE); + if (cmd_sts & TX_FIRST_DESC) { + dma_unmap_single(NULL, desc->buf_ptr, + desc->byte_cnt, DMA_TO_DEVICE); + } else { + dma_unmap_page(NULL, desc->buf_ptr, + desc->byte_cnt, DMA_TO_DEVICE); + } if (skb) dev_kfree_skb(skb); - - __netif_tx_lock(nq, smp_processor_id()); } __netif_tx_unlock(nq); -- cgit v1.2.3 From 99ab08e091df65ce8e191d85ebdc23f78b8355cb Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 28 Aug 2008 05:53:18 +0200 Subject: mv643xx_eth: replace array of skbs awaiting transmit completion with a queue Get rid of the skb pointer array that we currently use for transmit reclaim, and replace it with an skb queue, to which skbuffs are appended when they are passed to the xmit function, and removed from the front and freed when we do transmit queue reclaim and hit a descriptor with the 'owned by device' bit clear and 'last descriptor' bit set. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 7410eca8782..099e0be0d8c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -336,7 +336,8 @@ struct tx_queue { struct tx_desc *tx_desc_area; dma_addr_t tx_desc_dma; int tx_desc_area_size; - struct sk_buff **tx_skb; + + struct sk_buff_head tx_skb; unsigned long tx_packets; unsigned long tx_bytes; @@ -676,10 +677,8 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb) desc->cmd_sts = BUFFER_OWNED_BY_DMA | ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; - txq->tx_skb[tx_index] = skb; } else { desc->cmd_sts = BUFFER_OWNED_BY_DMA; - txq->tx_skb[tx_index] = NULL; } desc->l4i_chk = 0; @@ -712,13 +711,10 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) if (nr_frags) { txq_submit_frag_skb(txq, skb); - length = skb_headlen(skb); - txq->tx_skb[tx_index] = NULL; } else { cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; length = skb->len; - txq->tx_skb[tx_index] = skb; } desc->byte_cnt = length; @@ -772,6 +768,8 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) desc->l4i_chk = 0; } + __skb_queue_tail(&txq->tx_skb, skb); + /* ensure all other descriptors are written before first cmd_sts */ wmb(); desc->cmd_sts = cmd_sts; @@ -884,8 +882,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) reclaimed++; txq->tx_desc_count--; - skb = txq->tx_skb[tx_index]; - txq->tx_skb[tx_index] = NULL; + skb = NULL; + if (cmd_sts & TX_LAST_DESC) + skb = __skb_dequeue(&txq->tx_skb); if (cmd_sts & ERROR_SUMMARY) { dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n"); @@ -1692,18 +1691,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) if (txq->tx_desc_area == NULL) { dev_printk(KERN_ERR, &mp->dev->dev, "can't allocate tx ring (%d bytes)\n", size); - goto out; + return -ENOMEM; } memset(txq->tx_desc_area, 0, size); txq->tx_desc_area_size = size; - txq->tx_skb = kmalloc(txq->tx_ring_size * sizeof(*txq->tx_skb), - GFP_KERNEL); - if (txq->tx_skb == NULL) { - dev_printk(KERN_ERR, &mp->dev->dev, - "can't allocate tx skb ring\n"); - goto out_free; - } tx_desc = (struct tx_desc *)txq->tx_desc_area; for (i = 0; i < txq->tx_ring_size; i++) { @@ -1719,18 +1711,9 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) nexti * sizeof(struct tx_desc); } - return 0; + skb_queue_head_init(&txq->tx_skb); -out_free: - if (index == 0 && size <= mp->tx_desc_sram_size) - iounmap(txq->tx_desc_area); - else - dma_free_coherent(NULL, size, - txq->tx_desc_area, - txq->tx_desc_dma); - -out: - return -ENOMEM; + return 0; } static void txq_deinit(struct tx_queue *txq) @@ -1748,8 +1731,6 @@ static void txq_deinit(struct tx_queue *txq) else dma_free_coherent(NULL, txq->tx_desc_area_size, txq->tx_desc_area, txq->tx_desc_dma); - - kfree(txq->tx_skb); } -- cgit v1.2.3 From 2b4a624d706d404a3edccb6d1bb2c440a6dbbc31 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 14 Sep 2008 14:09:59 +0200 Subject: mv643xx_eth: shrink default receive and transmit queue sizes Since the size of the receive queue is directly related to the data cache footprint of the driver (between refilling a receive ring entry with a fresh skb and receiving a packet in that entry, queue_size - 1 other skbs will have been touched), shrink the default receive queue size to a saner number of entries, as 400 is definite overkill for almost all workloads. While we are at it, trim the default transmit queue size a bit as well. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 099e0be0d8c..4fbd62e45ae 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -165,8 +165,8 @@ static char mv643xx_eth_driver_version[] = "1.3"; #define FORCE_LINK_PASS (1 << 1) #define SERIAL_PORT_ENABLE (1 << 0) -#define DEFAULT_RX_QUEUE_SIZE 400 -#define DEFAULT_TX_QUEUE_SIZE 800 +#define DEFAULT_RX_QUEUE_SIZE 128 +#define DEFAULT_TX_QUEUE_SIZE 256 /* -- cgit v1.2.3 From 6b8f90c276ac25cd37f143a00d467a8ccb19c4c6 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 14 Sep 2008 15:50:32 +0200 Subject: mv643xx_eth: avoid reading ->byte_cnt twice during receive processing Currently, the receive processing reads ->byte_cnt twice (once to update interface statistics and once to properly size the data area of the received skb), but since receive descriptors live in uncached memory, caching this value in a local variable saves one uncached access, and increases routing performance a tiny little bit more. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 4fbd62e45ae..6564be122ac 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -477,6 +477,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) struct rx_desc *rx_desc; unsigned int cmd_sts; struct sk_buff *skb; + u16 byte_cnt; rx_desc = &rxq->rx_desc_area[rxq->rx_curr_desc]; @@ -499,6 +500,8 @@ static int rxq_process(struct rx_queue *rxq, int budget) mp->work_rx_refill |= 1 << rxq->index; + byte_cnt = rx_desc->byte_cnt; + /* * Update statistics. * @@ -508,7 +511,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) * byte CRC at the end of the packet (which we do count). */ stats->rx_packets++; - stats->rx_bytes += rx_desc->byte_cnt - 2; + stats->rx_bytes += byte_cnt - 2; /* * In case we received a packet without first / last bits @@ -537,7 +540,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) * The -4 is for the CRC in the trailer of the * received packet */ - skb_put(skb, rx_desc->byte_cnt - 2 - 4); + skb_put(skb, byte_cnt - 2 - 4); if (cmd_sts & LAYER_4_CHECKSUM_OK) { skb->ip_summed = CHECKSUM_UNNECESSARY; -- cgit v1.2.3 From 457b1d5a4b7b8c2b3b6bd032098da600c50dd6b2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 4 Sep 2008 12:22:34 +0200 Subject: mv643xx_eth: add support for chips without transmit bandwidth control Add support for mv643xx_eth versions that have no transmit bandwidth control registers at all, such as the ethernet block found in the Marvell 88F6183 ARM SoC. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 89 ++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 6564be122ac..408827de7d3 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -271,9 +271,13 @@ struct mv643xx_eth_shared_private { */ unsigned int t_clk; int extended_rx_coal_limit; - int tx_bw_control_moved; + int tx_bw_control; }; +#define TX_BW_CONTROL_ABSENT 0 +#define TX_BW_CONTROL_OLD_LAYOUT 1 +#define TX_BW_CONTROL_NEW_LAYOUT 2 + /* per-port *****************************************************************/ struct mib_counters { @@ -938,14 +942,17 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst) if (bucket_size > 65535) bucket_size = 65535; - if (mp->shared->tx_bw_control_moved) { - wrl(mp, TX_BW_RATE_MOVED(mp->port_num), token_rate); - wrl(mp, TX_BW_MTU_MOVED(mp->port_num), mtu); - wrl(mp, TX_BW_BURST_MOVED(mp->port_num), bucket_size); - } else { + switch (mp->shared->tx_bw_control) { + case TX_BW_CONTROL_OLD_LAYOUT: wrl(mp, TX_BW_RATE(mp->port_num), token_rate); wrl(mp, TX_BW_MTU(mp->port_num), mtu); wrl(mp, TX_BW_BURST(mp->port_num), bucket_size); + break; + case TX_BW_CONTROL_NEW_LAYOUT: + wrl(mp, TX_BW_RATE_MOVED(mp->port_num), token_rate); + wrl(mp, TX_BW_MTU_MOVED(mp->port_num), mtu); + wrl(mp, TX_BW_BURST_MOVED(mp->port_num), bucket_size); + break; } } @@ -977,14 +984,21 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq) /* * Turn on fixed priority mode. */ - if (mp->shared->tx_bw_control_moved) - off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num); - else + off = 0; + switch (mp->shared->tx_bw_control) { + case TX_BW_CONTROL_OLD_LAYOUT: off = TXQ_FIX_PRIO_CONF(mp->port_num); + break; + case TX_BW_CONTROL_NEW_LAYOUT: + off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num); + break; + } - val = rdl(mp, off); - val |= 1 << txq->index; - wrl(mp, off, val); + if (off) { + val = rdl(mp, off); + val |= 1 << txq->index; + wrl(mp, off, val); + } } static void txq_set_wrr(struct tx_queue *txq, int weight) @@ -996,23 +1010,30 @@ static void txq_set_wrr(struct tx_queue *txq, int weight) /* * Turn off fixed priority mode. */ - if (mp->shared->tx_bw_control_moved) - off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num); - else + off = 0; + switch (mp->shared->tx_bw_control) { + case TX_BW_CONTROL_OLD_LAYOUT: off = TXQ_FIX_PRIO_CONF(mp->port_num); + break; + case TX_BW_CONTROL_NEW_LAYOUT: + off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num); + break; + } - val = rdl(mp, off); - val &= ~(1 << txq->index); - wrl(mp, off, val); + if (off) { + val = rdl(mp, off); + val &= ~(1 << txq->index); + wrl(mp, off, val); - /* - * Configure WRR weight for this queue. - */ - off = TXQ_BW_WRR_CONF(mp->port_num, txq->index); + /* + * Configure WRR weight for this queue. + */ + off = TXQ_BW_WRR_CONF(mp->port_num, txq->index); - val = rdl(mp, off); - val = (val & ~0xff) | (weight & 0xff); - wrl(mp, off, val); + val = rdl(mp, off); + val = (val & ~0xff) | (weight & 0xff); + wrl(mp, off, val); + } } @@ -2288,14 +2309,20 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp) msp->extended_rx_coal_limit = 0; /* - * Check whether the TX rate control registers are in the - * old or the new place. + * Check whether the MAC supports TX rate control, and if + * yes, whether its associated registers are in the old or + * the new place. */ writel(1, msp->base + TX_BW_MTU_MOVED(0)); - if (readl(msp->base + TX_BW_MTU_MOVED(0)) & 1) - msp->tx_bw_control_moved = 1; - else - msp->tx_bw_control_moved = 0; + if (readl(msp->base + TX_BW_MTU_MOVED(0)) & 1) { + msp->tx_bw_control = TX_BW_CONTROL_NEW_LAYOUT; + } else { + writel(7, msp->base + TX_BW_RATE(0)); + if (readl(msp->base + TX_BW_RATE(0)) & 7) + msp->tx_bw_control = TX_BW_CONTROL_OLD_LAYOUT; + else + msp->tx_bw_control = TX_BW_CONTROL_ABSENT; + } } static int mv643xx_eth_shared_probe(struct platform_device *pdev) -- cgit v1.2.3 From 5670a43d710a12fcbbfaefd3991002768b488d82 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 14 Sep 2008 07:42:23 -0700 Subject: xen: fix for xen guest with mem > 3.7G PFN_PHYS() can truncate large addresses unless its passed a suitable large type. This is fixed more generally in the patch series introducing phys_addr_t, but we need a short-term fix to solve a Xen regression reported by Roberto De Ioris. Reported-by: Roberto De Ioris Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- arch/x86/xen/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index b6acc3a0af4..d6790108388 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -42,7 +42,7 @@ char * __init xen_memory_setup(void) e820.nr_map = 0; - e820_add_region(0, PFN_PHYS(max_pfn), E820_RAM); + e820_add_region(0, PFN_PHYS((u64)max_pfn), E820_RAM); /* * Even though this is normal, usable memory under Xen, reserve -- cgit v1.2.3 From 5132895f14a57607152f7865dc862fb076ce2585 Mon Sep 17 00:00:00 2001 From: Alex Nixon Date: Wed, 3 Sep 2008 14:36:40 +0100 Subject: x86/paravirt: Remove duplicate paravirt_pagetable_setup_{start, done}() They were already called once in arch/x86/kernel/setup.c - we don't need to call them again. fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11485 Signed-off-by: Alex Nixon Signed-off-by: Ingo Molnar --- arch/x86/mm/init_32.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index d37f29376b0..60ec1d08ff2 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -458,11 +458,7 @@ static void __init pagetable_init(void) { pgd_t *pgd_base = swapper_pg_dir; - paravirt_pagetable_setup_start(pgd_base); - permanent_kmaps_init(pgd_base); - - paravirt_pagetable_setup_done(pgd_base); } #ifdef CONFIG_ACPI_SLEEP -- cgit v1.2.3 From ba95487df97f9c45cfdae2a47de56235e7a13dc5 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Sun, 14 Sep 2008 13:41:19 -0700 Subject: crypto: talitos - Avoid consecutive packets going out with same IV The SEC's h/w IV out implementation DMAs the trailing encrypted payload block of the last encryption to ctx->iv. Since the last encryption may still be pending completion, we can sufficiently prevent successive packets from being transmitted with the same IV by xoring with sequence number. Also initialize alg_list earlier to prevent oopsing on a failed probe. Signed-off-by: Kim Phillips Signed-off-by: Lee Nipper Signed-off-by: Herbert Xu --- drivers/crypto/talitos.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index ee827a7f7c6..b6ad3ac5916 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1157,6 +1157,8 @@ static int aead_authenc_givencrypt( edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT; memcpy(req->giv, ctx->iv, crypto_aead_ivsize(authenc)); + /* avoid consecutive packets going out with same IV */ + *(__be64 *)req->giv ^= cpu_to_be64(req->seq); return ipsec_esp(edesc, areq, req->giv, req->seq, ipsec_esp_encrypt_done); @@ -1449,6 +1451,8 @@ static int talitos_probe(struct of_device *ofdev, priv->ofdev = ofdev; + INIT_LIST_HEAD(&priv->alg_list); + tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev); tasklet_init(&priv->error_task, talitos_error, (unsigned long)dev); @@ -1575,8 +1579,6 @@ static int talitos_probe(struct of_device *ofdev, } /* register crypto algorithms the device supports */ - INIT_LIST_HEAD(&priv->alg_list); - for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { struct talitos_crypto_alg *t_alg; -- cgit v1.2.3 From 02b71b70129aaaa38f280af2aa5a767a4dec9107 Mon Sep 17 00:00:00 2001 From: Salman Qazi Date: Thu, 11 Sep 2008 12:25:41 -0700 Subject: slub: fixed uninitialized counter in struct kmem_cache_node Initialized total objects atomic for the node in init_kmem_cache_node. The uninitialized value was ruining the stats in /proc/slabinfo. Acked-by: Christoph Lameter Signed-off-by: Salman Qazi Signed-off-by: Pekka Enberg --- mm/slub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/slub.c b/mm/slub.c index fb486d5540f..0c83e6afe7b 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1932,6 +1932,7 @@ init_kmem_cache_node(struct kmem_cache_node *n, struct kmem_cache *s) INIT_LIST_HEAD(&n->partial); #ifdef CONFIG_SLUB_DEBUG atomic_long_set(&n->nr_slabs, 0); + atomic_long_set(&n->total_objects, 0); INIT_LIST_HEAD(&n->full); #endif } -- cgit v1.2.3 From 93821778def10ec1e69aa3ac10adee975dad4ff3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 15 Sep 2008 11:48:46 -0700 Subject: udp: Fix rcv socket locking The previous patch in response to the recursive locking on IPsec reception is broken as it tries to drop the BH socket lock while in user context. This patch fixes it by shrinking the section protected by the socket lock to sock_queue_rcv_skb only. The only reason we added the lock is for the accounting which happens in that function. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/udp.c | 62 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8e42fbbd576..57e26fa6618 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -951,6 +951,27 @@ int udp_disconnect(struct sock *sk, int flags) return 0; } +static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + int is_udplite = IS_UDPLITE(sk); + int rc; + + if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { + /* Note that an ENOMEM error is charged twice */ + if (rc == -ENOMEM) + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, + is_udplite); + goto drop; + } + + return 0; + +drop: + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); + kfree_skb(skb); + return -1; +} + /* returns: * -1: error * 0: success @@ -989,9 +1010,7 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) up->encap_rcv != NULL) { int ret; - bh_unlock_sock(sk); ret = (*up->encap_rcv)(sk, skb); - bh_lock_sock(sk); if (ret <= 0) { UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INDATAGRAMS, @@ -1044,17 +1063,16 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) goto drop; } - if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { - /* Note that an ENOMEM error is charged twice */ - if (rc == -ENOMEM) { - UDP_INC_STATS_BH(sock_net(sk), - UDP_MIB_RCVBUFERRORS, is_udplite); - atomic_inc(&sk->sk_drops); - } - goto drop; - } + rc = 0; - return 0; + bh_lock_sock(sk); + if (!sock_owned_by_user(sk)) + rc = __udp_queue_rcv_skb(sk, skb); + else + sk_add_backlog(sk, skb); + bh_unlock_sock(sk); + + return rc; drop: UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); @@ -1092,15 +1110,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, skb1 = skb_clone(skb, GFP_ATOMIC); if (skb1) { - int ret = 0; - - bh_lock_sock(sk); - if (!sock_owned_by_user(sk)) - ret = udp_queue_rcv_skb(sk, skb1); - else - sk_add_backlog(sk, skb1); - bh_unlock_sock(sk); - + int ret = udp_queue_rcv_skb(sk, skb1); if (ret > 0) /* we should probably re-process instead * of dropping packets here. */ @@ -1195,13 +1205,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], uh->dest, inet_iif(skb), udptable); if (sk != NULL) { - int ret = 0; - bh_lock_sock(sk); - if (!sock_owned_by_user(sk)) - ret = udp_queue_rcv_skb(sk, skb); - else - sk_add_backlog(sk, skb); - bh_unlock_sock(sk); + int ret = udp_queue_rcv_skb(sk, skb); sock_put(sk); /* a return value > 0 means to resubmit the input, but @@ -1494,7 +1498,7 @@ struct proto udp_prot = { .sendmsg = udp_sendmsg, .recvmsg = udp_recvmsg, .sendpage = udp_sendpage, - .backlog_rcv = udp_queue_rcv_skb, + .backlog_rcv = __udp_queue_rcv_skb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, .get_port = udp_v4_get_port, -- cgit v1.2.3 From 29bdc88384c2b24e37e5760df0dc898546083d6b Mon Sep 17 00:00:00 2001 From: Vladimir Sokolovsky Date: Mon, 15 Sep 2008 14:25:23 -0700 Subject: IB/mlx4: Fix up fast register page list format Byte swap the addresses in the page list for fast register work requests to big endian to match what the HCA expectx. Also, the addresses must have the "present" bit set so that the HCA knows it can access them. Otherwise the HCA will fault the first time it accesses the memory region. Signed-off-by: Vladimir Sokolovsky Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/qp.c | 6 ++++++ drivers/net/mlx4/mr.c | 2 -- include/linux/mlx4/device.h | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index f29dbb767e8..9559248f265 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1342,6 +1342,12 @@ static __be32 convert_access(int acc) static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr) { struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list); + int i; + + for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i) + wr->wr.fast_reg.page_list->page_list[i] = + cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] | + MLX4_MTT_FLAG_PRESENT); fseg->flags = convert_access(wr->wr.fast_reg.access_flags); fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey); diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 644adf074a3..d1dd5b48dbd 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -71,8 +71,6 @@ struct mlx4_mpt_entry { #define MLX4_MPT_PD_FLAG_RAE (1 << 28) #define MLX4_MPT_PD_FLAG_EN_INV (3 << 24) -#define MLX4_MTT_FLAG_PRESENT 1 - #define MLX4_MPT_STATUS_SW 0xF0 #define MLX4_MPT_STATUS_HW 0x00 diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 655ea0d1ee1..b2f94446831 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -141,6 +141,10 @@ enum { MLX4_STAT_RATE_OFFSET = 5 }; +enum { + MLX4_MTT_FLAG_PRESENT = 1 +}; + static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) { return (major << 32) | (minor << 16) | subminor; -- cgit v1.2.3 From a83479545d0e693da0886fd28d041d3a5c1bc966 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Mon, 15 Sep 2008 20:50:54 -0400 Subject: [MIPS] VR41xx: unsigned irq cannot be negative Signed-off-by: Roel Kluin Acked-by: Yoichi Yuasa Signed-off-by: Ralf Baechle --- arch/mips/vr41xx/common/irq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index cba36a247e3..92dd1a0ca35 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -72,6 +72,7 @@ static void irq_dispatch(unsigned int irq) cascade = irq_cascade + irq; if (cascade->get_irq != NULL) { unsigned int source_irq = irq; + int ret; desc = irq_desc + source_irq; if (desc->chip->mask_ack) desc->chip->mask_ack(source_irq); @@ -79,8 +80,9 @@ static void irq_dispatch(unsigned int irq) desc->chip->mask(source_irq); desc->chip->ack(source_irq); } - irq = cascade->get_irq(irq); - if (irq < 0) + ret = cascade->get_irq(irq); + irq = ret; + if (ret < 0) atomic_inc(&irq_err_count); else irq_dispatch(irq); -- cgit v1.2.3 From e1f4f59d1ab9ebac44830d6ae450fb358ac559d3 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Tue, 16 Sep 2008 14:27:13 +0100 Subject: PCI: Fix pcie_aspm=force pcie_aspm=force did not work because aspm_force was being double negated leading to the sanity check failing. Moving a bracket should fix this. Acked-by: Alan Cox Signed-off-by: Sitsofe Wheeler Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 9a7c9e1408a..851f5b83cdb 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -527,7 +527,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) */ pci_read_config_dword(child_dev, child_pos + PCI_EXP_DEVCAP, ®32); - if (!(reg32 & PCI_EXP_DEVCAP_RBER && !aspm_force)) { + if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { printk("Pre-1.1 PCIe device detected, " "disable ASPM for %s. It can be enabled forcedly" " with 'pcie_aspm=force'\n", pci_name(pdev)); -- cgit v1.2.3 From cd72ad3f57c400baa2ddb78b4fc2781cf68ffb6f Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sun, 14 Sep 2008 11:52:44 -0400 Subject: Input: bcm5974 - switch back to normal mode when closing Staying in multi-touch mode after closing the device sometimes makes the keyboard drop keys or repeat keys irratically. The conjecture is that some internal buffer starts to overflow, resulting in undefined behavior. Switching back to normal mode when closing the device makes the problem go away. Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 18f4d7f6ce6..2998a6ac9ae 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -351,8 +351,9 @@ static int report_tp_state(struct bcm5974 *dev, int size) #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 +#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 -static int bcm5974_wellspring_mode(struct bcm5974 *dev) +static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) { char *data = kmalloc(8, GFP_KERNEL); int retval = 0, size; @@ -377,7 +378,9 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev) } /* apply the mode switch */ - data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE; + data[0] = on ? + BCM5974_WELLSPRING_MODE_VENDOR_VALUE : + BCM5974_WELLSPRING_MODE_NORMAL_VALUE; /* write configuration */ size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), @@ -392,7 +395,8 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev) goto out; } - dprintk(2, "bcm5974: switched to wellspring mode.\n"); + dprintk(2, "bcm5974: switched to %s mode.\n", + on ? "wellspring" : "normal"); out: kfree(data); @@ -481,7 +485,7 @@ exit: */ static int bcm5974_start_traffic(struct bcm5974 *dev) { - if (bcm5974_wellspring_mode(dev)) { + if (bcm5974_wellspring_mode(dev, true)) { dprintk(1, "bcm5974: mode switch failed\n"); goto error; } @@ -504,6 +508,7 @@ static void bcm5974_pause_traffic(struct bcm5974 *dev) { usb_kill_urb(dev->tp_urb); usb_kill_urb(dev->bt_urb); + bcm5974_wellspring_mode(dev, false); } /* -- cgit v1.2.3 From ba0593bf553c450a03dbc5f8c1f0ff58b778a0c8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 16 Sep 2008 09:29:40 -0700 Subject: x86: completely disable NOPL on 32 bits Completely disable NOPL on 32 bits. It turns out that Microsoft Virtual PC is so broken it can't even reliably *fail* in the presence of NOPL. This leaves the infrastructure in place but disables it unconditionally. Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/common.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8aab8517642..4e456bd955b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -344,31 +344,15 @@ static void __init early_cpu_detect(void) /* * The NOPL instruction is supposed to exist on all CPUs with - * family >= 6, unfortunately, that's not true in practice because + * family >= 6; unfortunately, that's not true in practice because * of early VIA chips and (more importantly) broken virtualizers that - * are not easy to detect. Hence, probe for it based on first - * principles. + * are not easy to detect. In the latter case it doesn't even *fail* + * reliably, so probing for it doesn't even work. Disable it completely + * unless we can find a reliable way to detect all the broken cases. */ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) { - const u32 nopl_signature = 0x888c53b1; /* Random number */ - u32 has_nopl = nopl_signature; - clear_cpu_cap(c, X86_FEATURE_NOPL); - if (c->x86 >= 6) { - asm volatile("\n" - "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ - "2:\n" - " .section .fixup,\"ax\"\n" - "3: xor %0,%0\n" - " jmp 2b\n" - " .previous\n" - _ASM_EXTABLE(1b,3b) - : "+a" (has_nopl)); - - if (has_nopl == nopl_signature) - set_cpu_cap(c, X86_FEATURE_NOPL); - } } static void __cpuinit generic_identify(struct cpuinfo_x86 *c) -- cgit v1.2.3 From f26fd5d6e5006eae75a389c7ce74ed16761d094b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 16 Sep 2008 09:32:18 -0700 Subject: [S390] cio: Fix driver_data handling for ccwgroup devices. Since 16f7f9564c3ae190954f2ec55f385a268b93ac4d, we've seen oopses when grouping/ungrouping devices: Unable to handle kernel pointer dereference at virtual kernel address 0000000000 114000 Oops: 0004 [#1] PREEMPT SMP Modules linked in: bonding qeth_l2 dm_multipath sunrpc qeth_l3 dm_mod qeth chsc_ sch ccwgroup CPU: 1 Not tainted 2.6.26-29.x.20080815-s390xdefault #1 Process iperf (pid: 24412, task: 000000003f446038, ksp: 000000003c929e08) Krnl PSW : 0404d00180000000 000003e00006f6e6 (qeth_irq+0xda/0xb28 [qeth]) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3 Krnl GPRS: 0000000000000000 000003e000000003 0000000000000000 0000000000114ccc 000000003fb82e48 000003e00006f60c 000000000000000c 000000003ce72100 0000000000114944 000000003fb82e48 0000000000114ccc 000000003fe8fd28 000003e000066000 000003e000076128 000000003fe8fdb8 000000003fe8fd28 Krnl Code: 000003e00006f6da: bf3f2024 icm %r3,15,36(%r2) 000003e00006f6de: a774023c brc 7,3e00006fb56 000003e00006f6e2: a7280000 lhi %r2,0 >000003e00006f6e6: 5020a1a0 st %r2,416(%r10) 000003e00006f6ea: 58109000 l %r1,0(%r9) 000003e00006f6ee: a7111000 tmll %r1,4096 000003e00006f6f2: a77400f9 brc 7,3e00006f8e4 000003e00006f6f6: 8810000c srl %r1,12 Call Trace: ([<000000003fe8fd20>] 0x3fe8fd20) [<000000000033bf2a>] ccw_device_call_handler+0xb2/0xd8 [<0000000000339e1c>] ccw_device_irq+0x124/0x164 [<0000000000339758>] io_subchannel_irq+0x8c/0x118 [<00000000003309ba>] do_IRQ+0x192/0x1bc [<0000000000114f66>] io_return+0x0/0x8 [<00000000001149cc>] sysc_do_svc+0x0/0x22 ([<0000000000114a18>] sysc_noemu+0x10/0x16) [<00000200002e047c>] 0x200002e047c Last Breaking-Event-Address: [<000003e00006f6d6>] qeth_irq+0xca/0xb28 [qeth] The problem is that dev->driver_data for a ccw device is NULL, while it should point to the ccwgroup device it is a member of. This happened due to incorrect cleanup if creating a ccwgroup device failed because the ccw devices were already grouped. Fix this by setting cdev[i] to NULL in the error handling of ccwgroup_create_from_string() after we give up our reference and by checking if the driver_data points to the ccwgroup device in ccwgroup_release() just to be really sure. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e0ce65fca4e..9a50f245774 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -113,7 +113,8 @@ ccwgroup_release (struct device *dev) for (i = 0; i < gdev->count; i++) { if (gdev->cdev[i]) { - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); + if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) + dev_set_drvdata(&gdev->cdev[i]->dev, NULL); put_device(&gdev->cdev[i]->dev); } } @@ -296,6 +297,7 @@ error: if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) dev_set_drvdata(&gdev->cdev[i]->dev, NULL); put_device(&gdev->cdev[i]->dev); + gdev->cdev[i] = NULL; } mutex_unlock(&gdev->reg_mutex); put_device(&gdev->dev); -- cgit v1.2.3 From 9adb8c1d4f0ac78b3469e377ce5f8a846cbaedaf Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Tue, 16 Sep 2008 09:32:19 -0700 Subject: [S390] cio: fix orb initialization in cio_start_key The functions cio_tm_start_key and cio_start_key use the same private orb structure of a subchannel, so the orb needs to be cleared of old data before it is used again. A respective memset is missing from cio_start_key and hereby added. Signed-off-by: Stefan Weinhuber Acked-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5954b905e3c..326f4cc7f92 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -174,6 +174,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ CIO_TRACE_EVENT(4, sch->dev.bus_id); orb = &to_io_private(sch)->orb; + memset(orb, 0, sizeof(union orb)); /* sch is always under 2G. */ orb->cmd.intparm = (u32)(addr_t)sch; orb->cmd.fmt = 1; -- cgit v1.2.3 From f948cc6ab9e61a8e88d70ee9aafc690e6d26f92c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Sep 2008 09:53:42 -0700 Subject: sparc64: Fix OOPS in psycho_pcierr_intr_other(). We no longer put the top-level PCI controller device into the PCI layer device list. So pbm->pci_bus->self is always NULL. Therefore, use direct PCI config space accesses to get at the PCI controller's PCI_STATUS register. Tested by Meelis Roos. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index e205ade69cf..f85b6bebb0b 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -575,7 +575,7 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm { unsigned long csr_reg, csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; - u16 stat; + u16 stat, *addr; if (is_pbm_a) { csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; @@ -597,7 +597,9 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm printk("%s: PCI SERR signal asserted.\n", pbm->name); ret = IRQ_HANDLED; } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_STATUS); + pci_config_read16(addr, &stat); if (stat & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | @@ -605,7 +607,7 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm PCI_STATUS_SIG_SYSTEM_ERROR)) { printk("%s: PCI bus error, PCI_STATUS[%04x]\n", pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); + pci_config_write16(addr, 0xffff); ret = IRQ_HANDLED; } return ret; -- cgit v1.2.3 From 1577e4b70a04cce39f296cc714da5ad5d272105a Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Tue, 16 Sep 2008 14:19:25 -0400 Subject: Input: jornada720_ts - fix build error ( LONG() usage ) This patch removes the usage of LONG() which is deprecated; we also replace BIT() with BIT_MASK(). signed-off-by: Kristoffer Ericson Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/jornada720_ts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 1aca108b103..b7f1260738a 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -119,8 +119,8 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev) input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); -- cgit v1.2.3 From 9843099ff46467461d6476a827f6f9701682dbac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Sep 2008 11:44:00 -0700 Subject: sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace. Based upon a report by Meelis Roos. Any function call can try to access the current thread register via the _mcount hooks when the kernel is built with -pg (via ftrace or STACK_DEBUG). That can't be setup properly very early on during the bootup of other cpus for sun4u and some early sun4v systems. So add notrace markers to these specific functions, so that _mcount doesn't get invoked too early. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 5 +++-- arch/sparc64/kernel/traps.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 23963882bc1..7495bc77468 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -866,7 +867,7 @@ static void kill_prom_timer(void) : "g1", "g2"); } -void init_irqwork_curcpu(void) +void notrace init_irqwork_curcpu(void) { int cpu = hard_smp_processor_id(); @@ -897,7 +898,7 @@ static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type } } -void __cpuinit sun4v_register_mondo_queues(int this_cpu) +void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) { struct trap_per_cpu *tb = &trap_block[this_cpu]; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3d924121c79..c824df13f58 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -2453,7 +2454,7 @@ struct trap_per_cpu trap_block[NR_CPUS]; /* This can get invoked before sched_init() so play it super safe * and use hard_smp_processor_id(). */ -void init_cur_cpu_trap(struct thread_info *t) +void notrace init_cur_cpu_trap(struct thread_info *t) { int cpu = hard_smp_processor_id(); struct trap_per_cpu *p = &trap_block[cpu]; -- cgit v1.2.3 From d7ffd5076d4407d54b25bc4b25f3002f74fbafde Mon Sep 17 00:00:00 2001 From: Faisal Latif Date: Tue, 16 Sep 2008 11:56:26 -0700 Subject: RDMA/nes: Fix client side QP destroy Fix QP not being destroyed properly on the client, which leads to userspace programs hanging on exit. This is a missing chunk from the connection management rewrite in commit 6492cdf3 ("RDMA/nes: CM connection setup/teardown rework"). Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_cm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 9f0b964b2c9..499d3cf83e1 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1956,13 +1956,6 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, return ret; cleanup_retrans_entry(cm_node); cm_node->state = NES_CM_STATE_CLOSED; - ret = send_fin(cm_node, NULL); - - if (cm_node->accept_pend) { - BUG_ON(!cm_node->listener); - atomic_dec(&cm_node->listener->pend_accepts_cnt); - BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0); - } ret = send_reset(cm_node, NULL); return ret; @@ -2383,6 +2376,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) atomic_inc(&cm_disconnects); cm_event.event = IW_CM_EVENT_DISCONNECT; if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { + issued_disconnect_reset = 1; cm_event.status = IW_CM_EVENT_STATUS_RESET; nes_debug(NES_DBG_CM, "Generating a CM " "Disconnect Event (status reset) for " @@ -2508,7 +2502,6 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) nes_debug(NES_DBG_CM, "Call close API\n"); g_cm_core->api->close(g_cm_core, nesqp->cm_node); - nesqp->cm_node = NULL; } return ret; @@ -2837,6 +2830,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) cm_node->apbvt_set = 1; nesqp->cm_node = cm_node; cm_node->nesqp = nesqp; + nes_add_ref(&nesqp->ibqp); return 0; } @@ -3167,7 +3161,6 @@ static void cm_event_connect_error(struct nes_cm_event *event) if (ret) printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " "ret=%d\n", __func__, __LINE__, ret); - nes_rem_ref(&nesqp->ibqp); cm_id->rem_ref(cm_id); rem_ref_cm_node(event->cm_node->cm_core, event->cm_node); -- cgit v1.2.3 From e8224e4b804b4fd26723191c1891101a5959bb8a Mon Sep 17 00:00:00 2001 From: Yossi Etigin Date: Tue, 16 Sep 2008 11:57:45 -0700 Subject: IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop() Taking rtnl_lock in ipoib_mcast_join_complete() causes a deadlock with ipoib_stop(). We avoid it by scheduling the piece of code that takes the lock on ipoib_workqueue instead of executing it directly. This works because we only flush the ipoib_workqueue with the RTNL not held. The deadlock happens because ipoib_stop() calls ipoib_ib_dev_down() which calls ipoib_mcast_dev_flush(), which calls ipoib_mcast_free(), which calls ipoib_mcast_leave(). The latter calls ib_sa_free_multicast(), and this waits until the multicast completion handler finishes. This handler is ipoib_mcast_join_complete(), which waits for the rtnl_lock(), which was already taken by ipoib_stop(). This bug was introduced in commit a77a57a1 ("IPoIB: Fix deadlock on RTNL in ipoib_stop()"). Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 2 ++ drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 + drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 31 +++++++++++++++++--------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b0ffc9abe8c..05eb41b8ab6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -293,6 +293,7 @@ struct ipoib_dev_priv { struct delayed_work pkey_poll_task; struct delayed_work mcast_task; + struct work_struct carrier_on_task; struct work_struct flush_light; struct work_struct flush_normal; struct work_struct flush_heavy; @@ -464,6 +465,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); void ipoib_dev_cleanup(struct net_device *dev); void ipoib_mcast_join_task(struct work_struct *work); +void ipoib_mcast_carrier_on_task(struct work_struct *work); void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); void ipoib_mcast_restart_task(struct work_struct *work); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7e9e218738f..1b1df5cc411 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1075,6 +1075,7 @@ static void ipoib_setup(struct net_device *dev) INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); + INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ac33c8f3ea8..aae28620a6e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -366,6 +366,21 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast) return ret; } +void ipoib_mcast_carrier_on_task(struct work_struct *work) +{ + struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, + carrier_on_task); + + /* + * Take rtnl_lock to avoid racing with ipoib_stop() and + * turning the carrier back on while a device is being + * removed. + */ + rtnl_lock(); + netif_carrier_on(priv->dev); + rtnl_unlock(); +} + static int ipoib_mcast_join_complete(int status, struct ib_sa_multicast *multicast) { @@ -392,16 +407,12 @@ static int ipoib_mcast_join_complete(int status, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); - if (mcast == priv->broadcast) { - /* - * Take RTNL lock here to avoid racing with - * ipoib_stop() and turning the carrier back - * on while a device is being removed. - */ - rtnl_lock(); - netif_carrier_on(dev); - rtnl_unlock(); - } + /* + * Defer carrier on work to ipoib_workqueue to avoid a + * deadlock on rtnl_lock here. + */ + if (mcast == priv->broadcast) + queue_work(ipoib_workqueue, &priv->carrier_on_task); return 0; } -- cgit v1.2.3 From 2344abbcbdb82140050e8be29d3d55e4f6fe860b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 16 Sep 2008 11:32:50 -0700 Subject: clockevents: make device shutdown robust The device shut down does not cleanup the next_event variable of the clock event device. So when the device is reactivated the possible stale next_event value can prevent the device to be reprogrammed as it claims to wait on a event already. This is the root cause of the resurfacing suspend/resume problem, where systems need key press to come back to life. Fix this by setting next_event to KTIME_MAX when the device is shut down. Use a separate function for shutdown which takes care of that and only keep the direct set mode call in the broadcast code, where we can not touch the next_event value. Signed-off-by: Thomas Gleixner --- kernel/time/clockevents.c | 12 +++++++++++- kernel/time/tick-broadcast.c | 9 ++++----- kernel/time/tick-common.c | 4 ++-- kernel/time/tick-internal.h | 2 ++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 1876b526c77..f8d968063ce 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -71,6 +71,16 @@ void clockevents_set_mode(struct clock_event_device *dev, } } +/** + * clockevents_shutdown - shutdown the device and clear next_event + * @dev: device to shutdown + */ +void clockevents_shutdown(struct clock_event_device *dev) +{ + clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); + dev->next_event.tv64 = KTIME_MAX; +} + /** * clockevents_program_event - Reprogram the clock event device. * @expires: absolute expiry time (monotonic clock) @@ -206,7 +216,7 @@ void clockevents_exchange_device(struct clock_event_device *old, if (new) { BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); - clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(new); } local_irq_restore(flags); } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2f5a38294bf..f1f3eee2811 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -236,8 +236,7 @@ static void tick_do_broadcast_on_off(void *why) if (!cpu_isset(cpu, tick_broadcast_mask)) { cpu_set(cpu, tick_broadcast_mask); if (td->mode == TICKDEV_MODE_PERIODIC) - clockevents_set_mode(dev, - CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(dev); } if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) tick_broadcast_force = 1; @@ -254,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why) if (cpus_empty(tick_broadcast_mask)) { if (!bc_stopped) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); } else if (bc_stopped) { if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) tick_broadcast_start_periodic(bc); @@ -306,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup) if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { if (bc && cpus_empty(tick_broadcast_mask)) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); } spin_unlock_irqrestore(&tick_broadcast_lock, flags); @@ -321,7 +320,7 @@ void tick_suspend_broadcast(void) bc = tick_broadcast_device.evtdev; if (bc) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(bc); spin_unlock_irqrestore(&tick_broadcast_lock, flags); } diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index c4777193d56..019315ebf9d 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -249,7 +249,7 @@ static int tick_check_new_device(struct clock_event_device *newdev) * not give it back to the clockevents layer ! */ if (tick_is_broadcast_device(curdev)) { - clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(curdev); curdev = NULL; } clockevents_exchange_device(curdev, newdev); @@ -311,7 +311,7 @@ static void tick_suspend(void) unsigned long flags; spin_lock_irqsave(&tick_device_lock, flags); - clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_SHUTDOWN); + clockevents_shutdown(td->evtdev); spin_unlock_irqrestore(&tick_device_lock, flags); } diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 0ffc2918ea6..6e9db9734aa 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -10,6 +10,8 @@ extern int tick_do_timer_cpu __read_mostly; extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); extern void tick_handle_periodic(struct clock_event_device *dev); +extern void clockevents_shutdown(struct clock_event_device *dev); + /* * NO_HZ / high resolution timer shared code */ -- cgit v1.2.3 From 612f9d338a6060f814ef35b7108b43407a5df423 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 9 Sep 2008 14:43:39 -0500 Subject: powerpc: Fix interrupt values for DMA2 in MPC8610 HPCD device tree For Freescale 8xxx devices that use an MPIC, the interrupt numbers in the device tree must be 16 greater than the values documented in the reference manual. In these chips, the MPIC is wired to use the first 16 numbers for external interrupts, but the documentation numbers internal interrupts from 0. In the MPC8610 HPCD device tree, the interrupt properties for the DMA channels for DMA2 were not the adjusted values. This fixes that. Signed-off-by: Timur Tabi Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/boot/dts/mpc8610_hpcd.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 3b3a1062cb2..584a4f184eb 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -281,7 +281,7 @@ cell-index = <0>; reg = <0x0 0x80>; interrupt-parent = <&mpic>; - interrupts = <60 2>; + interrupts = <76 2>; }; dma-channel@1 { compatible = "fsl,mpc8610-dma-channel", @@ -289,7 +289,7 @@ cell-index = <1>; reg = <0x80 0x80>; interrupt-parent = <&mpic>; - interrupts = <61 2>; + interrupts = <77 2>; }; dma-channel@2 { compatible = "fsl,mpc8610-dma-channel", @@ -297,7 +297,7 @@ cell-index = <2>; reg = <0x100 0x80>; interrupt-parent = <&mpic>; - interrupts = <62 2>; + interrupts = <78 2>; }; dma-channel@3 { compatible = "fsl,mpc8610-dma-channel", @@ -305,7 +305,7 @@ cell-index = <3>; reg = <0x180 0x80>; interrupt-parent = <&mpic>; - interrupts = <63 2>; + interrupts = <79 2>; }; }; -- cgit v1.2.3 From b08508c40adf3fd1330aabc4f37d3254179776c4 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Tue, 26 Aug 2008 08:20:34 -0700 Subject: PCI: fix compiler warnings in pci_get_subsys() pci_get_subsys() changed in 2.6.26 so that the from pointer is modified when the call is being invoked, so fix up the 'const' marking of it that the compiler is complaining about. Reported-by: Rufus & Azrael Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jesse Barnes --- drivers/pci/search.c | 6 +++--- include/linux/pci.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 3b3b5f17879..4edfc4731bd 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -162,7 +162,7 @@ EXPORT_SYMBOL(pci_find_slot); * time. */ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from) + struct pci_dev *from) { struct pci_dev *pdev; @@ -263,7 +263,7 @@ static int match_pci_dev_by_id(struct device *dev, void *data) * this file. */ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, - const struct pci_dev *from) + struct pci_dev *from) { struct device *dev; struct device *dev_start = NULL; @@ -303,7 +303,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, */ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) + struct pci_dev *from) { struct pci_dev *pdev; struct pci_device_id *id; diff --git a/include/linux/pci.h b/include/linux/pci.h index c0e14008a3c..98dc6243a70 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -534,7 +534,7 @@ extern void pci_sort_breadthfirst(void); #ifdef CONFIG_PCI_LEGACY struct pci_dev __deprecated *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from); + struct pci_dev *from); struct pci_dev __deprecated *pci_find_slot(unsigned int bus, unsigned int devfn); #endif /* CONFIG_PCI_LEGACY */ @@ -550,7 +550,7 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from); struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from); + struct pci_dev *from); struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn); struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn); struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); @@ -816,7 +816,7 @@ _PCI_NOP_ALL(write,) static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, - const struct pci_dev *from) + struct pci_dev *from) { return NULL; } @@ -838,7 +838,7 @@ static inline struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) + struct pci_dev *from) { return NULL; } -- cgit v1.2.3 From e95926d05d028a6bf0ab60b21b484c3d622fdcd1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 16 Sep 2008 19:32:30 -0700 Subject: Revert "b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support" This reverts commit bc19d6e0b74ef03a3baf035412c95192b54dfc6f, which as Larry Finger reports causes the radio LED on his system to no longer respond to rfkill switch events. Reported-by: Larry Finger Requested-by: John W. Linville Signed-off-by: Linus Torvalds --- drivers/net/wireless/b43/rfkill.c | 18 ------------------ drivers/net/wireless/b43legacy/rfkill.c | 18 ------------------ 2 files changed, 36 deletions(-) diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index fec5645944a..34ae125d538 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -43,23 +43,6 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) return 0; } -/* Update the rfkill state */ -static void b43_rfkill_update_state(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (!dev->radio_hw_enable) { - rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; - return; - } - - if (!dev->phy.radio_on) - rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - else - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - -} - /* The poll callback for the hardware button. */ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) { @@ -77,7 +60,6 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; report_change = 1; - b43_rfkill_update_state(dev); b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); } diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 476add97e97..b32bf6a94f1 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -44,23 +44,6 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) return 0; } -/* Update the rfkill state */ -static void b43legacy_rfkill_update_state(struct b43legacy_wldev *dev) -{ - struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); - - if (!dev->radio_hw_enable) { - rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; - return; - } - - if (!dev->phy.radio_on) - rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - else - rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; - -} - /* The poll callback for the hardware button. */ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) { @@ -78,7 +61,6 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; report_change = 1; - b43legacy_rfkill_update_state(dev); b43legacyinfo(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); } -- cgit v1.2.3 From 49f276be7ce12d90b6941a000b09e61b68e6c4f2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 16 Sep 2008 16:04:12 -0700 Subject: hpplus: fix build regression This fixes kernel regression for 2.6.27-rc in http://bugzilla.kernel.org/show_bug.cgi?id=11547 The change to split 8390 into old isa and non-isa versions overlooked this driver. Signed-off-by: Stephen Hemminger Signed-off-by: Linus Torvalds --- drivers/net/hp-plus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 8239939554b..fbbd3e660c2 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -139,7 +139,7 @@ static int __init do_hpp_probe(struct net_device *dev) #ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = alloc_eip_netdev(); int err; if (!dev) @@ -284,7 +284,7 @@ hpp_open(struct net_device *dev) int option_reg; int retval; - if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) { return retval; } @@ -302,7 +302,7 @@ hpp_open(struct net_device *dev) /* Select the operational page. */ outw(Perf_Page, ioaddr + HP_PAGING); - ei_open(dev); + eip_open(dev); return 0; } @@ -313,7 +313,7 @@ hpp_close(struct net_device *dev) int option_reg = inw(ioaddr + HPP_OPTION); free_irq(dev->irq, dev); - ei_close(dev); + eip_close(dev); outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset, ioaddr + HPP_OPTION); -- cgit v1.2.3 From ef3d7714f6b75b51825ad0384b5ce48358427e50 Mon Sep 17 00:00:00 2001 From: David Miller Date: Tue, 16 Sep 2008 15:00:11 -0700 Subject: Fix PNP build failure, bugzilla #11276 This fill fix the following regression list entry: Bug-Entry : http://bugzilla.kernel.org/show_bug.cgi?id=11276 Subject : build error: CONFIG_OPTIMIZE_INLINING=y causes gcc 4.2 to do stupid things Submitter : Randy Dunlap Date : 2008-08-06 17:18 (38 days old) References : http://marc.info/?l=linux-kernel&m=121804329014332&w=4 http://lkml.org/lkml/2008/7/22/353 Handled-By : Bjorn Helgaas Patch : http://lkml.org/lkml/2008/7/22/364 with what I believe is a better fix than the one referenced in the regression entry above. These PNP header interfaces try to work in such a way that you can reference some of them even if PNP is not enabled, and the compiler was expected to optimize everything away. Which is mostly fine, except that there was one interface for which there was not provided an inline "NOP" implementation. Once we add that, all of these compile failures cannot handle any more. pnp: Provide NOP inline implementation of pnp_get_resource() when !PNP Fixes kernel bugzilla #11276. Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds --- include/linux/pnp.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 1ce54b63085..be764e514e3 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -21,7 +21,14 @@ struct pnp_dev; /* * Resource Management */ +#ifdef CONFIG_PNP struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int); +#else +static inline struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned int type, unsigned int num) +{ + return NULL; +} +#endif static inline int pnp_resource_valid(struct resource *res) { -- cgit v1.2.3 From 45e9c0de2e86485f8b6633fd64ab19cfbff167f6 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 15 Sep 2008 16:43:18 -0700 Subject: warn: Turn the netdev timeout WARN_ON() into a WARN() this patch turns the netdev timeout WARN_ON_ONCE() into a WARN_ONCE(), so that the device and driver names are inside the warning message. This helps automated tools like kerneloops.org to collect the data and do statistics, as well as making it more likely that humans cut-n-paste the important message as part of a bugreport. Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- include/asm-generic/bug.h | 10 ++++++++++ net/sched/sch_generic.c | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index a3f738cffdb..edc6ba82e09 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -97,6 +97,16 @@ extern void warn_slowpath(const char *file, const int line, unlikely(__ret_warn_once); \ }) +#define WARN_ONCE(condition, format...) ({ \ + static int __warned; \ + int __ret_warn_once = !!(condition); \ + \ + if (unlikely(__ret_warn_once)) \ + if (WARN(!__warned, format)) \ + __warned = 1; \ + unlikely(__ret_warn_once); \ +}) + #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON((condition) && __ratelimit(state)) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 9634091ee2f..ec0a0839ce5 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -215,10 +215,9 @@ static void dev_watchdog(unsigned long arg) time_after(jiffies, (dev->trans_start + dev->watchdog_timeo))) { char drivername[64]; - printk(KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", + WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", dev->name, netdev_drivername(dev, drivername, 64)); dev->tx_timeout(dev); - WARN_ON_ONCE(1); } if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + -- cgit v1.2.3 From 31bd61f2bb79e098117d823e054342b03aa87668 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:45:37 +1000 Subject: [XFS] Move memory allocations for log tracing out of the critical path Memory allocations for log->l_grant_trace and iclog->ic_trace are done on demand when the first event is logged. In xlog_state_get_iclog_space() we call xlog_trace_iclog() under a spinlock and allocating memory here can cause us to sleep with a spinlock held and deadlock the system. For the log grant tracing we use KM_NOSLEEP but that means we can lose trace entries. Since there is no locking to serialize the log grant tracing we could race and have multiple allocations and leak memory. So move the allocations to where we initialize the log/iclog structures. Use KM_NOFS to avoid recursing into the filesystem and drop log->l_trace since it's not even used. SGI-PV: 983738 SGI-Modid: xfs-linux-melb:xfs-kern:31896a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_log.c | 60 ++++++++++++++++++++++++++++++++++----------------- fs/xfs/xfs_log_priv.h | 1 - 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ccba14eb9db..7812bd036e2 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -124,16 +124,27 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, STATIC int xlog_iclogs_empty(xlog_t *log); #if defined(XFS_LOG_TRACE) + +#define XLOG_TRACE_LOGGRANT_SIZE 2048 +#define XLOG_TRACE_ICLOG_SIZE 256 + +void +xlog_trace_loggrant_alloc(xlog_t *log) +{ + log->l_grant_trace = ktrace_alloc(XLOG_TRACE_LOGGRANT_SIZE, KM_NOFS); +} + +void +xlog_trace_loggrant_dealloc(xlog_t *log) +{ + ktrace_free(log->l_grant_trace); +} + void xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) { unsigned long cnts; - if (!log->l_grant_trace) { - log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP); - if (!log->l_grant_trace) - return; - } /* ticket counts are 1 byte each */ cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8; @@ -156,11 +167,21 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) (void *)((unsigned long)tic->t_unit_res)); } +void +xlog_trace_iclog_alloc(xlog_in_core_t *iclog) +{ + iclog->ic_trace = ktrace_alloc(XLOG_TRACE_ICLOG_SIZE, KM_NOFS); +} + +void +xlog_trace_iclog_dealloc(xlog_in_core_t *iclog) +{ + ktrace_free(iclog->ic_trace); +} + void xlog_trace_iclog(xlog_in_core_t *iclog, uint state) { - if (!iclog->ic_trace) - iclog->ic_trace = ktrace_alloc(256, KM_NOFS); ktrace_enter(iclog->ic_trace, (void *)((unsigned long)state), (void *)((unsigned long)current_pid()), @@ -170,8 +191,15 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state) (void *)NULL, (void *)NULL); } #else + +#define xlog_trace_loggrant_alloc(log) +#define xlog_trace_loggrant_dealloc(log) #define xlog_trace_loggrant(log,tic,string) + +#define xlog_trace_iclog_alloc(iclog) +#define xlog_trace_iclog_dealloc(iclog) #define xlog_trace_iclog(iclog,state) + #endif /* XFS_LOG_TRACE */ @@ -1231,6 +1259,7 @@ xlog_alloc_log(xfs_mount_t *mp, spin_lock_init(&log->l_grant_lock); sv_init(&log->l_flush_wait, 0, "flush_wait"); + xlog_trace_loggrant_alloc(log); /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); @@ -1285,6 +1314,8 @@ xlog_alloc_log(xfs_mount_t *mp, sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); + xlog_trace_iclog_alloc(iclog); + iclogp = &iclog->ic_next; } *iclogp = log->l_iclog; /* complete ring */ @@ -1565,11 +1596,7 @@ xlog_dealloc_log(xlog_t *log) sv_destroy(&iclog->ic_force_wait); sv_destroy(&iclog->ic_write_wait); xfs_buf_free(iclog->ic_bp); -#ifdef XFS_LOG_TRACE - if (iclog->ic_trace != NULL) { - ktrace_free(iclog->ic_trace); - } -#endif + xlog_trace_iclog_dealloc(iclog); next_iclog = iclog->ic_next; kmem_free(iclog); iclog = next_iclog; @@ -1578,14 +1605,7 @@ xlog_dealloc_log(xlog_t *log) spinlock_destroy(&log->l_grant_lock); xfs_buf_free(log->l_xbuf); -#ifdef XFS_LOG_TRACE - if (log->l_trace != NULL) { - ktrace_free(log->l_trace); - } - if (log->l_grant_trace != NULL) { - ktrace_free(log->l_grant_trace); - } -#endif + xlog_trace_loggrant_dealloc(log); log->l_mp->m_log = NULL; kmem_free(log); } /* xlog_dealloc_log */ diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index c8a5b22ee3e..e7d8f84443f 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -448,7 +448,6 @@ typedef struct log { int l_grant_write_bytes; #ifdef XFS_LOG_TRACE - struct ktrace *l_trace; struct ktrace *l_grant_trace; #endif -- cgit v1.2.3 From 6efdf281777eb07fac28ac2b2d7df1e619ee6da1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 17 Sep 2008 16:49:33 +1000 Subject: [XFS] Fix regression introduced by remount fixup Logically we would return an error in xfs_fs_remount code to prevent users from believing they might have changed mount options using remount which can't be changed. But unfortunately mount(8) adds all options from mtab and fstab to the mount arguments in some cases so we can't blindly reject options, but have to check for each specified option if it actually differs from the currently set option and only reject it if that's the case. Until that is implemented we return success for every remount request, and silently ignore all options that we can't actually change. SGI-PV: 985710 SGI-Modid: xfs-linux-melb:xfs-kern:31908a Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 73c65f19e54..18d3c848783 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1302,9 +1302,29 @@ xfs_fs_remount( mp->m_flags &= ~XFS_MOUNT_BARRIER; break; default: + /* + * Logically we would return an error here to prevent + * users from believing they might have changed + * mount options using remount which can't be changed. + * + * But unfortunately mount(8) adds all options from + * mtab and fstab to the mount arguments in some cases + * so we can't blindly reject options, but have to + * check for each specified option if it actually + * differs from the currently set option and only + * reject it if that's the case. + * + * Until that is implemented we return success for + * every remount request, and silently ignore all + * options that we can't actually change. + */ +#if 0 printk(KERN_INFO "XFS: mount option \"%s\" not supported for remount\n", p); return -EINVAL; +#else + return 0; +#endif } } -- cgit v1.2.3 From 364f358a734ddcd827c662ccbfa58ee3ac510762 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:50:14 +1000 Subject: [XFS] Prevent direct I/O from mapping extents beyond eof With the help from some tracing I found that we try to map extents beyond eof when doing a direct I/O read. It appears that the way to inform the generic direct I/O path (ie do_direct_IO()) that we have breached eof is to return an unmapped buffer from xfs_get_blocks_direct(). This will cause do_direct_IO() to jump to the hole handling code where is will check for eof and then abort. This problem was found because a direct I/O read was trying to map beyond eof and was encountering delayed allocations. The delayed allocations beyond eof are speculative allocations and they didn't get converted when the direct I/O flushed the file because there was only enough space in the current AG to convert and write out the dirty pages within eof. Note that xfs_iomap_write_allocate() wont necessarily convert all the delayed allocation passed to it - it will return after allocating the first extent - so if the delayed allocation extends beyond eof then it will stay that way. SGI-PV: 983683 SGI-Modid: xfs-linux-melb:xfs-kern:31929a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_aops.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index f42f80a3b1f..a44d68eb50b 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1338,6 +1338,10 @@ __xfs_get_blocks( offset = (xfs_off_t)iblock << inode->i_blkbits; ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); size = bh_result->b_size; + + if (!create && direct && offset >= i_size_read(inode)) + return 0; + error = xfs_iomap(XFS_I(inode), offset, size, create ? flags : BMAPI_READ, &iomap, &niomap); if (error) -- cgit v1.2.3 From b5b8c9acd547244eb2b7d0280ba38b9dd01971cc Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 17 Sep 2008 16:50:50 +1000 Subject: [XFS] Fix barrier status change detection. The current code in xlog_iodone() uses the wrong macro to check if the barrier has been cleared due to an EOPNOTSUPP error form the lower layer. SGI-PV: 986143 SGI-Modid: xfs-linux-melb:xfs-kern:31984a Signed-off-by: David Chinner Signed-off-by: Nathaniel W. Turner Signed-off-by: Peter Leckie Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7812bd036e2..503ea89e8b9 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1037,7 +1037,7 @@ xlog_iodone(xfs_buf_t *bp) * layer, it means the underlyin device no longer supports * barrier I/O. Warn loudly and turn off barriers. */ - if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) { + if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; xfs_fs_cmn_err(CE_WARN, l->l_mp, "xlog_iodone: Barriers are no longer supported" -- cgit v1.2.3 From f9114eba1eb08ee75fd0f1eee780f0290fb3c043 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 17 Sep 2008 16:51:21 +1000 Subject: [XFS] Prevent lockdep false positives when locking two inodes. If we call xfs_lock_two_inodes() to grab both the iolock and the ilock, then drop the ilocks on both inodes, then grab them again (as xfs_swap_extents() does) then lockdep will report a locking order problem. This is a false positive. To avoid this, disallow xfs_lock_two_inodes() fom locking both inode locks at once - force calers to make two separate calls. This means that nested dropping and regaining of the ilocks will retain the same lockdep subclass and so lockdep will not see anything wrong with this code. SGI-PV: 986238 SGI-Modid: xfs-linux-melb:xfs-kern:31999a Signed-off-by: David Chinner Signed-off-by: Christoph Hellwig Signed-off-by: Peter Leckie Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_dfrag.c | 9 ++++++++- fs/xfs/xfs_vnodeops.c | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 760f4c5b516..75b0cd4da0e 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -149,7 +149,14 @@ xfs_swap_extents( sbp = &sxp->sx_stat; - xfs_lock_two_inodes(ip, tip, lock_flags); + /* + * we have to do two separate lock calls here to keep lockdep + * happy. If we try to get all the locks in one call, lock will + * report false positives when we drop the ILOCK and regain them + * below. + */ + xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); + xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); locked = 1; /* Verify that both files have the same format */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index aa238c8fbd7..98a0aecafdd 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1838,6 +1838,12 @@ again: #endif } +/* + * xfs_lock_two_inodes() can only be used to lock one type of lock + * at a time - the iolock or the ilock, but not both at once. If + * we lock both at once, lockdep will report false positives saying + * we have violated locking orders. + */ void xfs_lock_two_inodes( xfs_inode_t *ip0, @@ -1848,6 +1854,8 @@ xfs_lock_two_inodes( int attempts = 0; xfs_log_item_t *lp; + if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) + ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0); ASSERT(ip0->i_ino != ip1->i_ino); if (ip0->i_ino > ip1->i_ino) { -- cgit v1.2.3 From e1f5dbd7077eebec794452a516cb02f1669b036d Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:52:13 +1000 Subject: [XFS] Fix use-after-free with buffers We have a use-after-free issue where log completions access buffers via the buffer log item and the buffer has already been freed. Fix this by taking a reference on the buffer when attaching the buffer log item and release the hold when the buffer log item is detached and we no longer need the buffer. Also create a new function xfs_buf_item_free() to combine some common code. SGI-PV: 985757 SGI-Modid: xfs-linux-melb:xfs-kern:32025a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_buf_item.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 608c30c3f76..002fc2617c8 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -732,6 +732,7 @@ xfs_buf_item_init( bip->bli_item.li_ops = &xfs_buf_item_ops; bip->bli_item.li_mountp = mp; bip->bli_buf = bp; + xfs_buf_hold(bp); bip->bli_format.blf_type = XFS_LI_BUF; bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); @@ -867,6 +868,21 @@ xfs_buf_item_dirty( return (bip->bli_flags & XFS_BLI_DIRTY); } +STATIC void +xfs_buf_item_free( + xfs_buf_log_item_t *bip) +{ +#ifdef XFS_TRANS_DEBUG + kmem_free(bip->bli_orig); + kmem_free(bip->bli_logged); +#endif /* XFS_TRANS_DEBUG */ + +#ifdef XFS_BLI_TRACE + ktrace_free(bip->bli_trace); +#endif + kmem_zone_free(xfs_buf_item_zone, bip); +} + /* * This is called when the buf log item is no longer needed. It should * free the buf log item associated with the given buffer and clear @@ -887,18 +903,8 @@ xfs_buf_item_relse( (XFS_BUF_IODONE_FUNC(bp) != NULL)) { XFS_BUF_CLR_IODONE_FUNC(bp); } - -#ifdef XFS_TRANS_DEBUG - kmem_free(bip->bli_orig); - bip->bli_orig = NULL; - kmem_free(bip->bli_logged); - bip->bli_logged = NULL; -#endif /* XFS_TRANS_DEBUG */ - -#ifdef XFS_BLI_TRACE - ktrace_free(bip->bli_trace); -#endif - kmem_zone_free(xfs_buf_item_zone, bip); + xfs_buf_rele(bp); + xfs_buf_item_free(bip); } @@ -1120,6 +1126,7 @@ xfs_buf_iodone( ASSERT(bip->bli_buf == bp); + xfs_buf_rele(bp); mp = bip->bli_item.li_mountp; /* @@ -1136,18 +1143,7 @@ xfs_buf_iodone( * xfs_trans_delete_ail() drops the AIL lock. */ xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip); - -#ifdef XFS_TRANS_DEBUG - kmem_free(bip->bli_orig); - bip->bli_orig = NULL; - kmem_free(bip->bli_logged); - bip->bli_logged = NULL; -#endif /* XFS_TRANS_DEBUG */ - -#ifdef XFS_BLI_TRACE - ktrace_free(bip->bli_trace); -#endif - kmem_zone_free(xfs_buf_item_zone, bip); + xfs_buf_item_free(bip); } #if defined(XFS_BLI_TRACE) -- cgit v1.2.3 From 2fd6f6ec64ff347447d26646ac6188f3658b383c Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 17 Sep 2008 16:52:50 +1000 Subject: [XFS] Don't do I/O beyond eof when unreserving space When unreserving space with boundaries that are not block aligned we round up the start and round down the end boundaries and then use this function, xfs_zero_remaining_bytes(), to zero the parts of the blocks that got dropped during the rounding. The problem is we don't consider if these blocks are beyond eof. Worse still is if we encounter delayed allocations beyond eof we will try to use the magic delayed allocation block number as a real block number. If the file size is ever extended to expose these blocks then we'll go through xfs_zero_eof() to zero them anyway. SGI-PV: 983683 SGI-Modid: xfs-linux-melb:xfs-kern:32055a Signed-off-by: Lachlan McIlroy Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_vnodeops.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 98a0aecafdd..8b6812f66a1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3160,6 +3160,13 @@ error1: /* Just cancel transaction */ /* * Zero file bytes between startoff and endoff inclusive. * The iolock is held exclusive and no blocks are buffered. + * + * This function is used by xfs_free_file_space() to zero + * partial blocks when the range to free is not block aligned. + * When unreserving space with boundaries that are not block + * aligned we round up the start and round down the end + * boundaries and then use this function to zero the parts of + * the blocks that got dropped during the rounding. */ STATIC int xfs_zero_remaining_bytes( @@ -3176,6 +3183,17 @@ xfs_zero_remaining_bytes( int nimap; int error = 0; + /* + * Avoid doing I/O beyond eof - it's not necessary + * since nothing can read beyond eof. The space will + * be zeroed when the file is extended anyway. + */ + if (startoff >= ip->i_size) + return 0; + + if (endoff > ip->i_size) + endoff = ip->i_size; + bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize, XFS_IS_REALTIME_INODE(ip) ? mp->m_rtdev_targp : mp->m_ddev_targp); -- cgit v1.2.3 From 0855f310dff76ae42c5aac32f600f8f692bbd23f Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Tue, 9 Sep 2008 11:17:29 +0200 Subject: UBIFS: create the name of the background thread in every case If the ubifs partition is mounted RO and then remounted RW we end up with no thread name in ubifs_remount_rw() and the thread appears nameless. Signed-off-by: Sebastian Siewior Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 7562464ac83..3f4902060c7 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1024,14 +1024,13 @@ static int mount_ubifs(struct ubifs_info *c) goto out_dereg; } + sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); if (!mounted_read_only) { err = alloc_wbufs(c); if (err) goto out_cbuf; /* Create background thread */ - sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, - c->vi.vol_id); c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); if (!c->bgt) c->bgt = ERR_PTR(-EINVAL); -- cgit v1.2.3 From 6dcfac4f13d6b32fbaa60b64a23249999e66af8e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 12 Sep 2008 12:27:47 +0300 Subject: UBIFS: TNC / GC race fixes - update GC sequence number if any nodes may have been moved even if GC did not finish the LEB - don't ignore error return when reading Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 14 +++++++++++--- fs/ubifs/tnc.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 13f1019c859..02aba36fe3d 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) err = move_nodes(c, sleb); if (err) - goto out; + goto out_inc_seq; err = gc_sync_wbufs(c); if (err) - goto out; + goto out_inc_seq; err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); if (err) - goto out; + goto out_inc_seq; /* Allow for races with TNC */ c->gced_lnum = lnum; @@ -369,6 +369,14 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) out: ubifs_scan_destroy(sleb); return err; + +out_inc_seq: + /* We may have moved at least some nodes so allow for races with TNC */ + c->gced_lnum = lnum; + smp_wmb(); + c->gc_seq += 1; + smp_wmb(); + goto out; } /** diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 7da209ab937..7634c597088 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1476,7 +1476,7 @@ again: } err = fallible_read_node(c, key, &zbr, node); - if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) { /* * The node may have been GC'ed out from under us so try again * while keeping the TNC mutex locked. -- cgit v1.2.3 From 6e14968c869cd30e236bb626dd0c16421d2a658d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 17 Sep 2008 10:52:07 +0300 Subject: UBIFS: remove incorrect assert The assert was not valid because one of the variables 'taken_empty_lebs' has transient values out of sync with the other variables. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/find.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index e045c8b5542..47814cde240 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -507,7 +507,6 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; - ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); if (rsvd_idx_lebs < lebs) /* * OK to allocate an empty LEB, but we still don't want to go -- cgit v1.2.3 From 32dde0f975e430f00f03f80f7dbab585d8b45eab Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Sep 2008 04:00:28 +0000 Subject: powerpc: Holly board needs dtbImage target One of the changes in the bootwrapper makefile introduced the dtbImage targets for boards that need a simple zImage with a DTB embedded in them (595be948cce574ff2d5dde5d0426a636a4363c70, "[POWERPC] bootwrapper: Build multiple cuImages"). When this was done, it broke booting on the Holly board as the zImage.holly wrapper did not get the DTB embedded properly. This changes the target for the Holly board to a dtbImage so that the wrapper includes the vmlinux, wrapper bits, and DTB. Signed-off-by: Josh Boyer Signed-off-by: Paul Mackerras --- arch/powerpc/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 717a3bc1352..65d1a8454d2 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -195,7 +195,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac -image-$(CONFIG_PPC_HOLLY) += zImage.holly +image-$(CONFIG_PPC_HOLLY) += dtbImage.holly image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage -- cgit v1.2.3 From 2d291e902791e1c8d72bc223b6f063bbb27a1280 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 9 Sep 2008 14:04:18 +0000 Subject: Fix compile failure with non modular builds Commit deac93df26b20cf8438339b5935b5f5643bc30c9 ("lib: Correct printk %pF to work on all architectures") broke the non modular builds by moving an essential function into modules.c. Fix this by moving it out again and into asm/sections.h as an inline. To do this, the definition of struct ppc64_opd_entry has been lifted out of modules.c and put in asm/elf.h where it belongs. Signed-off-by: James Bottomley Signed-off-by: Paul Mackerras --- arch/powerpc/include/asm/elf.h | 7 +++++++ arch/powerpc/include/asm/sections.h | 12 +++++++++++- arch/powerpc/kernel/module_64.c | 19 ------------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 80d1f399ee5..64c6ee22eef 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -409,6 +409,13 @@ do { \ /* Keep this the last entry. */ #define R_PPC64_NUM 107 +/* There's actually a third entry here, but it's unused */ +struct ppc64_opd_entry +{ + unsigned long funcaddr; + unsigned long r2; +}; + #ifdef __KERNEL__ #ifdef CONFIG_SPU_BASE diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 7710e9e6660..07956f3e784 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -2,6 +2,8 @@ #define _ASM_POWERPC_SECTIONS_H #ifdef __KERNEL__ +#include +#include #include #ifdef __powerpc64__ @@ -17,7 +19,15 @@ static inline int in_kernel_text(unsigned long addr) } #undef dereference_function_descriptor -void *dereference_function_descriptor(void *); +static inline void *dereference_function_descriptor(void *ptr) +{ + struct ppc64_opd_entry *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->funcaddr, p)) + ptr = p; + return ptr; +} #endif diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ad79de272ff..1af2377e499 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -21,9 +21,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -43,13 +41,6 @@ #define DEBUGP(fmt , ...) #endif -/* There's actually a third entry here, but it's unused */ -struct ppc64_opd_entry -{ - unsigned long funcaddr; - unsigned long r2; -}; - /* Like PPC32, we need little trampolines to do > 24-bit jumps (into the kernel itself). But on PPC64, these need to be used for every jump, actually, to reset r2 (TOC+0x8000). */ @@ -452,13 +443,3 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; } - -void *dereference_function_descriptor(void *ptr) -{ - struct ppc64_opd_entry *desc = ptr; - void *p; - - if (!probe_kernel_address(&desc->funcaddr, p)) - ptr = p; - return ptr; -} -- cgit v1.2.3 From 380b0fdfd0227d7604cd91ad97fb846ba643e0e7 Mon Sep 17 00:00:00 2001 From: roelkluin Date: Mon, 15 Sep 2008 20:56:44 +0100 Subject: [ARM] 5249/1: davinci: remove redundant check in davinci_psc_config() id is unsigned, check is redundant. Signed-off-by: Roel Kluin Signed-off-by: Russell King --- arch/arm/mach-davinci/psc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 720c48b9ee0..aa2fc375a32 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -70,9 +70,6 @@ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) { u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; - if (id < 0) - return; - mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); if (enable) mdctl |= 0x00000003; /* Enable Module */ -- cgit v1.2.3 From 7e8bc3c6db9b4b74842b1c70bbf5c2a99a112b0d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 17 Sep 2008 20:58:11 +0100 Subject: [ARM] omap: back out 'internal_clock' support The structures weren't ready for this change: arch/arm/plat-omap/devices.c:320: error: 'struct omap_mmc_conf' has no member named 'internal_clock' arch/arm/plat-omap/devices.c:326: error: implicit declaration of function 'omap_ctrl_readl' arch/arm/plat-omap/devices.c:326: error: 'OMAP2_CONTROL_DEVCONF0' undeclared (first use in this function) arch/arm/plat-omap/devices.c:328: error: implicit declaration of function 'omap_ctrl_writel' Signed-off-by: Russell King --- arch/arm/plat-omap/devices.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index bc1cf30c83e..01da719a745 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -316,19 +316,6 @@ static inline void omap_init_mmc_conf(const struct omap_mmc_config *mmc_conf) omap_cfg_reg(MMC_DAT3); } } -#if defined(CONFIG_ARCH_OMAP2420) - if (mmc_conf->mmc[0].internal_clock) { - /* - * Use internal loop-back in MMC/SDIO - * Module Input Clock selection - */ - if (cpu_is_omap24xx()) { - u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - v |= (1 << 24); /* not used in 243x */ - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - } - } -#endif } #ifdef CONFIG_ARCH_OMAP16XX -- cgit v1.2.3 From 7424bac82ff3bd956ea04101550e01bdae17284d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 17 Sep 2008 22:09:41 +0400 Subject: UBIFS: fix printk format warnings fs/ubifs/dir.c:428: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type 'long unsigned int' fs/ubifs/debug.c:541: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type 'long unsigned int' Signed-off-by: Alexander Beregalov Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 +- fs/ubifs/dir.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b9cb7747375..d7f7645779f 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); for (i = 0; i < n; i++) printk(KERN_DEBUG "\t ino %llu\n", - le64_to_cpu(orph->inos[i])); + (unsigned long long)le64_to_cpu(orph->inos[i])); break; } default: diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 2b267c9a180..526c01ec800 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", - dent->name, le64_to_cpu(dent->inum), + dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); -- cgit v1.2.3 From ee2fa7435b6dddf1ca119f298ad0100cf50c0397 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 13:47:25 +0200 Subject: AMD IOMMU: set iommu sunc flag after command queuing The iommu->need_sync flag must be set after the command is queued to avoid race conditions. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 69b4d060b21..a96d8c049a8 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -140,6 +140,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid) { struct iommu_cmd cmd; + int ret; BUG_ON(iommu == NULL); @@ -147,9 +148,11 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid) CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY); cmd.data[0] = devid; + ret = iommu_queue_command(iommu, &cmd); + iommu->need_sync = 1; - return iommu_queue_command(iommu, &cmd); + return ret; } /* @@ -159,6 +162,7 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu, u64 address, u16 domid, int pde, int s) { struct iommu_cmd cmd; + int ret; memset(&cmd, 0, sizeof(cmd)); address &= PAGE_MASK; @@ -171,9 +175,11 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu, if (pde) /* PDE bit - we wan't flush everything not only the PTEs */ cmd.data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK; + ret = iommu_queue_command(iommu, &cmd); + iommu->need_sync = 1; - return iommu_queue_command(iommu, &cmd); + return ret; } /* -- cgit v1.2.3 From 7e4f88da7bf1887563f70bd5edbbd0479e31dc12 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 17 Sep 2008 14:19:15 +0200 Subject: AMD IOMMU: protect completion wait loop with iommu lock The unlocked polling of the ComWaitInt bit in the IOMMU completion wait path is racy. Protect it with the iommu lock. Signed-off-by: Joerg Roedel Signed-off-by: Ingo Molnar --- arch/x86/kernel/amd_iommu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a96d8c049a8..042fdc27bc9 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -101,10 +101,10 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd) */ static int iommu_completion_wait(struct amd_iommu *iommu) { - int ret, ready = 0; + int ret = 0, ready = 0; unsigned status = 0; struct iommu_cmd cmd; - unsigned long i = 0; + unsigned long flags, i = 0; memset(&cmd, 0, sizeof(cmd)); cmd.data[0] = CMD_COMPL_WAIT_INT_MASK; @@ -112,10 +112,12 @@ static int iommu_completion_wait(struct amd_iommu *iommu) iommu->need_sync = 0; - ret = iommu_queue_command(iommu, &cmd); + spin_lock_irqsave(&iommu->lock, flags); + + ret = __iommu_queue_command(iommu, &cmd); if (ret) - return ret; + goto out; while (!ready && (i < EXIT_LOOP_COUNT)) { ++i; @@ -130,6 +132,8 @@ static int iommu_completion_wait(struct amd_iommu *iommu) if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit())) printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n"); +out: + spin_unlock_irqrestore(&iommu->lock, flags); return 0; } -- cgit v1.2.3 From a3028b8ed1e1e9930bfa70ce4555fb7f9fad3dcc Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 02:48:25 -0700 Subject: sctp: set the skb->ip_summed correctly when sending over loopback. Loopback used to clobber the ip_summed filed which sctp then used to figure out if it needed to do checksumming or not. Now that loopback doesn't do that any more, sctp needs to set the ip_summed field correctly. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 0dc4a7dfb23..225c7123c41 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) if (!(dst->dev->features & NETIF_F_NO_CSUM)) { crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); crc32 = sctp_end_cksum(crc32); - } + } else + nskb->ip_summed = CHECKSUM_UNNECESSARY; /* 3) Put the resultant value into the checksum field in the * common header, and leave the rest of the bits unchanged. -- cgit v1.2.3 From 58005b325394b18b8b6a737e06b4128deb2c4e63 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Thu, 18 Sep 2008 12:19:39 +0100 Subject: [ARM] 5255/1: Update jornada ssp to remove build errors/warnings * Adds ssp functions into header so we don't get "implicit declaration" error at builtime. * Converts jornada_ssp_start/end functions into voids with proper declarations (to avoid "prototype..." warning). * Sorts include files in alphabetical order * Minor comment changes Signed-off-by: Kristoffer Ericson Signed-off-by: Russell King --- arch/arm/mach-sa1100/include/mach/jornada720.h | 11 ++++++++--- arch/arm/mach-sa1100/jornada720_ssp.c | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-sa1100/include/mach/jornada720.h b/arch/arm/mach-sa1100/include/mach/jornada720.h index bc120850d31..cc6b4bfcecf 100644 --- a/arch/arm/mach-sa1100/include/mach/jornada720.h +++ b/arch/arm/mach-sa1100/include/mach/jornada720.h @@ -1,10 +1,10 @@ /* * arch/arm/mach-sa1100/include/mach/jornada720.h * - * This file contains SSP/MCU communication definitions for HP Jornada 710/720/728 + * SSP/MCU communication definitions for HP Jornada 710/720/728 * - * Copyright (C) 2007 Kristoffer Ericson - * Copyright (C) 2000 John Ankcorn + * Copyright 2007,2008 Kristoffer Ericson + * Copyright 2000 John Ankcorn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -25,3 +25,8 @@ #define PWMOFF 0xDF #define TXDUMMY 0x11 #define ERRORCODE 0x00 + +extern void jornada_ssp_start(void); +extern void jornada_ssp_end(void); +extern int jornada_ssp_inout(u8 byte); +extern int jornada_ssp_byte(u8 byte); diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index 06ea7abd917..28cf3696797 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -21,8 +21,8 @@ #include #include -#include #include +#include static DEFINE_SPINLOCK(jornada_ssp_lock); static unsigned long jornada_ssp_flags; @@ -109,12 +109,12 @@ EXPORT_SYMBOL(jornada_ssp_inout); * jornada_ssp_start - enable mcu * */ -int jornada_ssp_start() +void jornada_ssp_start(void) { spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags); GPCR = GPIO_GPIO25; udelay(50); - return 0; + return; }; EXPORT_SYMBOL(jornada_ssp_start); @@ -122,11 +122,11 @@ EXPORT_SYMBOL(jornada_ssp_start); * jornada_ssp_end - disable mcu and turn off lock * */ -int jornada_ssp_end() +void jornada_ssp_end(void) { GPSR = GPIO_GPIO25; spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags); - return 0; + return; }; EXPORT_SYMBOL(jornada_ssp_end); -- cgit v1.2.3 From 0ef46e285c062cbe35d60c0adbff96f530d31c86 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 16:27:38 -0700 Subject: sctp: do not enable peer features if we can't do them. Do not enable peer features like addip and auth, if they are administratively disabled localy. If the peer resports that he supports something that we don't, neither end can use it so enabling it is pointless. This solves a problem when talking to a peer that has auth and addip enabled while we do not. Found by Andrei Pelinescu-Onciul . Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981..fe94f42fa06 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1886,11 +1886,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, /* if the peer reports AUTH, assume that he * supports AUTH. */ - asoc->peer.auth_capable = 1; + if (sctp_auth_enable) + asoc->peer.auth_capable = 1; break; case SCTP_CID_ASCONF: case SCTP_CID_ASCONF_ACK: - asoc->peer.asconf_capable = 1; + if (sctp_addip_enable) + asoc->peer.asconf_capable = 1; break; default: break; @@ -2460,6 +2462,9 @@ do_addr_param: break; case SCTP_PARAM_SET_PRIMARY: + if (!sctp_addip_enable) + goto fall_through; + addr_param = param.v + sizeof(sctp_addip_param_t); af = sctp_get_af_specific(param_type2af(param.p->type)); -- cgit v1.2.3 From add52379dde2e5300e2d574b172e62c6cf43b3d3 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 18 Sep 2008 16:28:27 -0700 Subject: sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH If INIT-ACK is received with SupportedExtensions parameter which indicates that the peer does not support AUTH, the packet will be silently ignore, and sctp_process_init() do cleanup all of the transports in the association. When T1-Init timer is expires, OOPS happen while we try to choose a different init transport. The solution is to only clean up the non-active transports, i.e the ones that the peer added. However, that introduces a problem with sctp_connectx(), because we don't mark the proper state for the transports provided by the user. So, we'll simply mark user-provided transports as ACTIVE. That will allow INIT retransmissions to work properly in the sctp_connectx() context and prevent the crash. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/associola.c | 9 +++++---- net/sctp/sm_make_chunk.c | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c..abd51cef241 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, /* Check to see if this is a duplicate. */ peer = sctp_assoc_lookup_paddr(asoc, addr); if (peer) { + /* An UNKNOWN state is only set on transports added by + * user in sctp_connectx() call. Such transports should be + * considered CONFIRMED per RFC 4960, Section 5.4. + */ if (peer->state == SCTP_UNKNOWN) { - if (peer_state == SCTP_ACTIVE) - peer->state = SCTP_ACTIVE; - if (peer_state == SCTP_UNCONFIRMED) - peer->state = SCTP_UNCONFIRMED; + peer->state = SCTP_ACTIVE; } return peer; } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fe94f42fa06..b599cbba4fb 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2321,12 +2321,10 @@ clean_up: /* Release the transport structures. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - list_del_init(pos); - sctp_transport_free(transport); + if (transport->state != SCTP_ACTIVE) + sctp_assoc_rm_peer(asoc, transport); } - asoc->peer.transport_count = 0; - nomem: return 0; } -- cgit v1.2.3 From 27ed9ddfde8d2967076c51815e4ce297c4a18139 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Thu, 18 Sep 2008 16:46:11 -0700 Subject: bnx2: Promote vector field in bnx2_irq structure from u16 to unsigned int The bnx2 driver stores/uses the irq value from the pci_dev internally. But when it stores the irq value, it has been performing an integer demotion. Because of the recent changes made to arch/x86/kernel/io_apic.c, the new method in creating the irq value (using build_irq_for_pci_dev()) has exposed this bug on x86 systems. Because of this demotion when calling request_irq() from bnx2_request_irq(), the driver would get a return code of -EINVAL. This is because the kernel could not find the requested irq descriptor. By storing the irq value properly, the kernel can find the correct irq descriptor and the bnx2 driver can operate normally. Signed-off-by: Benjamin Li Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index c3c579f98ed..dfacd31f7ed 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6597,7 +6597,7 @@ struct flash_spec { struct bnx2_irq { irq_handler_t handler; - u16 vector; + unsigned int vector; u8 requested; char name[16]; }; -- cgit v1.2.3 From f55c21fd9a92a444e55ad1ca4e4732d56661bf2e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 13 Sep 2008 13:10:31 -0700 Subject: forcedeth: call restore mac addr in nv_shutdown path after | commit f735a2a1a4f2a0f5cd823ce323e82675990469e2 | Author: Tobias Diedrich | Date: Sun May 18 15:02:37 2008 +0200 | | [netdrvr] forcedeth: setup wake-on-lan before shutting down | | When hibernating in 'shutdown' mode, after saving the image the suspend hook | is not called again. | However, if the device is in promiscous mode, wake-on-lan will not work. | This adds a shutdown hook to setup wake-on-lan before the final shutdown. | | Signed-off-by: Tobias Diedrich | Signed-off-by: Jeff Garzik my servers with nvidia ck804 and mcp55 will reverse mac address with kexec. it turns out that we need to restore the mac addr in nv_shutdown(). [akpm@linux-foundation.org: fix typo in printk] Signed-off-by: Yinghai Lu Cc: Tobias Diedrich Cc: Ayaz Abdulla Cc: Jeff Garzik Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0b6ecef9a84..eeb55ed2152 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5643,6 +5643,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff; dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff; writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); + printk(KERN_DEBUG "nv_probe: set workaround bit for reversed mac addr\n"); } memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); @@ -5890,14 +5891,12 @@ static void nv_restore_phy(struct net_device *dev) } } -static void __devexit nv_remove(struct pci_dev *pci_dev) +static void nv_restore_mac_addr(struct pci_dev *pci_dev) { struct net_device *dev = pci_get_drvdata(pci_dev); struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - unregister_netdev(dev); - /* special op: write back the misordered MAC address - otherwise * the next nv_probe would see a wrong address. */ @@ -5905,6 +5904,15 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) writel(np->orig_mac[1], base + NvRegMacAddrB); writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll); +} + +static void __devexit nv_remove(struct pci_dev *pci_dev) +{ + struct net_device *dev = pci_get_drvdata(pci_dev); + + unregister_netdev(dev); + + nv_restore_mac_addr(pci_dev); /* restore any phy related changes */ nv_restore_phy(dev); @@ -5975,6 +5983,8 @@ static void nv_shutdown(struct pci_dev *pdev) if (netif_running(dev)) nv_close(dev); + nv_restore_mac_addr(pdev); + pci_disable_device(pdev); if (system_state == SYSTEM_POWER_OFF) { if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) -- cgit v1.2.3 From 78566fecbb12a7616ae9a88b2ffbc8062c4a89e3 Mon Sep 17 00:00:00 2001 From: Christopher Li Date: Fri, 5 Sep 2008 14:04:05 -0700 Subject: e1000: prevent corruption of EEPROM/NVM Andrey reports e1000 corruption, and that a patch in vmware's ESX fixed it. The EEPROM corruption is triggered by concurrent access of the EEPROM read/write. Putting a lock around it solve the problem. [akpm@linux-foundation.org: use DEFINE_SPINLOCK to avoid confusing lockdep] Signed-off-by: Christopher Li Reported-by: Andrey Borzenkov Cc: Zach Amsden Cc: Pratap Subrahmanyam Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Bruce Allan Cc: PJ Waskiewicz Cc: John Ronciak Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_hw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 9d6edf3e73f..d04eef53571 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -144,6 +144,8 @@ static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer); static u8 e1000_calculate_mng_checksum(char *buffer, u32 length); static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex); static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw); +static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); /* IGP cable length table */ static const @@ -168,6 +170,8 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] = 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, 124}; +static DEFINE_SPINLOCK(e1000_eeprom_lock); + /****************************************************************************** * Set the phy type member in the hw struct. * @@ -4903,6 +4907,15 @@ static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw) * words - number of words to read *****************************************************************************/ s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + s32 ret; + spin_lock(&e1000_eeprom_lock); + ret = e1000_do_read_eeprom(hw, offset, words, data); + spin_unlock(&e1000_eeprom_lock); + return ret; +} + +static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_eeprom_info *eeprom = &hw->eeprom; u32 i = 0; @@ -5235,6 +5248,16 @@ s32 e1000_update_eeprom_checksum(struct e1000_hw *hw) * EEPROM will most likely contain an invalid checksum. *****************************************************************************/ s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + s32 ret; + spin_lock(&e1000_eeprom_lock); + ret = e1000_do_write_eeprom(hw, offset, words, data); + spin_unlock(&e1000_eeprom_lock); + return ret; +} + + +static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_eeprom_info *eeprom = &hw->eeprom; s32 status = 0; -- cgit v1.2.3 From e7272403d2f9be3dbb7cc185fcc390e781b1af6b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 8 Aug 2008 00:18:04 +0200 Subject: e100: Use pci_pme_active to clear PME_Status and disable PME# Currently e100 uses pci_enable_wake() to clear pending wake-up events and disable PME# during intitialization, but that function is not suitable for this purpose, because it immediately returns error code if device_may_wakeup() returns false for given device. Make e100 use pci_pme_active(), which carries out exactly the required operations, instead. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/net/e100.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 453115acaad..5cf78d612c4 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2738,9 +2738,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->flags |= wol_magic; /* ack any pending wake events, disable PME */ - err = pci_enable_wake(pdev, 0, 0); - if (err) - DPRINTK(PROBE, ERR, "Error clearing wake event\n"); + pci_pme_active(pdev, false); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) { -- cgit v1.2.3 From 9744197c3d7b329590c2be33ad7b17409bd798fe Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 19 Sep 2008 11:49:54 +1000 Subject: md: Don't wait UNINTERRUPTIBLE for other resync to finish When two md arrays share some block device (e.g each uses different partitions on the one device), a resync of one array will wait for the resync on the other to finish. This can be a long time and as it currently waits TASK_UNINTERRUPTIBLE, the softlockup code notices and complains. So use TASK_INTERRUPTIBLE instead and make sure to flush signals before calling schedule. Signed-off-by: NeilBrown --- drivers/md/md.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 4790c83d78d..deeac4b4417 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5761,7 +5761,11 @@ void md_do_sync(mddev_t *mddev) * time 'round when curr_resync == 2 */ continue; - prepare_to_wait(&resync_wait, &wq, TASK_UNINTERRUPTIBLE); + /* We need to wait 'interruptible' so as not to + * contribute to the load average, and not to + * be caught by 'softlockup' + */ + prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); if (!kthread_should_stop() && mddev2->curr_resync >= mddev->curr_resync) { printk(KERN_INFO "md: delaying %s of %s" @@ -5769,6 +5773,8 @@ void md_do_sync(mddev_t *mddev) " share one or more physical units)\n", desc, mdname(mddev), mdname(mddev2)); mddev_put(mddev2); + if (signal_pending(current)) + flush_signals(current); schedule(); finish_wait(&resync_wait, &wq); goto try_again; -- cgit v1.2.3 From 170e7108a368c52df1ec466966fd1db6e45a7ad2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 02:58:50 +0200 Subject: mv643xx_eth: fix receive checksumming We have to explicitly tell the hardware to include the pseudo-header when doing receive checksumming, otherwise hardware checksumming will fail for every received packet and we'll end up setting CHECKSUM_NONE on every received packet. While we're at it, when skb->ip_summed is set to CHECKSUM_UNNECESSARY on received packets, skb->csum is supposed to be undefined, and thus there is no need to set it. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 408827de7d3..94c13be292a 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -546,11 +546,8 @@ static int rxq_process(struct rx_queue *rxq, int budget) */ skb_put(skb, byte_cnt - 2 - 4); - if (cmd_sts & LAYER_4_CHECKSUM_OK) { + if (cmd_sts & LAYER_4_CHECKSUM_OK) skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->csum = htons( - (cmd_sts & 0x0007fff8) >> 3); - } skb->protocol = eth_type_trans(skb, mp->dev); netif_receive_skb(skb); } @@ -1994,9 +1991,10 @@ static void port_start(struct mv643xx_eth_private *mp) /* * Receive all unmatched unicast, TCP, UDP, BPDU and broadcast - * frames to RX queue #0. + * frames to RX queue #0, and include the pseudo-header when + * calculating receive checksums. */ - wrl(mp, PORT_CONFIG(mp->port_num), 0x00000000); + wrl(mp, PORT_CONFIG(mp->port_num), 0x02000000); /* * Treat BPDUs as normal multicasts, and disable partition mode. -- cgit v1.2.3 From 4df89bd5a5fc33860f15f5f001a78f2b3f150725 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 04:05:00 +0200 Subject: mv643xx_eth: deal with unexpected ethernet header sizes When the IP header doesn't start 14, 18, 22 or 26 bytes into the packet (which are the only four cases that the hardware can deal with if asked to do IP checksumming on transmit), invoke the software checksum helper instead of letting the packet go out with a corrupt checksum inserted into the packet in the wrong place. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 95 +++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 94c13be292a..9522c449cce 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -699,79 +699,74 @@ static inline __be16 sum16_as_be(__sum16 sum) return (__force __be16)sum; } -static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) +static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) { struct mv643xx_eth_private *mp = txq_to_mp(txq); int nr_frags = skb_shinfo(skb)->nr_frags; int tx_index; struct tx_desc *desc; u32 cmd_sts; + u16 l4i_chk; int length; cmd_sts = TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA; - - tx_index = txq_alloc_desc_index(txq); - desc = &txq->tx_desc_area[tx_index]; - - if (nr_frags) { - txq_submit_frag_skb(txq, skb); - length = skb_headlen(skb); - } else { - cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; - length = skb->len; - } - - desc->byte_cnt = length; - desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + l4i_chk = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) { - int mac_hdr_len; + int tag_bytes; BUG_ON(skb->protocol != htons(ETH_P_IP) && skb->protocol != htons(ETH_P_8021Q)); - cmd_sts |= GEN_TCP_UDP_CHECKSUM | - GEN_IP_V4_CHECKSUM | - ip_hdr(skb)->ihl << TX_IHL_SHIFT; + tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN; + if (unlikely(tag_bytes & ~12)) { + if (skb_checksum_help(skb) == 0) + goto no_csum; + kfree_skb(skb); + return 1; + } - mac_hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; - switch (mac_hdr_len - ETH_HLEN) { - case 0: - break; - case 4: - cmd_sts |= MAC_HDR_EXTRA_4_BYTES; - break; - case 8: - cmd_sts |= MAC_HDR_EXTRA_8_BYTES; - break; - case 12: + if (tag_bytes & 4) cmd_sts |= MAC_HDR_EXTRA_4_BYTES; + if (tag_bytes & 8) cmd_sts |= MAC_HDR_EXTRA_8_BYTES; - break; - default: - if (net_ratelimit()) - dev_printk(KERN_ERR, &txq_to_mp(txq)->dev->dev, - "mac header length is %d?!\n", mac_hdr_len); - break; - } + + cmd_sts |= GEN_TCP_UDP_CHECKSUM | + GEN_IP_V4_CHECKSUM | + ip_hdr(skb)->ihl << TX_IHL_SHIFT; switch (ip_hdr(skb)->protocol) { case IPPROTO_UDP: cmd_sts |= UDP_FRAME; - desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); + l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); break; case IPPROTO_TCP: - desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); + l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); break; default: BUG(); } } else { +no_csum: /* Errata BTS #50, IHL must be 5 if no HW checksum */ cmd_sts |= 5 << TX_IHL_SHIFT; - desc->l4i_chk = 0; } + tx_index = txq_alloc_desc_index(txq); + desc = &txq->tx_desc_area[tx_index]; + + if (nr_frags) { + txq_submit_frag_skb(txq, skb); + length = skb_headlen(skb); + } else { + cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT; + length = skb->len; + } + + desc->l4i_chk = l4i_chk; + desc->byte_cnt = length; + desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + __skb_queue_tail(&txq->tx_skb, skb); /* ensure all other descriptors are written before first cmd_sts */ @@ -786,6 +781,8 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) txq_enable(txq); txq->tx_desc_count += nr_frags + 1; + + return 0; } static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) @@ -794,7 +791,6 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) int queue; struct tx_queue *txq; struct netdev_queue *nq; - int entries_left; queue = skb_get_queue_mapping(skb); txq = mp->txq + queue; @@ -815,14 +811,17 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - txq_submit_skb(txq, skb); - txq->tx_bytes += skb->len; - txq->tx_packets++; - dev->trans_start = jiffies; + if (!txq_submit_skb(txq, skb)) { + int entries_left; + + txq->tx_bytes += skb->len; + txq->tx_packets++; + dev->trans_start = jiffies; - entries_left = txq->tx_ring_size - txq->tx_desc_count; - if (entries_left < MAX_SKB_FRAGS + 1) - netif_tx_stop_queue(nq); + entries_left = txq->tx_ring_size - txq->tx_desc_count; + if (entries_left < MAX_SKB_FRAGS + 1) + netif_tx_stop_queue(nq); + } return NETDEV_TX_OK; } -- cgit v1.2.3 From 4ff3495a51c7226376d8013c5742d1d5e54876a7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 19 Sep 2008 05:04:57 +0200 Subject: mv643xx_eth: enforce frequent hardware statistics polling If we don't poll the hardware statistics counters at least once every ~34 seconds, overflow might occur without us noticing. So, set up a timer to poll the statistics counters at least once every 30 seconds. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9522c449cce..d0ecc440aac 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -356,7 +356,10 @@ struct mv643xx_eth_private { int phy_addr; + struct timer_list mib_counters_timer; + spinlock_t mib_counters_lock; struct mib_counters mib_counters; + struct work_struct tx_timeout_task; struct mii_if_info mii; @@ -1176,6 +1179,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) { struct mib_counters *p = &mp->mib_counters; + spin_lock(&mp->mib_counters_lock); p->good_octets_received += mib_read(mp, 0x00); p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; p->bad_octets_received += mib_read(mp, 0x08); @@ -1208,6 +1212,16 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->bad_crc_event += mib_read(mp, 0x74); p->collision += mib_read(mp, 0x78); p->late_collision += mib_read(mp, 0x7c); + spin_unlock(&mp->mib_counters_lock); + + mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); +} + +static void mib_counters_timer_wrapper(unsigned long _mp) +{ + struct mv643xx_eth_private *mp = (void *)_mp; + + mib_counters_update(mp); } @@ -2148,6 +2162,8 @@ static int mv643xx_eth_stop(struct net_device *dev) wrl(mp, INT_MASK(mp->port_num), 0x00000000); rdl(mp, INT_MASK(mp->port_num)); + del_timer_sync(&mp->mib_counters_timer); + napi_disable(&mp->napi); del_timer_sync(&mp->rx_oom); @@ -2625,6 +2641,19 @@ static int mv643xx_eth_probe(struct platform_device *pdev) } init_pscr(mp, pd->speed, pd->duplex); + + mib_counters_clear(mp); + + init_timer(&mp->mib_counters_timer); + mp->mib_counters_timer.data = (unsigned long)mp; + mp->mib_counters_timer.function = mib_counters_timer_wrapper; + mp->mib_counters_timer.expires = jiffies + 30 * HZ; + add_timer(&mp->mib_counters_timer); + + spin_lock_init(&mp->mib_counters_lock); + + INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); + netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 128); init_timer(&mp->rx_oom); -- cgit v1.2.3 From 4fd5f812c23c7deee6425f4a318e85c317cd1d6c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 13:08:46 +0200 Subject: phylib: allow incremental scanning of an mii bus This patch splits the bus scanning code in mdiobus_register() off into a separate function, and makes this function available for calling from external code. This allows incrementally scanning an mii bus, e.g. as information about which addresses are 'safe' to scan becomes available. Signed-off-by: Lennert Buytenhek Acked-by: Andy Fleming --- drivers/net/phy/mdio_bus.c | 89 +++++++++++++++++++++++++--------------------- include/linux/phy.h | 2 ++ 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 94e0b7ed76f..e7508c10887 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -60,49 +60,14 @@ int mdiobus_register(struct mii_bus *bus) bus->reset(bus); for (i = 0; i < PHY_MAX_ADDR; i++) { - struct phy_device *phydev; + bus->phy_map[i] = NULL; + if ((bus->phy_mask & (1 << i)) == 0) { + struct phy_device *phydev; - if (bus->phy_mask & (1 << i)) { - bus->phy_map[i] = NULL; - continue; + phydev = mdiobus_scan(bus, i); + if (IS_ERR(phydev)) + err = PTR_ERR(phydev); } - - phydev = get_phy_device(bus, i); - - if (IS_ERR(phydev)) - return PTR_ERR(phydev); - - /* There's a PHY at this address - * We need to set: - * 1) IRQ - * 2) bus_id - * 3) parent - * 4) bus - * 5) mii_bus - * And, we need to register it */ - if (phydev) { - phydev->irq = bus->irq[i]; - - phydev->dev.parent = bus->dev; - phydev->dev.bus = &mdio_bus_type; - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); - - phydev->bus = bus; - - /* Run all of the fixups for this PHY */ - phy_scan_fixups(phydev); - - err = device_register(&phydev->dev); - - if (err) { - printk(KERN_ERR "phy %d failed to register\n", - i); - phy_device_free(phydev); - phydev = NULL; - } - } - - bus->phy_map[i] = phydev; } pr_info("%s: probed\n", bus->name); @@ -122,6 +87,48 @@ void mdiobus_unregister(struct mii_bus *bus) } EXPORT_SYMBOL(mdiobus_unregister); +struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) +{ + struct phy_device *phydev; + int err; + + phydev = get_phy_device(bus, addr); + if (IS_ERR(phydev) || phydev == NULL) + return phydev; + + /* There's a PHY at this address + * We need to set: + * 1) IRQ + * 2) bus_id + * 3) parent + * 4) bus + * 5) mii_bus + * And, we need to register it */ + + phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; + + phydev->dev.parent = bus->dev; + phydev->dev.bus = &mdio_bus_type; + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr); + + phydev->bus = bus; + + /* Run all of the fixups for this PHY */ + phy_scan_fixups(phydev); + + err = device_register(&phydev->dev); + if (err) { + printk(KERN_ERR "phy %d failed to register\n", addr); + phy_device_free(phydev); + phydev = NULL; + } + + bus->phy_map[addr] = phydev; + + return phydev; +} +EXPORT_SYMBOL(mdiobus_scan); + /** * mdio_bus_match - determine if given PHY driver supports the given PHY device * @dev: target PHY device diff --git a/include/linux/phy.h b/include/linux/phy.h index 7224c4099a2..5f170f5b1a3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -410,6 +410,8 @@ int phy_start_aneg(struct phy_device *phydev); int mdiobus_register(struct mii_bus *bus); void mdiobus_unregister(struct mii_bus *bus); +struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); + void phy_sanitize_settings(struct phy_device *phydev); int phy_stop_interrupts(struct phy_device *phydev); int phy_enable_interrupts(struct phy_device *phydev); -- cgit v1.2.3 From 7fb61a7b6f9111245867fa2bce47949f4298d430 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 17:56:54 +0200 Subject: atstk1000: fix build breakage with BOARD_ATSTK100X_SW2_CUSTOM=y The #ifdef surrounding the code adding the mmc controller had a typo, causing it to be compiled even when mmc was supposed to be disabled. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index ee4c292683e..dfc3443e23a 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -325,7 +325,7 @@ static int __init atstk1002_init(void) #ifdef CONFIG_BOARD_ATSTK100X_SPI1 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif -#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM at32_add_device_mci(0, MCI_PDATA); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM -- cgit v1.2.3 From 1b771c12b56fdea6c0596a69c63b097b62ce9f41 Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Mon, 8 Sep 2008 00:22:45 +0200 Subject: avr32: add .gitignore files Ignore Kernel binaries, kernel/vmlinux.lds and a log file. Signed-off-by: Markus Heidelberg Signed-off-by: Haavard Skinnemoen --- arch/avr32/boot/images/.gitignore | 4 ++++ arch/avr32/kernel/.gitignore | 1 + 2 files changed, 5 insertions(+) create mode 100644 arch/avr32/boot/images/.gitignore create mode 100644 arch/avr32/kernel/.gitignore diff --git a/arch/avr32/boot/images/.gitignore b/arch/avr32/boot/images/.gitignore new file mode 100644 index 00000000000..64ea9d0141d --- /dev/null +++ b/arch/avr32/boot/images/.gitignore @@ -0,0 +1,4 @@ +uImage +uImage.srec +vmlinux.cso +sfdwarf.log diff --git a/arch/avr32/kernel/.gitignore b/arch/avr32/kernel/.gitignore new file mode 100644 index 00000000000..c5f676c3c22 --- /dev/null +++ b/arch/avr32/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds -- cgit v1.2.3 From e37925ebdb9738fc7968119198c6997e79093c02 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 10 Sep 2008 15:52:04 +0200 Subject: avr32: add generic_find_next_le_bit bit function This patch implements the generic_find_next_le_bit bit function for AVR32 architecture. This is used by EXT4 file system. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/avr32_ksyms.c | 1 + arch/avr32/lib/findbit.S | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 84a7d44edc6..11e310c567a 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -58,6 +58,7 @@ EXPORT_SYMBOL(find_first_zero_bit); EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_first_bit); EXPORT_SYMBOL(find_next_bit); +EXPORT_SYMBOL(generic_find_next_le_bit); EXPORT_SYMBOL(generic_find_next_zero_le_bit); /* I/O primitives (lib/io-*.S) */ diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S index c6b91dee857..997b33b2288 100644 --- a/arch/avr32/lib/findbit.S +++ b/arch/avr32/lib/findbit.S @@ -123,6 +123,36 @@ ENTRY(find_next_bit) brgt 1b retal r11 +ENTRY(generic_find_next_le_bit) + lsr r8, r10, 5 + sub r9, r11, r10 + retle r11 + + lsl r8, 2 + add r12, r8 + andl r10, 31, COH + breq 1f + + /* offset is not word-aligned. Handle the first (32 - r10) bits */ + ldswp.w r8, r12[0] + sub r12, -4 + lsr r8, r8, r10 + brne .L_found + + /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ + add r9, r10 + sub r9, 32 + retle r11 + + /* Main loop. offset must be word-aligned */ +1: ldswp.w r8, r12[0] + cp.w r8, 0 + brne .L_found + sub r12, -4 + sub r9, 32 + brgt 1b + retal r11 + ENTRY(generic_find_next_zero_le_bit) lsr r8, r10, 5 sub r9, r11, r10 -- cgit v1.2.3 From 73d4393d1df4ff3892b040396f101ede94e9e846 Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 17 Sep 2008 13:39:45 +0200 Subject: avr32: fix sys_sync_file_range() call convention On AVR32, all parameters beyond the 5th are passed on the stack. System calls don't use the stack -- they borrow a callee-saved register instead. This means that syscalls that take 6 parameters must be called through a stub that pushes the last parameter on the stack. This patch adds a stub for sync_file_range syscall on AVR32 architecture. Tested with uClibc snapshot. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/syscall-stubs.S | 9 +++++++++ arch/avr32/kernel/syscall_table.S | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 890286a1e62..673178e235f 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -109,3 +109,12 @@ __sys_epoll_pwait: rcall sys_epoll_pwait sub sp, -4 popm pc + + .global __sys_sync_file_range + .type __sys_sync_file_range,@function +__sys_sync_file_range: + pushm lr + st.w --sp, ARG6 + rcall sys_sync_file_range + sub sp, -4 + popm pc diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 478bda4c4a0..7ee0057613b 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -275,7 +275,7 @@ sys_call_table: .long sys_set_robust_list .long sys_get_robust_list /* 260 */ .long __sys_splice - .long sys_sync_file_range + .long __sys_sync_file_range .long sys_tee .long sys_vmsplice .long __sys_epoll_pwait /* 265 */ -- cgit v1.2.3 From ed94493fb38a665cebcf750dfabe8a6dd13e136f Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 26 Aug 2008 13:34:19 +0200 Subject: mv643xx_eth: convert to phylib Switch mv643xx_eth from using drivers/net/mii.c to using phylib. Since the mv643xx_eth hardware does all the link state handling and PHY polling, the driver will use phylib in the "Doing it all yourself" mode described in the phylib documentation. Signed-off-by: Lennert Buytenhek Acked-by: Andy Fleming --- drivers/net/Kconfig | 2 +- drivers/net/mv643xx_eth.c | 248 +++++++++++++++++++--------------------------- 2 files changed, 105 insertions(+), 145 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4a11296a951..d85d76019af 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2262,7 +2262,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION - select MII + select PHYLIB help This driver supports the gigabit ethernet MACs in the Marvell Discovery PPC/MIPS chipset family (MV643XX) and diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index d0ecc440aac..1f944a23f53 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -248,9 +248,9 @@ struct mv643xx_eth_shared_private { struct mv643xx_eth_shared_private *smi; /* - * Protects access to SMI_REG, which is shared between ports. + * Provides access to local SMI interface. */ - struct mutex phy_lock; + struct mii_bus smi_bus; /* * If we have access to the error interrupt pin (which is @@ -354,14 +354,13 @@ struct mv643xx_eth_private { struct net_device *dev; - int phy_addr; + struct phy_device *phy; struct timer_list mib_counters_timer; spinlock_t mib_counters_lock; struct mib_counters mib_counters; struct work_struct tx_timeout_task; - struct mii_if_info mii; struct napi_struct napi; u8 work_link; @@ -1076,62 +1075,50 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) return 0; } -static int smi_reg_read(struct mv643xx_eth_private *mp, - unsigned int addr, unsigned int reg) +static int smi_bus_read(struct mii_bus *bus, int addr, int reg) { - struct mv643xx_eth_shared_private *msp = mp->shared->smi; + struct mv643xx_eth_shared_private *msp = bus->priv; void __iomem *smi_reg = msp->base + SMI_REG; int ret; - mutex_lock(&msp->phy_lock); - if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - ret = -ETIMEDOUT; - goto out; + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; } writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg); if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - ret = -ETIMEDOUT; - goto out; + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; } ret = readl(smi_reg); if (!(ret & SMI_READ_VALID)) { - printk("%s: SMI bus read not valid\n", mp->dev->name); - ret = -ENODEV; - goto out; + printk("mv643xx_eth: SMI bus read not valid\n"); + return -ENODEV; } - ret &= 0xffff; - -out: - mutex_unlock(&msp->phy_lock); - - return ret; + return ret & 0xffff; } -static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, - unsigned int reg, unsigned int value) +static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val) { - struct mv643xx_eth_shared_private *msp = mp->shared->smi; + struct mv643xx_eth_shared_private *msp = bus->priv; void __iomem *smi_reg = msp->base + SMI_REG; - mutex_lock(&msp->phy_lock); - if (smi_wait_ready(msp)) { - printk("%s: SMI bus busy timeout\n", mp->dev->name); - mutex_unlock(&msp->phy_lock); + printk("mv643xx_eth: SMI bus busy timeout\n"); return -ETIMEDOUT; } writel(SMI_OPCODE_WRITE | (reg << 21) | - (addr << 16) | (value & 0xffff), smi_reg); + (addr << 16) | (val & 0xffff), smi_reg); - mutex_unlock(&msp->phy_lock); + if (smi_wait_ready(msp)) { + printk("mv643xx_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } return 0; } @@ -1287,7 +1274,9 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd * struct mv643xx_eth_private *mp = netdev_priv(dev); int err; - err = mii_ethtool_gset(&mp->mii, cmd); + err = phy_read_status(mp->phy); + if (err == 0) + err = phy_ethtool_gset(mp->phy, cmd); /* * The MAC does not support 1000baseT_Half. @@ -1341,7 +1330,7 @@ static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd * */ cmd->advertising &= ~ADVERTISED_1000baseT_Half; - return mii_ethtool_sset(&mp->mii, cmd); + return phy_ethtool_sset(mp->phy, cmd); } static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd) @@ -1363,7 +1352,7 @@ static int mv643xx_eth_nway_reset(struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); - return mii_nway_restart(&mp->mii); + return genphy_restart_aneg(mp->phy); } static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) @@ -1373,14 +1362,7 @@ static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) static u32 mv643xx_eth_get_link(struct net_device *dev) { - struct mv643xx_eth_private *mp = netdev_priv(dev); - - return mii_link_ok(&mp->mii); -} - -static u32 mv643xx_eth_get_link_phyless(struct net_device *dev) -{ - return 1; + return !!netif_carrier_ok(dev); } static void mv643xx_eth_get_strings(struct net_device *dev, @@ -1448,7 +1430,7 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = { .set_settings = mv643xx_eth_set_settings_phyless, .get_drvinfo = mv643xx_eth_get_drvinfo, .nway_reset = mv643xx_eth_nway_reset_phyless, - .get_link = mv643xx_eth_get_link_phyless, + .get_link = mv643xx_eth_get_link, .set_sg = ethtool_op_set_sg, .get_strings = mv643xx_eth_get_strings, .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, @@ -1941,16 +1923,16 @@ static void phy_reset(struct mv643xx_eth_private *mp) { int data; - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + data = phy_read(mp->phy, MII_BMCR); if (data < 0) return; data |= BMCR_RESET; - if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data) < 0) + if (phy_write(mp->phy, MII_BMCR, data) < 0) return; do { - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); + data = phy_read(mp->phy, MII_BMCR); } while (data >= 0 && data & BMCR_RESET); } @@ -1962,7 +1944,7 @@ static void port_start(struct mv643xx_eth_private *mp) /* * Perform PHY reset, if there is a PHY. */ - if (mp->phy_addr != -1) { + if (mp->phy != NULL) { struct ethtool_cmd cmd; mv643xx_eth_get_settings(mp->dev, &cmd); @@ -1979,7 +1961,7 @@ static void port_start(struct mv643xx_eth_private *mp) wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); pscr |= DO_NOT_FORCE_LINK_FAIL; - if (mp->phy_addr == -1) + if (mp->phy == NULL) pscr |= FORCE_LINK_PASS; wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr); @@ -2188,8 +2170,8 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mv643xx_eth_private *mp = netdev_priv(dev); - if (mp->phy_addr != -1) - return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); + if (mp->phy != NULL) + return phy_mii_ioctl(mp->phy, if_mii(ifr), cmd); return -EOPNOTSUPP; } @@ -2259,18 +2241,6 @@ static void mv643xx_eth_netpoll(struct net_device *dev) } #endif -static int mv643xx_eth_mdio_read(struct net_device *dev, int addr, int reg) -{ - struct mv643xx_eth_private *mp = netdev_priv(dev); - return smi_reg_read(mp, addr, reg); -} - -static void mv643xx_eth_mdio_write(struct net_device *dev, int addr, int reg, int val) -{ - struct mv643xx_eth_private *mp = netdev_priv(dev); - smi_reg_write(mp, addr, reg, val); -} - /* platform glue ************************************************************/ static void @@ -2365,11 +2335,23 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (msp->base == NULL) goto out_free; - msp->smi = msp; - if (pd != NULL && pd->shared_smi != NULL) + /* + * Set up and register SMI bus. + */ + if (pd == NULL || pd->shared_smi == NULL) { + msp->smi_bus.priv = msp; + msp->smi_bus.name = "mv643xx_eth smi"; + msp->smi_bus.read = smi_bus_read; + msp->smi_bus.write = smi_bus_write, + snprintf(msp->smi_bus.id, MII_BUS_ID_SIZE, "%d", pdev->id); + msp->smi_bus.dev = &pdev->dev; + msp->smi_bus.phy_mask = 0xffffffff; + if (mdiobus_register(&msp->smi_bus) < 0) + goto out_unmap; + msp->smi = msp; + } else { msp->smi = platform_get_drvdata(pd->shared_smi); - - mutex_init(&msp->phy_lock); + } msp->err_interrupt = NO_IRQ; init_waitqueue_head(&msp->smi_busy_wait); @@ -2405,6 +2387,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) return 0; +out_unmap: + iounmap(msp->base); out_free: kfree(msp); out: @@ -2414,7 +2398,10 @@ out: static int mv643xx_eth_shared_remove(struct platform_device *pdev) { struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); + struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; + if (pd == NULL || pd->shared_smi == NULL) + mdiobus_unregister(&msp->smi_bus); if (msp->err_interrupt != NO_IRQ) free_irq(msp->err_interrupt, msp); iounmap(msp->base); @@ -2462,17 +2449,6 @@ static void set_params(struct mv643xx_eth_private *mp, else uc_addr_get(mp, dev->dev_addr); - if (pd->phy_addr == MV643XX_ETH_PHY_NONE) { - mp->phy_addr = -1; - } else { - if (pd->phy_addr != MV643XX_ETH_PHY_ADDR_DEFAULT) { - mp->phy_addr = pd->phy_addr & 0x3f; - phy_addr_set(mp, mp->phy_addr); - } else { - mp->phy_addr = phy_addr_get(mp); - } - } - mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE; if (pd->rx_queue_size) mp->default_rx_ring_size = pd->rx_queue_size; @@ -2490,76 +2466,60 @@ static void set_params(struct mv643xx_eth_private *mp, mp->txq_count = pd->tx_queue_count ? : 1; } -static int phy_detect(struct mv643xx_eth_private *mp) +static struct phy_device *phy_scan(struct mv643xx_eth_private *mp, + int phy_addr) { - int data; - int data2; + struct mii_bus *bus = &mp->shared->smi->smi_bus; + struct phy_device *phydev; + int start; + int num; + int i; - data = smi_reg_read(mp, mp->phy_addr, MII_BMCR); - if (data < 0) - return -ENODEV; + if (phy_addr == MV643XX_ETH_PHY_ADDR_DEFAULT) { + start = phy_addr_get(mp) & 0x1f; + num = 32; + } else { + start = phy_addr & 0x1f; + num = 1; + } - if (smi_reg_write(mp, mp->phy_addr, MII_BMCR, data ^ BMCR_ANENABLE) < 0) - return -ENODEV; + phydev = NULL; + for (i = 0; i < num; i++) { + int addr = (start + i) & 0x1f; - data2 = smi_reg_read(mp, mp->phy_addr, MII_BMCR); - if (data2 < 0) - return -ENODEV; + if (bus->phy_map[addr] == NULL) + mdiobus_scan(bus, addr); - if (((data ^ data2) & BMCR_ANENABLE) == 0) - return -ENODEV; - - smi_reg_write(mp, mp->phy_addr, MII_BMCR, data); + if (phydev == NULL) { + phydev = bus->phy_map[addr]; + if (phydev != NULL) + phy_addr_set(mp, addr); + } + } - return 0; + return phydev; } -static int phy_init(struct mv643xx_eth_private *mp, - struct mv643xx_eth_platform_data *pd) +static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) { - struct ethtool_cmd cmd; - int err; + struct phy_device *phy = mp->phy; - err = phy_detect(mp); - if (err) { - dev_printk(KERN_INFO, &mp->dev->dev, - "no PHY detected at addr %d\n", mp->phy_addr); - return err; - } phy_reset(mp); - mp->mii.phy_id = mp->phy_addr; - mp->mii.phy_id_mask = 0x3f; - mp->mii.reg_num_mask = 0x1f; - mp->mii.dev = mp->dev; - mp->mii.mdio_read = mv643xx_eth_mdio_read; - mp->mii.mdio_write = mv643xx_eth_mdio_write; - - mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii); - - memset(&cmd, 0, sizeof(cmd)); - - cmd.port = PORT_MII; - cmd.transceiver = XCVR_INTERNAL; - cmd.phy_address = mp->phy_addr; - if (pd->speed == 0) { - cmd.autoneg = AUTONEG_ENABLE; - cmd.speed = SPEED_100; - cmd.advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full; - if (mp->mii.supports_gmii) - cmd.advertising |= ADVERTISED_1000baseT_Full; + phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); + + if (speed == 0) { + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->advertising = phy->supported | ADVERTISED_Autoneg; } else { - cmd.autoneg = AUTONEG_DISABLE; - cmd.speed = pd->speed; - cmd.duplex = pd->duplex; + phy->autoneg = AUTONEG_DISABLE; + phy->advertising = 0; + phy->speed = speed; + phy->duplex = duplex; } - - mv643xx_eth_set_settings(mp->dev, &cmd); - - return 0; + phy_start_aneg(phy); } static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) @@ -2573,7 +2533,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) } pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED; - if (mp->phy_addr == -1) { + if (mp->phy == NULL) { pscr |= DISABLE_AUTO_NEG_SPEED_GMII; if (speed == SPEED_1000) pscr |= SET_GMII_SPEED_TO_1000; @@ -2627,18 +2587,16 @@ static int mv643xx_eth_probe(struct platform_device *pdev) set_params(mp, pd); dev->real_num_tx_queues = mp->txq_count; - mib_counters_clear(mp); - INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); - - if (mp->phy_addr != -1) { - err = phy_init(mp, pd); - if (err) - goto out; + if (pd->phy_addr != MV643XX_ETH_PHY_NONE) + mp->phy = phy_scan(mp, pd->phy_addr); + if (mp->phy != NULL) { + phy_init(mp, pd->speed, pd->duplex); SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); } else { SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); } + init_pscr(mp, pd->speed, pd->duplex); @@ -2711,6 +2669,8 @@ static int mv643xx_eth_remove(struct platform_device *pdev) struct mv643xx_eth_private *mp = platform_get_drvdata(pdev); unregister_netdev(mp->dev); + if (mp->phy != NULL) + phy_detach(mp->phy); flush_scheduled_work(); free_netdev(mp->dev); -- cgit v1.2.3 From 042af53c7839282de15cc7fd7ad8ab938d74ab7c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 09:01:57 +0200 Subject: mv643xx_eth: bump version to 1.4 Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 1f944a23f53..55aa8ba7e0f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -55,7 +55,7 @@ #include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; -static char mv643xx_eth_driver_version[] = "1.3"; +static char mv643xx_eth_driver_version[] = "1.4"; /* -- cgit v1.2.3 From 3d431a742728e6b619ce57a030a92d228c13d1d2 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Wed, 20 Aug 2008 15:39:59 +0200 Subject: avr32: nmi_enter() without nmi_exit() While updating the rcu code, I noticed that do_nmi() for AVR32 is odd: There is an nmi_enter() call without an nmi_exit(). This can't be correct, it breaks rcu (at least the preempt version) and lockdep. [haavard.skinnemoen@atmel.com: fixed another case that returned directly] Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/traps.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index b835c4c0136..0d987373bc0 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -116,15 +116,15 @@ asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) switch (ret) { case NOTIFY_OK: case NOTIFY_STOP: - return; + break; case NOTIFY_BAD: die("Fatal Non-Maskable Interrupt", regs, SIGINT); default: + printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n"); + nmi_disable(); break; } - - printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n"); - nmi_disable(); + nmi_exit(); } asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs) -- cgit v1.2.3 From 9f7263236aa4401f8e52cae084f652175b7a7b5f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 12 Sep 2008 14:12:08 +0200 Subject: KVM: ia64: 'struct fdesc' build fix Commit 4611a77 ("[IA64] fix compile failure with non modular builds") introduced struct fdesc into asm/elf.h, which duplicates KVM's definition. Remove the latter to avoid the build error. Signed-off-by: Jes Sorensen Acked-by: Tony Luck Signed-off-by: Avi Kivity --- arch/ia64/kvm/kvm-ia64.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 7a37d06376b..cd0d1a7284b 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "misc.h" #include "vti.h" @@ -61,12 +62,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { NULL } }; - -struct fdesc{ - unsigned long ip; - unsigned long gp; -}; - static void kvm_flush_icache(unsigned long start, unsigned long len) { int l; -- cgit v1.2.3 From 13b3c3fa27f8f4ed306ce624f446fab000dd8ee4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 10:25:19 +0200 Subject: hwmon: (atxp1) Fix device detection logic The atxp1 device detection code has a major logic flaw, fix it. Not sure how we managed to miss this when the driver was merged... Signed-off-by: Jean Delvare Acked-by: Sebastian Witt --- drivers/hwmon/atxp1.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index d191118ba0c..d6b490d3e36 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -31,7 +31,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); -MODULE_VERSION("0.6.2"); +MODULE_VERSION("0.6.3"); MODULE_AUTHOR("Sebastian Witt "); #define ATXP1_VID 0x00 @@ -289,16 +289,16 @@ static int atxp1_detect(struct i2c_client *new_client, int kind, if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && - (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) { + (i2c_smbus_read_byte_data(new_client, 0xff) == 0))) + return -ENODEV; - /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) - * showing the same as register 0x00 */ - temp = i2c_smbus_read_byte_data(new_client, 0x00); + /* No vendor ID, now checking if registers 0x10,0x11 (non-existent) + * showing the same as register 0x00 */ + temp = i2c_smbus_read_byte_data(new_client, 0x00); - if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && - (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) - return -ENODEV; - } + if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && + (i2c_smbus_read_byte_data(new_client, 0x11) == temp))) + return -ENODEV; /* Get VRM */ temp = vid_which_vrm(); -- cgit v1.2.3 From 859b9ef30cc1bdba4b55327b95b22489bd5591c2 Mon Sep 17 00:00:00 2001 From: Andrew Paprocki Date: Sat, 20 Sep 2008 10:25:19 +0200 Subject: hwmon: (it87) Fix fan tachometer reading in IT8712F rev 0x7 (I) The IT8712F v0.9.1 datasheet applies to revisions >= 0x8 (J). The driver was incorrectly attempting to enable 16-bit fan readings on rev 0x7 (I) which led to incorrect RPM values. Signed-off-by: Andrew Paprocki Tested-by: John Gumb Signed-off-by: Jean Delvare --- drivers/hwmon/it87.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 30cdb095677..f1133081cc4 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -273,10 +273,10 @@ struct it87_data { static inline int has_16bit_fans(const struct it87_data *data) { /* IT8705F Datasheet 0.4.1, 3h == Version G. - IT8712F Datasheet 0.9.1, section 8.3.5 indicates 7h == Version I. + IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. These are the first revisions with 16bit tachometer support. */ return (data->type == it87 && data->revision >= 0x03) - || (data->type == it8712 && data->revision >= 0x07) + || (data->type == it8712 && data->revision >= 0x08) || data->type == it8716 || data->type == it8718; } -- cgit v1.2.3 From d130d97154f5342973a0fffc0b5a144359273c79 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 20 Sep 2008 10:25:20 +0200 Subject: hwmon: (ad7414) Make ad7414_update_device() static This patch makes the needlessly global ad7414_update_device() static. Signed-off-by: Adrian Bunk Acked-by: Sean MacLennan Signed-off-by: Jean Delvare --- drivers/hwmon/ad7414.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index ce8d94fbfd7..bfda8c80ef2 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -69,7 +69,7 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) return i2c_smbus_write_byte_data(client, reg, value); } -struct ad7414_data *ad7414_update_device(struct device *dev) +static struct ad7414_data *ad7414_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct ad7414_data *data = i2c_get_clientdata(client); -- cgit v1.2.3 From fe246eb0b7f2e995c4f172f360bc4e86baccaafe Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 3 Sep 2008 19:33:30 +0400 Subject: tmio_mmc: fix compilation with debug enabled Signed-off-by: Dmitry Baryshkov Acked-by: Ian Molton Signed-off-by: Pierre Ossman --- drivers/mmc/host/tmio_mmc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9e647a06054..ba2b4240a86 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -159,10 +159,10 @@ static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host, #define STATUS_TO_TEXT(a) \ do { \ if (status & TMIO_STAT_##a) \ - printf(#a); \ + printk(#a); \ } while (0) -void debug_status(u32 status) +void pr_debug_status(u32 status) { printk(KERN_DEBUG "status: %08x = ", status); STATUS_TO_TEXT(CARD_REMOVE); -- cgit v1.2.3 From 87e60f2b80202575a23fa1bf56c6eb3b419c480a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:27 +0200 Subject: atmel-mci: debugfs: enable clock before dumping regs Make sure that the peripheral clock is enabled before reading the MMIO registers for the debugfs "regs" dump. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 0bd06f5bd62..6de773d3a0c 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -195,7 +195,9 @@ static int atmci_regs_show(struct seq_file *s, void *v) /* Grab a more or less consistent snapshot */ spin_lock_irq(&host->mmc->lock); + clk_enable(host->mck); memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); + clk_disable(host->mck); spin_unlock_irq(&host->mmc->lock); seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", -- cgit v1.2.3 From b17339a12c279d73869c74a37642035cd2f896f8 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:28 +0200 Subject: atmel-mci: Fix memory leak in atmci_regs_show The debugfs hook atmci_regs_show allocates a temporary buffer for storing a register snapshot, but it doesn't free it before returning. Plug this leak. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 6de773d3a0c..becca914507 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -218,6 +218,8 @@ static int atmci_regs_show(struct seq_file *s, void *v) atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + kfree(buf); + return 0; } -- cgit v1.2.3 From 75d33cc751214f8388d58fca3ef6d1df786b5861 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:29 +0200 Subject: atmel-mci: Fix bogus debugfs file size We used to store a binary register snapshot in the "regs" file, so we set the file size to be the size of this snapshot. This is no longer valid since we switched to using seq_file. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index becca914507..39096083bb6 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -241,7 +241,6 @@ static void atmci_init_debugfs(struct atmel_mci *host) struct mmc_host *mmc; struct dentry *root; struct dentry *node; - struct resource *res; mmc = host->mmc; root = mmc->debugfs_root; @@ -255,9 +254,6 @@ static void atmci_init_debugfs(struct atmel_mci *host) if (!node) goto err; - res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); - node->d_inode->i_size = res->end - res->start + 1; - node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops); if (!node) goto err; -- cgit v1.2.3 From da45b66ec89bbf3a1c172688c35d4d3a6e8e757f Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 21:09:30 +0200 Subject: atmel-mci: Set MMC_CAP_NEEDS_POLL if no detect_pin This allows the mmc core to detect card insertion/removal for slots that don't have any CD pin wired up. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 39096083bb6..917035e16da 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1059,6 +1059,10 @@ static int __init atmci_probe(struct platform_device *pdev) host->present = !gpio_get_value(host->detect_pin); } } + + if (!gpio_is_valid(host->detect_pin)) + mmc->caps |= MMC_CAP_NEEDS_POLL; + if (gpio_is_valid(host->wp_pin)) { if (gpio_request(host->wp_pin, "mmc_wp")) { dev_dbg(&mmc->class_dev, "no WP pin available\n"); -- cgit v1.2.3 From 9d4e98e9609bc19d4a8ac4a5c3218358d1820114 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 13 Sep 2008 19:02:07 +0900 Subject: mmc_block: handle error from mmc_register_driver() Check error from mmc_register_driver() and properly unwind block device registration. Signed-off-by: Akinobu Mita Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 86dbb366415..43d9a5b53e8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -613,14 +613,19 @@ static struct mmc_driver mmc_driver = { static int __init mmc_blk_init(void) { - int res = -ENOMEM; + int res; res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); if (res) goto out; - return mmc_register_driver(&mmc_driver); + res = mmc_register_driver(&mmc_driver); + if (res) + goto out2; + return 0; + out2: + unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); out: return res; } -- cgit v1.2.3 From a650031a6bd16cb6789da9b3c27fc97341239f12 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 13 Sep 2008 19:03:32 +0900 Subject: mmc_test: initialize mmc_test_lock statically The mutex mmc_test_lock is initialized at every time mmc_test device is probed. Probing another mmc_test device may break the mutex, if the probe function is called while the mutex is locked. This patch fixes it by statically initializing mmc_test_lock. Signed-off-by: Akinobu Mita Signed-off-by: Pierre Ossman --- drivers/mmc/card/mmc_test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index f26b01d811a..b92b172074e 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -1040,7 +1040,7 @@ static const struct mmc_test_case mmc_test_cases[] = { }; -static struct mutex mmc_test_lock; +static DEFINE_MUTEX(mmc_test_lock); static void mmc_test_run(struct mmc_test_card *test, int testcase) { @@ -1171,8 +1171,6 @@ static int mmc_test_probe(struct mmc_card *card) if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD)) return -ENODEV; - mutex_init(&mmc_test_lock); - ret = device_create_file(&card->dev, &dev_attr_test); if (ret) return ret; -- cgit v1.2.3 From 7ee766d8fba9dfd93bf3eca7a8d84a25404a68dc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 20 Sep 2008 22:00:40 -0700 Subject: sparc64: Fix disappearing PCI devices on e3500. Based upon a bug report by Meelis Roos. The OF device layer builds properties by matching bus types and applying 'range' properties as appropriate, up to the root. The match for "PCI" busses is looking at the 'device_type' property, and this does work %99 of the time. But on an E3500 system with a PCI QFE card, the DEC 21153 bridge sitting above the QFE network interface devices has a 'name' of "pci", but it completely lacks a 'device_type' property. So we don't match it as a PCI bus, and subsequently we end up with no resource values at all for the devices sitting under that DEC bridge. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f845f150f56..100ebd52749 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -169,7 +169,7 @@ static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long fla static int of_bus_pci_match(struct device_node *np) { - if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + if (!strcmp(np->name, "pci")) { const char *model = of_get_property(np, "model", NULL); if (model && !strcmp(model, "SUNW,simba")) @@ -200,7 +200,7 @@ static int of_bus_simba_match(struct device_node *np) /* Treat PCI busses lacking ranges property just like * simba. */ - if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + if (!strcmp(np->name, "pci")) { if (!of_find_property(np, "ranges", NULL)) return 1; } @@ -429,7 +429,7 @@ static int __init use_1to1_mapping(struct device_node *pp) * it lacks a ranges property, and this will include * cases like Simba. */ - if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex")) + if (!strcmp(pp->name, "pci")) return 0; return 1; @@ -714,8 +714,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, break; } } else { - if (!strcmp(pp->type, "pci") || - !strcmp(pp->type, "pciex")) { + if (!strcmp(pp->name, "pci")) { unsigned int this_orig_irq = irq; irq = pci_irq_swizzle(dp, pp, irq); -- cgit v1.2.3 From ad55dcaff0e34269f86975ce2ea0da22e9eb74a1 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 20 Sep 2008 22:05:50 -0700 Subject: netdev: simple_tx_hash shouldn't hash inside fragments Currently simple_tx_hash is hashing inside of udp fragments. As a result packets are getting getting sent to all queues when they shouldn't be. This causes a serious performance regression which can be seen by sending UDP frames larger than mtu on multiqueue devices. This change will make it so that fragments are hashed only as IP datagrams w/o any protocol information. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index e719ed29310..e8eb2b47834 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include @@ -1667,7 +1668,7 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) { u32 addr1, addr2, ports; u32 hash, ihl; - u8 ip_proto; + u8 ip_proto = 0; if (unlikely(!simple_tx_hashrnd_initialized)) { get_random_bytes(&simple_tx_hashrnd, 4); @@ -1676,7 +1677,8 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) switch (skb->protocol) { case __constant_htons(ETH_P_IP): - ip_proto = ip_hdr(skb)->protocol; + if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) + ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl; -- cgit v1.2.3 From b80a1b80818cd83c6c2109081b43551e7af72c84 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 20 Sep 2008 17:20:04 +0200 Subject: [MIPS] Fix 64-bit IP checksum code Use unsigned loads to avoid possible misscalculation of IP checksums. This bug was instruced in f761106cd728bcf65b7fe161b10221ee00cf7132 (lmo) / ed99e2bc1dc5dc54eb5a019f4975562dbef20103 (kernel.org). [Original fix by Atsushi. Improved instruction scheduling and fix for unaligned unsigned load by me -- Ralf] Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/lib/csum_partial.S | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 8d7784122c1..edac9892c51 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -39,12 +39,14 @@ #ifdef USE_DOUBLE #define LOAD ld +#define LOAD32 lwu #define ADD daddu #define NBYTES 8 #else #define LOAD lw +#define LOAD32 lw #define ADD addu #define NBYTES 4 @@ -60,6 +62,14 @@ ADD sum, v1; \ .set pop +#define ADDC32(sum,reg) \ + .set push; \ + .set noat; \ + addu sum, reg; \ + sltu v1, sum, reg; \ + addu sum, v1; \ + .set pop + #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ LOAD _t0, (offset + UNIT(0))(src); \ LOAD _t1, (offset + UNIT(1))(src); \ @@ -132,7 +142,7 @@ LEAF(csum_partial) beqz t8, .Lqword_align andi t8, src, 0x8 - lw t0, 0x00(src) + LOAD32 t0, 0x00(src) LONG_SUBU a1, a1, 0x4 ADDC(sum, t0) PTR_ADDU src, src, 0x4 @@ -211,7 +221,7 @@ LEAF(csum_partial) LONG_SRL t8, t8, 0x2 .Lend_words: - lw t0, (src) + LOAD32 t0, (src) LONG_SUBU t8, t8, 0x1 ADDC(sum, t0) .set reorder /* DADDI_WAR */ @@ -230,6 +240,9 @@ LEAF(csum_partial) /* Still a full word to go */ ulw t1, (src) PTR_ADDIU src, 4 +#ifdef USE_DOUBLE + dsll t1, t1, 32 /* clear lower 32bit */ +#endif ADDC(sum, t1) 1: move t1, zero @@ -280,7 +293,7 @@ LEAF(csum_partial) 1: .set reorder /* Add the passed partial csum. */ - ADDC(sum, a2) + ADDC32(sum, a2) jr ra .set noreorder END(csum_partial) @@ -681,7 +694,7 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc) .set pop 1: .set reorder - ADDC(sum, psum) + ADDC32(sum, psum) jr ra .set noreorder -- cgit v1.2.3 From 6657fe0a0281e06ff46eb42bc18ecb68d8b14b27 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 9 Sep 2008 15:19:10 +0200 Subject: [MIPS] SMTC: Clear TIF_FPUBOUND on clone / fork. Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b16facd9ea8..ce7684335a4 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -148,6 +148,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, clear_tsk_thread_flag(p, TIF_USEDFPU); #ifdef CONFIG_MIPS_MT_FPAFF + clear_tsk_thread_flag(p, TIF_FPUBOUND); + /* * FPU affinity support is cleaner if we track the * user-visible CPU affinity from the very beginning. -- cgit v1.2.3 From c65a5480ff29198c241f11d39d9e34ab22c72c69 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Mon, 12 Nov 2007 02:05:18 +0900 Subject: [MIPS] Fix potential latency problem due to non-atomic cpu_wait. If an interrupt happened between checking of NEED_RESCHED and WAIT instruction, adjust EPC to restart from checking of NEED_RESCHED. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 16 ++-------------- arch/mips/kernel/genex.S | 37 +++++++++++++++++++++++++++++++++++++ arch/mips/kernel/traps.c | 22 ++++++++++++++++------ 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 335a6ae3d59..11c92dc5379 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -45,18 +45,7 @@ static void r39xx_wait(void) local_irq_enable(); } -/* - * There is a race when WAIT instruction executed with interrupt - * enabled. - * But it is implementation-dependent wheter the pipelie restarts when - * a non-enabled interrupt is requested. - */ -static void r4k_wait(void) -{ - __asm__(" .set mips3 \n" - " wait \n" - " .set mips0 \n"); -} +extern void r4k_wait(void); /* * This variant is preferable as it allows testing need_resched and going to @@ -128,7 +117,7 @@ static int __init wait_disable(char *s) __setup("nowait", wait_disable); -static inline void check_wait(void) +void __init check_wait(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -242,7 +231,6 @@ static inline void check_errata(void) void __init check_bugs32(void) { - check_wait(); check_errata(); } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index c6ada98ee04..f886dd7f708 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -20,6 +20,7 @@ #include #include #include +#include #define PANIC_PIC(msg) \ .set push; \ @@ -126,7 +127,42 @@ handle_vcei: __FINIT + .align 5 /* 32 byte rollback region */ +LEAF(r4k_wait) + .set push + .set noreorder + /* start of rollback region */ + LONG_L t0, TI_FLAGS($28) + nop + andi t0, _TIF_NEED_RESCHED + bnez t0, 1f + nop + nop + nop + .set mips3 + wait + /* end of rollback region (the region size must be power of two) */ + .set pop +1: + jr ra + END(r4k_wait) + + .macro BUILD_ROLLBACK_PROLOGUE handler + FEXPORT(rollback_\handler) + .set push + .set noat + MFC0 k0, CP0_EPC + PTR_LA k1, r4k_wait + ori k0, 0x1f /* 32 byte rollback region */ + xori k0, 0x1f + bne k0, k1, 9f + MTC0 k0, CP0_EPC +9: + .set pop + .endm + .align 5 +BUILD_ROLLBACK_PROLOGUE handle_int NESTED(handle_int, PT_SIZE, sp) #ifdef CONFIG_TRACE_IRQFLAGS /* @@ -201,6 +237,7 @@ NESTED(except_vec_ejtag_debug, 0, sp) * This prototype is copied to ebase + n*IntCtl.VS and patched * to invoke the handler */ +BUILD_ROLLBACK_PROLOGUE except_vec_vi NESTED(except_vec_vi, 0, sp) SAVE_SOME SAVE_AT diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6bee29097a5..5fd0cd020af 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -46,6 +46,9 @@ #include #include +extern void check_wait(void); +extern asmlinkage void r4k_wait(void); +extern asmlinkage void rollback_handle_int(void); extern asmlinkage void handle_int(void); extern asmlinkage void handle_tlbm(void); extern asmlinkage void handle_tlbl(void); @@ -1251,6 +1254,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) extern char except_vec_vi, except_vec_vi_lui; extern char except_vec_vi_ori, except_vec_vi_end; + extern char rollback_except_vec_vi; + char *vec_start = (cpu_wait == r4k_wait) ? + &rollback_except_vec_vi : &except_vec_vi; #ifdef CONFIG_MIPS_MT_SMTC /* * We need to provide the SMTC vectored interrupt handler @@ -1258,11 +1264,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) * Status.IM bit to be masked before going there. */ extern char except_vec_vi_mori; - const int mori_offset = &except_vec_vi_mori - &except_vec_vi; + const int mori_offset = &except_vec_vi_mori - vec_start; #endif /* CONFIG_MIPS_MT_SMTC */ - const int handler_len = &except_vec_vi_end - &except_vec_vi; - const int lui_offset = &except_vec_vi_lui - &except_vec_vi; - const int ori_offset = &except_vec_vi_ori - &except_vec_vi; + const int handler_len = &except_vec_vi_end - vec_start; + const int lui_offset = &except_vec_vi_lui - vec_start; + const int ori_offset = &except_vec_vi_ori - vec_start; if (handler_len > VECTORSPACING) { /* @@ -1272,7 +1278,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) panic("VECTORSPACING too small"); } - memcpy(b, &except_vec_vi, handler_len); + memcpy(b, vec_start, handler_len); #ifdef CONFIG_MIPS_MT_SMTC BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ @@ -1554,6 +1560,10 @@ void __init trap_init(void) extern char except_vec3_generic, except_vec3_r4000; extern char except_vec4; unsigned long i; + int rollback; + + check_wait(); + rollback = (cpu_wait == r4k_wait); #if defined(CONFIG_KGDB) if (kgdb_early_setup) @@ -1618,7 +1628,7 @@ void __init trap_init(void) if (board_be_init) board_be_init(); - set_except_vector(0, handle_int); + set_except_vector(0, rollback ? rollback_handle_int : handle_int); set_except_vector(1, handle_tlbm); set_except_vector(2, handle_tlbl); set_except_vector(3, handle_tlbs); -- cgit v1.2.3 From 6b3766a263a62fc82ca0457faa73dc34b98ceb87 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 5 Aug 2008 23:45:14 +0900 Subject: [MIPS] vmlinux.lds.S: handle .text.* The -ffunction-sections puts each text in .text.function_name section. Without this patch, most functions are placed outside _text..._etext area and it breaks show_stacktrace(), etc. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index b5470ceb418..afb119f3568 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -36,6 +36,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT KPROBES_TEXT + *(.text.*) *(.fixup) *(.gnu.warning) } :text = 0 -- cgit v1.2.3 From 795fb7e74dff04f661b61eccd3c48554b7d1f747 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 12:33:08 +0200 Subject: MAINTAINERS: Trivial whitespace cleanups * Drop trailing whitespace. * Replace spaces and combinations of spaces and tabs by single tabs. Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds --- MAINTAINERS | 162 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0a613cb926c..85cfd4d2ff4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -271,20 +271,20 @@ W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI WMI DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk -L: linux-acpi@vger.kernel.org -W: http://www.lesswatts.org/projects/acpi/ -S: Maintained +P: Carlos Corbacho +M: carlos@strangeworlds.co.uk +L: linux-acpi@vger.kernel.org +W: http://www.lesswatts.org/projects/acpi/ +S: Maintained AD1889 ALSA SOUND DRIVER -P: Kyle McMartin -M: kyle@mcmartin.ca -P: Thibaut Varene -M: T-Bone@parisc-linux.org -W: http://wiki.parisc-linux.org/AD1889 -L: linux-parisc@vger.kernel.org -S: Maintained +P: Kyle McMartin +M: kyle@mcmartin.ca +P: Thibaut Varene +M: T-Bone@parisc-linux.org +W: http://wiki.parisc-linux.org/AD1889 +L: linux-parisc@vger.kernel.org +S: Maintained ADM1025 HARDWARE MONITOR DRIVER P: Jean Delvare @@ -473,11 +473,11 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/ATMEL AT91RM9200 ARM ARCHITECTURE -P: Andrew Victor -M: linux@maxim.org.za -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -W: http://maxim.org.za/at91_26.html -S: Maintained +P: Andrew Victor +M: linux@maxim.org.za +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://maxim.org.za/at91_26.html +S: Maintained ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE P: Lennert Buytenhek @@ -532,10 +532,10 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/HP JORNADA 7XX MACHINE SUPPORT -P: Kristoffer Ericson -M: kristoffer.ericson@gmail.com -W: www.jlime.com -S: Maintained +P: Kristoffer Ericson +M: kristoffer.ericson@gmail.com +W: www.jlime.com +S: Maintained ARM/INTEL IOP32X ARM ARCHITECTURE P: Lennert Buytenhek @@ -1017,7 +1017,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER -P: Jonathan Corbet +P: Jonathan Corbet M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained @@ -1423,12 +1423,12 @@ L: linux-acpi@vger.kernel.org S: Supported DOCUMENTATION (/Documentation directory) -P: Michael Kerrisk -M: mtk.manpages@gmail.com -P: Randy Dunlap -M: rdunlap@xenotime.net -L: linux-doc@vger.kernel.org -S: Maintained +P: Michael Kerrisk +M: mtk.manpages@gmail.com +P: Randy Dunlap +M: rdunlap@xenotime.net +L: linux-doc@vger.kernel.org +S: Maintained DOUBLETALK DRIVER P: James R. Van Zandt @@ -1459,7 +1459,7 @@ S: Maintained DVB SUBSYSTEM AND DRIVERS P: LinuxTV.org Project M: v4l-dvb-maintainer@linuxtv.org -L: linux-dvb@linuxtv.org (subscription required) +L: linux-dvb@linuxtv.org (subscription required) W: http://linuxtv.org/ T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git S: Maintained @@ -2108,7 +2108,7 @@ M: rolandd@cisco.com P: Sean Hefty M: sean.hefty@intel.com P: Hal Rosenstock -M: hal.rosenstock@gmail.com +M: hal.rosenstock@gmail.com L: general@lists.openfabrics.org W: http://www.openib.org/ T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git @@ -2696,17 +2696,17 @@ S: Maintained MARVELL YUKON / SYSKONNECT DRIVER P: Mirko Lindner -M: mlindner@syskonnect.de +M: mlindner@syskonnect.de P: Ralph Roesler -M: rroesler@syskonnect.de -W: http://www.syskonnect.com -S: Supported +M: rroesler@syskonnect.de +W: http://www.syskonnect.com +S: Supported MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 P: Michael Kerrisk M: mtk.manpages@gmail.com -W: http://www.kernel.org/doc/man-pages -S: Supported +W: http://www.kernel.org/doc/man-pages +S: Supported MARVELL LIBERTAS WIRELESS DRIVER P: Dan Williams @@ -2867,10 +2867,10 @@ L: linux-kernel@vger.kernel.org S: Maintained MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER -P: Felipe Balbi -M: felipe.balbi@nokia.com -L: linux-usb@vger.kernel.org -S: Maintained +P: Felipe Balbi +M: felipe.balbi@nokia.com +L: linux-usb@vger.kernel.org +S: Maintained MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) P: Andrew Gallatin @@ -2882,7 +2882,7 @@ W: http://www.myri.com/scs/download-Myri10GE.html S: Supported NATSEMI ETHERNET DRIVER (DP8381x) -P: Tim Hockin +P: Tim Hockin M: thockin@hockin.org S: Maintained @@ -3101,7 +3101,7 @@ M: laforge@gnumonks.org S: Maintained OMNIVISION OV7670 SENSOR DRIVER -P: Jonathan Corbet +P: Jonathan Corbet M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained @@ -3211,7 +3211,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git S: Supported PCI HOTPLUG CORE -P: Kristen Carlson Accardi +P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com S: Supported @@ -3650,7 +3650,7 @@ M: jmorris@namei.org P: Eric Paris M: eparis@parisplace.org L: linux-kernel@vger.kernel.org (kernel issues) -L: selinux@tycho.nsa.gov (subscribers-only, general discussion) +L: selinux@tycho.nsa.gov (subscribers-only, general discussion) W: http://www.nsa.gov/selinux S: Supported @@ -3768,10 +3768,10 @@ M: bn@niasdigital.com S: Maintained SOC-CAMERA V4L2 SUBSYSTEM -P: Guennadi Liakhovetski -M: g.liakhovetski@gmx.de -L: video4linux-list@redhat.com -S: Maintained +P: Guennadi Liakhovetski +M: g.liakhovetski@gmx.de +L: video4linux-list@redhat.com +S: Maintained SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar @@ -4006,9 +4006,9 @@ T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git S: Maintained TI FLASH MEDIA INTERFACE DRIVER -P: Alex Dubov -M: oakad@yahoo.com -S: Maintained +P: Alex Dubov +M: oakad@yahoo.com +S: Maintained TI OMAP MMC INTERFACE DRIVER P: Carlos Aguiar, Anderson Briglia and Syed Khasim @@ -4154,13 +4154,13 @@ USB BLOCK DRIVER (UB ub) P: Pete Zaitcev M: zaitcev@redhat.com L: linux-kernel@vger.kernel.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB CDC ETHERNET DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ @@ -4187,13 +4187,13 @@ S: Maintained USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Odd Fixes USB ET61X[12]51 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4201,33 +4201,33 @@ S: Maintained USB GADGET/PERIPHERAL SUBSYSTEM P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) P: Jiri Kosina M: jkosina@suse.cz -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ @@ -4235,26 +4235,26 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ USB OHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Odd Fixes USB OPTION-CARD DRIVER P: Matthias Urlichs M: smurf@smurf.noris.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB OV511 DRIVER P: Mark McClelland M: mmcclell@bigfoot.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained USB PEGASUS DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -4262,13 +4262,13 @@ S: Maintained USB PRINTER DRIVER (usblp) P: Pete Zaitcev M: zaitcev@redhat.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB RTL8150 DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -4276,20 +4276,20 @@ S: Maintained USB SE401 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse M: wgreathouse@smva.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL CYPRESS M8 DRIVER P: Lonnie Mendez M: dignome@gmail.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i W: http://firstlight.net/cvs @@ -4304,39 +4304,39 @@ USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers M: pberger@brimson.com M: alborchers@steinerpoint.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL DRIVER P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Supported USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL KEYSPAN DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained USB SERIAL WHITEHEAT DRIVER P: Support Department M: support@connecttech.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4344,7 +4344,7 @@ S: Maintained USB SUBSYSTEM P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported @@ -4352,7 +4352,7 @@ S: Supported USB UHCI DRIVER P: Alan Stern M: stern@rowland.harvard.edu -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org S: Maintained USB "USBNET" DRIVER FRAMEWORK @@ -4373,7 +4373,7 @@ S: Maintained USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4387,7 +4387,7 @@ S: Maintained USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4395,14 +4395,14 @@ S: Maintained USB ZD1201 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained USB ZR364XX DRIVER P: Antoine Jacquet M: royale@zerezo.com -L: linux-usb@vger.kernel.org +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://royale.zerezo.com/zr364xx/ S: Maintained -- cgit v1.2.3 From baaea1dc0befb7b64e6dbf2d1469d0a296a79e54 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 20 Sep 2008 12:34:33 +0200 Subject: MAINTAINERS: Various fixes * Normalize some S: entries to match the enumeration at the beginning of the file. * Change one mailing list entry from S: to L:. Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds --- MAINTAINERS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 85cfd4d2ff4..cad81a24e83 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1359,7 +1359,7 @@ P: Digi International, Inc M: Eng.Linux@digi.com L: Eng.Linux@digi.com W: http://www.digi.com -S: Orphaned +S: Orphan DIRECTORY NOTIFICATION P: Stephen Rothwell @@ -1797,7 +1797,7 @@ FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) P: Rik Faith M: faith@cs.unc.edu L: linux-scsi@vger.kernel.org -S: Odd fixes (e.g., new signatures) +S: Odd Fixes (e.g., new signatures) GDT SCSI DISK ARRAY CONTROLLER DRIVER P: Achim Leubner @@ -1838,10 +1838,10 @@ S: Maintained HARDWARE MONITORING L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ -S: Orphaned +S: Orphan HARDWARE RANDOM NUMBER GENERATOR CORE -S: Orphaned +S: Orphan HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER P: Robert Love @@ -2735,7 +2735,7 @@ S: Maintained MEGARAID SCSI DRIVERS P: Neela Syam Kolli M: megaraidlinux@lsi.com -S: linux-scsi@vger.kernel.org +L: linux-scsi@vger.kernel.org W: http://megaraid.lsilogic.com S: Maintained @@ -2853,7 +2853,7 @@ MULTIMEDIA CARD (MMC) ETC. OVER SPI P: David Brownell M: dbrownell@users.sourceforge.net L: linux-kernel@vger.kernel.org -S: Odd fixes +S: Odd Fixes MULTISOUND SOUND DRIVER P: Andrew Veliath @@ -3925,7 +3925,7 @@ S: Maintained STARMODE RADIO IP (STRIP) PROTOCOL DRIVER W: http://mosquitonet.Stanford.EDU/strip.html -S: Unsupported ? +S: Orphan STRADIS MPEG-2 DECODER DRIVER P: Nathan Laredo -- cgit v1.2.3 From 72d31053f62c4bc464c2783974926969614a8649 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 Sep 2008 15:29:55 -0700 Subject: Linux 2.6.27-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ff83ea36c1..cab896a9729 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Rotary Wombat # *DOCUMENTATION* -- cgit v1.2.3 From 43f59c89399fd76883a06c551f24794e98409432 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Sep 2008 21:28:51 -0700 Subject: net: Remove __skb_insert() calls outside of skbuff internals. This minor cleanup simplifies later changes which will convert struct sk_buff and friends over to using struct list_head. Signed-off-by: David S. Miller --- drivers/net/cassini.c | 2 +- drivers/net/ppp_generic.c | 2 +- drivers/net/pppol2tp.c | 2 +- include/net/tcp.h | 4 ++-- net/ipv4/tcp_input.c | 4 ++-- net/sctp/ulpqueue.c | 5 ++--- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index f1936d51b45..40ff6a90d0d 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2182,7 +2182,7 @@ static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words, * do any additional locking here. stick the buffer * at the end. */ - __skb_insert(skb, flow->prev, (struct sk_buff *) flow, flow); + __skb_queue_tail(flow, skb); if (words[0] & RX_COMP1_RELEASE_FLOW) { while ((skb = __skb_dequeue(flow))) { cas_skb_release(skb); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index ddccc074a76..98e04958fef 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1864,7 +1864,7 @@ ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb) for (p = list->next; p != (struct sk_buff *)list; p = p->next) if (seq_before(seq, p->sequence)) break; - __skb_insert(skb, p->prev, p, list); + __skb_queue_before(list, p, skb); } /* diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index ff175e8f36b..185b1dff10a 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -353,7 +353,7 @@ static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_ spin_lock_bh(&session->reorder_q.lock); skb_queue_walk_safe(&session->reorder_q, skbp, tmp) { if (PPPOL2TP_SKB_CB(skbp)->ns > ns) { - __skb_insert(skb, skbp->prev, skbp, &session->reorder_q); + __skb_queue_before(&session->reorder_q, skbp, skb); PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n", session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns, diff --git a/include/net/tcp.h b/include/net/tcp.h index ea815723d41..f857c3eff71 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1268,12 +1268,12 @@ static inline void tcp_insert_write_queue_after(struct sk_buff *skb, __skb_queue_after(&sk->sk_write_queue, skb, buff); } -/* Insert skb between prev and next on the write queue of sk. */ +/* Insert new before skb on the write queue of sk. */ static inline void tcp_insert_write_queue_before(struct sk_buff *new, struct sk_buff *skb, struct sock *sk) { - __skb_insert(new, skb->prev, skb, &sk->sk_write_queue); + __skb_queue_before(&sk->sk_write_queue, skb, new); if (sk->sk_send_head == skb) sk->sk_send_head = new; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 85627f83665..cbfe13d5f42 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4156,7 +4156,7 @@ drop: skb1 = skb1->prev; } } - __skb_insert(skb, skb1, skb1->next, &tp->out_of_order_queue); + __skb_queue_after(&tp->out_of_order_queue, skb1, skb); /* And clean segments covered by new one as whole. */ while ((skb1 = skb->next) != @@ -4254,7 +4254,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, memcpy(nskb->head, skb->head, header); memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start; - __skb_insert(nskb, skb->prev, skb, list); + __skb_queue_before(list, skb, nskb); skb_set_owner_r(nskb, sk); /* Copy data, releasing collapsed skbs. */ diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 5061a26c502..7b23803343c 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -317,7 +317,7 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, } /* Insert before pos. */ - __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm); + __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event)); } @@ -825,8 +825,7 @@ static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, /* Insert before pos. */ - __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby); - + __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event)); } static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, -- cgit v1.2.3 From ceade961c4c8d8bc033dc7907047818c9525c326 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Sep 2008 21:38:26 -0700 Subject: atm: idt77252: Use generic SKB queue management instead of home-grown scheme. Signed-off-by: David S. Miller --- drivers/atm/idt77252.c | 32 +++++++++----------------------- drivers/atm/idt77252.h | 4 +--- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 3a504e94a4d..e33ae0025b1 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1114,11 +1114,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) rpp = &vc->rcv.rx_pool; + __skb_queue_tail(&rpp->queue, skb); rpp->len += skb->len; - if (!rpp->count++) - rpp->first = skb; - *rpp->last = skb; - rpp->last = &skb->next; if (stat & SAR_RSQE_EPDU) { unsigned char *l1l2; @@ -1145,7 +1142,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) atomic_inc(&vcc->stats->rx_err); return; } - if (rpp->count > 1) { + if (skb_queue_len(&rpp->queue) > 1) { struct sk_buff *sb; skb = dev_alloc_skb(rpp->len); @@ -1161,12 +1158,9 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) dev_kfree_skb(skb); return; } - sb = rpp->first; - for (i = 0; i < rpp->count; i++) { + skb_queue_walk(&rpp->queue, sb) memcpy(skb_put(skb, sb->len), sb->data, sb->len); - sb = sb->next; - } recycle_rx_pool_skb(card, rpp); @@ -1180,7 +1174,6 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) return; } - skb->next = NULL; flush_rx_pool(card, rpp); if (!atm_charge(vcc, skb->truesize)) { @@ -1918,25 +1911,18 @@ recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb) static void flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp) { + skb_queue_head_init(&rpp->queue); rpp->len = 0; - rpp->count = 0; - rpp->first = NULL; - rpp->last = &rpp->first; } static void recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp) { - struct sk_buff *skb, *next; - int i; + struct sk_buff *skb, *tmp; - skb = rpp->first; - for (i = 0; i < rpp->count; i++) { - next = skb->next; - skb->next = NULL; + skb_queue_walk_safe(&rpp->queue, skb, tmp) recycle_rx_skb(card, skb); - skb = next; - } + flush_rx_pool(card, rpp); } @@ -2537,7 +2523,7 @@ idt77252_close(struct atm_vcc *vcc) waitfor_idle(card); spin_unlock_irqrestore(&card->cmd_lock, flags); - if (vc->rcv.rx_pool.count) { + if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) { DPRINTK("%s: closing a VC with pending rx buffers.\n", card->name); @@ -2970,7 +2956,7 @@ close_card_oam(struct idt77252_dev *card) waitfor_idle(card); spin_unlock_irqrestore(&card->cmd_lock, flags); - if (vc->rcv.rx_pool.count) { + if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) { DPRINTK("%s: closing a VC " "with pending rx buffers.\n", card->name); diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h index e83eaf120da..5042bb2dab1 100644 --- a/drivers/atm/idt77252.h +++ b/drivers/atm/idt77252.h @@ -173,10 +173,8 @@ struct scq_info }; struct rx_pool { - struct sk_buff *first; - struct sk_buff **last; + struct sk_buff_head queue; unsigned int len; - unsigned int count; }; struct aal1 { -- cgit v1.2.3 From 67fed45930fa31e92c11beb3a3dbf83a1a92a58d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Sep 2008 22:36:24 -0700 Subject: net: Add new interfaces for SKB list light-weight init and splicing. This will be used by subsequent changesets. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index aa80ad9cbc8..027b06170b4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -660,6 +660,22 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_) return list_->qlen; } +/** + * __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head + * @list: queue to initialize + * + * This initializes only the list and queue length aspects of + * an sk_buff_head object. This allows to initialize the list + * aspects of an sk_buff_head without reinitializing things like + * the spinlock. It can also be used for on-stack sk_buff_head + * objects where the spinlock is known to not be used. + */ +static inline void __skb_queue_head_init(struct sk_buff_head *list) +{ + list->prev = list->next = (struct sk_buff *)list; + list->qlen = 0; +} + /* * This function creates a split out lock class for each invocation; * this is needed for now since a whole lot of users of the skb-queue @@ -671,8 +687,7 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_) static inline void skb_queue_head_init(struct sk_buff_head *list) { spin_lock_init(&list->lock); - list->prev = list->next = (struct sk_buff *)list; - list->qlen = 0; + __skb_queue_head_init(list); } static inline void skb_queue_head_init_class(struct sk_buff_head *list, @@ -699,6 +714,83 @@ static inline void __skb_insert(struct sk_buff *newsk, list->qlen++; } +static inline void __skb_queue_splice(const struct sk_buff_head *list, + struct sk_buff *prev, + struct sk_buff *next) +{ + struct sk_buff *first = list->next; + struct sk_buff *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * skb_queue_splice - join two skb lists, this is designed for stacks + * @list: the new list to add + * @head: the place to add it in the first list + */ +static inline void skb_queue_splice(const struct sk_buff_head *list, + struct sk_buff_head *head) +{ + if (!skb_queue_empty(list)) { + __skb_queue_splice(list, (struct sk_buff *) head, head->next); + head->qlen = list->qlen; + } +} + +/** + * skb_queue_splice - join two skb lists and reinitialise the emptied list + * @list: the new list to add + * @head: the place to add it in the first list + * + * The list at @list is reinitialised + */ +static inline void skb_queue_splice_init(struct sk_buff_head *list, + struct sk_buff_head *head) +{ + if (!skb_queue_empty(list)) { + __skb_queue_splice(list, (struct sk_buff *) head, head->next); + head->qlen = list->qlen; + __skb_queue_head_init(list); + } +} + +/** + * skb_queue_splice_tail - join two skb lists, each list being a queue + * @list: the new list to add + * @head: the place to add it in the first list + */ +static inline void skb_queue_splice_tail(const struct sk_buff_head *list, + struct sk_buff_head *head) +{ + if (!skb_queue_empty(list)) { + __skb_queue_splice(list, head->prev, (struct sk_buff *) head); + head->qlen = list->qlen; + } +} + +/** + * skb_queue_splice_tail - join two skb lists and reinitialise the emptied list + * @list: the new list to add + * @head: the place to add it in the first list + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void skb_queue_splice_tail_init(struct sk_buff_head *list, + struct sk_buff_head *head) +{ + if (!skb_queue_empty(list)) { + __skb_queue_splice(list, head->prev, (struct sk_buff *) head); + head->qlen = list->qlen; + __skb_queue_head_init(list); + } +} + /** * __skb_queue_after - queue a buffer at the list head * @list: list to use -- cgit v1.2.3 From e9bb8fb0b6d61a822201537b25206a0ca34b9d1d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Sep 2008 22:36:49 -0700 Subject: aoe: Use SKB interfaces for list management instead of home-grown stuff. Signed-off-by: David S. Miller --- drivers/block/aoe/aoe.h | 9 ++--- drivers/block/aoe/aoeblk.c | 8 ++--- drivers/block/aoe/aoechr.c | 8 ++++- drivers/block/aoe/aoecmd.c | 85 +++++++++++++++++---------------------------- drivers/block/aoe/aoedev.c | 12 +++---- drivers/block/aoe/aoemain.c | 1 + drivers/block/aoe/aoenet.c | 9 ++--- 7 files changed, 56 insertions(+), 76 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 5b4c6e649c1..93f3690396a 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -159,11 +159,8 @@ struct aoedev { sector_t ssize; struct timer_list timer; spinlock_t lock; - struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ - struct sk_buff *sendq_tl; - struct sk_buff *skbpool_hd; - struct sk_buff *skbpool_tl; - int nskbpool; + struct sk_buff_head sendq; + struct sk_buff_head skbpool; mempool_t *bufpool; /* for deadlock-free Buf allocation */ struct list_head bufq; /* queue of bios to work on */ struct buf *inprocess; /* the one we're currently working on */ @@ -199,7 +196,7 @@ int aoedev_flush(const char __user *str, size_t size); int aoenet_init(void); void aoenet_exit(void); -void aoenet_xmit(struct sk_buff *); +void aoenet_xmit(struct sk_buff_head *); int is_aoe_netif(struct net_device *ifp); int set_aoe_iflist(const char __user *str, size_t size); diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 0c39782b266..fd2cf5439a1 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -158,9 +158,9 @@ aoeblk_release(struct inode *inode, struct file *filp) static int aoeblk_make_request(struct request_queue *q, struct bio *bio) { + struct sk_buff_head queue; struct aoedev *d; struct buf *buf; - struct sk_buff *sl; ulong flags; blk_queue_bounce(q, &bio); @@ -213,11 +213,11 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) list_add_tail(&buf->bufs, &d->bufq); aoecmd_work(d); - sl = d->sendq_hd; - d->sendq_hd = d->sendq_tl = NULL; + __skb_queue_head_init(&queue); + skb_queue_splice_init(&d->sendq, &queue); spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); + aoenet_xmit(&queue); return 0; } diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 181ebb85f0b..1f56d2c5b7f 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "aoe.h" enum { @@ -103,7 +104,12 @@ loop: spin_lock_irqsave(&d->lock, flags); goto loop; } - aoenet_xmit(skb); + if (skb) { + struct sk_buff_head queue; + __skb_queue_head_init(&queue); + __skb_queue_tail(&queue, skb); + aoenet_xmit(&queue); + } aoecmd_cfg(major, minor); return 0; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 2f1746295d0..e33da30be4c 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -114,29 +114,22 @@ ifrotate(struct aoetgt *t) static void skb_pool_put(struct aoedev *d, struct sk_buff *skb) { - if (!d->skbpool_hd) - d->skbpool_hd = skb; - else - d->skbpool_tl->next = skb; - d->skbpool_tl = skb; + __skb_queue_tail(&d->skbpool, skb); } static struct sk_buff * skb_pool_get(struct aoedev *d) { - struct sk_buff *skb; + struct sk_buff *skb = skb_peek(&d->skbpool); - skb = d->skbpool_hd; if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) { - d->skbpool_hd = skb->next; - skb->next = NULL; + __skb_unlink(skb, &d->skbpool); return skb; } - if (d->nskbpool < NSKBPOOLMAX - && (skb = new_skb(ETH_ZLEN))) { - d->nskbpool++; + if (skb_queue_len(&d->skbpool) < NSKBPOOLMAX && + (skb = new_skb(ETH_ZLEN))) return skb; - } + return NULL; } @@ -293,29 +286,22 @@ aoecmd_ata_rw(struct aoedev *d) skb->dev = t->ifp->nd; skb = skb_clone(skb, GFP_ATOMIC); - if (skb) { - if (d->sendq_hd) - d->sendq_tl->next = skb; - else - d->sendq_hd = skb; - d->sendq_tl = skb; - } + if (skb) + __skb_queue_tail(&d->sendq, skb); return 1; } /* some callers cannot sleep, and they can call this function, * transmitting the packets later, when interrupts are on */ -static struct sk_buff * -aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) +static void +aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *queue) { struct aoe_hdr *h; struct aoe_cfghdr *ch; - struct sk_buff *skb, *sl, *sl_tail; + struct sk_buff *skb; struct net_device *ifp; - sl = sl_tail = NULL; - read_lock(&dev_base_lock); for_each_netdev(&init_net, ifp) { dev_hold(ifp); @@ -329,8 +315,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) } skb_put(skb, sizeof *h + sizeof *ch); skb->dev = ifp; - if (sl_tail == NULL) - sl_tail = skb; + __skb_queue_tail(queue, skb); h = (struct aoe_hdr *) skb_mac_header(skb); memset(h, 0, sizeof *h + sizeof *ch); @@ -342,16 +327,10 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) h->minor = aoeminor; h->cmd = AOECMD_CFG; - skb->next = sl; - sl = skb; cont: dev_put(ifp); } read_unlock(&dev_base_lock); - - if (tail != NULL) - *tail = sl_tail; - return sl; } static void @@ -406,11 +385,7 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f) skb = skb_clone(skb, GFP_ATOMIC); if (skb == NULL) return; - if (d->sendq_hd) - d->sendq_tl->next = skb; - else - d->sendq_hd = skb; - d->sendq_tl = skb; + __skb_queue_tail(&d->sendq, skb); } static int @@ -508,16 +483,15 @@ ata_scnt(unsigned char *packet) { static void rexmit_timer(ulong vp) { + struct sk_buff_head queue; struct aoedev *d; struct aoetgt *t, **tt, **te; struct aoeif *ifp; struct frame *f, *e; - struct sk_buff *sl; register long timeout; ulong flags, n; d = (struct aoedev *) vp; - sl = NULL; /* timeout is always ~150% of the moving average */ timeout = d->rttavg; @@ -589,7 +563,7 @@ rexmit_timer(ulong vp) } } - if (d->sendq_hd) { + if (!skb_queue_empty(&d->sendq)) { n = d->rttavg <<= 1; if (n > MAXTIMER) d->rttavg = MAXTIMER; @@ -600,15 +574,15 @@ rexmit_timer(ulong vp) aoecmd_work(d); } - sl = d->sendq_hd; - d->sendq_hd = d->sendq_tl = NULL; + __skb_queue_head_init(&queue); + skb_queue_splice_init(&d->sendq, &queue); d->timer.expires = jiffies + TIMERTICK; add_timer(&d->timer); spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); + aoenet_xmit(&queue); } /* enters with d->lock held */ @@ -767,12 +741,12 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector void aoecmd_ata_rsp(struct sk_buff *skb) { + struct sk_buff_head queue; struct aoedev *d; struct aoe_hdr *hin, *hout; struct aoe_atahdr *ahin, *ahout; struct frame *f; struct buf *buf; - struct sk_buff *sl; struct aoetgt *t; struct aoeif *ifp; register long n; @@ -893,21 +867,21 @@ aoecmd_ata_rsp(struct sk_buff *skb) aoecmd_work(d); xmit: - sl = d->sendq_hd; - d->sendq_hd = d->sendq_tl = NULL; + __skb_queue_head_init(&queue); + skb_queue_splice_init(&d->sendq, &queue); spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); + aoenet_xmit(&queue); } void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) { - struct sk_buff *sl; - - sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL); + struct sk_buff_head queue; - aoenet_xmit(sl); + __skb_queue_head_init(&queue); + aoecmd_cfg_pkts(aoemajor, aoeminor, &queue); + aoenet_xmit(&queue); } struct sk_buff * @@ -1076,7 +1050,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb) spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(sl); + if (sl) { + struct sk_buff_head queue; + __skb_queue_head_init(&queue); + __skb_queue_tail(&queue, sl); + aoenet_xmit(&queue); + } } void diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index a1d813ab0d6..75a610adf51 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -188,14 +188,12 @@ skbfree(struct sk_buff *skb) static void skbpoolfree(struct aoedev *d) { - struct sk_buff *skb; + struct sk_buff *skb, *tmp; - while ((skb = d->skbpool_hd)) { - d->skbpool_hd = skb->next; - skb->next = NULL; + skb_queue_walk_safe(&d->skbpool, skb, tmp) skbfree(skb); - } - d->skbpool_tl = NULL; + + __skb_queue_head_init(&d->skbpool); } /* find it or malloc it */ @@ -217,6 +215,8 @@ aoedev_by_sysminor_m(ulong sysminor) goto out; INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); + skb_queue_head_init(&d->sendq); + skb_queue_head_init(&d->skbpool); init_timer(&d->timer); d->timer.data = (ulong) d; d->timer.function = dummy_timer; diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 7b15a5e9cec..7f83ad90e76 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "aoe.h" MODULE_LICENSE("GPL"); diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 0c81ca73128..8fb26030eba 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -95,15 +95,12 @@ mac_addr(char addr[6]) } void -aoenet_xmit(struct sk_buff *sl) +aoenet_xmit(struct sk_buff_head *queue) { - struct sk_buff *skb; + struct sk_buff *skb, *tmp; - while ((skb = sl)) { - sl = sl->next; - skb->next = skb->prev = NULL; + skb_queue_walk_safe(queue, skb, tmp) dev_queue_xmit(skb); - } } /* -- cgit v1.2.3 From 8fc5387cb837f9e44a0be2d7e297bbbcab36a292 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Sep 2008 22:44:08 -0700 Subject: bluetooth: hci_bcsp: Use SKB list interfaces instead of home-grown stuff. Signed-off-by: David S. Miller --- drivers/bluetooth/hci_bcsp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 4d37bb312ee..7938062c1cc 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -352,14 +352,14 @@ static int bcsp_flush(struct hci_uart *hu) /* Remove ack'ed packets */ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) { + struct sk_buff *skb, *tmp; unsigned long flags; - struct sk_buff *skb; int i, pkts_to_be_removed; u8 seqno; spin_lock_irqsave(&bcsp->unack.lock, flags); - pkts_to_be_removed = bcsp->unack.qlen; + pkts_to_be_removed = skb_queue_len(&bcsp->unack); seqno = bcsp->msgq_txseq; while (pkts_to_be_removed) { @@ -373,19 +373,19 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) BT_ERR("Peer acked invalid packet"); BT_DBG("Removing %u pkts out of %u, up to seqno %u", - pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07); + pkts_to_be_removed, skb_queue_len(&bcsp->unack), + (seqno - 1) & 0x07); - for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed - && skb != (struct sk_buff *) &bcsp->unack; i++) { - struct sk_buff *nskb; + i = 0; + skb_queue_walk_safe(&bcsp->unack, skb, tmp) { + if (i++ >= pkts_to_be_removed) + break; - nskb = skb->next; __skb_unlink(skb, &bcsp->unack); kfree_skb(skb); - skb = nskb; } - if (bcsp->unack.qlen == 0) + if (skb_queue_empty(&bcsp->unack)) del_timer(&bcsp->tbcsp); spin_unlock_irqrestore(&bcsp->unack.lock, flags); -- cgit v1.2.3 From 38783e671399b5405f1fd177d602c400a9577ae6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 01:15:02 -0700 Subject: isdn: isdn_ppp: Use SKB list facilities instead of home-grown implementation. Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_ppp.c | 352 ++++++++++++++++++++++++-------------------- include/linux/isdn_ppp.h | 2 +- 2 files changed, 190 insertions(+), 164 deletions(-) diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 127cfdad68e..77c280ef2eb 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -1533,8 +1533,10 @@ static int isdn_ppp_mp_bundle_array_init(void) int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL ) return -ENOMEM; - for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { spin_lock_init(&isdn_ppp_bundle_arr[i].lock); + skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags); + } return 0; } @@ -1567,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ) if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL) return -ENOMEM; lp->next = lp->last = lp; /* nobody else in a queue */ - lp->netdev->pb->frags = NULL; + skb_queue_head_init(&lp->netdev->pb->frags); lp->netdev->pb->frames = 0; lp->netdev->pb->seq = UINT_MAX; } @@ -1579,28 +1581,29 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ) static u32 isdn_ppp_mp_get_seq( int short_seq, struct sk_buff * skb, u32 last_seq ); -static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, - struct sk_buff * from, struct sk_buff * to ); -static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff * from, struct sk_buff * to ); -static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb ); +static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from, + struct sk_buff *to); +static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp, + struct sk_buff *from, struct sk_buff *to, + u32 lastseq); +static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb); static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ); static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb) + struct sk_buff *skb) { - struct ippp_struct *is; - isdn_net_local * lpq; - ippp_bundle * mp; - isdn_mppp_stats * stats; - struct sk_buff * newfrag, * frag, * start, *nextf; + struct sk_buff *newfrag, *frag, *start, *nextf; u32 newseq, minseq, thisseq; + isdn_mppp_stats *stats; + struct ippp_struct *is; unsigned long flags; + isdn_net_local *lpq; + ippp_bundle *mp; int slot; spin_lock_irqsave(&net_dev->pb->lock, flags); - mp = net_dev->pb; - stats = &mp->stats; + mp = net_dev->pb; + stats = &mp->stats; slot = lp->ppp_slot; if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d)\n", @@ -1611,20 +1614,19 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, return; } is = ippp_table[slot]; - if( ++mp->frames > stats->max_queue_len ) + if (++mp->frames > stats->max_queue_len) stats->max_queue_len = mp->frames; - + if (is->debug & 0x8) isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb); - newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, - skb, is->last_link_seqno); - + newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, + skb, is->last_link_seqno); /* if this packet seq # is less than last already processed one, * toss it right away, but check for sequence start case first */ - if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) { + if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) { mp->seq = newseq; /* the first packet: required for * rfc1990 non-compliant clients -- * prevents constant packet toss */ @@ -1634,7 +1636,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, spin_unlock_irqrestore(&mp->lock, flags); return; } - + /* find the minimum received sequence number over all links */ is->last_link_seqno = minseq = newseq; for (lpq = net_dev->queue;;) { @@ -1655,22 +1657,31 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * packets */ newfrag = skb; - /* if this new fragment is before the first one, then enqueue it now. */ - if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) { - newfrag->next = frag; - mp->frags = frag = newfrag; - newfrag = NULL; - } + /* Insert new fragment into the proper sequence slot. */ + skb_queue_walk(&mp->frags, frag) { + if (MP_SEQ(frag) == newseq) { + isdn_ppp_mp_free_skb(mp, newfrag); + newfrag = NULL; + break; + } + if (MP_LT(newseq, MP_SEQ(frag))) { + __skb_queue_before(&mp->frags, frag, newfrag); + newfrag = NULL; + break; + } + } + if (newfrag) + __skb_queue_tail(&mp->frags, newfrag); - start = MP_FLAGS(frag) & MP_BEGIN_FRAG && - MP_SEQ(frag) == mp->seq ? frag : NULL; + frag = skb_peek(&mp->frags); + start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) && + (MP_SEQ(frag) == mp->seq)) ? frag : NULL; + if (!start) + goto check_overflow; - /* - * main fragment traversing loop + /* main fragment traversing loop * * try to accomplish several tasks: - * - insert new fragment into the proper sequence slot (once that's done - * newfrag will be set to NULL) * - reassemble any complete fragment sequence (non-null 'start' * indicates there is a continguous sequence present) * - discard any incomplete sequences that are below minseq -- due @@ -1679,71 +1690,46 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * come to complete such sequence and it should be discarded * * loop completes when we accomplished the following tasks: - * - new fragment is inserted in the proper sequence ('newfrag' is - * set to NULL) * - we hit a gap in the sequence, so no reassembly/processing is * possible ('start' would be set to NULL) * * algorithm for this code is derived from code in the book * 'PPP Design And Debugging' by James Carlson (Addison-Wesley) */ - while (start != NULL || newfrag != NULL) { - - thisseq = MP_SEQ(frag); - nextf = frag->next; - - /* drop any duplicate fragments */ - if (newfrag != NULL && thisseq == newseq) { - isdn_ppp_mp_free_skb(mp, newfrag); - newfrag = NULL; - } - - /* insert new fragment before next element if possible. */ - if (newfrag != NULL && (nextf == NULL || - MP_LT(newseq, MP_SEQ(nextf)))) { - newfrag->next = nextf; - frag->next = nextf = newfrag; - newfrag = NULL; - } - - if (start != NULL) { - /* check for misplaced start */ - if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { - printk(KERN_WARNING"isdn_mppp(seq %d): new " - "BEGIN flag with no prior END", thisseq); - stats->seqerrs++; - stats->frame_drops++; - start = isdn_ppp_mp_discard(mp, start,frag); - nextf = frag->next; - } - } else if (MP_LE(thisseq, minseq)) { - if (MP_FLAGS(frag) & MP_BEGIN_FRAG) + skb_queue_walk_safe(&mp->frags, frag, nextf) { + thisseq = MP_SEQ(frag); + + /* check for misplaced start */ + if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { + printk(KERN_WARNING"isdn_mppp(seq %d): new " + "BEGIN flag with no prior END", thisseq); + stats->seqerrs++; + stats->frame_drops++; + isdn_ppp_mp_discard(mp, start, frag); + start = frag; + } else if (MP_LE(thisseq, minseq)) { + if (MP_FLAGS(frag) & MP_BEGIN_FRAG) start = frag; - else { + else { if (MP_FLAGS(frag) & MP_END_FRAG) - stats->frame_drops++; - if( mp->frags == frag ) - mp->frags = nextf; + stats->frame_drops++; + __skb_unlink(skb, &mp->frags); isdn_ppp_mp_free_skb(mp, frag); - frag = nextf; continue; - } + } } - - /* if start is non-null and we have end fragment, then - * we have full reassembly sequence -- reassemble - * and process packet now + + /* if we have end fragment, then we have full reassembly + * sequence -- reassemble and process packet now */ - if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) { - minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; - /* Reassemble the packet then dispatch it */ - isdn_ppp_mp_reassembly(net_dev, lp, start, nextf); - - start = NULL; - frag = NULL; + if (MP_FLAGS(frag) & MP_END_FRAG) { + minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; + /* Reassemble the packet then dispatch it */ + isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq); - mp->frags = nextf; - } + start = NULL; + frag = NULL; + } /* check if need to update start pointer: if we just * reassembled the packet and sequence is contiguous @@ -1754,26 +1740,25 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * below low watermark and set start to the next frag or * clear start ptr. */ - if (nextf != NULL && + if (nextf != (struct sk_buff *)&mp->frags && ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) { - /* if we just reassembled and the next one is here, - * then start another reassembly. */ - - if (frag == NULL) { + /* if we just reassembled and the next one is here, + * then start another reassembly. + */ + if (frag == NULL) { if (MP_FLAGS(nextf) & MP_BEGIN_FRAG) - start = nextf; - else - { - printk(KERN_WARNING"isdn_mppp(seq %d):" - " END flag with no following " - "BEGIN", thisseq); + start = nextf; + else { + printk(KERN_WARNING"isdn_mppp(seq %d):" + " END flag with no following " + "BEGIN", thisseq); stats->seqerrs++; } } - - } else { - if ( nextf != NULL && frag != NULL && - MP_LT(thisseq, minseq)) { + } else { + if (nextf != (struct sk_buff *)&mp->frags && + frag != NULL && + MP_LT(thisseq, minseq)) { /* we've got a break in the sequence * and we not at the end yet * and we did not just reassembled @@ -1782,41 +1767,39 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * discard all the frames below low watermark * and start over */ stats->frame_drops++; - mp->frags = isdn_ppp_mp_discard(mp,start,nextf); + isdn_ppp_mp_discard(mp, start, nextf); } /* break in the sequence, no reassembly */ - start = NULL; - } - - frag = nextf; - } /* while -- main loop */ - - if (mp->frags == NULL) - mp->frags = frag; - + start = NULL; + } + if (!start) + break; + } + +check_overflow: /* rather straighforward way to deal with (not very) possible - * queue overflow */ + * queue overflow + */ if (mp->frames > MP_MAX_QUEUE_LEN) { stats->overflows++; - while (mp->frames > MP_MAX_QUEUE_LEN) { - frag = mp->frags->next; - isdn_ppp_mp_free_skb(mp, mp->frags); - mp->frags = frag; + skb_queue_walk_safe(&mp->frags, frag, nextf) { + if (mp->frames <= MP_MAX_QUEUE_LEN) + break; + __skb_unlink(frag, &mp->frags); + isdn_ppp_mp_free_skb(mp, frag); } } spin_unlock_irqrestore(&mp->lock, flags); } -static void isdn_ppp_mp_cleanup( isdn_net_local * lp ) +static void isdn_ppp_mp_cleanup(isdn_net_local *lp) { - struct sk_buff * frag = lp->netdev->pb->frags; - struct sk_buff * nextfrag; - while( frag ) { - nextfrag = frag->next; - isdn_ppp_mp_free_skb(lp->netdev->pb, frag); - frag = nextfrag; - } - lp->netdev->pb->frags = NULL; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) { + __skb_unlink(skb, &lp->netdev->pb->frags); + isdn_ppp_mp_free_skb(lp->netdev->pb, skb); + } } static u32 isdn_ppp_mp_get_seq( int short_seq, @@ -1853,72 +1836,115 @@ static u32 isdn_ppp_mp_get_seq( int short_seq, return seq; } -struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, - struct sk_buff * from, struct sk_buff * to ) +static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from, + struct sk_buff *to) { - if( from ) - while (from != to) { - struct sk_buff * next = from->next; - isdn_ppp_mp_free_skb(mp, from); - from = next; + if (from) { + struct sk_buff *skb, *tmp; + int freeing = 0; + + skb_queue_walk_safe(&mp->frags, skb, tmp) { + if (skb == to) + break; + if (skb == from) + freeing = 1; + if (!freeing) + continue; + __skb_unlink(skb, &mp->frags); + isdn_ppp_mp_free_skb(mp, skb); } - return from; + } } -void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff * from, struct sk_buff * to ) +static unsigned int calc_tot_len(struct sk_buff_head *queue, + struct sk_buff *from, struct sk_buff *to) { - ippp_bundle * mp = net_dev->pb; - int proto; - struct sk_buff * skb; + unsigned int tot_len = 0; + struct sk_buff *skb; + int found_start = 0; + + skb_queue_walk(queue, skb) { + if (skb == from) + found_start = 1; + if (!found_start) + continue; + tot_len += skb->len - MP_HEADER_LEN; + if (skb == to) + break; + } + return tot_len; +} + +/* Reassemble packet using fragments in the reassembly queue from + * 'from' until 'to', inclusive. + */ +static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp, + struct sk_buff *from, struct sk_buff *to, + u32 lastseq) +{ + ippp_bundle *mp = net_dev->pb; unsigned int tot_len; + struct sk_buff *skb; + int proto; if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", __func__, lp->ppp_slot); return; } - if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) { - if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + + tot_len = calc_tot_len(&mp->frags, from, to); + + if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) { + if (ippp_table[lp->ppp_slot]->debug & 0x40) printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, " - "len %d\n", MP_SEQ(from), from->len ); + "len %d\n", MP_SEQ(from), from->len); skb = from; skb_pull(skb, MP_HEADER_LEN); + __skb_unlink(skb, &mp->frags); mp->frames--; } else { - struct sk_buff * frag; - int n; + struct sk_buff *walk, *tmp; + int found_start = 0; - for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++) - tot_len += frag->len - MP_HEADER_LEN; - - if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + if (ippp_table[lp->ppp_slot]->debug & 0x40) printk(KERN_DEBUG"isdn_mppp: reassembling frames %d " - "to %d, len %d\n", MP_SEQ(from), - (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len ); - if( (skb = dev_alloc_skb(tot_len)) == NULL ) { + "to %d, len %d\n", MP_SEQ(from), lastseq, + tot_len); + + skb = dev_alloc_skb(tot_len); + if (!skb) printk(KERN_ERR "isdn_mppp: cannot allocate sk buff " - "of size %d\n", tot_len); - isdn_ppp_mp_discard(mp, from, to); - return; - } + "of size %d\n", tot_len); + + found_start = 0; + skb_queue_walk_safe(&mp->frags, walk, tmp) { + if (walk == from) + found_start = 1; + if (!found_start) + continue; - while( from != to ) { - unsigned int len = from->len - MP_HEADER_LEN; + if (skb) { + unsigned int len = walk->len - MP_HEADER_LEN; + skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN, + skb_put(skb, len), + len); + } + __skb_unlink(walk, &mp->frags); + isdn_ppp_mp_free_skb(mp, walk); - skb_copy_from_linear_data_offset(from, MP_HEADER_LEN, - skb_put(skb,len), - len); - frag = from->next; - isdn_ppp_mp_free_skb(mp, from); - from = frag; + if (walk == to) + break; } } + if (!skb) + return; + proto = isdn_ppp_strip_proto(skb); isdn_ppp_push_higher(net_dev, lp, skb, proto); } -static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb) +static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb) { dev_kfree_skb(skb); mp->frames--; diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h index 8687a7dc063..4c218ee7587 100644 --- a/include/linux/isdn_ppp.h +++ b/include/linux/isdn_ppp.h @@ -157,7 +157,7 @@ typedef struct { typedef struct { int mp_mrru; /* unused */ - struct sk_buff * frags; /* fragments sl list -- use skb->next */ + struct sk_buff_head frags; /* fragments sl list */ long frames; /* number of frames in the frame list */ unsigned int seq; /* last processed packet seq #: any packets * with smaller seq # will be dropped -- cgit v1.2.3 From 147e70e62fdd5af6263106ad634b03c5154c1e56 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 01:29:52 -0700 Subject: cxgb3: Use SKB list interfaces instead of home-grown implementation. Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 3 +-- drivers/net/cxgb3/l2t.c | 39 +++++++++++++++++---------------------- drivers/net/cxgb3/l2t.h | 3 +-- drivers/net/cxgb3/sge.c | 45 +++++++++++++++++++++++---------------------- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 271140433b0..4f5cc6987ec 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -124,8 +124,7 @@ struct sge_rspq { /* state for an SGE response queue */ dma_addr_t phys_addr; /* physical address of the ring */ unsigned int cntxt_id; /* SGE context id for the response q */ spinlock_t lock; /* guards response processing */ - struct sk_buff *rx_head; /* offload packet receive queue head */ - struct sk_buff *rx_tail; /* offload packet receive queue tail */ + struct sk_buff_head rx_queue; /* offload packet receive queue */ struct sk_buff *pg_skb; /* used to build frag list in napi handler */ unsigned long offload_pkts; diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c index 825e510bd9e..b2c5314582a 100644 --- a/drivers/net/cxgb3/l2t.c +++ b/drivers/net/cxgb3/l2t.c @@ -86,6 +86,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, struct l2t_entry *e) { struct cpl_l2t_write_req *req; + struct sk_buff *tmp; if (!skb) { skb = alloc_skb(sizeof(*req), GFP_ATOMIC); @@ -103,13 +104,11 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); skb->priority = CPL_PRIORITY_CONTROL; cxgb3_ofld_send(dev, skb); - while (e->arpq_head) { - skb = e->arpq_head; - e->arpq_head = skb->next; - skb->next = NULL; + + skb_queue_walk_safe(&e->arpq, skb, tmp) { + __skb_unlink(skb, &e->arpq); cxgb3_ofld_send(dev, skb); } - e->arpq_tail = NULL; e->state = L2T_STATE_VALID; return 0; @@ -121,12 +120,7 @@ static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, */ static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) { - skb->next = NULL; - if (e->arpq_head) - e->arpq_tail->next = skb; - else - e->arpq_head = skb; - e->arpq_tail = skb; + __skb_queue_tail(&e->arpq, skb); } int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, @@ -167,7 +161,7 @@ again: break; spin_lock_bh(&e->lock); - if (e->arpq_head) + if (!skb_queue_empty(&e->arpq)) setup_l2e_send_pending(dev, skb, e); else /* we lost the race */ __kfree_skb(skb); @@ -357,14 +351,14 @@ EXPORT_SYMBOL(t3_l2t_get); * XXX: maybe we should abandon the latter behavior and just require a failure * handler. */ -static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq) +static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff_head *arpq) { - while (arpq) { - struct sk_buff *skb = arpq; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(arpq, skb, tmp) { struct l2t_skb_cb *cb = L2T_SKB_CB(skb); - arpq = skb->next; - skb->next = NULL; + __skb_unlink(skb, arpq); if (cb->arp_failure_handler) cb->arp_failure_handler(dev, skb); else @@ -378,8 +372,8 @@ static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq) */ void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) { + struct sk_buff_head arpq; struct l2t_entry *e; - struct sk_buff *arpq = NULL; struct l2t_data *d = L2DATA(dev); u32 addr = *(u32 *) neigh->primary_key; int ifidx = neigh->dev->ifindex; @@ -395,6 +389,8 @@ void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) return; found: + __skb_queue_head_init(&arpq); + read_unlock(&d->lock); if (atomic_read(&e->refcnt)) { if (neigh != e->neigh) @@ -402,8 +398,7 @@ found: if (e->state == L2T_STATE_RESOLVING) { if (neigh->nud_state & NUD_FAILED) { - arpq = e->arpq_head; - e->arpq_head = e->arpq_tail = NULL; + skb_queue_splice_init(&e->arpq, &arpq); } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE)) setup_l2e_send_pending(dev, NULL, e); } else { @@ -415,8 +410,8 @@ found: } spin_unlock_bh(&e->lock); - if (arpq) - handle_failed_resolution(dev, arpq); + if (!skb_queue_empty(&arpq)) + handle_failed_resolution(dev, &arpq); } struct l2t_data *t3_init_l2t(unsigned int l2t_capacity) diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h index d79001336cf..42ce65f76a8 100644 --- a/drivers/net/cxgb3/l2t.h +++ b/drivers/net/cxgb3/l2t.h @@ -64,8 +64,7 @@ struct l2t_entry { struct neighbour *neigh; /* associated neighbour */ struct l2t_entry *first; /* start of hash chain */ struct l2t_entry *next; /* next l2t_entry on chain */ - struct sk_buff *arpq_head; /* queue of packets awaiting resolution */ - struct sk_buff *arpq_tail; + struct sk_buff_head arpq; /* queue of packets awaiting resolution */ spinlock_t lock; atomic_t refcnt; /* entry reference count */ u8 dmac[6]; /* neighbour's MAC address */ diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 1b0861d73ab..6990c0ddc85 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1704,16 +1704,15 @@ int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb) */ static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb) { - skb->next = skb->prev = NULL; - if (q->rx_tail) - q->rx_tail->next = skb; - else { + int was_empty = skb_queue_empty(&q->rx_queue); + + __skb_queue_tail(&q->rx_queue, skb); + + if (was_empty) { struct sge_qset *qs = rspq_to_qset(q); napi_schedule(&qs->napi); - q->rx_head = skb; } - q->rx_tail = skb; } /** @@ -1754,26 +1753,29 @@ static int ofld_poll(struct napi_struct *napi, int budget) int work_done = 0; while (work_done < budget) { - struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE]; + struct sk_buff *skb, *tmp, *skbs[RX_BUNDLE_SIZE]; + struct sk_buff_head queue; int ngathered; spin_lock_irq(&q->lock); - head = q->rx_head; - if (!head) { + __skb_queue_head_init(&queue); + skb_queue_splice_init(&q->rx_queue, &queue); + if (skb_queue_empty(&queue)) { napi_complete(napi); spin_unlock_irq(&q->lock); return work_done; } - - tail = q->rx_tail; - q->rx_head = q->rx_tail = NULL; spin_unlock_irq(&q->lock); - for (ngathered = 0; work_done < budget && head; work_done++) { - prefetch(head->data); - skbs[ngathered] = head; - head = head->next; - skbs[ngathered]->next = NULL; + ngathered = 0; + skb_queue_walk_safe(&queue, skb, tmp) { + if (work_done >= budget) + break; + work_done++; + + __skb_unlink(skb, &queue); + prefetch(skb->data); + skbs[ngathered] = skb; if (++ngathered == RX_BUNDLE_SIZE) { q->offload_bundles++; adapter->tdev.recv(&adapter->tdev, skbs, @@ -1781,12 +1783,10 @@ static int ofld_poll(struct napi_struct *napi, int budget) ngathered = 0; } } - if (head) { /* splice remaining packets back onto Rx queue */ + if (!skb_queue_empty(&queue)) { + /* splice remaining packets back onto Rx queue */ spin_lock_irq(&q->lock); - tail->next = q->rx_head; - if (!q->rx_head) - q->rx_tail = tail; - q->rx_head = head; + skb_queue_splice(&queue, &q->rx_queue); spin_unlock_irq(&q->lock); } deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered); @@ -2934,6 +2934,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->rspq.gen = 1; q->rspq.size = p->rspq_size; spin_lock_init(&q->rspq.lock); + skb_queue_head_init(&q->rspq.rx_queue); q->txq[TXQ_ETH].stop_thres = nports * flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); -- cgit v1.2.3 From b61e06f258e50b25c38a73bea782bdb6876f0f70 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Sat, 20 Sep 2008 18:02:27 +0200 Subject: x86, oprofile: BUG scheduling while atomic nmi_shutdown() calls unregister_die_notifier() from an atomic context after setting preempt_disable() via get_cpu_var(): [ 1049.404154] BUG: scheduling while atomic: oprofiled/7796/0x00000002 [ 1049.404171] INFO: lockdep is turned off. [ 1049.404176] Modules linked in: oprofile af_packet rfcomm l2cap kvm_intel kvm i915 drm acpi_cpufreq cpufreq_userspace cpufreq_conservative cpufreq_ondemand cpufreq_powersave freq_table container sbs sbshc dm_mod arc4 ecb cryptomgr aead snd_hda_intel crypto_blkcipher snd_pcm_oss crypto_algapi snd_pcm iwlagn iwlcore snd_timer iTCO_wdt led_class btusb iTCO_vendor_support snd psmouse bluetooth mac80211 soundcore cfg80211 snd_page_alloc intel_agp video output button battery ac dcdbas evdev ext3 jbd mbcache sg sd_mod piix ata_piix libata scsi_mod dock tg3 libphy ehci_hcd uhci_hcd usbcore thermal processor fan fuse [ 1049.404362] Pid: 7796, comm: oprofiled Not tainted 2.6.27-rc5-mm1 #30 [ 1049.404368] Call Trace: [ 1049.404384] [] thread_return+0x4a0/0x7d3 [ 1049.404396] [] generic_exec_single+0x52/0xe0 [ 1049.404405] [] generic_exec_single+0xda/0xe0 [ 1049.404414] [] smp_call_function_single+0x73/0x150 [ 1049.404423] [] schedule_timeout+0x95/0xd0 [ 1049.404430] [] wait_for_common+0x43/0x180 [ 1049.404438] [] wait_for_common+0x114/0x180 [ 1049.404448] [] default_wake_function+0x0/0x10 [ 1049.404457] [] synchronize_rcu+0x30/0x40 [ 1049.404463] [] wakeme_after_rcu+0x0/0x10 [ 1049.404472] [] _spin_unlock_irqrestore+0x40/0x80 [ 1049.404482] [] atomic_notifier_chain_unregister+0x3f/0x60 [ 1049.404501] [] nmi_shutdown+0x51/0x90 [oprofile] [ 1049.404517] [] oprofile_shutdown+0x34/0x70 [oprofile] [ 1049.404532] [] event_buffer_release+0xe/0x40 [oprofile] [ 1049.404543] [] __fput+0xcd/0x240 [ 1049.404551] [] filp_close+0x54/0x90 [ 1049.404560] [] put_files_struct+0xb1/0xd0 [ 1049.404568] [] do_exit+0x18f/0x930 [ 1049.404576] [] restore_args+0x0/0x30 [ 1049.404584] [] do_group_exit+0x36/0xa0 [ 1049.404592] [] system_call_fastpath+0x16/0x1b This can be easily triggered with 'opcontrol --shutdown'. Simply move get_cpu_var() above unregister_die_notifier(). Signed-off-by: Andrea Righi Acked-by: Robert Richter Signed-off-by: Ingo Molnar --- arch/x86/oprofile/nmi_int.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 0227694f7da..8a5f1614a3d 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -295,10 +295,12 @@ static void nmi_cpu_shutdown(void *dummy) static void nmi_shutdown(void) { - struct op_msrs *msrs = &get_cpu_var(cpu_msrs); + struct op_msrs *msrs; + nmi_enabled = 0; on_each_cpu(nmi_cpu_shutdown, NULL, 1); unregister_die_notifier(&profile_exceptions_nb); + msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); free_msrs(); put_cpu_var(cpu_msrs); -- cgit v1.2.3 From b1132b3d874dcef296a63b46680a41b02de66bb4 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 18:50:45 +0200 Subject: ALSA: ASoC: Fix at32-pcm build breakage with PM enabled s/PDC_PTCR/ATMEL_PDC_PTCR/ Signed-off-by: Haavard Skinnemoen Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/soc/at32/at32-pcm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c index 435f1daf177..c83584f989a 100644 --- a/sound/soc/at32/at32-pcm.c +++ b/sound/soc/at32/at32-pcm.c @@ -434,7 +434,8 @@ static int at32_pcm_suspend(struct platform_device *pdev, params = prtd->params; /* Disable the PDC and save the PDC registers */ - ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable); + ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, + params->mask->pdc_disable); prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); @@ -464,7 +465,7 @@ static int at32_pcm_resume(struct platform_device *pdev, ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); - ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable); + ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable); return 0; } #else /* CONFIG_PM */ -- cgit v1.2.3 From cec5eb7be3a104fffd27ca967ee8e15a123050e2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 22 Sep 2008 15:58:14 +0100 Subject: pcmcia: Fix broken abuse of dev->driver_data PCMCIA abuses dev->private_data in the probe methods. Unfortunately it continues to abuse it after calling drv->probe() which leads to crashes and other nasties (such as bogus probes of multifunction devices) giving errors like pcmcia: registering new device pcmcia0.1 kernel: 0.1: GetNextTuple: No more items Extract the passed data before calling the driver probe function that way we don't blow up when the driver reuses dev->private_data as its right. As its close to the final release just move the hack so it works out, hopefully someone will be sufficiently embarrassed to produce a nice rework for 2.6.28. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4174d9656e3..34c83d3ca0f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -427,6 +427,18 @@ static int pcmcia_device_probe(struct device * dev) p_drv = to_pcmcia_drv(dev->driver); s = p_dev->socket; + /* The PCMCIA code passes the match data in via dev->driver_data + * which is an ugly hack. Once the driver probe is called it may + * and often will overwrite the match data so we must save it first + * + * handle pseudo multifunction devices: + * there are at most two pseudo multifunction devices. + * if we're matching against the first, schedule a + * call which will then check whether there are two + * pseudo devices, and if not, add the second one. + */ + did = p_dev->dev.driver_data; + ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id, p_drv->drv.name); @@ -455,21 +467,14 @@ static int pcmcia_device_probe(struct device * dev) goto put_module; } - /* handle pseudo multifunction devices: - * there are at most two pseudo multifunction devices. - * if we're matching against the first, schedule a - * call which will then check whether there are two - * pseudo devices, and if not, add the second one. - */ - did = p_dev->dev.driver_data; if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) pcmcia_add_device_later(p_dev->socket, 0); - put_module: +put_module: if (ret) module_put(p_drv->owner); - put_dev: +put_dev: if (ret) put_device(dev); return (ret); -- cgit v1.2.3 From d0be7cc7688d0cc2e4daf952c43b5ce86e5c8a1d Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 17 Sep 2008 12:39:49 +0530 Subject: ath9k: connectivity is lost after Group rekeying is done Connectivtiy is lost after Group rekeying is done. The keytype maintained by ath9k is reset when group key is updated. Though sc_keytype can be reset only for broadcast key the proper fix would be to use mac80211 provided key type from txinfo during xmit and get rid of sc_keytype from ath9k ath_softc. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Senthil Balasubramanian Tested-by: Steven Noonan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.h | 1 - drivers/net/wireless/ath9k/main.c | 3 --- drivers/net/wireless/ath9k/xmit.c | 6 +++--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ee695b76b8..2f84093331e 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -974,7 +974,6 @@ struct ath_softc { u32 sc_keymax; /* size of key cache */ DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */ u8 sc_splitmic; /* split TKIP MIC keys */ - int sc_keytype; /* RX */ struct list_head sc_rxbuf; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 99badf1404c..099719649c9 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -206,8 +206,6 @@ static int ath_key_config(struct ath_softc *sc, if (!ret) return -EIO; - if (mac) - sc->sc_keytype = hk.kv_type; return 0; } @@ -778,7 +776,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw, case DISABLE_KEY: ath_key_delete(sc, key); clear_bit(key->keyidx, sc->sc_keymap); - sc->sc_keytype = ATH9K_CIPHER_CLR; break; default: ret = -EINVAL; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 550129f717e..8b332e11a65 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -315,11 +315,11 @@ static int ath_tx_prepare(struct ath_softc *sc, txctl->keyix = tx_info->control.hw_key->hw_key_idx; txctl->frmlen += tx_info->control.icv_len; - if (sc->sc_keytype == ATH9K_CIPHER_WEP) + if (tx_info->control.hw_key->alg == ALG_WEP) txctl->keytype = ATH9K_KEY_TYPE_WEP; - else if (sc->sc_keytype == ATH9K_CIPHER_TKIP) + else if (tx_info->control.hw_key->alg == ALG_TKIP) txctl->keytype = ATH9K_KEY_TYPE_TKIP; - else if (sc->sc_keytype == ATH9K_CIPHER_AES_CCM) + else if (tx_info->control.hw_key->alg == ALG_CCMP) txctl->keytype = ATH9K_KEY_TYPE_AES; } -- cgit v1.2.3 From 5d89945e6ec44494285cb8de85d4f43d4647b740 Mon Sep 17 00:00:00 2001 From: "born.into.silence@gmail.com" Date: Fri, 19 Sep 2008 16:47:06 -0700 Subject: wireless: zd1211rw: add device ID fix wifi dongle "trust nw-3100" akpm: taken from http://bugzilla.kernel.org/show_bug.cgi?id=11587 I bought the wifi dongle trust nw-3100 wich is in fact a zd1211rw. Its hardware id was missing in the sources, adding it made it work flawlessly. Cc: Daniel Drake Cc: Ulrich Kunitz Cc: Johannes Berg Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index da8b7433e3a..a60ae86bd5c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -58,6 +58,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3 From 06f95ea8988513b172080c419e4be8826c55a318 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 16 Sep 2008 18:25:33 -0600 Subject: [IA64] Ski simulator doesn't need check_sal_cache_flush Peter Chubb reported that commit 3463a93def55c309f3c0d0a8aaf216be3be42d64 (Update check_sal_cache_flush to use platform_send_ipi()) broke Ski because it does not implement IPIs. Tony Luck suggested we just #ifndef out the call (since the simulator does not have the SAL bug that this code is attempting to detect and workaround) Signed-off-by: Alex Chiang Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index c27d5b2c182..de636b21567 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -616,7 +616,9 @@ setup_arch (char **cmdline_p) ia64_mca_init(); platform_setup(cmdline_p); +#ifndef CONFIG_IA64_HP_SIM check_sal_cache_flush(); +#endif paging_init(); } -- cgit v1.2.3 From d3758f87f39c5b072dde74c55bfb988262a3a45c Mon Sep 17 00:00:00 2001 From: Jay Lan Date: Mon, 22 Sep 2008 14:21:19 -0700 Subject: [IA64] kexec fails on systems with blocks of uncached memory Currently a memory segment in memory map with attribute of EFI_MEMORY_UC is denoted as "System RAM" in /proc/iomem, while memory of attribute (EFI_MEMORY_WB|EFI_MEMORY_UC) is also labeled the same. The kexec utility then includes uncached memory as part of vmcore. The kdump kernel MCA'ed when it tries to save the vmcore to a disk. A normal "cached" access may cause MCAs. This patch would label memory with attribute of EFI_MEMORY_UC only as "Uncached RAM" so that kexec would know not to include it in the vmcore. I will submit a separate kexec-tools patch to the kexec list. Signed-off-by: Jay Lan Acked-by: Simon Horman Signed-off-by: Tony Luck --- arch/ia64/kernel/efi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index d45f215bc8f..51b75cea701 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -1232,9 +1232,10 @@ efi_initialize_iomem_resources(struct resource *code_resource, if (md->attribute & EFI_MEMORY_WP) { name = "System ROM"; flags |= IORESOURCE_READONLY; - } else { + } else if (md->attribute == EFI_MEMORY_UC) + name = "Uncached RAM"; + else name = "System RAM"; - } break; case EFI_ACPI_MEMORY_NVS: -- cgit v1.2.3 From 6115e8557a75b5f24b56ed46c60dffef7e7fa992 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Mon, 22 Sep 2008 14:22:39 +0530 Subject: ath9k: Fix IRQ nobody cared issue with ath9k IRQs should be disabled before calling free_irq. Also flush pending IRQs. Pasted the kernel log message for reference. kernel: irq 17: nobody cared (try booting with the "irqpoll" option) kernel: [] __report_bad_irq+0x2e/0x6f kernel: [] note_interrupt+0x1b5/0x207 kernel: [] ? handle_IRQ_event+0x21/0x48 kernel: [] handle_fasteoi_irq+0x8e/0xad kernel: [] do_IRQ+0x6c/0x84 kernel: [] common_interrupt+0x23/0x28 kernel: [] ? acpi_idle_enter_simple+0x198/0x205 kernel: [] ? menu_select+0x5c/0x78 kernel: [] cpuidle_idle_call+0x59/0x89 kernel: [] cpu_idle+0xae/0xcf kernel: [] rest_init+0x4e/0x50 kernel: ======================= kernel: handlers: kernel: [] (ath_isr+0x0/0x13a [ath9k]) kernel: Disabling IRQ #17 Signed-off-by: Senthil Balasubramanian Tested-by: Steven Noonan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.c | 4 ++-- drivers/net/wireless/ath9k/main.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index f6c45288d0e..c04959357bd 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c @@ -294,8 +294,6 @@ static int ath_stop(struct ath_softc *sc) * hardware is gone (invalid). */ - if (!sc->sc_invalid) - ath9k_hw_set_interrupts(ah, 0); ath_draintxq(sc, false); if (!sc->sc_invalid) { ath_stoprecv(sc); @@ -1336,6 +1334,8 @@ void ath_deinit(struct ath_softc *sc) DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); ath_stop(sc); if (!sc->sc_invalid) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 099719649c9..acebdf1d20a 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1411,10 +1411,17 @@ static void ath_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; + enum ath9k_int status; - if (pdev->irq) + if (pdev->irq) { + ath9k_hw_set_interrupts(sc->sc_ah, 0); + /* clear the ISR */ + ath9k_hw_getisr(sc->sc_ah, &status); + sc->sc_invalid = 1; free_irq(pdev->irq, sc); + } ath_detach(sc); + pci_iounmap(pdev, sc->mem); pci_release_region(pdev, 0); pci_disable_device(pdev); -- cgit v1.2.3 From bdbef3d696ca83489eb653459b5a7a62ecf5596a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:35 +0200 Subject: [Bluetooth] Fix I/O errors on MacBooks with Broadcom chips The newer MacBooks contain a Broadcom based Bluetooth chip and to make this work properly, HCI_Reset must be send first. If HCI_Reset is not used then a lot of I/O errors show up and its triggers packets from non-existent ACL links. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6a010681ecf..7665347238c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -104,6 +104,9 @@ static struct usb_device_id blacklist_table[] = { /* Broadcom BCM2046 */ { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, + /* Apple MacBook Pro with Broadcom chip */ + { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET }, + /* IBM/Lenovo ThinkPad with Broadcom chip */ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, -- cgit v1.2.3 From e8c3c3d22b340a406a9aab1b7a9f436636c3de9d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:36 +0200 Subject: [Bluetooth] Fix wrong URB handling of btusb driver The btusb driver contains two typos that result in some buggy behavior, but the impact is not immediately visible. During initialization the submitting of interrupt URBs might fail and then make sure to remove the correct flag and not one of the hci_dev flags. When closing down the interface make sure to kill the anchor for the ISOC URBs and not kill the interrupt URBs twice. Also cancel any scheduled work when closing down the interface. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7665347238c..b4756a6a3a6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -519,7 +519,7 @@ static int btusb_open(struct hci_dev *hdev) err = btusb_submit_intr_urb(hdev); if (err < 0) { - clear_bit(BTUSB_INTR_RUNNING, &hdev->flags); + clear_bit(BTUSB_INTR_RUNNING, &data->flags); clear_bit(HCI_RUNNING, &hdev->flags); } @@ -535,8 +535,10 @@ static int btusb_close(struct hci_dev *hdev) if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; + cancel_work_sync(&data->work); + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->intr_anchor); + usb_kill_anchored_urbs(&data->isoc_anchor); clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); -- cgit v1.2.3 From 5fbcd260c2c52f78cd699f65e9c7af2e60b5380c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:36 +0200 Subject: [Bluetooth] Fix USB disconnect handling of btusb driver The USB transport specification for Bluetooth splits the ACL and SCO handling into two separate interfaces. In Linux it possible to probe and disconnect these interfaces independently. So make sure that both interfaces are tightly bound together. This fixes the suspend regression that some people have expierenced. Signed-off-by: Oliver Neukum Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b4756a6a3a6..29ae99817c6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -172,6 +172,7 @@ static struct usb_device_id blacklist_table[] = { struct btusb_data { struct hci_dev *hdev; struct usb_device *udev; + struct usb_interface *intf; struct usb_interface *isoc; spinlock_t lock; @@ -826,6 +827,7 @@ static int btusb_probe(struct usb_interface *intf, } data->udev = interface_to_usbdev(intf); + data->intf = intf; spin_lock_init(&data->lock); @@ -894,7 +896,7 @@ static int btusb_probe(struct usb_interface *intf, if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, - data->isoc, NULL); + data->isoc, data); if (err < 0) { hci_free_dev(hdev); kfree(data); @@ -926,13 +928,22 @@ static void btusb_disconnect(struct usb_interface *intf) hdev = data->hdev; - if (data->isoc) - usb_driver_release_interface(&btusb_driver, data->isoc); + __hci_dev_hold(hdev); - usb_set_intfdata(intf, NULL); + usb_set_intfdata(data->intf, NULL); + + if (data->isoc) + usb_set_intfdata(data->isoc, NULL); hci_unregister_dev(hdev); + if (intf == data->isoc) + usb_driver_release_interface(&btusb_driver, data->intf); + else if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); + + __hci_dev_put(hdev); + hci_free_dev(hdev); } -- cgit v1.2.3 From 44b50e5a1af13c605d6c3b17a60e42eb0ee48d5f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 15:42:24 -0700 Subject: sparc64: Fix missing devices due to PCI bridge test in of_create_pci_dev(). Just like in the arch/sparc64/kernel/of_device.c code fix commit 071d7f4c3b411beae08d27656e958070c43b78b4 ("sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace.") we have to check the OF device node name for "pci" instead of relying upon the 'device_type' property being there on all PCI bridges. Tested by Meelis Roos, and confirmed to make the PCI QFE devices reappear on the E3500 system. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 55096195458..80dad76f8b8 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -425,7 +425,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->current_state = 4; /* unknown power state */ dev->error_state = pci_channel_io_normal; - if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { + if (!strcmp(node->name, "pci")) { /* a PCI-PCI bridge */ dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; dev->rom_base_reg = PCI_ROM_ADDRESS1; -- cgit v1.2.3 From 2cdc55751c33829f00510e0104562d0f8d8a9b85 Mon Sep 17 00:00:00 2001 From: Kaihui Luo Date: Mon, 22 Sep 2008 19:02:36 -0700 Subject: netfilter: xt_time gives a wrong monthday in a leap year The function localtime_3 in xt_time.c gives a wrong monthday in a leap year after 28th 2. calculating monthday should use the array days_since_leapyear[] not days_since_year[] in a leap year. Signed-off-by: Kaihui Luo Acked-by: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/netfilter/xt_time.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index 9f328593287..307a2c3c2df 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c @@ -136,17 +136,19 @@ static void localtime_3(struct xtm *r, time_t time) * from w repeatedly while counting.) */ if (is_leap(year)) { + /* use days_since_leapyear[] in a leap year */ for (i = ARRAY_SIZE(days_since_leapyear) - 1; - i > 0 && days_since_year[i] > w; --i) + i > 0 && days_since_leapyear[i] > w; --i) /* just loop */; + r->monthday = w - days_since_leapyear[i] + 1; } else { for (i = ARRAY_SIZE(days_since_year) - 1; i > 0 && days_since_year[i] > w; --i) /* just loop */; + r->monthday = w - days_since_year[i] + 1; } r->month = i + 1; - r->monthday = w - days_since_year[i] + 1; return; } -- cgit v1.2.3 From 4d5392cc4de3403d71b929f39f3bc659db029ad1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Sep 2008 19:04:54 -0700 Subject: drivers/isdn/capi/kcapi.c: Adjust error handling code involving capi_ctr_put After calling capi_ctr_get, error handling code should call capi_ctr_put. The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r@ expression x,E; statement S; position p1,p2,p3; @@ ( if ((x = capi_ctr_get@p1(...)) == NULL || ...) S | x = capi_ctr_get@p1(...) ... when != x if (x == NULL || ...) S ) <... if@p3 (...) { ... when != capi_ctr_put(x) when != if (x) { ... capi_ctr_put(x); ...} return@p2 ...; } ...> ( return x; | return 0; | x = E | E = x | capi_ctr_put(x) ) @exists@ position r.p1,r.p2,r.p3; expression x; int ret != 0; statement S; @@ * x = capi_ctr_get@p1(...) <... * if@p3 (...) S ...> * return@p2 \(NULL\|ret\); // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 75726ea0fbb..5360c4fd473 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -828,15 +828,18 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) return -ESRCH; if (card->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); + capi_ctr_put(card); return -ESRCH; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); + capi_ctr_put(card); return -EINVAL; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); + capi_ctr_put(card); return -EINVAL; } @@ -849,6 +852,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) if (card->cardstate != CARD_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); + capi_ctr_put(card); return -EBUSY; } card->cardstate = CARD_LOADING; -- cgit v1.2.3 From f11d32dfaa0753cfab7b2e5052923e8784a3c141 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 22 Sep 2008 19:16:20 -0700 Subject: mISDN: endian annotations for struct zt Found two possible bugs where the z1 value was used directly without byteswapping. Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfc_pci.h | 4 ++-- drivers/isdn/hardware/mISDN/hfcpci.c | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h index fd2c9be6d84..5783d22a18f 100644 --- a/drivers/isdn/hardware/mISDN/hfc_pci.h +++ b/drivers/isdn/hardware/mISDN/hfc_pci.h @@ -183,8 +183,8 @@ #define D_FREG_MASK 0xF struct zt { - unsigned short z1; /* Z1 pointer 16 Bit */ - unsigned short z2; /* Z2 pointer 16 Bit */ + __le16 z1; /* Z1 pointer 16 Bit */ + __le16 z2; /* Z2 pointer 16 Bit */ }; struct dfifo { diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 9cf5edbb1a9..9f808ecc689 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -366,8 +366,7 @@ static void hfcpci_clear_fifo_tx(struct hfc_pci *hc, int fifo) bzt->f2 = MAX_B_FRAMES; bzt->f1 = bzt->f2; /* init F pointers to remain constant */ bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1); - bzt->za[MAX_B_FRAMES].z2 = cpu_to_le16( - le16_to_cpu(bzt->za[MAX_B_FRAMES].z1 - 1)); + bzt->za[MAX_B_FRAMES].z2 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 2); if (fifo_state) hc->hw.fifo_en |= fifo_state; Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en); @@ -482,7 +481,7 @@ receive_dmsg(struct hfc_pci *hc) df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ df->za[df->f2 & D_FREG_MASK].z2 = - cpu_to_le16((zp->z2 + rcnt) & (D_FIFO_SIZE - 1)); + cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1)); } else { dch->rx_skb = mI_alloc_skb(rcnt - 3, GFP_ATOMIC); if (!dch->rx_skb) { @@ -526,7 +525,7 @@ receive_dmsg(struct hfc_pci *hc) int hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) { - unsigned short *z1r, *z2r; + __le16 *z1r, *z2r; int new_z2, fcnt, maxlen; u_char *ptr, *ptr1; @@ -724,7 +723,7 @@ hfcpci_fill_fifo(struct bchannel *bch) struct bzfifo *bz; u_char *bdata; u_char new_f1, *src, *dst; - unsigned short *z1t, *z2t; + __le16 *z1t, *z2t; if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO)) printk(KERN_DEBUG "%s\n", __func__); -- cgit v1.2.3 From 1532dcb75c238d79c54a037da87c3f495cbf605b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 22 Sep 2008 19:16:51 -0700 Subject: mISDN: annotate iomem pointer and add statics Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcpci.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 9f808ecc689..cd8302af40e 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); module_param(debug, uint, 0); static LIST_HEAD(HFClist); -DEFINE_RWLOCK(HFClock); +static DEFINE_RWLOCK(HFClock); enum { HFC_CCD_2BD0, @@ -88,7 +88,7 @@ struct hfcPCI_hw { unsigned char bswapped; unsigned char protocol; int nt_timer; - unsigned char *pci_io; /* start of PCI IO memory */ + unsigned char __iomem *pci_io; /* start of PCI IO memory */ dma_addr_t dmahandle; void *fifos; /* FIFO memory */ int last_bfifo_cnt[2]; @@ -153,7 +153,7 @@ release_io_hfcpci(struct hfc_pci *hc) pci_write_config_word(hc->pdev, PCI_COMMAND, 0); del_timer(&hc->hw.timer); pci_free_consistent(hc->pdev, 0x8000, hc->hw.fifos, hc->hw.dmahandle); - iounmap((void *)hc->hw.pci_io); + iounmap(hc->hw.pci_io); } /* @@ -522,7 +522,7 @@ receive_dmsg(struct hfc_pci *hc) /* * check for transparent receive data and read max one threshold size if avail */ -int +static int hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) { __le16 *z1r, *z2r; @@ -575,7 +575,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) /* * B-channel main receive routine */ -void +static void main_rec_hfcpci(struct bchannel *bch) { struct hfc_pci *hc = bch->hw; @@ -1678,7 +1678,7 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) * called for card init message */ -void +static void inithfcpci(struct hfc_pci *hc) { printk(KERN_DEBUG "inithfcpci: entered\n"); @@ -1965,7 +1965,7 @@ setup_hw(struct hfc_pci *hc) printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return 1; } - hc->hw.pci_io = (char *)(ulong)hc->pdev->resource[1].start; + hc->hw.pci_io = (char __iomem *)(unsigned long)hc->pdev->resource[1].start; if (!hc->hw.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); -- cgit v1.2.3 From ce425a9f2c0182e9a9e49c7dc18699f2db4c3f48 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 22 Sep 2008 19:18:15 -0700 Subject: mISDN: misc timerdev fixes - Remove noop VFS stubs. The VFS does that on a NULL pointer anyways. - Fix timer handler prototype to be correct - Comment ugly SMP race I didn't fix. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/mISDN/timerdev.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index b5fabc7019d..e7462924b50 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -124,18 +124,6 @@ mISDN_read(struct file *filep, char *buf, size_t count, loff_t *off) return ret; } -static loff_t -mISDN_llseek(struct file *filep, loff_t offset, int orig) -{ - return -ESPIPE; -} - -static ssize_t -mISDN_write(struct file *filep, const char *buf, size_t count, loff_t *off) -{ - return -EOPNOTSUPP; -} - static unsigned int mISDN_poll(struct file *filep, poll_table *wait) { @@ -157,8 +145,9 @@ mISDN_poll(struct file *filep, poll_table *wait) } static void -dev_expire_timer(struct mISDNtimer *timer) +dev_expire_timer(unsigned long data) { + struct mISDNtimer *timer = (void *)data; u_long flags; spin_lock_irqsave(&timer->dev->lock, flags); @@ -191,7 +180,7 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout) spin_unlock_irqrestore(&dev->lock, flags); timer->dev = dev; timer->tl.data = (long)timer; - timer->tl.function = (void *) dev_expire_timer; + timer->tl.function = dev_expire_timer; init_timer(&timer->tl); timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000); add_timer(&timer->tl); @@ -211,6 +200,9 @@ misdn_del_timer(struct mISDNtimerdev *dev, int id) list_for_each_entry(timer, &dev->pending, list) { if (timer->id == id) { list_del_init(&timer->list); + /* RED-PEN AK: race -- timer can be still running on + * other CPU. Needs reference count I think + */ del_timer(&timer->tl); ret = timer->id; kfree(timer); @@ -268,9 +260,7 @@ mISDN_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, } static struct file_operations mISDN_fops = { - .llseek = mISDN_llseek, .read = mISDN_read, - .write = mISDN_write, .poll = mISDN_poll, .ioctl = mISDN_ioctl, .open = mISDN_open, -- cgit v1.2.3 From 978e9aec262d66d13ccceece93b867bfc0fcd2f1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 22 Sep 2008 19:20:06 -0700 Subject: irda: follow lspci device/vendor style Use "[%04x:%04x]" for PCI vendor/device IDs to follow the format used by lspci(8). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/irda/vlsi_ir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 18f4b3a96ae..9c926d205de 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -165,7 +165,7 @@ static void vlsi_proc_pdev(struct seq_file *seq, struct pci_dev *pdev) unsigned iobase = pci_resource_start(pdev, 0); unsigned i; - seq_printf(seq, "\n%s (vid/did: %04x/%04x)\n", + seq_printf(seq, "\n%s (vid/did: [%04x:%04x])\n", pci_name(pdev), (int)pdev->vendor, (int)pdev->device); seq_printf(seq, "pci-power-state: %u\n", (unsigned) pdev->current_state); seq_printf(seq, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n", -- cgit v1.2.3 From d48abfecea8513cfd2fd7e341439c1b8a28e9ff4 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 22 Sep 2008 19:20:51 -0700 Subject: net: em_cmp.c use unaligned access helpers Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/sched/em_cmp.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c index cc49c932641..bc450397487 100644 --- a/net/sched/em_cmp.c +++ b/net/sched/em_cmp.c @@ -14,6 +14,7 @@ #include #include #include +#include #include static inline int cmp_needs_transformation(struct tcf_em_cmp *cmp) @@ -37,8 +38,7 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, break; case TCF_EM_ALIGN_U16: - val = *ptr << 8; - val |= *(ptr+1); + val = get_unaligned_be16(ptr); if (cmp_needs_transformation(cmp)) val = be16_to_cpu(val); @@ -47,10 +47,7 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, case TCF_EM_ALIGN_U32: /* Worth checking boundries? The branching seems * to get worse. Visit again. */ - val = *ptr << 24; - val |= *(ptr+1) << 16; - val |= *(ptr+2) << 8; - val |= *(ptr+3); + val = get_unaligned_be32(ptr); if (cmp_needs_transformation(cmp)) val = be32_to_cpu(val); -- cgit v1.2.3 From ca330c5a913a9b1690c709f4cfcd6be0c8696b14 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 22 Sep 2008 19:21:51 -0700 Subject: hci_usb: replace mb with smp_mb smp_mb is enough for ordering memory operations among processors,and mb is more expensive than smp_mb for UP machine, so replace it with smp_mb(). Signed-off-by: Ming Lei Acked-by: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/bluetooth/hci_usb.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 1790cc8e431..8e659914523 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h @@ -70,8 +70,8 @@ static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb) { unsigned long flags; spin_lock_irqsave(&q->lock, flags); - /* _urb_unlink needs to know which spinlock to use, thus mb(). */ - _urb->queue = q; mb(); list_add(&_urb->list, &q->head); + /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */ + _urb->queue = q; smp_mb(); list_add(&_urb->list, &q->head); spin_unlock_irqrestore(&q->lock, flags); } @@ -79,8 +79,8 @@ static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb) { unsigned long flags; spin_lock_irqsave(&q->lock, flags); - /* _urb_unlink needs to know which spinlock to use, thus mb(). */ - _urb->queue = q; mb(); list_add_tail(&_urb->list, &q->head); + /* _urb_unlink needs to know which spinlock to use, thus smp_mb(). */ + _urb->queue = q; smp_mb(); list_add_tail(&_urb->list, &q->head); spin_unlock_irqrestore(&q->lock, flags); } @@ -89,7 +89,7 @@ static inline void _urb_unlink(struct _urb *_urb) struct _urb_queue *q; unsigned long flags; - mb(); + smp_mb(); q = _urb->queue; /* If q is NULL, it will die at easy-to-debug NULL pointer dereference. No need to BUG(). */ -- cgit v1.2.3 From 6a19309db0a02d821494f4df754046c85a230627 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Sep 2008 19:22:58 -0700 Subject: drivers/atm: Use DIV_ROUND_UP The kernel.h macro DIV_ROUND_UP performs the computation (((n) + (d) - 1) / (d)) but is perhaps more readable. In the case of the file drivers/atm/eni.c, I am a little bit suspicious of the -1 at the end of the affected expression. Please check that that is what is wanted. An extract of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ #include @depends on haskernel@ expression n,d; @@ ( - (n + d - 1) / d + DIV_ROUND_UP(n,d) | - (n + (d - 1)) / d + DIV_ROUND_UP(n,d) ) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP((n),d) + DIV_ROUND_UP(n,d) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP(n,(d)) + DIV_ROUND_UP(n,d) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/eni.c | 2 +- drivers/atm/horizon.c | 8 ++++---- drivers/atm/zatm.c | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 41b2204ebc6..5503bfc8e13 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -1270,7 +1270,7 @@ static int comp_tx(struct eni_dev *eni_dev,int *pcr,int reserved,int *pre, if (*pre < 3) (*pre)++; /* else fail later */ div = pre_div[*pre]*-*pcr; DPRINTK("max div %d\n",div); - *res = (TS_CLOCK+div-1)/div-1; + *res = DIV_ROUND_UP(TS_CLOCK, div)-1; } if (*res < 0) *res = 0; if (*res > MID_SEG_MAX_RATE) *res = MID_SEG_MAX_RATE; diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index c0ac728dc56..615412364e9 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -635,7 +635,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, // take care of rounding switch (r) { case round_down: - pre = (br+(c<qos.rxtp.max_sdu = 65464; /* fix this - we may want to receive 64kB SDUs later */ - cells = (vcc->qos.rxtp.max_sdu+ATM_AAL5_TRAILER+ - ATM_CELL_PAYLOAD-1)/ATM_CELL_PAYLOAD; + cells = DIV_ROUND_UP(vcc->qos.rxtp.max_sdu + ATM_AAL5_TRAILER, + ATM_CELL_PAYLOAD); zatm_vcc->pool = pool_index(cells*ATM_CELL_PAYLOAD); } else { @@ -820,7 +820,7 @@ static int alloc_shaper(struct atm_dev *dev,int *pcr,int min,int max,int ubr) } else { i = 255; - m = (ATM_OC3_PCR*255+max-1)/max; + m = DIV_ROUND_UP(ATM_OC3_PCR*255, max); } } if (i > m) { -- cgit v1.2.3 From bb55b327cb7638d5b5320c766950bfb328636e9f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Sep 2008 19:23:48 -0700 Subject: drivers/net/wan: Use DIV_ROUND_UP The kernel.h macro DIV_ROUND_UP performs the computation (((n) + (d) - 1) / (d)) but is perhaps more readable. An extract of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ #include @depends on haskernel@ expression n,d; @@ ( - (n + d - 1) / d + DIV_ROUND_UP(n,d) | - (n + (d - 1)) / d + DIV_ROUND_UP(n,d) ) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP((n),d) + DIV_ROUND_UP(n,d) @depends on haskernel@ expression n,d; @@ - DIV_ROUND_UP(n,(d)) + DIV_ROUND_UP(n,d) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 6596cd0742b..f972fef87c9 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -856,7 +856,7 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev ) len = SBNI_MIN_LEN; nl->tx_buf_p = skb; - nl->tx_frameno = (len + nl->maxframe - 1) / nl->maxframe; + nl->tx_frameno = DIV_ROUND_UP(len, nl->maxframe); nl->framelen = len < nl->maxframe ? len : nl->maxframe; outb( inb( dev->base_addr + CSR0 ) | TR_REQ, dev->base_addr + CSR0 ); -- cgit v1.2.3 From 5e687220a047dc4f0c2fb9ce886359a23075ddbc Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Sep 2008 19:24:45 -0700 Subject: net/atm/lec.c: drop code after return The break after the return serves no purpose. Signed-off-by: Julia Lawall Reviewed-by: Richard Genoud Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/atm/lec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index 5799fb52365..8f701cde594 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1931,7 +1931,6 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, switch (priv->lane_version) { case 1: return priv->mcast_vcc; - break; case 2: /* LANE2 wants arp for multicast addresses */ if (!compare_ether_addr(mac_to_find, bus_mac)) return priv->mcast_vcc; -- cgit v1.2.3 From fcaa40669cd798ca2ac0d15441e8a1d1145f2b16 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Date: Mon, 22 Sep 2008 19:27:10 -0700 Subject: cassini: use request_firmware Firmware blob looks like this... __le16 load_address unsigned char data[] [akpm@linux-foundation.org: include vmalloc.h] Signed-off-by: Jaswinder Singh Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/cassini.c | 54 +- drivers/net/cassini.h | 1522 +---------------------------------------- firmware/Makefile | 1 + firmware/WHENCE | 10 + firmware/sun/cassini.bin.ihex | 143 ++++ 5 files changed, 207 insertions(+), 1523 deletions(-) create mode 100644 firmware/sun/cassini.bin.ihex diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 40ff6a90d0d..86909cfb14d 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,7 @@ #include #include #include +#include #include @@ -197,6 +199,7 @@ static int link_mode; MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("sun/cassini.bin"); module_param(cassini_debug, int, 0); MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); module_param(link_mode, int, 0); @@ -812,9 +815,44 @@ static int cas_reset_mii_phy(struct cas *cp) return (limit <= 0); } +static int cas_saturn_firmware_init(struct cas *cp) +{ + const struct firmware *fw; + const char fw_name[] = "sun/cassini.bin"; + int err; + + if (PHY_NS_DP83065 != cp->phy_id) + return 0; + + err = request_firmware(&fw, fw_name, &cp->pdev->dev); + if (err) { + printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n", + fw_name); + return err; + } + if (fw->size < 2) { + printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n", + fw->size, fw_name); + err = -EINVAL; + goto out; + } + cp->fw_load_addr= fw->data[1] << 8 | fw->data[0]; + cp->fw_size = fw->size - 2; + cp->fw_data = vmalloc(cp->fw_size); + if (!cp->fw_data) { + err = -ENOMEM; + printk(KERN_ERR "cassini: \"%s\" Failed %d\n", fw_name, err); + goto out; + } + memcpy(cp->fw_data, &fw->data[2], cp->fw_size); +out: + release_firmware(fw); + return err; +} + static void cas_saturn_firmware_load(struct cas *cp) { - cas_saturn_patch_t *patch = cas_saturn_patch; + int i; cas_phy_powerdown(cp); @@ -833,11 +871,9 @@ static void cas_saturn_firmware_load(struct cas *cp) /* download new firmware */ cas_phy_write(cp, DP83065_MII_MEM, 0x1); - cas_phy_write(cp, DP83065_MII_REGE, patch->addr); - while (patch->addr) { - cas_phy_write(cp, DP83065_MII_REGD, patch->val); - patch++; - } + cas_phy_write(cp, DP83065_MII_REGE, cp->fw_load_addr); + for (i = 0; i < cp->fw_size; i++) + cas_phy_write(cp, DP83065_MII_REGD, cp->fw_data[i]); /* enable firmware */ cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8); @@ -5108,6 +5144,9 @@ static int __devinit cas_init_one(struct pci_dev *pdev, cas_reset(cp, 0); if (cas_check_invariants(cp)) goto err_out_iounmap; + if (cp->cas_flags & CAS_FLAG_SATURN) + if (cas_saturn_firmware_init(cp)) + goto err_out_iounmap; cp->init_block = (struct cas_init_block *) pci_alloc_consistent(pdev, sizeof(struct cas_init_block), @@ -5217,6 +5256,9 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) cp = netdev_priv(dev); unregister_netdev(dev); + if (cp->fw_data) + vfree(cp->fw_data); + mutex_lock(&cp->pm_mutex); flush_scheduled_work(); if (cp->hw_running) diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h index 552af89ca1c..fd17a002b45 100644 --- a/drivers/net/cassini.h +++ b/drivers/net/cassini.h @@ -2514,1523 +2514,6 @@ static cas_hp_inst_t cas_prog_null[] = { {NULL} }; #define CAS_HP_FIRMWARE cas_prog_null #endif -/* firmware patch for NS_DP83065 */ -typedef struct cas_saturn_patch { - u16 addr; - u16 val; -} cas_saturn_patch_t; - -#if 1 -cas_saturn_patch_t cas_saturn_patch[] = { -{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009}, -{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000}, -{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000}, -{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff}, -{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025}, -{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f}, -{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026}, -{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011}, -{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d}, -{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086}, -{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f}, -{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3}, -{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047}, -{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a}, -{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047}, -{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033}, -{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f}, -{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084}, -{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004}, -{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096}, -{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c}, -{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027}, -{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084}, -{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047}, -{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a}, -{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047}, -{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054}, -{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f}, -{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084}, -{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004}, -{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6}, -{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084}, -{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003}, -{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025}, -{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6}, -{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f}, -{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7}, -{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f}, -{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec}, -{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa}, -{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7}, -{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082}, -{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001}, -{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046}, -{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081}, -{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a}, -{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020}, -{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027}, -{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084}, -{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7}, -{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084}, -{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047}, -{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a}, -{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047}, -{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad}, -{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082}, -{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001}, -{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084}, -{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041}, -{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026}, -{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023}, -{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027}, -{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed}, -{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083}, -{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042}, -{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e}, -{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084}, -{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003}, -{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df}, -{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6}, -{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f}, -{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7}, -{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f}, -{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec}, -{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa}, -{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011}, -{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd}, -{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce}, -{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff}, -{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096}, -{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c}, -{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027}, -{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049}, -{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091}, -{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6}, -{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085}, -{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c}, -{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1}, -{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f}, -{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025}, -{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016}, -{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052}, -{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e}, -{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7}, -{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6}, -{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4}, -{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083}, -{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001}, -{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046}, -{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081}, -{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a}, -{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd}, -{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025}, -{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084}, -{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084}, -{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018}, -{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019}, -{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004}, -{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e}, -{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b}, -{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007}, -{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027}, -{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081}, -{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b}, -{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007}, -{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027}, -{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e}, -{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd}, -{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086}, -{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049}, -{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012}, -{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071}, -{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f}, -{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084}, -{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008}, -{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6}, -{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4}, -{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006}, -{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025}, -{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016}, -{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e}, -{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd}, -{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026}, -{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082}, -{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001}, -{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084}, -{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f}, -{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec}, -{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa}, -{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7}, -{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f}, -{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd}, -{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce}, -{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff}, -{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096}, -{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c}, -{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026}, -{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012}, -{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f}, -{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027}, -{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023}, -{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027}, -{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084}, -{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051}, -{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091}, -{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e}, -{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce}, -{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff}, -{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e}, -{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd}, -{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c}, -{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce}, -{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff}, -{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e}, -{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096}, -{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c}, -{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026}, -{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024}, -{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026}, -{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018}, -{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019}, -{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001}, -{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009}, -{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020}, -{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081}, -{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015}, -{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044}, -{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1}, -{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f}, -{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044}, -{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029}, -{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025}, -{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f}, -{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047}, -{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a}, -{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047}, -{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034}, -{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011}, -{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084}, -{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002}, -{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e}, -{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096}, -{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc}, -{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097}, -{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1}, -{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086}, -{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012}, -{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7}, -{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010}, -{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd}, -{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031}, -{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e}, -{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6}, -{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f}, -{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7}, -{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f}, -{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec}, -{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa}, -{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008}, -{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5}, -{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002}, -{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6}, -{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4}, -{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084}, -{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001}, -{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046}, -{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081}, -{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003}, -{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f}, -{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd}, -{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025}, -{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085}, -{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044}, -{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026}, -{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012}, -{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001}, -{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010}, -{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd}, -{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce}, -{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff}, -{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e}, -{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096}, -{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003}, -{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026}, -{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012}, -{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003}, -{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027}, -{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085}, -{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044}, -{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026}, -{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012}, -{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001}, -{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010}, -{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce}, -{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff}, -{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e}, -{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6}, -{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a}, -{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010}, -{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085}, -{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8}, -{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000}, -{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084}, -{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001}, -{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085}, -{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046}, -{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081}, -{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009}, -{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030}, -{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081}, -{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f}, -{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044}, -{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b}, -{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029}, -{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026}, -{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011}, -{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022}, -{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6}, -{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba}, -{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084}, -{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d}, -{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085}, -{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005}, -{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e}, -{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca}, -{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022}, -{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000}, -{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018}, -{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000}, -{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046}, -{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085}, -{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002}, -{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085}, -{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001}, -{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f}, -{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004}, -{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004}, -{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7}, -{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086}, -{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012}, -{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007}, -{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006}, -{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d}, -{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070}, -{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba}, -{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7}, -{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001}, -{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001}, -{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6}, -{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084}, -{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002}, -{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004}, -{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001}, -{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001}, -{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4}, -{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7}, -{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6}, -{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084}, -{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008}, -{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6}, -{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081}, -{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008}, -{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7}, -{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e}, -{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086}, -{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040}, -{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e}, -{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7}, -{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f}, -{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082}, -{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f}, -{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f}, -{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f}, -{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f}, -{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f}, -{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f}, -{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f}, -{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f}, -{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f}, -{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f}, -{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f}, -{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f}, -{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f}, -{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012}, -{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010}, -{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004}, -{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7}, -{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7}, -{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7}, -{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7}, -{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086}, -{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012}, -{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012}, -{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7}, -{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004}, -{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004}, -{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001}, -{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001}, -{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008}, -{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081}, -{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b}, -{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce}, -{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd}, -{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e}, -{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081}, -{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b}, -{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce}, -{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd}, -{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e}, -{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081}, -{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b}, -{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce}, -{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd}, -{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e}, -{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081}, -{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b}, -{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce}, -{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd}, -{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e}, -{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081}, -{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b}, -{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce}, -{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd}, -{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e}, -{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081}, -{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b}, -{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce}, -{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd}, -{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e}, -{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081}, -{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b}, -{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce}, -{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd}, -{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e}, -{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081}, -{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008}, -{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce}, -{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd}, -{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6}, -{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081}, -{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003}, -{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047}, -{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009}, -{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081}, -{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006}, -{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009}, -{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe}, -{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006}, -{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081}, -{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008}, -{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7}, -{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e}, -{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6}, -{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026}, -{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f}, -{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7}, -{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e}, -{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6}, -{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084}, -{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f}, -{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b}, -{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012}, -{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012}, -{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc}, -{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009}, -{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe}, -{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070}, -{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f}, -{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c}, -{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f}, -{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084}, -{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f}, -{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c}, -{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f}, -{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1}, -{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003}, -{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040}, -{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f}, -{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027}, -{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b}, -{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081}, -{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b}, -{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027}, -{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087}, -{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f}, -{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002}, -{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a}, -{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7}, -{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086}, -{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f}, -{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012}, -{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075}, -{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7}, -{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020}, -{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f}, -{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002}, -{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071}, -{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047}, -{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097}, -{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089}, -{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f}, -{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089}, -{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f}, -{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089}, -{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f}, -{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089}, -{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f}, -{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089}, -{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7}, -{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7}, -{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6}, -{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027}, -{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f}, -{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f}, -{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f}, -{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d}, -{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078}, -{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c}, -{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6}, -{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027}, -{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f}, -{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f}, -{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f}, -{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b}, -{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d}, -{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075}, -{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c}, -{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a}, -{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027}, -{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f}, -{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f}, -{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c}, -{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083}, -{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075}, -{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078}, -{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b}, -{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc}, -{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d}, -{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000}, -{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070}, -{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072}, -{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e}, -{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6}, -{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026}, -{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce}, -{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd}, -{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e}, -{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6}, -{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026}, -{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce}, -{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd}, -{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e}, -{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6}, -{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026}, -{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce}, -{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd}, -{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e}, -{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086}, -{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040}, -{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x0000}, -{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075}, -{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e}, -{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012}, -{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8}, -{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012}, -{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f}, -{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007}, -{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048}, -{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6}, -{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4}, -{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7}, -{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6}, -{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081}, -{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf}, -{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005}, -{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b}, -{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005}, -{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6}, -{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd}, -{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086}, -{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f}, -{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089}, -{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002}, -{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077}, -{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094}, -{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6}, -{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd}, -{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce}, -{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6}, -{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001}, -{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081}, -{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003}, -{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066}, -{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8}, -{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084}, -{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b}, -{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079}, -{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008}, -{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e}, -{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6}, -{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a}, -{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012}, -{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012}, -{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb}, -{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7}, -{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6}, -{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036}, -{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c}, -{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7}, -{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086}, -{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012}, -{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012}, -{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001}, -{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001}, -{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe}, -{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004}, -{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004}, -{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba}, -{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7}, -{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086}, -{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012}, -{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012}, -{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7}, -{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6}, -{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084}, -{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008}, -{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c}, -{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026}, -{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076}, -{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e}, -{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e}, -{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6}, -{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081}, -{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c}, -{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7}, -{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d}, -{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb}, -{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004}, -{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7}, -{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce}, -{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6}, -{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081}, -{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005}, -{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6}, -{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6}, -{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084}, -{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012}, -{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083}, -{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c}, -{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000}, -{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006}, -{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b}, -{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083}, -{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041}, -{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e}, -{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7}, -{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086}, -{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f}, -{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012}, -{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f}, -{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c}, -{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7}, -{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086}, -{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a}, -{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012}, -{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009}, -{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c}, -{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d}, -{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c}, -{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e}, -{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027}, -{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020}, -{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e}, -{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c}, -{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba}, -{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7}, -{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6}, -{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048}, -{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d}, -{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021}, -{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004}, -{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7}, -{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd}, -{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f}, -{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000}, -{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000}, -{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008}, -{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5}, -{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c}, -{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba}, -{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7}, -{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6}, -{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084}, -{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001}, -{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006}, -{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7}, -{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036}, -{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7}, -{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032}, -{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026}, -{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f}, -{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089}, -{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001}, -{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1}, -{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c}, -{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027}, -{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f}, -{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005}, -{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080}, -{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080}, -{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7}, -{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6}, -{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005}, -{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f}, -{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f}, -{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4}, -{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b}, -{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007}, -{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f}, -{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000}, -{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000}, -{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000}, -{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6}, -{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6}, -{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7}, -{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001}, -{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018}, -{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018}, -{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7}, -{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6}, -{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007}, -{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4}, -{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054}, -{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7}, -{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a}, -{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039}, -{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084}, -{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022}, -{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7}, -{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6}, -{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7}, -{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6}, -{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4}, -{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f}, -{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072}, -{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072}, -{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071}, -{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027}, -{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001}, -{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081}, -{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024}, -{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070}, -{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096}, -{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080}, -{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064}, -{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070}, -{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096}, -{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010}, -{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064}, -{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070}, -{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096}, -{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020}, -{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064}, -{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070}, -{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096}, -{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040}, -{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074}, -{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074}, -{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078}, -{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6}, -{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085}, -{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af}, -{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4}, -{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6}, -{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081}, -{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036}, -{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026}, -{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022}, -{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044}, -{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022}, -{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020}, -{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081}, -{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d}, -{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084}, -{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044}, -{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022}, -{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020}, -{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081}, -{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f}, -{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084}, -{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044}, -{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6}, -{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f}, -{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022}, -{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c}, -{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006}, -{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed}, -{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007}, -{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9}, -{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006}, -{0x8aca, 0x0039}, { 0x0, 0x0 } -}; -#else -cas_saturn_patch_t cas_saturn_patch[] = { -{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009}, -{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000}, -{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000}, -{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff}, -{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025}, -{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f}, -{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026}, -{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011}, -{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d}, -{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086}, -{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f}, -{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3}, -{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047}, -{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a}, -{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047}, -{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033}, -{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f}, -{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084}, -{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004}, -{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096}, -{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c}, -{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027}, -{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084}, -{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047}, -{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a}, -{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047}, -{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054}, -{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f}, -{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084}, -{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004}, -{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6}, -{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084}, -{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003}, -{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025}, -{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6}, -{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f}, -{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7}, -{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f}, -{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec}, -{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa}, -{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7}, -{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082}, -{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001}, -{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046}, -{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081}, -{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a}, -{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020}, -{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027}, -{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084}, -{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7}, -{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084}, -{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047}, -{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a}, -{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047}, -{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad}, -{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082}, -{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001}, -{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084}, -{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041}, -{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026}, -{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023}, -{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027}, -{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed}, -{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083}, -{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042}, -{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e}, -{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084}, -{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003}, -{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df}, -{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6}, -{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f}, -{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7}, -{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f}, -{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec}, -{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa}, -{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011}, -{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd}, -{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce}, -{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff}, -{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096}, -{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c}, -{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027}, -{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049}, -{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091}, -{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6}, -{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085}, -{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c}, -{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1}, -{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f}, -{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025}, -{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016}, -{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052}, -{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e}, -{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7}, -{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6}, -{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4}, -{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083}, -{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001}, -{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046}, -{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081}, -{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a}, -{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd}, -{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025}, -{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084}, -{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084}, -{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018}, -{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019}, -{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004}, -{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e}, -{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b}, -{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007}, -{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027}, -{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081}, -{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b}, -{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007}, -{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027}, -{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e}, -{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd}, -{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086}, -{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049}, -{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012}, -{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071}, -{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f}, -{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084}, -{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008}, -{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6}, -{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4}, -{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006}, -{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025}, -{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016}, -{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e}, -{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd}, -{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026}, -{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082}, -{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001}, -{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084}, -{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f}, -{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec}, -{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa}, -{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7}, -{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f}, -{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd}, -{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce}, -{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff}, -{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096}, -{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c}, -{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026}, -{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012}, -{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f}, -{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027}, -{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023}, -{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027}, -{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084}, -{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051}, -{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091}, -{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e}, -{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce}, -{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff}, -{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e}, -{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd}, -{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c}, -{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce}, -{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff}, -{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e}, -{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096}, -{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c}, -{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026}, -{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024}, -{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026}, -{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018}, -{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019}, -{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001}, -{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009}, -{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020}, -{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081}, -{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015}, -{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044}, -{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1}, -{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f}, -{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044}, -{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029}, -{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025}, -{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f}, -{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047}, -{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a}, -{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047}, -{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034}, -{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011}, -{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084}, -{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002}, -{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e}, -{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096}, -{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc}, -{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097}, -{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1}, -{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086}, -{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012}, -{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7}, -{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010}, -{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd}, -{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031}, -{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e}, -{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6}, -{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f}, -{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7}, -{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f}, -{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec}, -{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa}, -{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008}, -{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5}, -{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002}, -{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6}, -{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4}, -{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084}, -{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001}, -{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046}, -{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081}, -{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003}, -{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f}, -{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd}, -{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025}, -{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085}, -{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044}, -{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026}, -{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012}, -{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001}, -{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010}, -{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd}, -{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce}, -{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff}, -{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e}, -{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096}, -{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003}, -{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026}, -{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012}, -{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003}, -{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027}, -{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085}, -{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044}, -{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026}, -{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012}, -{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001}, -{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010}, -{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce}, -{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff}, -{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e}, -{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6}, -{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a}, -{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010}, -{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085}, -{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8}, -{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000}, -{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084}, -{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001}, -{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085}, -{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046}, -{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081}, -{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009}, -{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030}, -{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081}, -{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f}, -{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044}, -{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b}, -{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029}, -{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026}, -{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011}, -{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022}, -{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6}, -{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba}, -{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084}, -{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d}, -{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085}, -{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005}, -{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e}, -{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca}, -{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022}, -{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000}, -{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018}, -{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000}, -{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046}, -{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085}, -{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002}, -{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085}, -{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001}, -{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f}, -{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004}, -{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004}, -{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7}, -{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086}, -{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012}, -{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007}, -{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006}, -{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d}, -{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070}, -{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba}, -{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7}, -{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001}, -{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001}, -{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6}, -{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084}, -{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002}, -{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004}, -{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001}, -{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001}, -{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4}, -{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7}, -{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6}, -{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084}, -{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008}, -{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6}, -{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081}, -{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008}, -{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7}, -{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e}, -{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086}, -{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040}, -{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e}, -{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7}, -{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f}, -{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082}, -{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f}, -{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f}, -{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f}, -{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f}, -{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f}, -{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f}, -{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f}, -{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f}, -{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f}, -{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f}, -{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f}, -{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f}, -{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f}, -{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012}, -{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010}, -{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004}, -{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7}, -{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7}, -{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7}, -{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7}, -{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086}, -{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012}, -{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012}, -{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7}, -{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004}, -{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004}, -{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001}, -{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001}, -{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008}, -{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081}, -{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b}, -{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce}, -{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd}, -{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e}, -{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081}, -{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b}, -{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce}, -{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd}, -{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e}, -{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081}, -{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b}, -{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce}, -{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd}, -{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e}, -{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081}, -{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b}, -{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce}, -{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd}, -{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e}, -{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081}, -{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b}, -{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce}, -{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd}, -{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e}, -{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081}, -{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b}, -{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce}, -{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd}, -{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e}, -{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081}, -{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b}, -{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce}, -{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd}, -{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e}, -{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081}, -{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008}, -{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce}, -{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd}, -{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6}, -{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081}, -{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003}, -{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047}, -{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009}, -{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081}, -{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006}, -{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009}, -{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe}, -{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006}, -{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081}, -{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008}, -{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7}, -{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e}, -{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6}, -{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026}, -{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f}, -{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7}, -{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e}, -{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6}, -{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084}, -{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f}, -{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b}, -{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012}, -{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012}, -{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc}, -{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009}, -{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe}, -{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070}, -{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f}, -{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c}, -{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f}, -{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084}, -{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f}, -{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c}, -{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f}, -{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1}, -{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003}, -{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040}, -{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f}, -{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027}, -{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b}, -{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081}, -{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b}, -{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027}, -{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087}, -{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f}, -{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002}, -{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a}, -{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7}, -{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086}, -{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f}, -{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012}, -{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075}, -{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7}, -{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020}, -{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f}, -{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002}, -{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071}, -{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047}, -{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097}, -{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089}, -{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f}, -{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089}, -{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f}, -{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089}, -{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f}, -{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089}, -{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f}, -{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089}, -{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7}, -{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7}, -{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6}, -{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027}, -{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f}, -{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f}, -{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f}, -{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d}, -{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078}, -{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c}, -{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6}, -{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027}, -{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f}, -{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f}, -{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f}, -{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b}, -{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d}, -{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075}, -{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c}, -{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a}, -{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027}, -{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f}, -{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f}, -{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c}, -{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083}, -{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075}, -{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078}, -{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b}, -{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc}, -{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d}, -{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000}, -{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070}, -{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072}, -{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e}, -{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6}, -{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026}, -{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce}, -{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd}, -{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e}, -{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6}, -{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026}, -{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce}, -{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd}, -{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e}, -{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6}, -{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026}, -{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce}, -{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd}, -{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e}, -{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086}, -{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040}, -{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x006e}, -{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075}, -{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e}, -{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012}, -{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8}, -{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012}, -{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f}, -{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007}, -{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048}, -{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6}, -{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4}, -{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7}, -{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6}, -{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081}, -{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf}, -{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005}, -{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b}, -{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005}, -{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6}, -{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd}, -{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086}, -{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f}, -{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089}, -{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002}, -{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077}, -{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094}, -{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6}, -{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd}, -{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce}, -{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6}, -{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001}, -{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081}, -{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003}, -{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066}, -{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8}, -{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084}, -{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b}, -{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079}, -{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008}, -{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e}, -{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6}, -{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a}, -{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012}, -{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012}, -{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb}, -{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7}, -{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6}, -{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036}, -{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c}, -{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7}, -{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086}, -{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012}, -{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012}, -{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001}, -{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001}, -{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe}, -{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004}, -{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004}, -{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba}, -{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7}, -{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086}, -{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012}, -{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012}, -{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7}, -{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6}, -{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084}, -{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008}, -{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c}, -{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026}, -{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076}, -{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e}, -{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e}, -{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6}, -{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081}, -{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c}, -{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7}, -{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d}, -{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb}, -{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004}, -{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7}, -{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce}, -{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6}, -{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081}, -{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005}, -{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6}, -{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6}, -{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084}, -{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012}, -{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083}, -{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c}, -{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000}, -{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006}, -{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b}, -{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083}, -{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041}, -{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e}, -{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7}, -{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086}, -{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f}, -{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012}, -{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f}, -{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c}, -{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7}, -{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086}, -{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a}, -{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012}, -{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009}, -{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c}, -{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d}, -{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c}, -{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e}, -{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027}, -{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020}, -{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e}, -{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c}, -{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba}, -{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7}, -{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6}, -{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048}, -{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d}, -{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021}, -{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004}, -{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7}, -{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd}, -{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f}, -{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000}, -{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000}, -{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008}, -{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5}, -{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c}, -{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba}, -{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7}, -{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6}, -{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084}, -{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001}, -{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006}, -{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7}, -{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036}, -{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7}, -{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032}, -{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026}, -{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f}, -{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089}, -{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001}, -{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1}, -{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c}, -{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027}, -{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f}, -{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005}, -{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080}, -{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080}, -{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7}, -{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6}, -{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005}, -{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f}, -{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f}, -{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4}, -{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b}, -{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007}, -{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f}, -{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000}, -{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000}, -{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000}, -{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6}, -{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6}, -{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7}, -{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001}, -{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018}, -{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018}, -{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7}, -{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6}, -{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007}, -{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4}, -{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054}, -{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7}, -{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a}, -{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039}, -{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084}, -{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022}, -{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7}, -{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6}, -{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7}, -{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6}, -{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4}, -{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f}, -{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072}, -{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072}, -{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071}, -{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027}, -{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001}, -{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081}, -{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024}, -{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070}, -{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096}, -{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080}, -{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064}, -{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070}, -{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096}, -{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010}, -{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064}, -{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070}, -{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096}, -{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020}, -{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064}, -{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070}, -{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096}, -{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040}, -{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074}, -{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074}, -{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078}, -{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6}, -{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085}, -{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af}, -{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4}, -{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6}, -{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081}, -{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036}, -{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026}, -{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022}, -{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044}, -{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022}, -{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020}, -{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081}, -{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d}, -{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084}, -{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044}, -{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022}, -{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020}, -{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081}, -{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f}, -{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084}, -{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044}, -{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6}, -{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f}, -{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022}, -{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c}, -{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006}, -{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed}, -{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007}, -{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9}, -{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006}, -{0x8aca, 0x0039}, { 0x0, 0x0 } -}; -#endif - - /* phy types */ #define CAS_PHY_UNKNOWN 0x00 #define CAS_PHY_SERDES 0x01 @@ -4389,6 +2872,11 @@ struct cas { dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS]; struct pci_dev *pdev; struct net_device *dev; + + /* Firmware Info */ + u16 fw_load_addr; + u32 fw_size; + u8 *fw_data; }; #define TX_DESC_NEXT(r, x) (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1)) diff --git a/firmware/Makefile b/firmware/Makefile index da75a6fbc6b..ca8cd305ff9 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -22,6 +22,7 @@ fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE)) fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw +fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin diff --git a/firmware/WHENCE b/firmware/WHENCE index 66c51b275e9..57002cdecd4 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -339,3 +339,13 @@ Licence: Allegedly GPLv2+, but no source visible. Marked: Found in hex form in kernel source. -------------------------------------------------------------------------- + +Driver: CASSINI - Sun Cassini + +File: sun/cassini.bin + +Licence: Unknown + +Found in hex form in kernel source. + +-------------------------------------------------------------------------- diff --git a/firmware/sun/cassini.bin.ihex b/firmware/sun/cassini.bin.ihex new file mode 100644 index 00000000000..5cd7ae70e71 --- /dev/null +++ b/firmware/sun/cassini.bin.ihex @@ -0,0 +1,143 @@ +:1000000000827E82090000000000008E8EFFCE82FA +:1000100025FF010FCE8426FF0111CE853DDFE58649 +:1000200039B78FF87EC3C2964784F38A009747CECC +:100030008233FF010F9646840C8104270B96468479 +:100040000C810827577E8425964784F38A049747B6 +:10005000CE8254FF010F9646840C81042638B612D6 +:1000600020842026037E8425967BD67CFE8F56BD79 +:10007000F7B6FE8F4EBDEC8EBDFAF7BDF728CE82E7 +:1000800082FF010F9646840C8104260AB612208452 +:100090002027B57E8425BDF71F7E841F964784F3F5 +:1000A0008A089747DEE1AD00CE82AFFF010F7E8464 +:1000B00025964185102606962385402706BDED002E +:1000C0007E83A2DE42BDEB8E9624840827037E83C6 +:1000D000DF967BD67CFE8F56BDF7B6FE8F50BDEC0B +:1000E0008EBDFAF78611C649BDE412CE82EFFF013C +:1000F0000F9646840C81002717C649BDE491240D54 +:10010000B612208520260CCE82C1FF010F7E8425E9 +:100110007E8416FE8F52BDEC8EBDFAF7866AC64904 +:10012000BDE412CE8327FF010F9646840C81002781 +:100130000AC649BDE49125067E84257E8416B6183C +:1001400070BB19702A0481AF2E19967BF62007FA2E +:100150002027C4388138270BF62007FA2027CB0840 +:100160007E82D3BDF7668674C649BDE412CE837124 +:10017000FF010F9646840C8108260AC649BDE4910A +:1001800025067E84257E8416BDF73E260EBDE50934 +:100190002606CE82C1FF010F7E8425FE8F54BDEC62 +:1001A0008EBDFAF7BDF733860FC651BDE412CE837C +:1001B000B2FF010F9646840C8108265CB61220849B +:1001C0003F813A271C9623854027037E8425C6510C +:1001D000BDE49125037E8425CE82C1FF010F7E847C +:1001E00025BDF8377C007ACE83EEFF010F7E842593 +:1001F0009646840C81082620962484082629B61861 +:1002000082BB1982B1013B2209B6122084378132A8 +:100210002715BDF8447E82C1BDF71FBDF844BDFC63 +:1002200029CE8225FF010F39964784FC8A00974723 +:10023000CE8434FF011196468403810227037E8514 +:100240001E964784FC8A029747DEE1AD008601B71F +:100250001251BDF714B6103184FDB71031BDF81E30 +:100260009681D682FE8F5ABDF7B6FE8F5CBDEC8EAE +:10027000BDFAF78608D600C51026028B20C651BDF0 +:10028000E412CE8486FF011196468403810227037F +:100290007E850FC651BDE49125037E851E9644855B +:1002A00010260AB61250BA013C851027A8BDF76681 +:1002B000CE84B7FF01117E851E96468403810226F7 +:1002C00050B612308403810127037E851E96448533 +:1002D000102613B61250BA013C85102609CE84535D +:1002E000FF01117E851EB610318A02B71031BD851F +:1002F0001FBDF8377C0080CE84FEFF01117E851E75 +:100300009646840381022609B612308403810127B0 +:100310000FBDF844BDF70BBDFC29CE8426FF0111AB +:1003200039D622C40FB61230BA12328404270D9681 +:100330002285042705CA107E853ACA20D72239862D +:1003400000978318CE1C00BDEB4696578501270207 +:100350004F3985022701397F8F7D8604B7120486C5 +:1003600008B712078610B7120C8607B71206B68FA9 +:100370007DB712708601BA1204B71204010101019F +:100380000101B6120484FE8A02B7120401010101C0 +:10039000010186FDB41204B71204B612008408816C +:1003A000082716B68F7D810C27088B04B78F7D7EBA +:1003B000856C860397407E896E8607B712065FF7C5 +:1003C0008F825FF78F7FF78F70F78F71F78F72F7DC +:1003D0008F73F78F74F78F75F78F76F78F77F78FA7 +:1003E00078F78F79F78F7AF78F7BB612048A10B778 +:1003F000120486E4B71270B71207F71205F7120954 +:100400008608BA1204B7120486F7B41204B71204AD +:10041000010101010101B61208277F8180260B86A8 +:1004200008CE8F79BD897B7E868E8140260B86041F +:10043000CE8F76BD897B7E868E8120260B8602CE6E +:100440008F73BD897B7E868E8110260B8601CE8FB1 +:1004500070BD897B7E868E8108260B8608CE8F79BB +:10046000BD897F7E868E8104260B8604CE8F76BD65 +:10047000897F7E868E8102260B8A02CE8F73BD898C +:100480007F7E868E810126088601CE8F70BD897F92 +:10049000B68F7F810F26037E8747B61209840381BA +:1004A0000327067C12097E85FEB6120684078107A3 +:1004B00027088B01B712067E86D5B68F82260A7C66 +:1004C0008F824FB712067E85C0B61206843F813FE9 +:1004D00027108B08B71206B6120984FCB712097EE2 +:1004E00085FECE8F7018CE8F84C60CBD896FCE8FDF +:1004F0008418CE8F70C60CBD896FD683C14F2D0373 +:100500007E8740B68F7F8107270F810B2715810DCE +:10051000271B810E27217E8740F78F7B8602B78FAE +:100520007A201CF78F788602B78F772012F78F75A5 +:100530008602B78F742008F78F728602B78F717E9C +:100540008747860497407E896ECE8F72BD89F7CE2D +:100550008F75BD89F7CE8F78BD89F7CE8F7BBD892A +:10056000F74FB78F7DB78F81B68F7227477C8F7D0E +:10057000B68F75273F7C8F7DB68F7827377C8F7D30 +:10058000B68F7B272F7F8F7D7C8F817A8F72271B81 +:100590007C8F7D7A8F7527167C8F7D7A8F782711D7 +:1005A0007C8F7D7A8F7B270C7E87837A8F757A8FFD +:1005B000787A8F7BCEC1FCF68F7D3AA600B7127099 +:1005C000B68F7226037E87FAB68F75260A18CE8FED +:1005D00073BD89D57E87FAB68F78260A18CE8F76B6 +:1005E000BD89D57E87FAB68F7B260A18CE8F79BD56 +:1005F00089D57E87FA860597407E8900B68F7581FA +:10060000072EF2F61206C4F81BB71206B68F7881D1 +:10061000072EE2484848F61206C4C71BB71206B6B2 +:100620008F7B81072ECFF61205C4F81BB712058603 +:1006300000F68F71BD89948601F68F74BD8994860A +:1006400002F68F77BD89948603F68F7ABD8994CEA2 +:100650008F70A60181012707810327037E8866A684 +:1006600000B88F818401260B8C8F792C0E08080826 +:100670007E8850B612048A40B71204B6120484FB76 +:1006800084EFB71204B6120736B68F7C4848B7120B +:10069000078601BA1204B7120401010101010186A3 +:1006A000FEB41204B712048602BA1204B71204860A +:1006B000FDB41204B7120432B71207B61200840850 +:1006C0008108270F7C82082607867697407E896EF0 +:1006D0007E86ECB68F7F810F273CBDE6C7B7120D33 +:1006E000BDE6CBB612048A20B71204CEFFFFB612C5 +:1006F00000810C26050926F6271CB6120484DFB7F4 +:100700001204968381072C057C0083200696838B38 +:100710000897837E85417F8F7E8680B7120C860185 +:10072000B78F7DB6120C847FB7120C8A80B7120C7B +:10073000860ABD8A06B6120A2A09B6120CBA8F7D3D +:10074000B7120CB68F7E8160271A8B20B78F7EB6CA +:10075000120C849FBA8F7EB7120CB68F7D48B78F6C +:100760007D7E8921B612048A20B71204BD8A0A4F01 +:1007700039A60018A7000818085A26F539366C0063 +:1007800032BA8F7FB78F7FB612098403A701B612E2 +:1007900006843FA70239368603B78F8032C1002610 +:1007A00006B78F7C7E89C9C1012718C102270CC1F9 +:1007B000032700F68F800505F78F80F68F800505EB +:1007C000F78F80F68F800505F78F80F68F8053F4C2 +:1007D00012071BB7120739CE8F70A60018E6001853 +:1007E000A700E700A60118E60118A701E701A60285 +:1007F00018E60218A702E70239A6008407E600C43B +:10080000385454541BA700394A26FD399622840FC8 +:1008100097228601B78F70B61207B78F71F6120C48 +:10082000C40FC80FF78F72F68F72B68F71840327CB +:10083000148101271C81022724F48F70272A962215 +:100840008A807E8A64F48F70271E96228A107E8AA0 +:1008500064F48F70271296228A207E8A64F48F7047 +:10086000270696228A409722748F71748F71788F31 +:1008700070B68F70851027AFD622C41058B612708C +:1008800081E4273681E1260C96228420441BD6225F +:10089000C4CF20235881C6260D9622844044441B91 +:1008A000D622C4AF2011588127260F962284804477 +:1008B00044441BD622C46F1B972239270C7C820626 +:0D08C000BDD9EDB682077E8AB97F82063968 +:00000001FF +/* firmware patch for NS_DP83065 */ -- cgit v1.2.3 From 5c1824587f0797373c95719a196f6098f7c6d20c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 22 Sep 2008 19:48:19 -0700 Subject: ipsec: Fix xfrm_state_walk race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As discovered by Timo Teräs, the currently xfrm_state_walk scheme is racy because if a second dump finishes before the first, we may free xfrm states that the first dump would walk over later. This patch fixes this by storing the dumps in a list in order to calculate the correct completion counter which cures this problem. I've expanded netlink_cb in order to accomodate the extra state related to this. It shouldn't be a big deal since netlink_cb is kmalloced for each dump and we're just increasing it by 4 or 8 bytes. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netlink.h | 2 +- include/net/xfrm.h | 10 +++------- net/xfrm/xfrm_state.c | 39 ++++++++++++++++++++++++++++++--------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 9ff1b54908f..cbba7760545 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -220,7 +220,7 @@ struct netlink_callback int (*dump)(struct sk_buff * skb, struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); int family; - long args[6]; + long args[7]; }; struct netlink_notify diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 4bb94992b5f..48630b26659 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1246,6 +1246,8 @@ struct xfrm6_tunnel { }; struct xfrm_state_walk { + struct list_head list; + unsigned long genid; struct xfrm_state *state; int count; u8 proto; @@ -1281,13 +1283,7 @@ static inline void xfrm6_fini(void) extern int xfrm_proc_init(void); #endif -static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) -{ - walk->proto = proto; - walk->state = NULL; - walk->count = 0; -} - +extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); extern int xfrm_state_walk(struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *); extern void xfrm_state_walk_done(struct xfrm_state_walk *walk); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index abbe2702c40..053970e8765 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -64,6 +64,9 @@ static unsigned long xfrm_state_walk_ongoing; /* Counter indicating walk completion, protected by xfrm_cfg_mutex. */ static unsigned long xfrm_state_walk_completed; +/* List of outstanding state walks used to set the completed counter. */ +static LIST_HEAD(xfrm_state_walks); + static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); @@ -1584,7 +1587,6 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, if (err) { xfrm_state_hold(last); walk->state = last; - xfrm_state_walk_ongoing++; goto out; } } @@ -1599,25 +1601,44 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, err = func(last, 0, data); out: spin_unlock_bh(&xfrm_state_lock); - if (old != NULL) { + if (old != NULL) xfrm_state_put(old); - xfrm_state_walk_completed++; - if (!list_empty(&xfrm_state_gc_leftovers)) - schedule_work(&xfrm_state_gc_work); - } return err; } EXPORT_SYMBOL(xfrm_state_walk); +void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) +{ + walk->proto = proto; + walk->state = NULL; + walk->count = 0; + list_add_tail(&walk->list, &xfrm_state_walks); + walk->genid = ++xfrm_state_walk_ongoing; +} +EXPORT_SYMBOL(xfrm_state_walk_init); + void xfrm_state_walk_done(struct xfrm_state_walk *walk) { + struct list_head *prev; + if (walk->state != NULL) { xfrm_state_put(walk->state); walk->state = NULL; - xfrm_state_walk_completed++; - if (!list_empty(&xfrm_state_gc_leftovers)) - schedule_work(&xfrm_state_gc_work); } + + prev = walk->list.prev; + list_del(&walk->list); + + if (prev != &xfrm_state_walks) { + list_entry(prev, struct xfrm_state_walk, list)->genid = + walk->genid; + return; + } + + xfrm_state_walk_completed = walk->genid; + + if (!list_empty(&xfrm_state_gc_leftovers)) + schedule_work(&xfrm_state_gc_work); } EXPORT_SYMBOL(xfrm_state_walk_done); -- cgit v1.2.3 From bce7b15426cac3000bf6a9cf59d9356ef0be2dec Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 19:51:15 -0700 Subject: Phonet: global definitions Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/if_ether.h | 1 + include/linux/if_phonet.h | 14 ++++++ include/linux/phonet.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rtnetlink.h | 4 ++ include/linux/socket.h | 4 +- net/core/sock.c | 9 ++-- 6 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 include/linux/if_phonet.h create mode 100644 include/linux/phonet.h diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 5028e0b6082..723a1c5fbc6 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -100,6 +100,7 @@ #define ETH_P_ECONET 0x0018 /* Acorn Econet */ #define ETH_P_HDLC 0x0019 /* HDLC frames */ #define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ +#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ /* * This is an Ethernet frame header. diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h new file mode 100644 index 00000000000..22df25fbc4e --- /dev/null +++ b/include/linux/if_phonet.h @@ -0,0 +1,14 @@ +/* + * File: if_phonet.h + * + * Phonet interface kernel definitions + * + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + */ + +#define PHONET_HEADER_LEN 8 /* Phonet header length */ + +#define PHONET_MIN_MTU 6 +/* 6 bytes header + 65535 bytes payload */ +#define PHONET_MAX_MTU 65541 +#define PHONET_DEV_MTU PHONET_MAX_MTU diff --git a/include/linux/phonet.h b/include/linux/phonet.h new file mode 100644 index 00000000000..6a764f8584a --- /dev/null +++ b/include/linux/phonet.h @@ -0,0 +1,125 @@ +/** + * file phonet.h + * + * Phonet sockets kernel interface + * + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef LINUX_PHONET_H +#define LINUX_PHONET_H + +/* Automatic protocol selection */ +#define PN_PROTO_TRANSPORT 0 +/* Phonet datagram socket */ +#define PN_PROTO_PHONET 1 +#define PHONET_NPROTO 2 + +#define PNADDR_ANY 0 +#define PNPORT_RESOURCE_ROUTING 0 + +/* Phonet protocol header */ +struct phonethdr { + __u8 pn_rdev; + __u8 pn_sdev; + __u8 pn_res; + __be16 pn_length; + __u8 pn_robj; + __u8 pn_sobj; +} __attribute__((packed)); + +/* Phonet socket address structure */ +struct sockaddr_pn { + sa_family_t spn_family; + __u8 spn_obj; + __u8 spn_dev; + __u8 spn_resource; + __u8 spn_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - 3]; +} __attribute__ ((packed)); + +static inline __u16 pn_object(__u8 addr, __u16 port) +{ + return (addr << 8) | (port & 0x3ff); +} + +static inline __u8 pn_obj(__u16 handle) +{ + return handle & 0xff; +} + +static inline __u8 pn_dev(__u16 handle) +{ + return handle >> 8; +} + +static inline __u16 pn_port(__u16 handle) +{ + return handle & 0x3ff; +} + +static inline __u8 pn_addr(__u16 handle) +{ + return (handle >> 8) & 0xfc; +} + +static inline void pn_sockaddr_set_addr(struct sockaddr_pn *spn, __u8 addr) +{ + spn->spn_dev &= 0x03; + spn->spn_dev |= addr & 0xfc; +} + +static inline void pn_sockaddr_set_port(struct sockaddr_pn *spn, __u16 port) +{ + spn->spn_dev &= 0xfc; + spn->spn_dev |= (port >> 8) & 0x03; + spn->spn_obj = port & 0xff; +} + +static inline void pn_sockaddr_set_object(struct sockaddr_pn *spn, + __u16 handle) +{ + spn->spn_dev = pn_dev(handle); + spn->spn_obj = pn_obj(handle); +} + +static inline void pn_sockaddr_set_resource(struct sockaddr_pn *spn, + __u8 resource) +{ + spn->spn_resource = resource; +} + +static inline __u8 pn_sockaddr_get_addr(const struct sockaddr_pn *spn) +{ + return spn->spn_dev & 0xfc; +} + +static inline __u16 pn_sockaddr_get_port(const struct sockaddr_pn *spn) +{ + return ((spn->spn_dev & 0x03) << 8) | spn->spn_obj; +} + +static inline __u16 pn_sockaddr_get_object(const struct sockaddr_pn *spn) +{ + return pn_object(spn->spn_dev, spn->spn_obj); +} + +static inline __u8 pn_sockaddr_get_resource(const struct sockaddr_pn *spn) +{ + return spn->spn_resource; +} + +#endif diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index ca643b13b02..2b3d51c6ec9 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -582,6 +582,10 @@ enum rtnetlink_groups { #define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE RTNLGRP_ND_USEROPT, #define RTNLGRP_ND_USEROPT RTNLGRP_ND_USEROPT + RTNLGRP_PHONET_IFADDR, +#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR + RTNLGRP_PHONET_ROUTE, +#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) diff --git a/include/linux/socket.h b/include/linux/socket.h index dc5086fe773..818ca33bf79 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -190,7 +190,8 @@ struct ucred { #define AF_IUCV 32 /* IUCV sockets */ #define AF_RXRPC 33 /* RxRPC sockets */ #define AF_ISDN 34 /* mISDN sockets */ -#define AF_MAX 35 /* For now.. */ +#define AF_PHONET 35 /* Phonet sockets */ +#define AF_MAX 36 /* For now.. */ /* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC @@ -227,6 +228,7 @@ struct ucred { #define PF_IUCV AF_IUCV #define PF_RXRPC AF_RXRPC #define PF_ISDN AF_ISDN +#define PF_PHONET AF_PHONET #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ diff --git a/net/core/sock.c b/net/core/sock.c index 23b8b9da36b..2d358dd8a03 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -154,7 +154,8 @@ static const char *af_family_key_strings[AF_MAX+1] = { "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , - "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_MAX" + "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , + "sk_lock-AF_MAX" }; static const char *af_family_slock_key_strings[AF_MAX+1] = { "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , @@ -168,7 +169,8 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = { "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , "slock-27" , "slock-28" , "slock-AF_CAN" , "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , - "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_MAX" + "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , + "slock-AF_MAX" }; static const char *af_family_clock_key_strings[AF_MAX+1] = { "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , @@ -182,7 +184,8 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = { "clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" , "clock-27" , "clock-28" , "clock-AF_CAN" , "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , - "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_MAX" + "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , + "clock-AF_MAX" }; #endif -- cgit v1.2.3 From 4b07b3f69a8471cdc142c51461a331226fef248a Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:02:10 -0700 Subject: Phonet: PF_PHONET protocol family support This is the basis for the Phonet protocol families, and introduces the ETH_P_PHONET packet type and the PF_PHONET socket family. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/phonet.h | 74 +++++++++++++++ net/phonet/af_phonet.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 include/net/phonet/phonet.h create mode 100644 net/phonet/af_phonet.c diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h new file mode 100644 index 00000000000..c53f2abc059 --- /dev/null +++ b/include/net/phonet/phonet.h @@ -0,0 +1,74 @@ +/* + * File: af_phonet.h + * + * Phonet sockets kernel definitions + * + * Copyright (C) 2008 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef AF_PHONET_H +#define AF_PHONET_H + +/* + * The lower layers may not require more space, ever. Make sure it's + * enough. + */ +#define MAX_PHONET_HEADER 8 + +static inline struct phonethdr *pn_hdr(struct sk_buff *skb) +{ + return (struct phonethdr *)skb_network_header(skb); +} + +/* + * Get the other party's sockaddr from received skb. The skb begins + * with a Phonet header. + */ +static inline +void pn_skb_get_src_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa) +{ + struct phonethdr *ph = pn_hdr(skb); + u16 obj = pn_object(ph->pn_sdev, ph->pn_sobj); + + sa->spn_family = AF_PHONET; + pn_sockaddr_set_object(sa, obj); + pn_sockaddr_set_resource(sa, ph->pn_res); + memset(sa->spn_zero, 0, sizeof(sa->spn_zero)); +} + +static inline +void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa) +{ + struct phonethdr *ph = pn_hdr(skb); + u16 obj = pn_object(ph->pn_rdev, ph->pn_robj); + + sa->spn_family = AF_PHONET; + pn_sockaddr_set_object(sa, obj); + pn_sockaddr_set_resource(sa, ph->pn_res); + memset(sa->spn_zero, 0, sizeof(sa->spn_zero)); +} + +/* Protocols in Phonet protocol family. */ +struct phonet_protocol { + struct proto *prot; + int sock_type; +}; + +int phonet_proto_register(int protocol, struct phonet_protocol *pp); +void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); + +#endif diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c new file mode 100644 index 00000000000..0cfea9bc994 --- /dev/null +++ b/net/phonet/af_phonet.c @@ -0,0 +1,216 @@ +/* + * File: af_phonet.c + * + * Phonet protocols family + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * Original author: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +static struct net_proto_family phonet_proto_family; +static struct phonet_protocol *phonet_proto_get(int protocol); +static inline void phonet_proto_put(struct phonet_protocol *pp); + +/* protocol family functions */ + +static int pn_socket_create(struct net *net, struct socket *sock, int protocol) +{ + struct phonet_protocol *pnp; + int err; + + if (net != &init_net) + return -EAFNOSUPPORT; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (protocol == 0) { + /* Default protocol selection */ + switch (sock->type) { + case SOCK_DGRAM: + protocol = PN_PROTO_PHONET; + break; + default: + return -EPROTONOSUPPORT; + } + } + + pnp = phonet_proto_get(protocol); + if (pnp == NULL) + return -EPROTONOSUPPORT; + if (sock->type != pnp->sock_type) { + err = -EPROTONOSUPPORT; + goto out; + } + + /* TODO: create and init the struct sock */ + err = -EPROTONOSUPPORT; + +out: + phonet_proto_put(pnp); + return err; +} + +static struct net_proto_family phonet_proto_family = { + .family = AF_PHONET, + .create = pn_socket_create, + .owner = THIS_MODULE, +}; + +/* packet type functions */ + +/* + * Stuff received packets to associated sockets. + * On error, returns non-zero and releases the skb. + */ +static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pkttype, + struct net_device *orig_dev) +{ + struct phonethdr *ph; + struct sockaddr_pn sa; + u16 len; + + if (dev_net(dev) != &init_net) + goto out; + + /* check we have at least a full Phonet header */ + if (!pskb_pull(skb, sizeof(struct phonethdr))) + goto out; + + /* check that the advertised length is correct */ + ph = pn_hdr(skb); + len = get_unaligned_be16(&ph->pn_length); + if (len < 2) + goto out; + len -= 2; + if ((len > skb->len) || pskb_trim(skb, len)) + goto out; + skb_reset_transport_header(skb); + + pn_skb_get_dst_sockaddr(skb, &sa); + if (pn_sockaddr_get_addr(&sa) == 0) + goto out; /* currently, we cannot be device 0 */ + + /* TODO: put packets to sockets backlog */ + +out: + kfree_skb(skb); + return NET_RX_DROP; +} + +static struct packet_type phonet_packet_type = { + .type = __constant_htons(ETH_P_PHONET), + .dev = NULL, + .func = phonet_rcv, +}; + +/* Transport protocol registration */ +static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; +static DEFINE_SPINLOCK(proto_tab_lock); + +int __init_or_module phonet_proto_register(int protocol, + struct phonet_protocol *pp) +{ + int err = 0; + + if (protocol >= PHONET_NPROTO) + return -EINVAL; + + err = proto_register(pp->prot, 1); + if (err) + return err; + + spin_lock(&proto_tab_lock); + if (proto_tab[protocol]) + err = -EBUSY; + else + proto_tab[protocol] = pp; + spin_unlock(&proto_tab_lock); + + return err; +} +EXPORT_SYMBOL(phonet_proto_register); + +void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) +{ + spin_lock(&proto_tab_lock); + BUG_ON(proto_tab[protocol] != pp); + proto_tab[protocol] = NULL; + spin_unlock(&proto_tab_lock); + proto_unregister(pp->prot); +} +EXPORT_SYMBOL(phonet_proto_unregister); + +static struct phonet_protocol *phonet_proto_get(int protocol) +{ + struct phonet_protocol *pp; + + if (protocol >= PHONET_NPROTO) + return NULL; + + spin_lock(&proto_tab_lock); + pp = proto_tab[protocol]; + if (pp && !try_module_get(pp->prot->owner)) + pp = NULL; + spin_unlock(&proto_tab_lock); + + return pp; +} + +static inline void phonet_proto_put(struct phonet_protocol *pp) +{ + module_put(pp->prot->owner); +} + +/* Module registration */ +static int __init phonet_init(void) +{ + int err; + + err = sock_register(&phonet_proto_family); + if (err) { + printk(KERN_ALERT + "phonet protocol family initialization failed\n"); + return err; + } + + dev_add_pack(&phonet_packet_type); + return 0; +} + +static void __exit phonet_exit(void) +{ + sock_unregister(AF_PHONET); + dev_remove_pack(&phonet_packet_type); +} + +module_init(phonet_init); +module_exit(phonet_exit); +MODULE_DESCRIPTION("Phonet protocol stack for Linux"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8ead536dec142f27d5b5f72c3994eb39f4741717 Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:03:00 -0700 Subject: Phonet: add CONFIG_PHONET Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- net/Kconfig | 1 + net/Makefile | 1 + net/phonet/Kconfig | 16 ++++++++++++++++ net/phonet/Makefile | 4 ++++ 4 files changed, 22 insertions(+) create mode 100644 net/phonet/Kconfig create mode 100644 net/phonet/Makefile diff --git a/net/Kconfig b/net/Kconfig index d87de48ba65..9103a16a77b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -232,6 +232,7 @@ source "net/can/Kconfig" source "net/irda/Kconfig" source "net/bluetooth/Kconfig" source "net/rxrpc/Kconfig" +source "net/phonet/Kconfig" config FIB_RULES bool diff --git a/net/Makefile b/net/Makefile index 4f43e7f874f..acaf819f24a 100644 --- a/net/Makefile +++ b/net/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_AF_RXRPC) += rxrpc/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_DECNET) += decnet/ obj-$(CONFIG_ECONET) += econet/ +obj-$(CONFIG_PHONET) += phonet/ ifneq ($(CONFIG_VLAN_8021Q),) obj-y += 8021q/ endif diff --git a/net/phonet/Kconfig b/net/phonet/Kconfig new file mode 100644 index 00000000000..51a5669573f --- /dev/null +++ b/net/phonet/Kconfig @@ -0,0 +1,16 @@ +# +# Phonet protocol +# + +config PHONET + tristate "Phonet protocols family" + help + The Phone Network protocol (PhoNet) is a packet-oriented + communication protocol developped by Nokia for use with its modems. + + This is required for Maemo to use cellular data connectivity (if + supported). It can also be used to control Nokia phones + from a Linux computer, although AT commands may be easier to use. + + To compile this driver as a module, choose M here: the module + will be called phonet. If unsure, say N. diff --git a/net/phonet/Makefile b/net/phonet/Makefile new file mode 100644 index 00000000000..5dbff68a6f3 --- /dev/null +++ b/net/phonet/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_PHONET) += phonet.o + +phonet-objs := \ + af_phonet.o -- cgit v1.2.3 From f8ff60283de2b6775d7a14619056a08e3083bd40 Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:03:44 -0700 Subject: Phonet: network device and address handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This provides support for adding Phonet addresses to and removing Phonet addresses from network devices. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pn_dev.h | 50 +++++++++++ net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 3 + net/phonet/pn_dev.c | 208 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 include/net/phonet/pn_dev.h create mode 100644 net/phonet/pn_dev.c diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h new file mode 100644 index 00000000000..bbd2a836e04 --- /dev/null +++ b/include/net/phonet/pn_dev.h @@ -0,0 +1,50 @@ +/* + * File: pn_dev.h + * + * Phonet network device + * + * Copyright (C) 2008 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef PN_DEV_H +#define PN_DEV_H + +struct phonet_device_list { + struct list_head list; + spinlock_t lock; +}; + +extern struct phonet_device_list pndevs; + +struct phonet_device { + struct list_head list; + struct net_device *netdev; + DECLARE_BITMAP(addrs, 64); +}; + +void phonet_device_init(void); +void phonet_device_exit(void); +struct net_device *phonet_device_get(struct net *net); + +int phonet_address_add(struct net_device *dev, u8 addr); +int phonet_address_del(struct net_device *dev, u8 addr); +u8 phonet_address_get(struct net_device *dev, u8 addr); +int phonet_address_lookup(u8 addr); + +#define PN_NO_ADDR 0xff + +#endif diff --git a/net/phonet/Makefile b/net/phonet/Makefile index 5dbff68a6f3..980a3866c9a 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PHONET) += phonet.o phonet-objs := \ + pn_dev.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 0cfea9bc994..a8ba6f177b2 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -31,6 +31,7 @@ #include #include #include +#include static struct net_proto_family phonet_proto_family; static struct phonet_protocol *phonet_proto_get(int protocol); @@ -200,6 +201,7 @@ static int __init phonet_init(void) return err; } + phonet_device_init(); dev_add_pack(&phonet_packet_type); return 0; } @@ -208,6 +210,7 @@ static void __exit phonet_exit(void) { sock_unregister(AF_PHONET); dev_remove_pack(&phonet_packet_type); + phonet_device_exit(); } module_init(phonet_init); diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c new file mode 100644 index 00000000000..53be9fc82aa --- /dev/null +++ b/net/phonet/pn_dev.c @@ -0,0 +1,208 @@ +/* + * File: pn_dev.c + * + * Phonet network device + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * Original author: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +/* when accessing, remember to lock with spin_lock(&pndevs.lock); */ +struct phonet_device_list pndevs = { + .list = LIST_HEAD_INIT(pndevs.list), + .lock = __SPIN_LOCK_UNLOCKED(pndevs.lock), +}; + +/* Allocate new Phonet device. */ +static struct phonet_device *__phonet_device_alloc(struct net_device *dev) +{ + struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); + if (pnd == NULL) + return NULL; + pnd->netdev = dev; + bitmap_zero(pnd->addrs, 64); + + list_add(&pnd->list, &pndevs.list); + return pnd; +} + +static struct phonet_device *__phonet_get(struct net_device *dev) +{ + struct phonet_device *pnd; + + list_for_each_entry(pnd, &pndevs.list, list) { + if (pnd->netdev == dev) + return pnd; + } + return NULL; +} + +static void __phonet_device_free(struct phonet_device *pnd) +{ + list_del(&pnd->list); + kfree(pnd); +} + +struct net_device *phonet_device_get(struct net *net) +{ + struct phonet_device *pnd; + struct net_device *dev; + + spin_lock_bh(&pndevs.lock); + list_for_each_entry(pnd, &pndevs.list, list) { + dev = pnd->netdev; + BUG_ON(!dev); + + if (dev_net(dev) == net && + (dev->reg_state == NETREG_REGISTERED) && + ((pnd->netdev->flags & IFF_UP)) == IFF_UP) + break; + dev = NULL; + } + if (dev) + dev_hold(dev); + spin_unlock_bh(&pndevs.lock); + return dev; +} + +int phonet_address_add(struct net_device *dev, u8 addr) +{ + struct phonet_device *pnd; + int err = 0; + + spin_lock_bh(&pndevs.lock); + /* Find or create Phonet-specific device data */ + pnd = __phonet_get(dev); + if (pnd == NULL) + pnd = __phonet_device_alloc(dev); + if (unlikely(pnd == NULL)) + err = -ENOMEM; + else if (test_and_set_bit(addr >> 2, pnd->addrs)) + err = -EEXIST; + spin_unlock_bh(&pndevs.lock); + return err; +} + +int phonet_address_del(struct net_device *dev, u8 addr) +{ + struct phonet_device *pnd; + int err = 0; + + spin_lock_bh(&pndevs.lock); + pnd = __phonet_get(dev); + if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) + err = -EADDRNOTAVAIL; + if (bitmap_empty(pnd->addrs, 64)) + __phonet_device_free(pnd); + spin_unlock_bh(&pndevs.lock); + return err; +} + +/* Gets a source address toward a destination, through a interface. */ +u8 phonet_address_get(struct net_device *dev, u8 addr) +{ + struct phonet_device *pnd; + + spin_lock_bh(&pndevs.lock); + pnd = __phonet_get(dev); + if (pnd) { + BUG_ON(bitmap_empty(pnd->addrs, 64)); + + /* Use same source address as destination, if possible */ + if (!test_bit(addr >> 2, pnd->addrs)) + addr = find_first_bit(pnd->addrs, 64) << 2; + } else + addr = PN_NO_ADDR; + spin_unlock_bh(&pndevs.lock); + return addr; +} + +int phonet_address_lookup(u8 addr) +{ + struct phonet_device *pnd; + + spin_lock_bh(&pndevs.lock); + list_for_each_entry(pnd, &pndevs.list, list) { + /* Don't allow unregistering devices! */ + if ((pnd->netdev->reg_state != NETREG_REGISTERED) || + ((pnd->netdev->flags & IFF_UP)) != IFF_UP) + continue; + + if (test_bit(addr >> 2, pnd->addrs)) { + spin_unlock_bh(&pndevs.lock); + return 0; + } + } + spin_unlock_bh(&pndevs.lock); + return -EADDRNOTAVAIL; +} + +/* notify Phonet of device events */ +static int phonet_device_notify(struct notifier_block *me, unsigned long what, + void *arg) +{ + struct net_device *dev = arg; + + if (what == NETDEV_UNREGISTER) { + struct phonet_device *pnd; + + /* Destroy phonet-specific device data */ + spin_lock_bh(&pndevs.lock); + pnd = __phonet_get(dev); + if (pnd) + __phonet_device_free(pnd); + spin_unlock_bh(&pndevs.lock); + } + return 0; + +} + +static struct notifier_block phonet_device_notifier = { + .notifier_call = phonet_device_notify, + .priority = 0, +}; + +/* Initialize Phonet devices list */ +void phonet_device_init(void) +{ + register_netdevice_notifier(&phonet_device_notifier); +} + +void phonet_device_exit(void) +{ + struct phonet_device *pnd, *n; + + rtnl_unregister_all(PF_PHONET); + rtnl_lock(); + spin_lock_bh(&pndevs.lock); + + list_for_each_entry_safe(pnd, n, &pndevs.list, list) + __phonet_device_free(pnd); + + spin_unlock_bh(&pndevs.lock); + rtnl_unlock(); + unregister_netdevice_notifier(&phonet_device_notifier); +} -- cgit v1.2.3 From 8fb397406f6470f79040c41eec49af20900a9e3b Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:04:30 -0700 Subject: Phonet: Netlink interface This provides support for configuring Phonet addresses, notifying Phonet configuration changes, and dumping the configuration. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/phonet.h | 1 + net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 1 + net/phonet/pn_netlink.c | 186 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 net/phonet/pn_netlink.c diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index c53f2abc059..8b777943d20 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -71,4 +71,5 @@ struct phonet_protocol { int phonet_proto_register(int protocol, struct phonet_protocol *pp); void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); +void phonet_netlink_register(void); #endif diff --git a/net/phonet/Makefile b/net/phonet/Makefile index 980a3866c9a..4143c3e1dfd 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_PHONET) += phonet.o phonet-objs := \ pn_dev.o \ + pn_netlink.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index a8ba6f177b2..5c729ba5693 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -203,6 +203,7 @@ static int __init phonet_init(void) phonet_device_init(); dev_add_pack(&phonet_packet_type); + phonet_netlink_register(); return 0; } diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c new file mode 100644 index 00000000000..b1ea19a230d --- /dev/null +++ b/net/phonet/pn_netlink.c @@ -0,0 +1,186 @@ +/* + * File: pn_netlink.c + * + * Phonet netlink interface + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * Original author: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, + u32 pid, u32 seq, int event); + +static void rtmsg_notify(int event, struct net_device *dev, u8 addr) +{ + struct sk_buff *skb; + int err = -ENOBUFS; + + skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + + nla_total_size(1), GFP_KERNEL); + if (skb == NULL) + goto errout; + err = fill_addr(skb, dev, addr, 0, 0, event); + if (err < 0) { + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); + goto errout; + } + err = rtnl_notify(skb, dev_net(dev), 0, + RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); +errout: + if (err < 0) + rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); +} + +static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) +{ + struct rtattr **rta = attr; + struct ifaddrmsg *ifm = NLMSG_DATA(nlm); + struct net_device *dev; + int err; + u8 pnaddr; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + ASSERT_RTNL(); + + if (rta[IFA_LOCAL - 1] == NULL) + return -EINVAL; + + dev = __dev_get_by_index(&init_net, ifm->ifa_index); + if (dev == NULL) + return -ENODEV; + + if (ifm->ifa_prefixlen > 0) + return -EINVAL; + + memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); + + err = phonet_address_add(dev, pnaddr); + if (!err) + rtmsg_notify(RTM_NEWADDR, dev, pnaddr); + return err; +} + +static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) +{ + struct rtattr **rta = attr; + struct ifaddrmsg *ifm = NLMSG_DATA(nlm); + struct net_device *dev; + int err; + u8 pnaddr; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + ASSERT_RTNL(); + + if (rta[IFA_LOCAL - 1] == NULL) + return -EINVAL; + + dev = __dev_get_by_index(&init_net, ifm->ifa_index); + if (dev == NULL) + return -ENODEV; + + if (ifm->ifa_prefixlen > 0) + return -EADDRNOTAVAIL; + + memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); + + err = phonet_address_del(dev, pnaddr); + if (!err) + rtmsg_notify(RTM_DELADDR, dev, pnaddr); + return err; +} + +static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, + u32 pid, u32 seq, int event) +{ + struct ifaddrmsg *ifm; + struct nlmsghdr *nlh; + unsigned int orig_len = skb->len; + + nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg)); + ifm = NLMSG_DATA(nlh); + ifm->ifa_family = AF_PHONET; + ifm->ifa_prefixlen = 0; + ifm->ifa_flags = IFA_F_PERMANENT; + ifm->ifa_scope = RT_SCOPE_HOST; + ifm->ifa_index = dev->ifindex; + RTA_PUT(skb, IFA_LOCAL, 1, &addr); + nlh->nlmsg_len = skb->len - orig_len; + + return 0; + +nlmsg_failure: +rtattr_failure: + skb_trim(skb, orig_len); + + return -1; +} + +static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct phonet_device *pnd; + int dev_idx = 0, dev_start_idx = cb->args[0]; + int addr_idx = 0, addr_start_idx = cb->args[1]; + + spin_lock_bh(&pndevs.lock); + list_for_each_entry(pnd, &pndevs.list, list) { + u8 addr; + + if (dev_idx > dev_start_idx) + addr_start_idx = 0; + if (dev_idx++ < dev_start_idx) + continue; + + addr_idx = 0; + for (addr = find_first_bit(pnd->addrs, 64); addr < 64; + addr = find_next_bit(pnd->addrs, 64, 1+addr)) { + if (addr_idx++ < addr_start_idx) + continue; + + if (fill_addr(skb, pnd->netdev, addr << 2, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, RTM_NEWADDR)) + goto out; + } + } + +out: + spin_unlock_bh(&pndevs.lock); + cb->args[0] = dev_idx; + cb->args[1] = addr_idx; + + return skb->len; +} + +void __init phonet_netlink_register(void) +{ + rtnl_register(PF_PHONET, RTM_NEWADDR, newaddr_doit, NULL); + rtnl_register(PF_PHONET, RTM_DELADDR, deladdr_doit, NULL); + rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); +} -- cgit v1.2.3 From ba113a94b7503ee23ffe819e7045134b0c1d31de Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:05:19 -0700 Subject: Phonet: common socket glue This provides the socket API for the Phonet protocols family. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/phonet.h | 3 + include/net/phonet/phonet.h | 23 ++++ net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 28 +++- net/phonet/socket.c | 311 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 net/phonet/socket.c diff --git a/include/linux/phonet.h b/include/linux/phonet.h index 6a764f8584a..001c0e67909 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h @@ -32,6 +32,9 @@ #define PNADDR_ANY 0 #define PNPORT_RESOURCE_ROUTING 0 +/* ioctls */ +#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0) + /* Phonet protocol header */ struct phonethdr { __u8 pn_rdev; diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index 8b777943d20..2ae5cbb59b6 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -29,6 +29,28 @@ */ #define MAX_PHONET_HEADER 8 +/* + * Every Phonet* socket has this structure first in its + * protocol-specific structure under name c. + */ +struct pn_sock { + struct sock sk; + u16 sobject; + u8 resource; +}; + +static inline struct pn_sock *pn_sk(struct sock *sk) +{ + return (struct pn_sock *)sk; +} + +extern const struct proto_ops phonet_dgram_ops; + +struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa); +void pn_sock_hash(struct sock *sk); +void pn_sock_unhash(struct sock *sk); +int pn_sock_get_port(struct sock *sk, unsigned short sport); + static inline struct phonethdr *pn_hdr(struct sk_buff *skb) { return (struct phonethdr *)skb_network_header(skb); @@ -64,6 +86,7 @@ void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa) /* Protocols in Phonet protocol family. */ struct phonet_protocol { + const struct proto_ops *ops; struct proto *prot; int sock_type; }; diff --git a/net/phonet/Makefile b/net/phonet/Makefile index 4143c3e1dfd..c1d671de783 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_PHONET) += phonet.o phonet-objs := \ pn_dev.o \ pn_netlink.o \ + socket.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 5c729ba5693..ba54d53020f 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -41,6 +41,8 @@ static inline void phonet_proto_put(struct phonet_protocol *pp); static int pn_socket_create(struct net *net, struct socket *sock, int protocol) { + struct sock *sk; + struct pn_sock *pn; struct phonet_protocol *pnp; int err; @@ -69,8 +71,22 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol) goto out; } - /* TODO: create and init the struct sock */ - err = -EPROTONOSUPPORT; + sk = sk_alloc(net, PF_PHONET, GFP_KERNEL, pnp->prot); + if (sk == NULL) { + err = -ENOMEM; + goto out; + } + + sock_init_data(sock, sk); + sock->state = SS_UNCONNECTED; + sock->ops = pnp->ops; + sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; + sk->sk_protocol = protocol; + pn = pn_sk(sk); + pn->sobject = 0; + pn->resource = 0; + sk->sk_prot->init(sk); + err = 0; out: phonet_proto_put(pnp); @@ -94,6 +110,7 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, struct net_device *orig_dev) { struct phonethdr *ph; + struct sock *sk; struct sockaddr_pn sa; u16 len; @@ -118,7 +135,12 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, if (pn_sockaddr_get_addr(&sa) == 0) goto out; /* currently, we cannot be device 0 */ - /* TODO: put packets to sockets backlog */ + sk = pn_find_sock_by_sa(&sa); + if (sk == NULL) + goto out; + + /* Push data to the socket (or other sockets connected to it). */ + return sk_receive_skb(sk, skb, 0); out: kfree_skb(skb); diff --git a/net/phonet/socket.c b/net/phonet/socket.c new file mode 100644 index 00000000000..99a4945d565 --- /dev/null +++ b/net/phonet/socket.c @@ -0,0 +1,311 @@ +/* + * File: socket.c + * + * Phonet sockets + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * Original author: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +static int pn_socket_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (sk) { + sock->sk = NULL; + sk->sk_prot->close(sk, 0); + } + return 0; +} + +static struct { + struct hlist_head hlist; + spinlock_t lock; +} pnsocks = { + .hlist = HLIST_HEAD_INIT, + .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), +}; + +/* + * Find address based on socket address, match only certain fields. + * Also grab sock if it was found. Remember to sock_put it later. + */ +struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn) +{ + struct hlist_node *node; + struct sock *sknode; + struct sock *rval = NULL; + u16 obj = pn_sockaddr_get_object(spn); + u8 res = spn->spn_resource; + + spin_lock_bh(&pnsocks.lock); + + sk_for_each(sknode, node, &pnsocks.hlist) { + struct pn_sock *pn = pn_sk(sknode); + BUG_ON(!pn->sobject); /* unbound socket */ + + if (pn_port(obj)) { + /* Look up socket by port */ + if (pn_port(pn->sobject) != pn_port(obj)) + continue; + } else { + /* If port is zero, look up by resource */ + if (pn->resource != res) + continue; + } + if (pn_addr(pn->sobject) + && pn_addr(pn->sobject) != pn_addr(obj)) + continue; + + rval = sknode; + sock_hold(sknode); + break; + } + + spin_unlock_bh(&pnsocks.lock); + + return rval; + +} + +void pn_sock_hash(struct sock *sk) +{ + spin_lock_bh(&pnsocks.lock); + sk_add_node(sk, &pnsocks.hlist); + spin_unlock_bh(&pnsocks.lock); +} +EXPORT_SYMBOL(pn_sock_hash); + +void pn_sock_unhash(struct sock *sk) +{ + spin_lock_bh(&pnsocks.lock); + sk_del_node_init(sk); + spin_unlock_bh(&pnsocks.lock); +} +EXPORT_SYMBOL(pn_sock_unhash); + +static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) +{ + struct sock *sk = sock->sk; + struct pn_sock *pn = pn_sk(sk); + struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; + int err; + u16 handle; + u8 saddr; + + if (sk->sk_prot->bind) + return sk->sk_prot->bind(sk, addr, len); + + if (len < sizeof(struct sockaddr_pn)) + return -EINVAL; + if (spn->spn_family != AF_PHONET) + return -EAFNOSUPPORT; + + handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr); + saddr = pn_addr(handle); + if (saddr && phonet_address_lookup(saddr)) + return -EADDRNOTAVAIL; + + lock_sock(sk); + if (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) { + err = -EINVAL; /* attempt to rebind */ + goto out; + } + err = sk->sk_prot->get_port(sk, pn_port(handle)); + if (err) + goto out; + + /* get_port() sets the port, bind() sets the address if applicable */ + pn->sobject = pn_object(saddr, pn_port(pn->sobject)); + pn->resource = spn->spn_resource; + + /* Enable RX on the socket */ + sk->sk_prot->hash(sk); +out: + release_sock(sk); + return err; +} + +static int pn_socket_autobind(struct socket *sock) +{ + struct sockaddr_pn sa; + int err; + + memset(&sa, 0, sizeof(sa)); + sa.spn_family = AF_PHONET; + err = pn_socket_bind(sock, (struct sockaddr *)&sa, + sizeof(struct sockaddr_pn)); + if (err != -EINVAL) + return err; + BUG_ON(!pn_port(pn_sk(sock->sk)->sobject)); + return 0; /* socket was already bound */ +} + +static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, + int *sockaddr_len, int peer) +{ + struct sock *sk = sock->sk; + struct pn_sock *pn = pn_sk(sk); + + memset(addr, 0, sizeof(struct sockaddr_pn)); + addr->sa_family = AF_PHONET; + if (!peer) /* Race with bind() here is userland's problem. */ + pn_sockaddr_set_object((struct sockaddr_pn *)addr, + pn->sobject); + + *sockaddr_len = sizeof(struct sockaddr_pn); + return 0; +} + +static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + struct sock *sk = sock->sk; + struct pn_sock *pn = pn_sk(sk); + + if (cmd == SIOCPNGETOBJECT) { + struct net_device *dev; + u16 handle; + u8 saddr; + + if (get_user(handle, (__u16 __user *)arg)) + return -EFAULT; + + lock_sock(sk); + if (sk->sk_bound_dev_if) + dev = dev_get_by_index(sock_net(sk), + sk->sk_bound_dev_if); + else + dev = phonet_device_get(sock_net(sk)); + if (dev && (dev->flags & IFF_UP)) + saddr = phonet_address_get(dev, pn_addr(handle)); + else + saddr = PN_NO_ADDR; + release_sock(sk); + + if (dev) + dev_put(dev); + if (saddr == PN_NO_ADDR) + return -EHOSTUNREACH; + + handle = pn_object(saddr, pn_port(pn->sobject)); + return put_user(handle, (__u16 __user *)arg); + } + + return sk->sk_prot->ioctl(sk, cmd, arg); +} + +static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct sock *sk = sock->sk; + + if (pn_socket_autobind(sock)) + return -EAGAIN; + + return sk->sk_prot->sendmsg(iocb, sk, m, total_len); +} + +const struct proto_ops phonet_dgram_ops = { + .family = AF_PHONET, + .owner = THIS_MODULE, + .release = pn_socket_release, + .bind = pn_socket_bind, + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = pn_socket_getname, + .poll = datagram_poll, + .ioctl = pn_socket_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = sock_no_setsockopt, + .compat_getsockopt = sock_no_getsockopt, +#endif + .sendmsg = pn_socket_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + +static DEFINE_MUTEX(port_mutex); + +/* allocate port for a socket */ +int pn_sock_get_port(struct sock *sk, unsigned short sport) +{ + static int port_cur; + struct pn_sock *pn = pn_sk(sk); + struct sockaddr_pn try_sa; + struct sock *tmpsk; + + memset(&try_sa, 0, sizeof(struct sockaddr_pn)); + try_sa.spn_family = AF_PHONET; + + mutex_lock(&port_mutex); + + if (!sport) { + /* search free port */ + int port, pmin = 0x40, pmax = 0x7f; + + for (port = pmin; port <= pmax; port++) { + port_cur++; + if (port_cur < pmin || port_cur > pmax) + port_cur = pmin; + + pn_sockaddr_set_port(&try_sa, port_cur); + tmpsk = pn_find_sock_by_sa(&try_sa); + if (tmpsk == NULL) { + sport = port_cur; + goto found; + } else + sock_put(tmpsk); + } + } else { + /* try to find specific port */ + pn_sockaddr_set_port(&try_sa, sport); + tmpsk = pn_find_sock_by_sa(&try_sa); + if (tmpsk == NULL) + /* No sock there! We can use that port... */ + goto found; + else + sock_put(tmpsk); + } + mutex_unlock(&port_mutex); + + /* the port must be in use already */ + return -EADDRINUSE; + +found: + mutex_unlock(&port_mutex); + pn->sobject = pn_object(pn_addr(pn->sobject), sport); + return 0; +} +EXPORT_SYMBOL(pn_sock_get_port); -- cgit v1.2.3 From 107d0d9b8d9a236883db72841fb61cedd5be845e Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:05:57 -0700 Subject: Phonet: Phonet datagram transport protocol This provides the basic SOCK_DGRAM transport protocol for Phonet. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/phonet.h | 6 ++ net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 106 ++++++++++++++++++++++++ net/phonet/datagram.c | 197 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 net/phonet/datagram.c diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index 2ae5cbb59b6..d3957d3be0f 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -51,6 +51,9 @@ void pn_sock_hash(struct sock *sk); void pn_sock_unhash(struct sock *sk); int pn_sock_get_port(struct sock *sk, unsigned short sport); +int pn_skb_send(struct sock *sk, struct sk_buff *skb, + const struct sockaddr_pn *target); + static inline struct phonethdr *pn_hdr(struct sk_buff *skb) { return (struct phonethdr *)skb_network_header(skb); @@ -95,4 +98,7 @@ int phonet_proto_register(int protocol, struct phonet_protocol *pp); void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); void phonet_netlink_register(void); +int isi_register(void); +void isi_unregister(void); + #endif diff --git a/net/phonet/Makefile b/net/phonet/Makefile index c1d671de783..d218abc3f06 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -4,4 +4,5 @@ phonet-objs := \ pn_dev.o \ pn_netlink.o \ socket.o \ + datagram.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index ba54d53020f..e6771d3961c 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -99,6 +99,101 @@ static struct net_proto_family phonet_proto_family = { .owner = THIS_MODULE, }; +/* + * Prepends an ISI header and sends a datagram. + */ +static int pn_send(struct sk_buff *skb, struct net_device *dev, + u16 dst, u16 src, u8 res) +{ + struct phonethdr *ph; + int err; + + if (skb->len + 2 > 0xffff) { + /* Phonet length field would overflow */ + err = -EMSGSIZE; + goto drop; + } + + skb_reset_transport_header(skb); + WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ + skb_push(skb, sizeof(struct phonethdr)); + skb_reset_network_header(skb); + ph = pn_hdr(skb); + ph->pn_rdev = pn_dev(dst); + ph->pn_sdev = pn_dev(src); + ph->pn_res = res; + ph->pn_length = __cpu_to_be16(skb->len + 2 - sizeof(*ph)); + ph->pn_robj = pn_obj(dst); + ph->pn_sobj = pn_obj(src); + + skb->protocol = htons(ETH_P_PHONET); + skb->priority = 0; + skb->dev = dev; + + if (pn_addr(src) == pn_addr(dst)) { + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_LOOPBACK; + skb_orphan(skb); + netif_rx_ni(skb); + err = 0; + } else { + err = dev_hard_header(skb, dev, ntohs(skb->protocol), + NULL, NULL, skb->len); + if (err < 0) { + err = -EHOSTUNREACH; + goto drop; + } + err = dev_queue_xmit(skb); + } + + return err; +drop: + kfree_skb(skb); + return err; +} + +/* + * Create a Phonet header for the skb and send it out. Returns + * non-zero error code if failed. The skb is freed then. + */ +int pn_skb_send(struct sock *sk, struct sk_buff *skb, + const struct sockaddr_pn *target) +{ + struct net_device *dev; + struct pn_sock *pn = pn_sk(sk); + int err; + u16 src; + u8 daddr = pn_sockaddr_get_addr(target), saddr = PN_NO_ADDR; + + err = -EHOSTUNREACH; + if (sk->sk_bound_dev_if) + dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); + else + dev = phonet_device_get(sock_net(sk)); + if (!dev || !(dev->flags & IFF_UP)) + goto drop; + + saddr = phonet_address_get(dev, daddr); + if (saddr == PN_NO_ADDR) + goto drop; + + src = pn->sobject; + if (!pn_addr(src)) + src = pn_object(saddr, pn_obj(src)); + + err = pn_send(skb, dev, pn_sockaddr_get_object(target), + src, pn_sockaddr_get_resource(target)); + dev_put(dev); + return err; + +drop: + kfree_skb(skb); + if (dev) + dev_put(dev); + return err; +} +EXPORT_SYMBOL(pn_skb_send); + /* packet type functions */ /* @@ -226,11 +321,22 @@ static int __init phonet_init(void) phonet_device_init(); dev_add_pack(&phonet_packet_type); phonet_netlink_register(); + + err = isi_register(); + if (err) + goto err; return 0; + +err: + sock_unregister(AF_PHONET); + dev_remove_pack(&phonet_packet_type); + phonet_device_exit(); + return err; } static void __exit phonet_exit(void) { + isi_unregister(); sock_unregister(AF_PHONET); dev_remove_pack(&phonet_packet_type); phonet_device_exit(); diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c new file mode 100644 index 00000000000..e087862ed7e --- /dev/null +++ b/net/phonet/datagram.c @@ -0,0 +1,197 @@ +/* + * File: datagram.c + * + * Datagram (ISI) Phonet sockets + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * Original author: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb); + +/* associated socket ceases to exist */ +static void pn_sock_close(struct sock *sk, long timeout) +{ + sk_common_release(sk); +} + +static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + struct sk_buff *skb; + int answ; + + switch (cmd) { + case SIOCINQ: + lock_sock(sk); + skb = skb_peek(&sk->sk_receive_queue); + answ = skb ? skb->len : 0; + release_sock(sk); + return put_user(answ, (int __user *)arg); + } + + return -ENOIOCTLCMD; +} + +/* Destroy socket. All references are gone. */ +static void pn_destruct(struct sock *sk) +{ + skb_queue_purge(&sk->sk_receive_queue); +} + +static int pn_init(struct sock *sk) +{ + sk->sk_destruct = pn_destruct; + return 0; +} + +static int pn_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len) +{ + struct sockaddr_pn *target; + struct sk_buff *skb; + int err; + + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + + if (msg->msg_name == NULL) + return -EDESTADDRREQ; + + if (msg->msg_namelen < sizeof(struct sockaddr_pn)) + return -EINVAL; + + target = (struct sockaddr_pn *)msg->msg_name; + if (target->spn_family != AF_PHONET) + return -EAFNOSUPPORT; + + skb = sock_alloc_send_skb(sk, MAX_PHONET_HEADER + len, + msg->msg_flags & MSG_DONTWAIT, &err); + if (skb == NULL) + return err; + skb_reserve(skb, MAX_PHONET_HEADER); + + err = memcpy_fromiovec((void *)skb_put(skb, len), msg->msg_iov, len); + if (err < 0) { + kfree_skb(skb); + return err; + } + + /* + * Fill in the Phonet header and + * finally pass the packet forwards. + */ + err = pn_skb_send(sk, skb, target); + + /* If ok, return len. */ + return (err >= 0) ? len : err; +} + +static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len, int noblock, + int flags, int *addr_len) +{ + struct sk_buff *skb = NULL; + struct sockaddr_pn sa; + int rval = -EOPNOTSUPP; + int copylen; + + if (flags & MSG_OOB) + goto out_nofree; + + if (addr_len) + *addr_len = sizeof(sa); + + skb = skb_recv_datagram(sk, flags, noblock, &rval); + if (skb == NULL) + goto out_nofree; + + pn_skb_get_src_sockaddr(skb, &sa); + + copylen = skb->len; + if (len < copylen) { + msg->msg_flags |= MSG_TRUNC; + copylen = len; + } + + rval = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copylen); + if (rval) { + rval = -EFAULT; + goto out; + } + + rval = (flags & MSG_TRUNC) ? skb->len : copylen; + + if (msg->msg_name != NULL) + memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn)); + +out: + skb_free_datagram(sk, skb); + +out_nofree: + return rval; +} + +/* Queue an skb for a sock. */ +static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + int err = sock_queue_rcv_skb(sk, skb); + if (err < 0) + kfree_skb(skb); + return err ? NET_RX_DROP : NET_RX_SUCCESS; +} + +/* Module registration */ +static struct proto pn_proto = { + .close = pn_sock_close, + .ioctl = pn_ioctl, + .init = pn_init, + .sendmsg = pn_sendmsg, + .recvmsg = pn_recvmsg, + .backlog_rcv = pn_backlog_rcv, + .hash = pn_sock_hash, + .unhash = pn_sock_unhash, + .get_port = pn_sock_get_port, + .obj_size = sizeof(struct pn_sock), + .owner = THIS_MODULE, + .name = "PHONET", +}; + +static struct phonet_protocol pn_dgram_proto = { + .ops = &phonet_dgram_ops, + .prot = &pn_proto, + .sock_type = SOCK_DGRAM, +}; + +int __init isi_register(void) +{ + return phonet_proto_register(PN_PROTO_PHONET, &pn_dgram_proto); +} + +void __exit isi_unregister(void) +{ + phonet_proto_unregister(PN_PROTO_PHONET, &pn_dgram_proto); +} -- cgit v1.2.3 From 5f77076d75d35c9f5619e1f9d7e7428a627f65e6 Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:08:04 -0700 Subject: Phonet: provide MAC header operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/if_phonet.h | 4 ++++ net/phonet/af_phonet.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h index 22df25fbc4e..7e989216ec1 100644 --- a/include/linux/if_phonet.h +++ b/include/linux/if_phonet.h @@ -12,3 +12,7 @@ /* 6 bytes header + 65535 bytes payload */ #define PHONET_MAX_MTU 65541 #define PHONET_DEV_MTU PHONET_MAX_MTU + +#ifdef __KERNEL__ +extern struct header_ops phonet_header_ops; +#endif diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index e6771d3961c..51397ff308b 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -99,6 +99,35 @@ static struct net_proto_family phonet_proto_family = { .owner = THIS_MODULE, }; +/* Phonet device header operations */ +static int pn_header_create(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned len) +{ + u8 *media = skb_push(skb, 1); + + if (type != ETH_P_PHONET) + return -1; + + if (!saddr) + saddr = dev->dev_addr; + *media = *(const u8 *)saddr; + return 1; +} + +static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr) +{ + const u8 *media = skb_mac_header(skb); + *haddr = *media; + return 1; +} + +struct header_ops phonet_header_ops = { + .create = pn_header_create, + .parse = pn_header_parse, +}; +EXPORT_SYMBOL(phonet_header_ops); + /* * Prepends an ISI header and sends a datagram. */ -- cgit v1.2.3 From 87ab4e20b445c6d2d2727ab4f96fa17f7259511e Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:08:39 -0700 Subject: Phonet: proc interface for port range Phonet endpoints are bound to individual ports. This provides a /proc/sys/net/phonet (or sysctl) interface for selecting the range of automatically allocated ports (much like the ip_local_port_range with IPv4). Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/phonet.h | 3 ++ net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 3 ++ net/phonet/socket.c | 3 +- net/phonet/sysctl.c | 113 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 net/phonet/sysctl.c diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index d3957d3be0f..1c6f7e7d5fe 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -47,6 +47,7 @@ static inline struct pn_sock *pn_sk(struct sock *sk) extern const struct proto_ops phonet_dgram_ops; struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa); +void phonet_get_local_port_range(int *min, int *max); void pn_sock_hash(struct sock *sk); void pn_sock_unhash(struct sock *sk); int pn_sock_get_port(struct sock *sk, unsigned short sport); @@ -97,6 +98,8 @@ struct phonet_protocol { int phonet_proto_register(int protocol, struct phonet_protocol *pp); void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); +int phonet_sysctl_init(void); +void phonet_sysctl_exit(void); void phonet_netlink_register(void); int isi_register(void); void isi_unregister(void); diff --git a/net/phonet/Makefile b/net/phonet/Makefile index d218abc3f06..ae9c3ed5be8 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -5,4 +5,5 @@ phonet-objs := \ pn_netlink.o \ socket.o \ datagram.o \ + sysctl.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 51397ff308b..50dc258d5aa 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -350,6 +350,7 @@ static int __init phonet_init(void) phonet_device_init(); dev_add_pack(&phonet_packet_type); phonet_netlink_register(); + phonet_sysctl_init(); err = isi_register(); if (err) @@ -357,6 +358,7 @@ static int __init phonet_init(void) return 0; err: + phonet_sysctl_exit(); sock_unregister(AF_PHONET); dev_remove_pack(&phonet_packet_type); phonet_device_exit(); @@ -366,6 +368,7 @@ err: static void __exit phonet_exit(void) { isi_unregister(); + phonet_sysctl_exit(); sock_unregister(AF_PHONET); dev_remove_pack(&phonet_packet_type); phonet_device_exit(); diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 99a4945d565..dfd4061646d 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -273,8 +273,9 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) if (!sport) { /* search free port */ - int port, pmin = 0x40, pmax = 0x7f; + int port, pmin, pmax; + phonet_get_local_port_range(&pmin, &pmax); for (port = pmin; port <= pmax; port++) { port_cur++; if (port_cur < pmin || port_cur > pmax) diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c new file mode 100644 index 00000000000..600a4309b8c --- /dev/null +++ b/net/phonet/sysctl.c @@ -0,0 +1,113 @@ +/* + * File: sysctl.c + * + * Phonet /proc/sys/net/phonet interface implementation + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include + +#define DYNAMIC_PORT_MIN 0x40 +#define DYNAMIC_PORT_MAX 0x7f + +static DEFINE_SEQLOCK(local_port_range_lock); +static int local_port_range_min[2] = {0, 0}; +static int local_port_range_max[2] = {1023, 1023}; +static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX}; +static struct ctl_table_header *phonet_table_hrd; + +static void set_local_port_range(int range[2]) +{ + write_seqlock(&local_port_range_lock); + local_port_range[0] = range[0]; + local_port_range[1] = range[1]; + write_sequnlock(&local_port_range_lock); +} + +void phonet_get_local_port_range(int *min, int *max) +{ + unsigned seq; + do { + seq = read_seqbegin(&local_port_range_lock); + if (min) + *min = local_port_range[0]; + if (max) + *max = local_port_range[1]; + } while (read_seqretry(&local_port_range_lock, seq)); +} + +static int proc_local_port_range(ctl_table *table, int write, struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + int ret; + int range[2] = {local_port_range[0], local_port_range[1]}; + ctl_table tmp = { + .data = &range, + .maxlen = sizeof(range), + .mode = table->mode, + .extra1 = &local_port_range_min, + .extra2 = &local_port_range_max, + }; + + ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); + + if (write && ret == 0) { + if (range[1] < range[0]) + ret = -EINVAL; + else + set_local_port_range(range); + } + + return ret; +} + +static struct ctl_table phonet_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "local_port_range", + .data = &local_port_range, + .maxlen = sizeof(local_port_range), + .mode = 0644, + .proc_handler = &proc_local_port_range, + .strategy = NULL, + }, + { .ctl_name = 0 } +}; + +struct ctl_path phonet_ctl_path[] = { + { .procname = "net", .ctl_name = CTL_NET, }, + { .procname = "phonet", .ctl_name = CTL_UNNUMBERED, }, + { }, +}; + +int __init phonet_sysctl_init(void) +{ + phonet_table_hrd = register_sysctl_paths(phonet_ctl_path, phonet_table); + return phonet_table_hrd == NULL ? -ENOMEM : 0; +} + +void phonet_sysctl_exit(void) +{ + unregister_sysctl_table(phonet_table_hrd); +} -- cgit v1.2.3 From be0c52bfed7f7828494fa00060efd5d758e92580 Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:09:13 -0700 Subject: Phonet: emit errors when a packet cannot be delivered locally When there is no listener socket for a received packet, send an error back to the sender. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/phonet.h | 32 +++++++++++++++ include/net/phonet/phonet.h | 5 +++ net/phonet/af_phonet.c | 96 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/include/linux/phonet.h b/include/linux/phonet.h index 001c0e67909..3a027f588a4 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h @@ -45,6 +45,38 @@ struct phonethdr { __u8 pn_sobj; } __attribute__((packed)); +/* Common Phonet payload header */ +struct phonetmsg { + __u8 pn_trans_id; /* transaction ID */ + __u8 pn_msg_id; /* message type */ + union { + struct { + __u8 pn_submsg_id; /* message subtype */ + __u8 pn_data[5]; + } base; + struct { + __u16 pn_e_res_id; /* extended resource ID */ + __u8 pn_e_submsg_id; /* message subtype */ + __u8 pn_e_data[3]; + } ext; + } pn_msg_u; +}; +#define PN_COMMON_MESSAGE 0xF0 +#define PN_PREFIX 0xE0 /* resource for extended messages */ +#define pn_submsg_id pn_msg_u.base.pn_submsg_id +#define pn_e_submsg_id pn_msg_u.ext.pn_e_submsg_id +#define pn_e_res_id pn_msg_u.ext.pn_e_res_id +#define pn_data pn_msg_u.base.pn_data +#define pn_e_data pn_msg_u.ext.pn_e_data + +/* data for unreachable errors */ +#define PN_COMM_SERVICE_NOT_IDENTIFIED_RESP 0x01 +#define PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP 0x14 +#define pn_orig_msg_id pn_data[0] +#define pn_status pn_data[1] +#define pn_e_orig_msg_id pn_e_data[0] +#define pn_e_status pn_e_data[1] + /* Phonet socket address structure */ struct sockaddr_pn { sa_family_t spn_family; diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index 1c6f7e7d5fe..d4e72508e14 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -60,6 +60,11 @@ static inline struct phonethdr *pn_hdr(struct sk_buff *skb) return (struct phonethdr *)skb_network_header(skb); } +static inline struct phonetmsg *pn_msg(struct sk_buff *skb) +{ + return (struct phonetmsg *)skb_transport_header(skb); +} + /* * Get the other party's sockaddr from received skb. The skb begins * with a Phonet header. diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 50dc258d5aa..1d8df6b7e3d 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL(phonet_header_ops); * Prepends an ISI header and sends a datagram. */ static int pn_send(struct sk_buff *skb, struct net_device *dev, - u16 dst, u16 src, u8 res) + u16 dst, u16 src, u8 res, u8 irq) { struct phonethdr *ph; int err; @@ -163,7 +163,10 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev, skb_reset_mac_header(skb); skb->pkt_type = PACKET_LOOPBACK; skb_orphan(skb); - netif_rx_ni(skb); + if (irq) + netif_rx(skb); + else + netif_rx_ni(skb); err = 0; } else { err = dev_hard_header(skb, dev, ntohs(skb->protocol), @@ -181,6 +184,19 @@ drop: return err; } +static int pn_raw_send(const void *data, int len, struct net_device *dev, + u16 dst, u16 src, u8 res) +{ + struct sk_buff *skb = alloc_skb(MAX_PHONET_HEADER + len, GFP_ATOMIC); + if (skb == NULL) + return -ENOMEM; + + skb_reserve(skb, MAX_PHONET_HEADER); + __skb_put(skb, len); + skb_copy_to_linear_data(skb, data, len); + return pn_send(skb, dev, dst, src, res, 1); +} + /* * Create a Phonet header for the skb and send it out. Returns * non-zero error code if failed. The skb is freed then. @@ -211,7 +227,7 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb, src = pn_object(saddr, pn_obj(src)); err = pn_send(skb, dev, pn_sockaddr_get_object(target), - src, pn_sockaddr_get_resource(target)); + src, pn_sockaddr_get_resource(target), 0); dev_put(dev); return err; @@ -223,6 +239,73 @@ drop: } EXPORT_SYMBOL(pn_skb_send); +/* Do not send an error message in response to an error message */ +static inline int can_respond(struct sk_buff *skb) +{ + const struct phonethdr *ph; + const struct phonetmsg *pm; + u8 submsg_id; + + if (!pskb_may_pull(skb, 3)) + return 0; + + ph = pn_hdr(skb); + if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev) + return 0; /* we are not the destination */ + if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5)) + return 0; + + ph = pn_hdr(skb); /* re-acquires the pointer */ + pm = pn_msg(skb); + if (pm->pn_msg_id != PN_COMMON_MESSAGE) + return 1; + submsg_id = (ph->pn_res == PN_PREFIX) + ? pm->pn_e_submsg_id : pm->pn_submsg_id; + if (submsg_id != PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP && + pm->pn_e_submsg_id != PN_COMM_SERVICE_NOT_IDENTIFIED_RESP) + return 1; + return 0; +} + +static int send_obj_unreachable(struct sk_buff *rskb) +{ + const struct phonethdr *oph = pn_hdr(rskb); + const struct phonetmsg *opm = pn_msg(rskb); + struct phonetmsg resp; + + memset(&resp, 0, sizeof(resp)); + resp.pn_trans_id = opm->pn_trans_id; + resp.pn_msg_id = PN_COMMON_MESSAGE; + if (oph->pn_res == PN_PREFIX) { + resp.pn_e_res_id = opm->pn_e_res_id; + resp.pn_e_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP; + resp.pn_e_orig_msg_id = opm->pn_msg_id; + resp.pn_e_status = 0; + } else { + resp.pn_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP; + resp.pn_orig_msg_id = opm->pn_msg_id; + resp.pn_status = 0; + } + return pn_raw_send(&resp, sizeof(resp), rskb->dev, + pn_object(oph->pn_sdev, oph->pn_sobj), + pn_object(oph->pn_rdev, oph->pn_robj), + oph->pn_res); +} + +static int send_reset_indications(struct sk_buff *rskb) +{ + struct phonethdr *oph = pn_hdr(rskb); + static const u8 data[4] = { + 0x00 /* trans ID */, 0x10 /* subscribe msg */, + 0x00 /* subscription count */, 0x00 /* dummy */ + }; + + return pn_raw_send(data, sizeof(data), rskb->dev, + pn_object(oph->pn_sdev, 0x00), + pn_object(oph->pn_rdev, oph->pn_robj), 0x10); +} + + /* packet type functions */ /* @@ -260,8 +343,13 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, goto out; /* currently, we cannot be device 0 */ sk = pn_find_sock_by_sa(&sa); - if (sk == NULL) + if (sk == NULL) { + if (can_respond(skb)) { + send_obj_unreachable(skb); + send_reset_indications(skb); + } goto out; + } /* Push data to the socket (or other sockets connected to it). */ return sk_receive_skb(sk, skb, 0); -- cgit v1.2.3 From 953f551756a1275d9bfdbb70697323449305161a Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Mon, 22 Sep 2008 20:09:46 -0700 Subject: Phonet: kernel documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- Documentation/networking/phonet.txt | 111 ++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Documentation/networking/phonet.txt diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt new file mode 100644 index 00000000000..f3c72e0ca8d --- /dev/null +++ b/Documentation/networking/phonet.txt @@ -0,0 +1,111 @@ +Linux Phonet protocol family +============================ + +Introduction +------------ + +Phonet is a packet protocol used by Nokia cellular modems for both IPC +and RPC. With the Linux Phonet socket family, Linux host processes can +receive and send messages from/to the modem, or any other external +device attached to the modem. The modem takes care of routing. + +Phonet packets can be exchanged through various hardware connections +depending on the device, such as: + - USB with the CDC Phonet interface, + - infrared, + - Bluetooth, + - an RS232 serial port (with a dedicated "FBUS" line discipline), + - the SSI bus with some TI OMAP processors. + + +Packets format +-------------- + +Phonet packet have a common header as follow: + + struct phonethdr { + uint8_t pn_media; /* Media type (link-layer identifier) */ + uint8_t pn_rdev; /* Receiver device ID */ + uint8_t pn_sdev; /* Sender device ID */ + uint8_t pn_res; /* Resource ID or function */ + uint16_t pn_length; /* Big-endian message byte length (minus 6) */ + uint8_t pn_robj; /* Receiver object ID */ + uint8_t pn_sobj; /* Sender object ID */ + }; + +The device ID is split: the 6 higher order bits consitutes the device +address, while the 2 lower order bits are used for multiplexing, as are +the 8-bits object identifiers. As such, Phonet can be considered as a +network layer with 6 bits of address space and 10 bits for transport +protocol (much like port numbers in IP world). + +The modem always has address number zero. Each other device has a its +own 6-bits address. + + +Link layer +---------- + +Phonet links are always point-to-point links. The link layer header +consists of a single Phonet media type byte. It uniquely identifies the +link through which the packet is transmitted, from the modem's +perspective. + +Linux Phonet network interfaces use a dedicated link layer type +(ETH_P_PHONET) which is out of the Ethernet type range. They can only +send and receive Phonet packets. + +Note that Phonet interfaces are not allowed to re-order packets, so +only the (default) Linux FIFO qdisc should be used with them. + + +Network layer +------------- + +The Phonet socket address family maps the Phonet packet header: + + struct sockaddr_pn { + sa_family_t spn_family; /* AF_PHONET */ + uint8_t spn_obj; /* Object ID */ + uint8_t spn_dev; /* Device ID */ + uint8_t spn_resource; /* Resource or function */ + uint8_t spn_zero[...]; /* Padding */ + }; + +The resource field is only used when sending and receiving; +It is ignored by bind() and getsockname(). + + +Low-level datagram protocol +--------------------------- + +Applications can send Phonet messages using the Phonet datagram socket +protocol from the PF_PHONET family. Each socket is bound to one of the +2^10 object IDs available, and can send and receive packets with any +other peer. + + struct sockaddr_pn addr = { .spn_family = AF_PHONET, }; + ssize_t len; + socklen_t addrlen = sizeof(addr); + int fd; + + fd = socket(PF_PHONET, SOCK_DGRAM, 0); + bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + /* ... */ + + sendto(fd, msg, msglen, 0, (struct sockaddr *)&addr, sizeof(addr)); + len = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&addr, &addrlen); + +This protocol follows the SOCK_DGRAM connection-less semantics. +However, connect() and getpeername() are not supported, as they did +not seem useful with Phonet usages (could be added easily). + + +Authors +------- + +Linux Phonet was initially written by Sakari Ailus. +Other contributors include Mikä Liljeberg, Andras Domokos, +Carlos Chinea and Rémi Denis-Courmont. +Copyright (C) 2008 Nokia Corporation. -- cgit v1.2.3 From 83bfba5fca16d040bb78a24148da844db3de6a76 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 20:18:47 -0700 Subject: usbnet: Use skb_queue_walk_safe() instead of by-hand implementation. Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8463efb9e0b..02d25c74399 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -512,14 +512,13 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) int count = 0; spin_lock_irqsave (&q->lock, flags); - for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) { + skb_queue_walk_safe(q, skb, skbnext) { struct skb_data *entry; struct urb *urb; int retval; entry = (struct skb_data *) skb->cb; urb = entry->urb; - skbnext = skb->next; // during some PM-driven resume scenarios, // these (async) unlinks complete immediately -- cgit v1.2.3 From 0b815a1a6d43ab498674b8430c8c35ab08487a16 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 22 Sep 2008 21:28:11 -0700 Subject: net: network device name ifalias support This patch add support for keeping an additional character alias associated with an network interface. This is useful for maintaining the SNMP ifAlias value which is a user defined value. Routers use this to hold information like which circuit or line it is connected to. It is just an arbitrary text label on the network device. There are two exposed interfaces with this patch, the value can be read/written either via netlink or sysfs. This could be maintained just by the snmp daemon, but it is more generally useful for other management tools, and the kernel is good place to act as an agreed upon interface to store it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/if.h | 1 + include/linux/if_link.h | 1 + include/linux/netdevice.h | 3 +++ net/core/dev.c | 23 +++++++++++++++++++++++ net/core/net-sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ net/core/rtnetlink.c | 13 +++++++++++++ 6 files changed, 77 insertions(+) diff --git a/include/linux/if.h b/include/linux/if.h index 5c9d1fa93fe..65246846c84 100644 --- a/include/linux/if.h +++ b/include/linux/if.h @@ -24,6 +24,7 @@ #include /* for "__user" et al */ #define IFNAMSIZ 16 +#define IFALIASZ 256 #include /* Standard interface flags (netdevice->flags). */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 84c3492ae5c..f9032c88716 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -79,6 +79,7 @@ enum IFLA_LINKINFO, #define IFLA_LINKINFO IFLA_LINKINFO IFLA_NET_NS_PID, + IFLA_IFALIAS, __IFLA_MAX }; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 488c56e649b..d675df08b94 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -471,6 +471,8 @@ struct net_device char name[IFNAMSIZ]; /* device name hash chain */ struct hlist_node name_hlist; + /* snmp alias */ + char *ifalias; /* * I/O specific fields @@ -1224,6 +1226,7 @@ extern int dev_ethtool(struct net *net, struct ifreq *); extern unsigned dev_get_flags(const struct net_device *); extern int dev_change_flags(struct net_device *, unsigned); extern int dev_change_name(struct net_device *, char *); +extern int dev_set_alias(struct net_device *, const char *, size_t); extern int dev_change_net_namespace(struct net_device *, struct net *, const char *); extern int dev_set_mtu(struct net_device *, int); diff --git a/net/core/dev.c b/net/core/dev.c index fdfc4b6a644..e9139053399 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -953,6 +953,29 @@ rollback: return err; } +/** + * dev_set_alias - change ifalias of a device + * @dev: device + * @alias: name up to IFALIASZ + * + * Set ifalias for a device, + */ +int dev_set_alias(struct net_device *dev, const char *alias, size_t len) +{ + ASSERT_RTNL(); + + if (len >= IFALIASZ) + return -EINVAL; + + dev->ifalias = krealloc(dev->ifalias, len+1, GFP_KERNEL); + if (!dev->ifalias) + return -ENOMEM; + + strlcpy(dev->ifalias, alias, len+1); + return len; +} + + /** * netdev_features_change - device changes features * @dev: device to cause notification diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c1f4e0d428c..92d6b946731 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -209,9 +209,44 @@ static ssize_t store_tx_queue_len(struct device *dev, return netdev_store(dev, attr, buf, len, change_tx_queue_len); } +static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct net_device *netdev = to_net_dev(dev); + size_t count = len; + ssize_t ret; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* ignore trailing newline */ + if (len > 0 && buf[len - 1] == '\n') + --count; + + rtnl_lock(); + ret = dev_set_alias(netdev, buf, count); + rtnl_unlock(); + + return ret < 0 ? ret : len; +} + +static ssize_t show_ifalias(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct net_device *netdev = to_net_dev(dev); + ssize_t ret = 0; + + rtnl_lock(); + if (netdev->ifalias) + ret = sprintf(buf, "%s\n", netdev->ifalias); + rtnl_unlock(); + return ret; +} + static struct device_attribute net_class_attributes[] = { __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), + __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), __ATTR(iflink, S_IRUGO, show_iflink, NULL), __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), __ATTR(features, S_IRUGO, show_features, NULL), @@ -418,6 +453,7 @@ static void netdev_release(struct device *d) BUG_ON(dev->reg_state != NETREG_RELEASED); + kfree(dev->ifalias); kfree((char *)dev - dev->padded); } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 71edb8b3634..8862498fd4a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -586,6 +586,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ + nla_total_size(sizeof(struct rtnl_link_ifmap)) + nla_total_size(sizeof(struct rtnl_link_stats)) @@ -640,6 +641,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, if (txq->qdisc_sleeping) NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id); + if (dev->ifalias) + NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); + if (1) { struct rtnl_link_ifmap map = { .mem_start = dev->mem_start, @@ -713,6 +717,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_LINKMODE] = { .type = NLA_U8 }, [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_NET_NS_PID] = { .type = NLA_U32 }, + [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, }; static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { @@ -853,6 +858,14 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, modified = 1; } + if (tb[IFLA_IFALIAS]) { + err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), + nla_len(tb[IFLA_IFALIAS])); + if (err < 0) + goto errout; + modified = 1; + } + if (tb[IFLA_BROADCAST]) { nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); send_addr_notify = 1; -- cgit v1.2.3 From 1d4a31dde95af56edac4dee268249a29a21fa7c0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 21:57:21 -0700 Subject: net: Fix bus in SKB queue splicing interfaces. Handle the case of head being non-empty, by adding list->qlen to head->qlen instead of using direct assignment. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 027b06170b4..4a144e8d053 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -738,7 +738,7 @@ static inline void skb_queue_splice(const struct sk_buff_head *list, { if (!skb_queue_empty(list)) { __skb_queue_splice(list, (struct sk_buff *) head, head->next); - head->qlen = list->qlen; + head->qlen += list->qlen; } } @@ -754,7 +754,7 @@ static inline void skb_queue_splice_init(struct sk_buff_head *list, { if (!skb_queue_empty(list)) { __skb_queue_splice(list, (struct sk_buff *) head, head->next); - head->qlen = list->qlen; + head->qlen += list->qlen; __skb_queue_head_init(list); } } @@ -769,7 +769,7 @@ static inline void skb_queue_splice_tail(const struct sk_buff_head *list, { if (!skb_queue_empty(list)) { __skb_queue_splice(list, head->prev, (struct sk_buff *) head); - head->qlen = list->qlen; + head->qlen += list->qlen; } } @@ -786,7 +786,7 @@ static inline void skb_queue_splice_tail_init(struct sk_buff_head *list, { if (!skb_queue_empty(list)) { __skb_queue_splice(list, head->prev, (struct sk_buff *) head); - head->qlen = list->qlen; + head->qlen += list->qlen; __skb_queue_head_init(list); } } -- cgit v1.2.3 From 3d09274cc9d816d62945408840a9cb76a5e7aac7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 22:14:36 -0700 Subject: sctp: Use skb_queue_walk_safe() and skb_queue_split_tail_init(). Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 17b932b8a55..703305d0036 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -406,10 +406,7 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id); /* A macro to walk a list of skbs. */ #define sctp_skb_for_each(pos, head, tmp) \ -for (pos = (head)->next;\ - tmp = (pos)->next, pos != ((struct sk_buff *)(head));\ - pos = tmp) - + skb_queue_walk_safe(head, pos, tmp) /* A helper to append an entire skb list (list) to another (head). */ static inline void sctp_skb_list_tail(struct sk_buff_head *list, @@ -420,10 +417,7 @@ static inline void sctp_skb_list_tail(struct sk_buff_head *list, sctp_spin_lock_irqsave(&head->lock, flags); sctp_spin_lock(&list->lock); - list_splice((struct list_head *)list, (struct list_head *)head->prev); - - head->qlen += list->qlen; - list->qlen = 0; + skb_queue_splice_tail_init(list, head); sctp_spin_unlock(&list->lock); sctp_spin_unlock_irqrestore(&head->lock, flags); -- cgit v1.2.3 From 242f8bfefe4bed626df4e4727ac8f315d80b567a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 22:15:30 -0700 Subject: pkt_sched: Make qdisc->gso_skb a list. The idea is that we can use this to get rid of ->requeue(). Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 +- net/sched/sch_generic.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e5569625d2a..3b983e8a055 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -52,7 +52,7 @@ struct Qdisc u32 parent; atomic_t refcnt; unsigned long state; - struct sk_buff *gso_skb; + struct sk_buff_head requeue; struct sk_buff_head q; struct netdev_queue *dev_queue; struct Qdisc *next_sched; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ec0a0839ce5..5961536be60 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -45,7 +45,7 @@ static inline int qdisc_qlen(struct Qdisc *q) static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) { if (unlikely(skb->next)) - q->gso_skb = skb; + __skb_queue_head(&q->requeue, skb); else q->ops->requeue(skb, q); @@ -57,9 +57,8 @@ static inline struct sk_buff *dequeue_skb(struct Qdisc *q) { struct sk_buff *skb; - if ((skb = q->gso_skb)) - q->gso_skb = NULL; - else + skb = __skb_dequeue(&q->requeue); + if (!skb) skb = q->dequeue(q); return skb; @@ -327,6 +326,7 @@ struct Qdisc noop_qdisc = { .flags = TCQ_F_BUILTIN, .ops = &noop_qdisc_ops, .list = LIST_HEAD_INIT(noop_qdisc.list), + .requeue.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), .dev_queue = &noop_netdev_queue, }; @@ -352,6 +352,7 @@ static struct Qdisc noqueue_qdisc = { .flags = TCQ_F_BUILTIN, .ops = &noqueue_qdisc_ops, .list = LIST_HEAD_INIT(noqueue_qdisc.list), + .requeue.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), .q.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), .dev_queue = &noqueue_netdev_queue, }; @@ -472,6 +473,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, sch->padded = (char *) sch - (char *) p; INIT_LIST_HEAD(&sch->list); + skb_queue_head_init(&sch->requeue); skb_queue_head_init(&sch->q); sch->ops = ops; sch->enqueue = ops->enqueue; @@ -539,7 +541,7 @@ void qdisc_destroy(struct Qdisc *qdisc) module_put(ops->owner); dev_put(qdisc_dev(qdisc)); - kfree_skb(qdisc->gso_skb); + __skb_queue_purge(&qdisc->requeue); kfree((char *) qdisc - qdisc->padded); } -- cgit v1.2.3 From f0876520b0b721bedafd9cec3b1b0624ae566eee Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Sep 2008 22:15:58 -0700 Subject: pkt_sched: Always use q->requeue in dev_requeue_skb(). There is no reason to call into the complicated qdiscs just to remember the last SKB where we found the device blocked. The SKB is outside of the qdiscs realm at this point. Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5961536be60..1b508bd1c06 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -44,10 +44,7 @@ static inline int qdisc_qlen(struct Qdisc *q) static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) { - if (unlikely(skb->next)) - __skb_queue_head(&q->requeue, skb); - else - q->ops->requeue(skb, q); + __skb_queue_head(&q->requeue, skb); __netif_schedule(q); return 0; -- cgit v1.2.3 From ebf059821ed8a36acd706484b719d14d212ada32 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 22 Sep 2008 22:16:23 -0700 Subject: pkt_sched: Check the state of tx_queue in dequeue_skb() Check in dequeue_skb() the state of tx_queue for requeued skb to save on locking and re-requeuing, and possibly remove the current check in qdisc_run(). Based on the idea of Alexander Duyck. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 1b508bd1c06..5e7e0bd38fe 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -52,11 +52,21 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) static inline struct sk_buff *dequeue_skb(struct Qdisc *q) { - struct sk_buff *skb; - - skb = __skb_dequeue(&q->requeue); - if (!skb) + struct sk_buff *skb = skb_peek(&q->requeue); + + if (unlikely(skb)) { + struct net_device *dev = qdisc_dev(q); + struct netdev_queue *txq; + + /* check the reason of requeuing without tx lock first */ + txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); + if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) + __skb_unlink(skb, &q->requeue); + else + skb = NULL; + } else { skb = q->dequeue(q); + } return skb; } -- cgit v1.2.3 From 2aad7c8e9b4d1cabdeac2469e7276e9daef12fa0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:19:19 -0700 Subject: de4x5: Use skb_queue_head instead of by-hand implementation. Signed-off-by: David S. Miller --- drivers/net/tulip/de4x5.c | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 617ef41bdfe..6444cbec0bd 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -832,7 +832,7 @@ struct de4x5_private { s32 csr14; /* Saved SIA TX/RX Register */ s32 csr15; /* Saved SIA General Register */ int save_cnt; /* Flag if state already saved */ - struct sk_buff *skb; /* Save the (re-ordered) skb's */ + struct sk_buff_head queue; /* Save the (re-ordered) skb's */ } cache; struct de4x5_srom srom; /* A copy of the SROM */ int cfrv; /* Card CFRV copy */ @@ -1128,6 +1128,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; } else { + skb_queue_head_init(&lp->cache.queue); lp->cache.gepc = GEP_INIT; lp->asBit = GEP_SLNK; lp->asPolarity = GEP_SLNK; @@ -1487,7 +1488,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) } } else if (skb->len > 0) { /* If we already have stuff queued locally, use that first */ - if (lp->cache.skb && !lp->interrupt) { + if (!skb_queue_empty(&lp->cache.queue) && !lp->interrupt) { de4x5_put_cache(dev, skb); skb = de4x5_get_cache(dev); } @@ -1580,7 +1581,7 @@ de4x5_interrupt(int irq, void *dev_id) /* Load the TX ring with any locally stored packets */ if (!test_and_set_bit(0, (void *)&lp->cache.lock)) { - while (lp->cache.skb && !netif_queue_stopped(dev) && lp->tx_enable) { + while (!skb_queue_empty(&lp->cache.queue) && !netif_queue_stopped(dev) && lp->tx_enable) { de4x5_queue_pkt(de4x5_get_cache(dev), dev); } lp->cache.lock = 0; @@ -3679,11 +3680,7 @@ de4x5_free_tx_buffs(struct net_device *dev) } /* Unload the locally queued packets */ - while (lp->cache.skb) { - dev_kfree_skb(de4x5_get_cache(dev)); - } - - return; + __skb_queue_purge(&lp->cache.queue); } /* @@ -3781,43 +3778,24 @@ static void de4x5_put_cache(struct net_device *dev, struct sk_buff *skb) { struct de4x5_private *lp = netdev_priv(dev); - struct sk_buff *p; - - if (lp->cache.skb) { - for (p=lp->cache.skb; p->next; p=p->next); - p->next = skb; - } else { - lp->cache.skb = skb; - } - skb->next = NULL; - return; + __skb_queue_tail(&lp->cache.queue, skb); } static void de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb) { struct de4x5_private *lp = netdev_priv(dev); - struct sk_buff *p = lp->cache.skb; - - lp->cache.skb = skb; - skb->next = p; - return; + __skb_queue_head(&lp->cache.queue, skb); } static struct sk_buff * de4x5_get_cache(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - struct sk_buff *p = lp->cache.skb; - if (p) { - lp->cache.skb = p->next; - p->next = NULL; - } - - return p; + return __skb_dequeue(&lp->cache.queue); } /* -- cgit v1.2.3 From 47a227db746edbcfc8b78ac8a7787733faf6f171 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:23:30 -0700 Subject: zd1211: Use skb_queue_walk() instead of by-hand implementation. Signed-off-by: David S. Miller --- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a3da014f928..fe1867b25ff 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -611,7 +611,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, q = &zd_hw_mac(hw)->ack_wait_queue; spin_lock_irqsave(&q->lock, flags); - for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) { + skb_queue_walk(q, skb) { struct ieee80211_hdr *tx_hdr; tx_hdr = (struct ieee80211_hdr *)skb->data; -- cgit v1.2.3 From b5f61ab96dd093c5190c1540fed14f71ed821ce7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:27:47 -0700 Subject: usbatm: Use skb_queue_walk_safe() instead of by-hand implementation. Signed-off-by: David S. Miller --- drivers/usb/atm/usbatm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 07228721caf..0da2c25bab3 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -640,14 +640,13 @@ static void usbatm_cancel_send(struct usbatm_data *instance, atm_dbg(instance, "%s entered\n", __func__); spin_lock_irq(&instance->sndqueue.lock); - for (skb = instance->sndqueue.next, n = skb->next; - skb != (struct sk_buff *)&instance->sndqueue; - skb = n, n = skb->next) + skb_queue_walk_safe(&instance->sndqueue, skb, n) { if (UDSL_SKB(skb)->atm.vcc == vcc) { atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb); __skb_unlink(skb, &instance->sndqueue); usbatm_pop(vcc, skb); } + } spin_unlock_irq(&instance->sndqueue.lock); tasklet_disable(&instance->tx_channel.tasklet); -- cgit v1.2.3 From fc7ebb212d3e51d1188948d975aa93dbb0f58b25 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:34:07 -0700 Subject: net: Add skb_queue_is_last(). Several bits of code want to know "is this the last SKB in a queue", and all of them implement this by hand. Provide an common interface to make this check. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4a144e8d053..3a5838da160 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -472,6 +472,19 @@ static inline int skb_queue_empty(const struct sk_buff_head *list) return list->next == (struct sk_buff *)list; } +/** + * skb_queue_is_last - check if skb is the last entry in the queue + * @list: queue head + * @skb: buffer + * + * Returns true if @skb is the last buffer on the list. + */ +static inline bool skb_queue_is_last(const struct sk_buff_head *list, + const struct sk_buff *skb) +{ + return (skb->next == (struct sk_buff *) list); +} + /** * skb_get - reference buffer * @skb: buffer to reference -- cgit v1.2.3 From d258b4914bcda9177bcc7bbd8e1a97b281b460af Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:34:37 -0700 Subject: tcp: Use skb_queue_is_last() instead of by-hand version. Signed-off-by: David S. Miller --- include/net/tcp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f857c3eff71..5c5327e9a55 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1284,10 +1284,10 @@ static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk) __skb_unlink(skb, &sk->sk_write_queue); } -static inline int tcp_skb_is_last(const struct sock *sk, - const struct sk_buff *skb) +static inline bool tcp_skb_is_last(const struct sock *sk, + const struct sk_buff *skb) { - return skb->next == (struct sk_buff *)&sk->sk_write_queue; + return skb_queue_is_last(&sk->sk_write_queue, skb); } static inline int tcp_write_queue_empty(struct sock *sk) -- cgit v1.2.3 From 249c8b42c7e5e6f33d0ff983041f08278b137e53 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:44:42 -0700 Subject: net: Add skb_queue_next(). A lot of code wants to iterate over an SKB queue at the top level using it's own control structure and iterator scheme. Provide skb_queue_next(), which is only valid to invoke if skb_queue_is_last() returns false. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 3a5838da160..d2f1778877d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -485,6 +485,24 @@ static inline bool skb_queue_is_last(const struct sk_buff_head *list, return (skb->next == (struct sk_buff *) list); } +/** + * skb_queue_next - return the next packet in the queue + * @list: queue head + * @skb: current buffer + * + * Return the next packet in @list after @skb. It is only valid to + * call this if skb_queue_is_last() evaluates to false. + */ +static inline struct sk_buff *skb_queue_next(const struct sk_buff_head *list, + const struct sk_buff *skb) +{ + /* This BUG_ON may seem severe, but if we just return then we + * are going to dereference garbage. + */ + BUG_ON(skb_queue_is_last(list, skb)); + return skb->next; +} + /** * skb_get - reference buffer * @skb: buffer to reference -- cgit v1.2.3 From 1164f52a244204830c7625b3c22812781996d7b4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:49:44 -0700 Subject: net: Add skb_queue_walk_from() and skb_queue_walk_from_safe(). These will be used by TCP write queue handling and elsewhere. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d2f1778877d..a19ea43fea0 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1571,6 +1571,15 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) skb != (struct sk_buff *)(queue); \ skb = tmp, tmp = skb->next) +#define skb_queue_walk_from(queue, skb) \ + for (; prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ + skb = skb->next) + +#define skb_queue_walk_from_safe(queue, skb, tmp) \ + for (tmp = skb->next; \ + skb != (struct sk_buff *)(queue); \ + skb = tmp, tmp = skb->next) + #define skb_queue_reverse_walk(queue, skb) \ for (skb = (queue)->prev; \ prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \ -- cgit v1.2.3 From cd07a8ea0dd4b204919b4c9ced8d9efdd9924495 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 00:50:13 -0700 Subject: tcp: Use SKB queue handling interfaces instead of by-hand versions. Signed-off-by: David S. Miller --- include/net/tcp.h | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 5c5327e9a55..12c9b4fec04 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1181,49 +1181,45 @@ static inline void tcp_write_queue_purge(struct sock *sk) static inline struct sk_buff *tcp_write_queue_head(struct sock *sk) { - struct sk_buff *skb = sk->sk_write_queue.next; - if (skb == (struct sk_buff *) &sk->sk_write_queue) - return NULL; - return skb; + return skb_peek(&sk->sk_write_queue); } static inline struct sk_buff *tcp_write_queue_tail(struct sock *sk) { - struct sk_buff *skb = sk->sk_write_queue.prev; - if (skb == (struct sk_buff *) &sk->sk_write_queue) - return NULL; - return skb; + return skb_peek_tail(&sk->sk_write_queue); } static inline struct sk_buff *tcp_write_queue_next(struct sock *sk, struct sk_buff *skb) { - return skb->next; + return skb_queue_next(&sk->sk_write_queue, skb); } #define tcp_for_write_queue(skb, sk) \ - for (skb = (sk)->sk_write_queue.next; \ - (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ - skb = skb->next) + skb_queue_walk(&(sk)->sk_write_queue, skb) #define tcp_for_write_queue_from(skb, sk) \ - for (; (skb != (struct sk_buff *)&(sk)->sk_write_queue);\ - skb = skb->next) + skb_queue_walk_from(&(sk)->sk_write_queue, skb) #define tcp_for_write_queue_from_safe(skb, tmp, sk) \ - for (tmp = skb->next; \ - (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ - skb = tmp, tmp = skb->next) + skb_queue_walk_from_safe(&(sk)->sk_write_queue, skb, tmp) static inline struct sk_buff *tcp_send_head(struct sock *sk) { return sk->sk_send_head; } +static inline bool tcp_skb_is_last(const struct sock *sk, + const struct sk_buff *skb) +{ + return skb_queue_is_last(&sk->sk_write_queue, skb); +} + static inline void tcp_advance_send_head(struct sock *sk, struct sk_buff *skb) { - sk->sk_send_head = skb->next; - if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue) + if (tcp_skb_is_last(sk, skb)) sk->sk_send_head = NULL; + else + sk->sk_send_head = tcp_write_queue_next(sk, skb); } static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked) @@ -1284,12 +1280,6 @@ static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk) __skb_unlink(skb, &sk->sk_write_queue); } -static inline bool tcp_skb_is_last(const struct sock *sk, - const struct sk_buff *skb) -{ - return skb_queue_is_last(&sk->sk_write_queue, skb); -} - static inline int tcp_write_queue_empty(struct sock *sk) { return skb_queue_empty(&sk->sk_write_queue); -- cgit v1.2.3 From 7f605ac00416d763c2d9681e378a75e7adbb06e8 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 13 Sep 2008 18:47:19 +0900 Subject: [WATCHDOG] ibmasr: remove unnecessary spin_unlock() __asr_toggle() is always called with asr_lock held. But there is unnecessary spin_unlock() call in __asr_toggle(). Signed-off-by: Akinobu Mita Signed-off-by: Wim Van Sebroeck Acked-by: Andrey Panin Signed-off-by: Andrew Morton --- drivers/watchdog/ibmasr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c index b82405cfb4c..89fcefcc851 100644 --- a/drivers/watchdog/ibmasr.c +++ b/drivers/watchdog/ibmasr.c @@ -85,7 +85,6 @@ static void __asr_toggle(void) outb(reg & ~asr_toggle_mask, asr_write_addr); reg = inb(asr_read_addr); - spin_unlock(&asr_lock); } static void asr_toggle(void) -- cgit v1.2.3 From f4ab543201992fe499bef5c406e09f23aa97b4d5 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 23 Sep 2008 01:05:56 -0700 Subject: pkt_sched: Remove the tx queue state check in qdisc_run() The current check wrongly uses the state of one (currently the first) tx queue for all tx queues in case of non-default qdiscs. This check mainly prevented requeuing loop with __netif_schedule(), but now it's controlled inside __qdisc_run(), while dequeuing. The wrongness of this check was first noticed by Herbert Xu. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index b786a5b0925..4082f39f507 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -90,10 +90,7 @@ extern void __qdisc_run(struct Qdisc *q); static inline void qdisc_run(struct Qdisc *q) { - struct netdev_queue *txq = q->dev_queue; - - if (!netif_tx_queue_stopped(txq) && - !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) + if (!test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) __qdisc_run(q); } -- cgit v1.2.3 From edf86c9b98b5162bed64a70f9424bd2dd58a717e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 16 Sep 2008 11:31:01 +0100 Subject: [WATCHDOG] wdt285: fix sparse warnings The wdt285.c watchdog driver is producing a number of sparse errors due to missing __user attributes to calls to put_user and copy_to_user, as well as in the prototype of watchdog_write. wdt285.c:144:21: warning: incorrect type in argument 1 (different address spaces) wdt285.c:144:21: expected void [noderef] *to wdt285.c:144:21: got void * wdt285.c:150:9: warning: incorrect type in initializer (different address spaces) wdt285.c:150:9: expected int const [noderef] *register __p wdt285.c:150:9: got int * wdt285.c:159:9: warning: incorrect type in initializer (different address spaces) wdt285.c:159:9: expected int const [noderef] *register __p wdt285.c:159:9: got int * wdt285.c:174:9: warning: incorrect type in initializer (different address spaces) wdt285.c:174:9: expected int const [noderef] *register __p wdt285.c:174:9: got int * wdt285.c:183:12: warning: incorrect type in initializer (incompatible argument 2 (different address spaces)) wdt285.c:183:12: expected int ( *write )( ... ) wdt285.c:183:12: got int ( static [toplevel] * )( ... ) Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/wdt285.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c index db362c34958..191ea630210 100644 --- a/drivers/watchdog/wdt285.c +++ b/drivers/watchdog/wdt285.c @@ -115,8 +115,8 @@ static int watchdog_release(struct inode *inode, struct file *file) return 0; } -static ssize_t watchdog_write(struct file *file, const char *data, - size_t len, loff_t *ppos) +static ssize_t watchdog_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) { /* * Refresh the timer. @@ -133,21 +133,22 @@ static const struct watchdog_info ident = { }; static long watchdog_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) + unsigned long arg) { unsigned int new_margin; + int __user *int_arg = (int __user *)arg; int ret = -ENOTTY; switch (cmd) { case WDIOC_GETSUPPORT: ret = 0; - if (copy_to_user((void *)arg, &ident, sizeof(ident))) + if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) ret = -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int *)arg); + ret = put_user(0, int_arg); break; case WDIOC_KEEPALIVE: @@ -156,7 +157,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, break; case WDIOC_SETTIMEOUT: - ret = get_user(new_margin, (int *)arg); + ret = get_user(new_margin, int_arg); if (ret) break; @@ -171,7 +172,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, watchdog_ping(); /* Fall */ case WDIOC_GETTIMEOUT: - ret = put_user(soft_margin, (int *)arg); + ret = put_user(soft_margin, int_arg); break; } return ret; -- cgit v1.2.3 From f72051b0674f36c960698653a0583edaec1e495e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 01:11:18 -0700 Subject: neigh: Remove by-hand SKB queue handling. Signed-off-by: David S. Miller --- net/core/neighbour.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9d92e41826e..1dc728b3858 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -927,8 +927,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) if (skb_queue_len(&neigh->arp_queue) >= neigh->parms->queue_len) { struct sk_buff *buff; - buff = neigh->arp_queue.next; - __skb_unlink(buff, &neigh->arp_queue); + buff = __skb_dequeue(&neigh->arp_queue); kfree_skb(buff); NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards); } @@ -1259,24 +1258,20 @@ static void neigh_proxy_process(unsigned long arg) struct neigh_table *tbl = (struct neigh_table *)arg; long sched_next = 0; unsigned long now = jiffies; - struct sk_buff *skb; + struct sk_buff *skb, *n; spin_lock(&tbl->proxy_queue.lock); - skb = tbl->proxy_queue.next; - - while (skb != (struct sk_buff *)&tbl->proxy_queue) { - struct sk_buff *back = skb; - long tdif = NEIGH_CB(back)->sched_next - now; + skb_queue_walk_safe(&tbl->proxy_queue, skb, n) { + long tdif = NEIGH_CB(skb)->sched_next - now; - skb = skb->next; if (tdif <= 0) { - struct net_device *dev = back->dev; - __skb_unlink(back, &tbl->proxy_queue); + struct net_device *dev = skb->dev; + __skb_unlink(skb, &tbl->proxy_queue); if (tbl->proxy_redo && netif_running(dev)) - tbl->proxy_redo(back); + tbl->proxy_redo(skb); else - kfree_skb(back); + kfree_skb(skb); dev_put(dev); } else if (!sched_next || tdif < sched_next) -- cgit v1.2.3 From 7275fc8c36dbad3a871f82b1f9f1f524688176ea Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 18 Sep 2008 12:26:15 +0000 Subject: [WATCHDOG] unlocked_ioctl changes Fix some drivers so that they use the unlocked_ioctl call. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/geodewdt.c | 6 +++--- drivers/watchdog/pnx4008_wdt.c | 4 ++-- drivers/watchdog/rc32434_wdt.c | 6 +++--- drivers/watchdog/rdc321x_wdt.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 614a5c7017b..6799a6de66f 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -130,8 +130,8 @@ static ssize_t geodewdt_write(struct file *file, const char __user *data, return len; } -static int geodewdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long geodewdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; @@ -198,7 +198,7 @@ static const struct file_operations geodewdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = geodewdt_write, - .ioctl = geodewdt_ioctl, + .unlocked_ioctl = geodewdt_ioctl, .open = geodewdt_open, .release = geodewdt_release, }; diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 0ed84162437..6d9f3d4a998 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -173,8 +173,8 @@ static const struct watchdog_info ident = { .identity = "PNX4008 Watchdog", }; -static long pnx4008_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { int ret = -ENOTTY; int time; diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 6756bcb009e..c9c73b69c5e 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -182,8 +182,8 @@ static ssize_t rc32434_wdt_write(struct file *file, const char *data, return 0; } -static int rc32434_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; int new_timeout; @@ -242,7 +242,7 @@ static struct file_operations rc32434_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = rc32434_wdt_write, - .ioctl = rc32434_wdt_ioctl, + .unlocked_ioctl = rc32434_wdt_ioctl, .open = rc32434_wdt_open, .release = rc32434_wdt_release, }; diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 9108efa73e7..bf92802f2bb 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -144,8 +144,8 @@ static int rdc321x_wdt_release(struct inode *inode, struct file *file) return 0; } -static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; unsigned int value; @@ -204,7 +204,7 @@ static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, static const struct file_operations rdc321x_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = rdc321x_wdt_ioctl, + .unlocked_ioctl = rdc321x_wdt_ioctl, .open = rdc321x_wdt_open, .write = rdc321x_wdt_write, .release = rdc321x_wdt_release, -- cgit v1.2.3 From 38ce7c736916293b7ce09cd6a2133894fe2cec52 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 01:17:18 -0700 Subject: ppp_generic: Use skb_peek() in ppp_receive_mp_frame(). Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 98e04958fef..5d4d21516a6 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1833,9 +1833,11 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) /* If the queue is getting long, don't wait any longer for packets before the start of the queue. */ - if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN - && seq_before(ppp->minseq, ppp->mrq.next->sequence)) - ppp->minseq = ppp->mrq.next->sequence; + if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) { + struct sk_buff *skb = skb_peek(&ppp->mrq); + if (seq_before(ppp->minseq, skb->sequence)) + ppp->minseq = skb->sequence; + } /* Pull completed packets off the queue and receive them. */ while ((skb = ppp_mp_reconstruct(ppp))) -- cgit v1.2.3 From 77d40a0952b16e020ce07c4cf9fb22024448275b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 01:29:23 -0700 Subject: tcp: Fix order of tests in tcp_retransmit_skb() tcp_write_queue_next() must only be made if we know that tcp_skb_is_last() evaluates to false. Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c3d58ee3e16..a8499ef3234 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1932,8 +1932,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) /* Collapse two adjacent packets if worthwhile and we can. */ if (!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) && (skb->len < (cur_mss >> 1)) && - (tcp_write_queue_next(sk, skb) != tcp_send_head(sk)) && (!tcp_skb_is_last(sk, skb)) && + (tcp_write_queue_next(sk, skb) != tcp_send_head(sk)) && (skb_shinfo(skb)->nr_frags == 0 && skb_shinfo(tcp_write_queue_next(sk, skb))->nr_frags == 0) && (tcp_skb_pcount(skb) == 1 && -- cgit v1.2.3 From 05e12e1c4c09cd35ac9f4e6af1e42b0036375d72 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Mon, 22 Sep 2008 22:58:47 -0700 Subject: x86: fix 27-rc crash on vsmp due to paravirt during module load 27-rc fails to boot up if configured to use modules. Turns out vsmp_patch was marked __init, and vsmp_patch being the pvops 'patch' routine for vsmp, a call to vsmp_patch just turns out to execute a code page with series of 0xcc (POISON_FREE_INITMEM -- int3). vsmp_patch has been marked with __init ever since pvops, however, apply_paravirt can be called during module load causing calls to freed memory location. Since apply_paravirt can only be called during init/module load, make vsmp_patch with "__init_or_module" Signed-off-by: Ravikiran Thirumalai Signed-off-by: Ingo Molnar --- arch/x86/kernel/vsmp_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index 0c029e8959c..7766d36983f 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c @@ -61,7 +61,7 @@ static void vsmp_irq_enable(void) native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC)); } -static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf, +static unsigned __init_or_module vsmp_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) { switch (type) { -- cgit v1.2.3 From fa748203175de7c08f2df80e5a0eeca40329b5e2 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Mon, 22 Sep 2008 14:55:45 -0700 Subject: sched: fix init_hrtick() section mismatch warning LD kernel/built-in.o WARNING: kernel/built-in.o(.text+0x326): Section mismatch in reference from the function init_hrtick() to the variable .cpuinit.data:hotplug_hrtick_nb.8 The function init_hrtick() references the variable __cpuinitdata hotplug_hrtick_nb.8. This is often because init_hrtick lacks a __cpuinitdata annotation or the annotation of hotplug_hrtick_nb.8 is wrong. Signed-off-by: Md.Rakib H. Mullick Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- kernel/sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 98890807375..13dd2db9fb2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1087,7 +1087,7 @@ hotplug_hrtick(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_DONE; } -static void init_hrtick(void) +static __init void init_hrtick(void) { hotcpu_notifier(hotplug_hrtick, 0); } -- cgit v1.2.3 From 6441402b1f173fa38e561d3cee7c01c32e5281ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 18:46:37 +0200 Subject: clockevents: prevent cpu online to interfere with nohz Impact: rare hang which can be triggered on CPU online. tick_do_timer_cpu keeps track of the CPU which updates jiffies via do_timer. The value -1 is used to signal, that currently no CPU is doing this. There are two cases, where the variable can have this state: boot: necessary for systems where the boot cpu id can be != 0 nohz long idle sleep: When the CPU which did the jiffies update last goes into a long idle sleep it drops the update jiffies duty so another CPU which is not idle can pick it up and keep jiffies going. Using the same value for both situations is wrong, as the CPU online code can see the -1 state when the timer of the newly onlined CPU is setup. The setup for a newly onlined CPU goes through periodic mode and can pick up the do_timer duty without being aware of the nohz / highres mode of the already running system. Use two separate states and make them constants to avoid magic numbers confusion. Signed-off-by: Thomas Gleixner --- kernel/time/tick-common.c | 7 ++++--- kernel/time/tick-internal.h | 4 ++++ kernel/time/tick-sched.c | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 019315ebf9d..b523d095dec 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -33,7 +33,7 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device); */ ktime_t tick_next_period; ktime_t tick_period; -int tick_do_timer_cpu __read_mostly = -1; +int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; DEFINE_SPINLOCK(tick_device_lock); /* @@ -148,7 +148,7 @@ static void tick_setup_device(struct tick_device *td, * If no cpu took the do_timer update, assign it to * this cpu: */ - if (tick_do_timer_cpu == -1) { + if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) { tick_do_timer_cpu = cpu; tick_next_period = ktime_get(); tick_period = ktime_set(0, NSEC_PER_SEC / HZ); @@ -300,7 +300,8 @@ static void tick_shutdown(unsigned int *cpup) if (*cpup == tick_do_timer_cpu) { int cpu = first_cpu(cpu_online_map); - tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : -1; + tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : + TICK_DO_TIMER_NONE; } spin_unlock_irqrestore(&tick_device_lock, flags); } diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 6e9db9734aa..e18014fadf9 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -1,6 +1,10 @@ /* * tick internal variable and functions used by low/high res code */ + +#define TICK_DO_TIMER_NONE -1 +#define TICK_DO_TIMER_BOOT -2 + DECLARE_PER_CPU(struct tick_device, tick_cpu_device); extern spinlock_t tick_device_lock; extern ktime_t tick_next_period; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index a87b0468568..31a14e8caac 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -221,7 +221,7 @@ void tick_nohz_stop_sched_tick(int inidle) */ if (unlikely(!cpu_online(cpu))) { if (cpu == tick_do_timer_cpu) - tick_do_timer_cpu = -1; + tick_do_timer_cpu = TICK_DO_TIMER_NONE; } if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) @@ -303,7 +303,7 @@ void tick_nohz_stop_sched_tick(int inidle) * invoked. */ if (cpu == tick_do_timer_cpu) - tick_do_timer_cpu = -1; + tick_do_timer_cpu = TICK_DO_TIMER_NONE; ts->idle_sleeps++; @@ -468,7 +468,7 @@ static void tick_nohz_handler(struct clock_event_device *dev) * this duty, then the jiffies update is still serialized by * xtime_lock. */ - if (unlikely(tick_do_timer_cpu == -1)) + if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) tick_do_timer_cpu = cpu; /* Check, if the jiffies need an update */ @@ -570,7 +570,7 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) * this duty, then the jiffies update is still serialized by * xtime_lock. */ - if (unlikely(tick_do_timer_cpu == -1)) + if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) tick_do_timer_cpu = cpu; #endif -- cgit v1.2.3 From 4faac97d44ac27bdbb010a9c3597401a8f89341f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 18:54:29 +0200 Subject: x86: prevent stale state of c1e_mask across CPU offline/online Impact: hang which happens across CPU offline/online on AMD C1E systems. When a CPU goes offline then the corresponding bit in the broadcast mask is cleared. For AMD C1E enabled CPUs we do not reenable the broadcast when the CPU comes online again as we do not clear the corresponding bit in the c1e_mask, which keeps track which CPUs have been switched to broadcast already. So on those !$@#& machines we never switch back to broadcasting after a CPU offline/online cycle. Clear the bit when the CPU plays dead. Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process.c | 11 ++++++++--- arch/x86/kernel/process_32.c | 1 + arch/x86/kernel/process_64.c | 2 ++ include/asm-x86/idle.h | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7fc4d5b0a6a..2e2247117f6 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -246,6 +246,14 @@ static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) return 1; } +static cpumask_t c1e_mask = CPU_MASK_NONE; +static int c1e_detected; + +void c1e_remove_cpu(int cpu) +{ + cpu_clear(cpu, c1e_mask); +} + /* * C1E aware idle routine. We check for C1E active in the interrupt * pending message MSR. If we detect C1E, then we handle it the same @@ -253,9 +261,6 @@ static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) */ static void c1e_idle(void) { - static cpumask_t c1e_mask = CPU_MASK_NONE; - static int c1e_detected; - if (need_resched()) return; diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 3b7a1ddcc0b..4b3cfdf5421 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -88,6 +88,7 @@ static void cpu_exit_clear(void) cpu_clear(cpu, cpu_callin_map); numa_remove_cpu(cpu); + c1e_remove_cpu(cpu); } /* We don't actually take CPU down, just spin without interrupts. */ diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 71553b664e2..e12e0e4dd25 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -93,6 +93,8 @@ DECLARE_PER_CPU(int, cpu_state); static inline void play_dead(void) { idle_task_exit(); + c1e_remove_cpu(raw_smp_processor_id()); + mb(); /* Ack it */ __get_cpu_var(cpu_state) = CPU_DEAD; diff --git a/include/asm-x86/idle.h b/include/asm-x86/idle.h index d240e5b30a4..cbb64912361 100644 --- a/include/asm-x86/idle.h +++ b/include/asm-x86/idle.h @@ -10,4 +10,6 @@ void idle_notifier_register(struct notifier_block *n); void enter_idle(void); void exit_idle(void); +void c1e_remove_cpu(int cpu); + #endif -- cgit v1.2.3 From 49d670fb8dd62d3ed4e3ed2513538ea65b051aed Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 18:56:01 +0200 Subject: clockevents: prevent stale tick_next_period for onlining CPUs Impact: possible hang on CPU onlining in timer one shot mode. The tick_next_period variable is only used during boot on nohz/highres enabled systems, but for CPU onlining it needs to be maintained when the per cpu clock events device operates in one shot mode. Signed-off-by: Thomas Gleixner --- kernel/time/tick-sched.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 31a14e8caac..39019b3f762 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -75,6 +75,9 @@ static void tick_do_update_jiffies64(ktime_t now) incr * ticks); } do_timer(++ticks); + + /* Keep the tick_next_period variable up to date */ + tick_next_period = ktime_add(last_jiffies_update, tick_period); } write_sequnlock(&xtime_lock); } -- cgit v1.2.3 From 302745699c1b675b5d2a1af87271de10e4d96b6a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 19:02:25 +0200 Subject: clockevents: check broadcast device not tick device Impact: Possible hang on CPU online observed on AMD C1E machines. The broadcast setup code looks at the mode of the tick device to determine whether it needs to be shut down or setup. This is wrong when the broadcast mode is set to one shot already. This can happen when a CPU is brought online as it goes through the periodic setup first. The problem went unnoticed as sane systems do not call into that code before the switch to one shot for the clock event device happens. The AMD C1E idle routine switches over immediately and thereby shuts down the just setup device before the first interrupt happens. Signed-off-by: Thomas Gleixner --- kernel/time/tick-broadcast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f1f3eee2811..e2b66d1c8ca 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -235,7 +235,7 @@ static void tick_do_broadcast_on_off(void *why) case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: if (!cpu_isset(cpu, tick_broadcast_mask)) { cpu_set(cpu, tick_broadcast_mask); - if (td->mode == TICKDEV_MODE_PERIODIC) + if (bc->mode == TICKDEV_MODE_PERIODIC) clockevents_shutdown(dev); } if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) @@ -245,7 +245,7 @@ static void tick_do_broadcast_on_off(void *why) if (!tick_broadcast_force && cpu_isset(cpu, tick_broadcast_mask)) { cpu_clear(cpu, tick_broadcast_mask); - if (td->mode == TICKDEV_MODE_PERIODIC) + if (bc->mode == TICKDEV_MODE_PERIODIC) tick_setup_periodic(dev, 0); } break; -- cgit v1.2.3 From 27ce4cb4a0c7cf59b9a9952266883862f2e4c99f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 19:04:02 +0200 Subject: clockevents: prevent mode mismatch on cpu online Impact: timer hang on CPU online observed on AMD C1E systems When a CPU is brought online then the broadcast machinery can be in the one shot state already. Check this and setup the timer device of the new CPU in one shot mode so the broadcast code can pick up the next_event value correctly. Another AMD C1E oddity, as we switch to broadcast immediately and not after the full bring up via the ACPI cpu idle code. Signed-off-by: Thomas Gleixner --- kernel/time/tick-broadcast.c | 8 ++++++++ kernel/time/tick-common.c | 3 ++- kernel/time/tick-internal.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index e2b66d1c8ca..bd703454239 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -575,4 +575,12 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup) spin_unlock_irqrestore(&tick_broadcast_lock, flags); } +/* + * Check, whether the broadcast device is in one shot mode + */ +int tick_broadcast_oneshot_active(void) +{ + return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT; +} + #endif diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index b523d095dec..df12434b43c 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -109,7 +109,8 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast) if (!tick_device_is_functional(dev)) return; - if (dev->features & CLOCK_EVT_FEAT_PERIODIC) { + if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && + !tick_broadcast_oneshot_active()) { clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC); } else { unsigned long seq; diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index e18014fadf9..55c3f4be607 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -35,6 +35,7 @@ extern void tick_broadcast_oneshot_control(unsigned long reason); extern void tick_broadcast_switch_to_oneshot(void); extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc); +extern int tick_broadcast_oneshot_active(void); # else /* BROADCAST */ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { @@ -43,6 +44,7 @@ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) static inline void tick_broadcast_oneshot_control(unsigned long reason) { } static inline void tick_broadcast_switch_to_oneshot(void) { } static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } +static inline int tick_broadcast_oneshot_active(void) { return 0; } # endif /* !BROADCAST */ #else /* !ONESHOT */ -- cgit v1.2.3 From a8d6829044901a67732904be5f1eacdf8539604f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 22 Sep 2008 19:02:25 +0200 Subject: x86: prevent C-states hang on AMD C1E enabled machines Impact: System hang when AMD C1E machines switch into C2/C3 AMD C1E enabled systems do not work with normal ACPI C-states even if the BIOS is advertising them. Limit the C-states to C1 for the ACPI processor idle code. Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process.c | 1 + include/asm-x86/acpi.h | 2 ++ include/asm-x86/cpufeature.h | 1 + 3 files changed, 4 insertions(+) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2e2247117f6..d8c2a299bfe 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -272,6 +272,7 @@ static void c1e_idle(void) c1e_detected = 1; mark_tsc_unstable("TSC halt in C1E"); printk(KERN_INFO "System has C1E enabled\n"); + set_cpu_cap(&boot_cpu_data, X86_FEATURE_AMDC1E); } } diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h index 635d764dc13..35d1743b57a 100644 --- a/include/asm-x86/acpi.h +++ b/include/asm-x86/acpi.h @@ -140,6 +140,8 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) boot_cpu_data.x86_model <= 0x05 && boot_cpu_data.x86_mask < 0x0A) return 1; + else if (boot_cpu_has(X86_FEATURE_AMDC1E)) + return 1; else return max_cstate; } diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 9489283a4bc..cfcfb0a806b 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -81,6 +81,7 @@ #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ +#define X86_FEATURE_AMDC1E (3*32+21) /* AMD C1E detected */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ -- cgit v1.2.3 From 09bfeea13cea843fb03eaa96b5d891fa0abdcc90 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 18 Sep 2008 21:12:10 +0200 Subject: x86: c1e_idle: don't mark TSC unstable if CPU has invariant TSC Impact: Functional TSC is marked unstable on AMD family 0x10 and 0x11 CPUs. This would be wrong because for those CPUs "invariant TSC" means: "The TSC counts at the same rate in all P-states, all C states, S0, or S1" (See "Processor BIOS and Kernel Developer's Guides" for those CPUs.) [ tglx: Changed C1E to AMD C1E in the printks to avoid confusion with Intel C1E ] Signed-off-by: Andreas Herrmann Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index d8c2a299bfe..876e9189077 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -270,8 +270,9 @@ static void c1e_idle(void) rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi); if (lo & K8_INTP_C1E_ACTIVE_MASK) { c1e_detected = 1; - mark_tsc_unstable("TSC halt in C1E"); - printk(KERN_INFO "System has C1E enabled\n"); + if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) + mark_tsc_unstable("TSC halt in AMD C1E"); + printk(KERN_INFO "System has AMD C1E enabled\n"); set_cpu_cap(&boot_cpu_data, X86_FEATURE_AMDC1E); } } -- cgit v1.2.3 From 28e3487b7dd8a9791baac924bc887140ec747bed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 02:51:41 -0700 Subject: tcp: Fix queue traversal in tcp_use_frto(). We must check tcp_skb_is_last() before doing a tcp_write_queue_next(). Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cbfe13d5f42..3b76bce769d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1746,6 +1746,8 @@ int tcp_use_frto(struct sock *sk) return 0; skb = tcp_write_queue_head(sk); + if (tcp_skb_is_last(sk, skb)) + return 1; skb = tcp_write_queue_next(sk, skb); /* Skips head */ tcp_for_write_queue_from(skb, sk) { if (skb == tcp_send_head(sk)) -- cgit v1.2.3 From f8e256c687eb53850685747757c8d75e58756e15 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 23 Sep 2008 13:00:57 +0200 Subject: timers: fix build error in !oneshot case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kernel/time/tick-common.c: In function ‘tick_setup_periodic’: kernel/time/tick-common.c:113: error: implicit declaration of function ‘tick_broadcast_oneshot_active’ Signed-off-by: Ingo Molnar --- kernel/time/tick-internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 55c3f4be607..469248782c2 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -74,6 +74,7 @@ static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { return 0; } +static inline int tick_broadcast_oneshot_active(void) { return 0; } #endif /* !TICK_ONESHOT */ /* -- cgit v1.2.3 From b0b8daf7849cc98217ca018fbe82c61cd2b735bc Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 18 Sep 2008 14:36:37 +0100 Subject: ALSA: ASoC: maintainers - update email address for Liam Girdwood This patch updates the maintainers email address for Liam Girdwood and adds a URL for the ASoC website. Signed-off-by: Liam Girdwood Signed-off-by: Takashi Iwai --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 28c69aaefcd..657e0ffe2df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3826,11 +3826,12 @@ S: Maintained SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT P: Liam Girdwood -M: liam.girdwood@wolfsonmicro.com +M: lrg@slimlogic.co.uk P: Mark Brown M: broonie@opensource.wolfsonmicro.com T: git opensource.wolfsonmicro.com/linux-2.6-asoc L: alsa-devel@alsa-project.org (subscribers-only) +W: http://alsa-project.org/main/index.php/ASoC S: Supported SPI SUBSYSTEM -- cgit v1.2.3 From 683f40d7e7eee06811db43cb4c45349eab0d539e Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 22 Sep 2008 13:57:41 -0700 Subject: ibmasr: remove unnecessary spin_unlock() __asr_toggle() is always called with asr_lock held. But there is unnecessary spin_unlock() call in __asr_toggle(). Signed-off-by: Akinobu Mita Cc: Wim Van Sebroeck Acked-by: Andrey Panin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/watchdog/ibmasr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c index b82405cfb4c..89fcefcc851 100644 --- a/drivers/watchdog/ibmasr.c +++ b/drivers/watchdog/ibmasr.c @@ -85,7 +85,6 @@ static void __asr_toggle(void) outb(reg & ~asr_toggle_mask, asr_write_addr); reg = inb(asr_read_addr); - spin_unlock(&asr_lock); } static void asr_toggle(void) -- cgit v1.2.3 From c32a162fd420fe8dfb049db941b2438061047fcc Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Mon, 22 Sep 2008 13:57:43 -0700 Subject: smb.h: do not include linux/time.h in userspace linux/time.h conflicts with time.h from glibc It breaks building smbmount from samba. It's regression introduced by commit 76308da (" smb.h: uses struct timespec but didn't include linux/time.h"). Signed-off-by: Kirill A. Shutemov Cc: [2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/smb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/smb.h b/include/linux/smb.h index caa43b2370c..82fefddc598 100644 --- a/include/linux/smb.h +++ b/include/linux/smb.h @@ -11,7 +11,9 @@ #include #include +#ifdef __KERNEL__ #include +#endif enum smb_protocol { SMB_PROTOCOL_NONE, -- cgit v1.2.3 From 39f00c087d31f668eb6eaf97508af22a32c5b1d9 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 22 Sep 2008 13:57:44 -0700 Subject: kernel-doc: allow structs whose members are all private Struct members may be marked as private by using /* private: */ before them, as noted in Documentation/kernel-doc-nano-HOWTO.txt Fix kernel-doc to handle structs whose members are all private; otherwise invalid XML is generated: xmlto: input does not validate (status 3) linux-2.6.27-rc6-git4/Documentation/DocBook/debugobjects.xml:146: element variablelist: validity error : Element variablelist content does not follow the DTD, expecting ((title , titleabbrev?)? , varlistentry+), got () Document linux-2.6.27-rc6-git4/Documentation/DocBook/debugobjects.xml does not validate make[1]: *** [Documentation/DocBook/debugobjects.html] Error 3 Signed-off-by: Randy Dunlap Reported-by: Roland McGrath Cc: Roland McGrath Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kernel-doc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index ff787e6ff8e..44ee94d2ab7 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -781,6 +781,7 @@ sub output_struct_xml(%) { print " \n"; print " Members\n"; + if ($#{$args{'parameterlist'}} >= 0) { print " \n"; foreach $parameter (@{$args{'parameterlist'}}) { ($parameter =~ /^#/) && next; @@ -798,6 +799,9 @@ sub output_struct_xml(%) { print " \n"; } print " \n"; + } else { + print " \n None\n \n"; + } print " \n"; output_section_xml(@_); -- cgit v1.2.3 From f9092f358bc2ec5367621478811f046f82873376 Mon Sep 17 00:00:00 2001 From: Jonathan Steel Date: Mon, 22 Sep 2008 13:57:45 -0700 Subject: kexec: fix segmentation fault in kimage_add_entry A segmentation fault can occur in kimage_add_entry in kexec.c when loading a kernel image into memory. The fault occurs because a page is requested by calling kimage_alloc_page with gfp_mask GFP_KERNEL and the function may actually return a page with gfp_mask GFP_HIGHUSER. The high mem page is returned because it was swapped with the kernel page due to the kernel page being a page that will shortly be copied to. This patch ensures that kimage_alloc_page returns a page that was created with the correct gfp flags. I have verified the change and fixed the whitespace damage of the original patch. Jonathan did a great job of tracking this down after he hit the problem. -- Eric Signed-off-by: Jonathan Steel Signed-off-by: Eric W. Biederman Acked-by: Simon Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kexec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c index 59f3f0df35d..aef265325cd 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -753,8 +753,14 @@ static struct page *kimage_alloc_page(struct kimage *image, *old = addr | (*old & ~PAGE_MASK); /* The old page I have found cannot be a - * destination page, so return it. + * destination page, so return it if it's + * gfp_flags honor the ones passed in. */ + if (!(gfp_mask & __GFP_HIGHMEM) && + PageHighMem(old_page)) { + kimage_free_pages(old_page); + continue; + } addr = old_addr; page = old_page; break; -- cgit v1.2.3 From 6675ce13ed783f88ea5d82f0d855462b76ff0dad Mon Sep 17 00:00:00 2001 From: Marin Mitov Date: Mon, 22 Sep 2008 13:57:46 -0700 Subject: Documentation/DMA-mapping.txt: update for pci_dma_mapping_error() changes Make the example code consistent with changed API. Signed-off-by: Marin Mitov Acked-by: FUJITA Tomonori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-mapping.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index b463ecd0c7c..c74fec8c235 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt @@ -740,7 +740,7 @@ failure can be determined by: dma_addr_t dma_handle; dma_handle = pci_map_single(pdev, addr, size, direction); - if (pci_dma_mapping_error(dma_handle)) { + if (pci_dma_mapping_error(pdev, dma_handle)) { /* * reduce current DMA mapping usage, * delay and try again later or -- cgit v1.2.3 From 2d4c8266774188cda7f7e612e6dfb8ad12c579d5 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Mon, 22 Sep 2008 13:57:49 -0700 Subject: sys_paccept: disable paccept() until API design is resolved The reasons for disabling paccept() are as follows: * The API is more complex than needed. There is AFAICS no demonstrated use case that the sigset argument of this syscall serves that couldn't equally be served by the use of pselect/ppoll/epoll_pwait + traditional accept(). Roland seems to concur with this opinion (http://thread.gmane.org/gmane.linux.kernel/723953/focus=732255). I have (more than once) asked Ulrich to explain otherwise (http://thread.gmane.org/gmane.linux.kernel/723952/focus=731018), but he does not respond, so one is left to assume that he doesn't know of such a case. * The use of a sigset argument is not consistent with other I/O APIs that can block on a single file descriptor (e.g., read(), recv(), connect()). * The behavior of paccept() when interrupted by a signal is IMO strange: the kernel restarts the system call if SA_RESTART was set for the handler. I think that it should not do this -- that it should behave consistently with paccept()/ppoll()/epoll_pwait(), which never restart, regardless of SA_RESTART. The reasoning here is that the very purpose of paccept() is to wait for a connection or a signal, and that restarting in the latter case is probably never useful. (Note: Roland disagrees on this point, believing that rather paccept() should be consistent with accept() in its behavior wrt EINTR (http://thread.gmane.org/gmane.linux.kernel/723953/focus=732255).) I believe that instead, a simpler API, consistent with Ulrich's other recent additions, is preferable: accept4(int fd, struct sockaddr *sa, socklen_t *salen, ind flags); (This simpler API was originally proposed by Ulrich: http://thread.gmane.org/gmane.linux.network/92072) If this simpler API is added, then if we later decide that the sigset argument really is required, then a suitable bit in 'flags' could be added to indicate the presence of the sigset argument. At this point, I am hoping we either will get a counter-argument from Ulrich about why we really do need paccept()'s sigset argument, or that he will resubmit the original accept4() patch. Signed-off-by: Michael Kerrisk Cc: David Miller Cc: Davide Libenzi Cc: Alan Cox Cc: Ulrich Drepper Cc: Jakub Jelinek Cc: Roland McGrath Cc: Oleg Nesterov Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- net/socket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/socket.c b/net/socket.c index 8ef8ba81b9e..3e8d4e35c08 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1511,6 +1511,7 @@ out_fd: goto out_put; } +#if 0 #ifdef HAVE_SET_RESTORE_SIGMASK asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen, @@ -1564,6 +1565,7 @@ asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); } #endif +#endif asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) -- cgit v1.2.3 From db203d53d474aa068984e409d807628f5841da1b Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 22 Sep 2008 13:57:50 -0700 Subject: mm: tiny-shmem fix lock ordering: mmap_sem vs i_mutex tiny-shmem calls do_truncate in shmem_file_setup. do_truncate takes i_mutex, and shmem_file_setup is called with mmap_sem held. However i_mutex nests outside mmap_sem. Copy the code in shmem.c to avoid this problem. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Nick Piggin Reported-and-tested-by: Ingo Molnar Cc: Peter Zijlstra Cc: Matt Mackall Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/tiny-shmem.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index ae532f50194..d17cb6f6ab1 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -65,31 +65,25 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) if (!dentry) goto put_memory; - error = -ENOSPC; - inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); - if (!inode) - goto put_dentry; - - d_instantiate(dentry, inode); error = -ENFILE; - file = alloc_file(shm_mnt, dentry, FMODE_WRITE | FMODE_READ, - &ramfs_file_operations); + file = get_empty_filp(); if (!file) goto put_dentry; - inode->i_nlink = 0; /* It is unlinked */ - - /* notify everyone as to the change of file size */ - error = do_truncate(dentry, size, 0, file); - if (error < 0) + error = -ENOSPC; + inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); + if (!inode) goto close_file; + d_instantiate(dentry, inode); + inode->i_size = size; + inode->i_nlink = 0; /* It is unlinked */ + init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, + &ramfs_file_operations); return file; close_file: put_filp(file); - return ERR_PTR(error); - put_dentry: dput(dentry); put_memory: -- cgit v1.2.3 From b4d19cc84e8e6838f4aa0b26b3afcdc8c7f71505 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 22 Sep 2008 13:57:51 -0700 Subject: Documentation/sysctl/kernel.txt: fix softlockup_thresh description - s/s/seconds/ - s/10 seconds/60 seconds/ - Mention the zero-disables-it feature. Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysctl/kernel.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 276a7e63782..e1ff0d920a5 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -351,9 +351,10 @@ kernel. This value defaults to SHMMAX. softlockup_thresh: -This value can be used to lower the softlockup tolerance -threshold. The default threshold is 10s. If a cpu is locked up -for 10s, the kernel complains. Valid values are 1-60s. +This value can be used to lower the softlockup tolerance threshold. The +default threshold is 60 seconds. If a cpu is locked up for 60 seconds, +the kernel complains. Valid values are 1-60 seconds. Setting this +tunable to zero will disable the softlockup detection altogether. ============================================================== -- cgit v1.2.3 From a10cebf56ca7e7c034d1b6646230c6553e478967 Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Mon, 22 Sep 2008 13:57:52 -0700 Subject: memcg: check under limit at shrink_usage Current memory cgroup(both in mainline and -mm) doesn't account swap caches as memory(swap cache support is dropped temporarily now). So try_to_free_mem_cgroup_pages doesn't reflect the count of pages that have been moved to swap cache. But this makes mem_cgroup_shrink_usage fail easily if most of the pages are anon/shmem, and then shmem_getpage returns -ENOMEM and the process will be killed. This patch adds res_counter_check_under_limit to avoid these cases. BTW, even if swap cache support is enabled again, if a process is moved to another cgroup, which has been just made, between precharge and shrink_usage in shmem_getpage, shrink_usage may fail just because there is no pages to reclaim. So this change would make sense anyway. Signed-off-by: Daisuke Nishimura Cc: Balbir Singh Cc: Pavel Emelyanov Cc: KAMEZAWA Hiroyuki Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f1f7a7374b..c0500e4d3a2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -806,6 +806,7 @@ int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask) do { progress = try_to_free_mem_cgroup_pages(mem, gfp_mask); + progress += res_counter_check_under_limit(&mem->res); } while (!progress && --retry); css_put(&mem->css); -- cgit v1.2.3 From f05596dbc922276ed675c713519220bae8042e32 Mon Sep 17 00:00:00 2001 From: Anti Sullin Date: Mon, 22 Sep 2008 13:57:54 -0700 Subject: atmel_serial: update the powersave handler to match serial core This problem seems to be unnoticed so far: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b3b708fa2780cd2b5d8266a8f0c3a1cab364d4d2 has changed the serial core behavior to not to suspend the port if the device is enabled as a wakeup source. If the AT91 system goes to slow clock mode, the port should be suspended always and the clocks should be switched off. The patch attached updates the atmel_serial driver to match the changes in serial core. Also, the interrupts are disabled when the clock is disabled. If we disable the clock with interrupts enabled, an interrupt may get stuck. If this is the DBGU interrupt, this blocks the OR logic at system controller and thus all other sysc interrupts. Signed-off-by: Anti Sullin Signed-off-by: Haavard Skinnemoen Cc: Michael Trimarchi Cc: Andrew Victor Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/atmel_serial.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 3a6da80b081..61fb8b6d19a 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -131,7 +131,8 @@ struct atmel_uart_char { struct atmel_uart_port { struct uart_port uart; /* uart */ struct clk *clk; /* uart clock */ - unsigned short suspended; /* is port suspended? */ + int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */ + u32 backup_imr; /* IMR saved during suspend */ int break_active; /* break being received */ short use_dma_rx; /* enable PDC receiver */ @@ -984,8 +985,15 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, * This is called on uart_open() or a resume event. */ clk_enable(atmel_port->clk); + + /* re-enable interrupts if we disabled some on suspend */ + UART_PUT_IER(port, atmel_port->backup_imr); break; case 3: + /* Back up the interrupt mask and disable all interrupts */ + atmel_port->backup_imr = UART_GET_IMR(port); + UART_PUT_IDR(port, -1); + /* * Disable the peripheral clock for this serial port. * This is called on uart_close() or a suspend event. @@ -1475,13 +1483,12 @@ static int atmel_serial_suspend(struct platform_device *pdev, cpu_relax(); } - if (device_may_wakeup(&pdev->dev) - && !atmel_serial_clk_will_stop()) - enable_irq_wake(port->irq); - else { - uart_suspend_port(&atmel_uart, port); - atmel_port->suspended = 1; - } + /* we can not wake up if we're running on slow clock */ + atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); + if (atmel_serial_clk_will_stop()) + device_set_wakeup_enable(&pdev->dev, 0); + + uart_suspend_port(&atmel_uart, port); return 0; } @@ -1491,11 +1498,8 @@ static int atmel_serial_resume(struct platform_device *pdev) struct uart_port *port = platform_get_drvdata(pdev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_port->suspended) { - uart_resume_port(&atmel_uart, port); - atmel_port->suspended = 0; - } else - disable_irq_wake(port->irq); + uart_resume_port(&atmel_uart, port); + device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); return 0; } @@ -1513,6 +1517,8 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); port = &atmel_ports[pdev->id]; + port->backup_imr = 0; + atmel_init_port(port, pdev); if (!atmel_use_dma_rx(&port->uart)) { -- cgit v1.2.3 From 44ea91c597ae4641d9ac21b8bbba0795d2f4261e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 20 Sep 2008 00:31:50 +0000 Subject: [SCSI] Fix hang with split requests Sometimes, particularly for USB devices with the last sector bug, requests get completed in chunks. There's a bug in this in that if one of the chunks gets an error, we complete that chunk with an error but never move on to the remaining ones, leading to the request hanging (because it's not fully completed). Fix this by completing all remaining chunks if an error is encountered. Cc: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ff5d56b3ee4..62307bd794a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -852,7 +852,7 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd) void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) { int result = cmd->result; - int this_count = scsi_bufflen(cmd); + int this_count; struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; int error = 0; @@ -908,6 +908,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) */ if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) return; + this_count = blk_rq_bytes(req); /* good_bytes = 0, or (inclusive) there were leftovers and * result = 0, so scsi_end_request couldn't retry. -- cgit v1.2.3 From c9bab96bbfdda59fa8a35ba536c22e66055669e5 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Tue, 26 Aug 2008 18:30:45 -0700 Subject: USB Storage: Sierra: Non-configurable TRU-Install This patch alters the Sierra Mass Storage patch so that it is non-configurable. Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 12 ------------ drivers/usb/storage/Makefile | 3 +-- drivers/usb/storage/unusual_devs.h | 2 -- drivers/usb/storage/usb.c | 2 -- 4 files changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c76034672c1..3d9249632ae 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -146,18 +146,6 @@ config USB_STORAGE_KARMA on the resulting scsi device node returns the Karma to normal operation. -config USB_STORAGE_SIERRA - bool "Sierra Wireless TRU-Install Feature Support" - depends on USB_STORAGE - help - Say Y here to include additional code to support Sierra Wireless - products with the TRU-Install feature (e.g., AC597E, AC881U). - - This code switches the Sierra Wireless device from being in - Mass Storage mode to Modem mode. It also has the ability to - support host software upgrades should full Linux support be added - to TRU-Install. - config USB_STORAGE_CYPRESS_ATACB bool "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index bc3415b475c..7f8beb5366a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -21,11 +21,10 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SIERRA) += sierra_ms.o usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ - initializers.o $(usb-storage-obj-y) + initializers.o sierra_ms.o $(usb-storage-obj-y) ifneq ($(CONFIG_USB_LIBUSUAL),) obj-$(CONFIG_USB) += libusual.o diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index ba412e68d47..0d44f7c11b7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1576,7 +1576,6 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, 0), -#ifdef CONFIG_USB_STORAGE_SIERRA /* Reported by Kevin Lloyd * Entry is needed for the initializer function override, * which instructs the device to load as a modem @@ -1587,7 +1586,6 @@ UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999, "USB MMC Storage", US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init, 0), -#endif /* Reported by Jaco Kroon * The usb-storage module found on the Digitech GNX4 (and supposedly other diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 73679aa506d..27016fd2cad 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -102,9 +102,7 @@ #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB #include "cypress_atacb.h" #endif -#ifdef CONFIG_USB_STORAGE_SIERRA #include "sierra_ms.h" -#endif /* Some informational data */ MODULE_AUTHOR("Matthew Dharm "); -- cgit v1.2.3 From 73b2c2057579314c4fea1a37e35a501fbb8b9916 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Mon, 25 Aug 2008 19:20:40 -0700 Subject: USB Serial: Sierra: Device addition & version rev This patch adds devices to the sierra driver and rev's the driver version. Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 706033753ad..396f099ba9f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -14,7 +14,7 @@ Whom based his on the Keyspan driver by Hugh Blemings */ -#define DRIVER_VERSION "v.1.2.13a" +#define DRIVER_VERSION "v.1.3.2" #define DRIVER_AUTHOR "Kevin Lloyd " #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -30,9 +30,6 @@ #define SWIMS_USB_REQUEST_SetPower 0x00 #define SWIMS_USB_REQUEST_SetNmea 0x07 -#define SWIMS_USB_REQUEST_SetMode 0x0B -#define SWIMS_USB_REQUEST_GetSwocInfo 0x0A -#define SWIMS_SET_MODE_Modem 0x0001 /* per port private data */ #define N_IN_URB 4 @@ -175,6 +172,8 @@ static struct usb_device_id id_table [] = { /* Sierra Wireless Device */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */ + { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */ + { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ @@ -204,6 +203,8 @@ static struct usb_device_id id_table [] = { /* Sierra Wireless Device */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, /* Sierra Wireless Device */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, + /* Sierra Wireless Device */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ -- cgit v1.2.3 From 0bcfeb3ec9467a8dfae3e906925ec28fe788afcf Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 26 Aug 2008 14:43:46 -0700 Subject: USB: ehci: fix some ehci hangs and crashes I noticed that the "Refactor "if (handshake()) state = HC_STATE_HALT" patch from earlier this year perpetuated a potential problem: it can mark the controller as halted when it's still running (but not acting as, perhaps wrongly, expected). That caused some hangs and crashes, rather than more polite failure modes of a truly halted controller. This patch forces a true halt, and emits a (previously missing) diagnostic. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d9d53f289ca..8409e0705d6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -145,16 +145,6 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, return -ETIMEDOUT; } -static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - int error = handshake(ehci, ptr, mask, done, usec); - if (error) - ehci_to_hcd(ehci)->state = HC_STATE_HALT; - - return error; -} - /* force HC to halt state from unknown (EHCI spec section 2.3) */ static int ehci_halt (struct ehci_hcd *ehci) { @@ -173,6 +163,22 @@ static int ehci_halt (struct ehci_hcd *ehci) STS_HALT, STS_HALT, 16 * 125); } +static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, + u32 mask, u32 done, int usec) +{ + int error; + + error = handshake(ehci, ptr, mask, done, usec); + if (error) { + ehci_halt(ehci); + ehci_to_hcd(ehci)->state = HC_STATE_HALT; + ehci_err(ehci, "force halt; handhake %p %08x %08x -> %d\n", + ptr, mask, done, error); + } + + return error; +} + /* put TDI/ARC silicon into EHCI mode */ static void tdi_reset (struct ehci_hcd *ehci) { -- cgit v1.2.3 From 0a4d7f45ac173862796eb81942afc843d6244798 Mon Sep 17 00:00:00 2001 From: Richard Nauber Date: Tue, 26 Aug 2008 23:34:11 +0200 Subject: USB: Fix the Nokia 6300 storage-mode. This patch fixes that behavior: ... Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] Sense Key : 0x0 [current] Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] ASC=0x0 ASCQ=0x0 Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] Sense Key : 0x0 [current] Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] ASC=0x0 ASCQ=0x0 Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] Sense Key : 0x0 [current] Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] ASC=0x0 ASCQ=0x0 Aug 26 22:39:23 rnauber sd 2:0:0:0: [sda] Sense Key : 0x0 [current] ... cat /proc/bus/usb/devices ... T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0421 ProdID=04fa Rev= 6.01 S: Manufacturer=Nokia S: Product=Nokia 6300 S: SerialNumber=35XXXXXXXX C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms ... From: Richard Nauber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0d44f7c11b7..37f45c6c8f7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -232,6 +232,13 @@ UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Richard Nauber */ +UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601, + "Nokia", + "6300", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From f8834f1febb8f56cdcfeb35485e0cc7a8d547818 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Fri, 22 Aug 2008 17:30:44 -0500 Subject: USB: Correct Sierra Wireless USB EVDO Modem Device ID I was trying to figure out why my device wasn't supported by the drivers/usb/serial/sierra.c driver, while looking throught the device IDs I spotted what I believe to be a typo in the device IDs. Please apply the following patch If you look down further, there is another HP wireless broadband card, which has a vendor ID of 03f0, like my device. Below is my "lsusb -v -d 03f0:1b1d". Bus 001 Device 005: ID 03f0:1b1d Hewlett-Packard Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x03f0 Hewlett-Packard idProduct 0x1b1d bcdDevice 0.01 iManufacturer 1 HP iProduct 2 HP ev2200 1xEV-DO Broadband Wireless Module iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 67 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower 0mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 7 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 255 Vendor Specific Subclass bInterfaceProtocol 255 Vendor Specific Protocol iInterface 3 Data Interface Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0010 1x 16 bytes bInterval 128 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x04 EP 4 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x85 EP 5 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x05 EP 5 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 0 Device Status: 0x0000 (Bus Powered) From: Tony Murray Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 396f099ba9f..eb87640f362 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -160,7 +160,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ -- cgit v1.2.3 From 83a798207361cc26385187b2e71efa2b5d75de7f Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 22 Aug 2008 14:13:00 -0700 Subject: USB: fix hcd interrupt disabling Commit de85422b94ddb23c021126815ea49414047c13dc, 'USB: fix interrupt disabling for HCDs with shared interrupt handlers' changed usb_add_hcd() to strip IRQF_DISABLED from irqflags prior to calling request_irq() with the justification that such a removal was necessary for shared interrupts to work properly. Unfortunately, the change in that commit unconditionally removes the IRQF_DISABLED flag, causing problems on platforms that don't use a shared interrupt but require IRQF_DISABLED. This change adds a check for IRQF_SHARED prior to removing the IRQF_DISABLED flag. Fixes the PS3 system startup hang reported with recent Fedora and OpenSUSE kernels. Note that this problem is hidden when CONFIG_LOCKDEP=y (ps3_defconfig), as local_irq_enable_in_hardirq() is defined as a null statement for that config. CC: stable Signed-off-by: Geoff Levand Cc: Alan Stern Cc: Stefan Becker Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8abd4e59bf4..8ab389dca2b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1876,7 +1876,8 @@ int usb_add_hcd(struct usb_hcd *hcd, * with IRQF_SHARED. As usb_hcd_irq() will always disable * interrupts we can remove it here. */ - irqflags &= ~IRQF_DISABLED; + if (irqflags & IRQF_SHARED) + irqflags &= ~IRQF_DISABLED; snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); -- cgit v1.2.3 From 697e04db5678fadf96d437806b676403ebee806d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 2 Sep 2008 10:52:08 +0200 Subject: USB: update of Documentation/usb/anchors.txt The extended anchor API is documented Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/anchors.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt index 7304bcf5a30..5e6b64c20d2 100644 --- a/Documentation/usb/anchors.txt +++ b/Documentation/usb/anchors.txt @@ -42,9 +42,21 @@ This function kills all URBs associated with an anchor. The URBs are called in the reverse temporal order they were submitted. This way no data can be reordered. +usb_unlink_anchored_urbs() +-------------------------- + +This function unlinks all URBs associated with an anchor. The URBs +are processed in the reverse temporal order they were submitted. +This is similar to usb_kill_anchored_urbs(), but it will not sleep. +Therefore no guarantee is made that the URBs have been unlinked when +the call returns. They may be unlinked later but will be unlinked in +finite time. + usb_wait_anchor_empty_timeout() ------------------------------- This function waits for all URBs associated with an anchor to finish or a timeout, whichever comes first. Its return value will tell you whether the timeout was reached. + + -- cgit v1.2.3 From c3e3208e4b0cf4ed69cbcaa5e059e5cf64437c9a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 31 Aug 2008 18:04:27 -0700 Subject: usb gadget: fix omap_udc DMA regression This resolves another regression caused by the "use omap_read/write instead of __REG" patch: the hardware address used for DMA to/from the UDC became wrong. Bug noted by Russell King. Reported-by: Russell King Signed-off-by: David Brownell Acked-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/omap_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 574c53831a0..bb54cca4c54 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -787,7 +787,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p(UDC_DATA_DMA), + UDC_DATA_DMA, 0, 0); } } else { @@ -804,7 +804,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p(UDC_DATA_DMA), + UDC_DATA_DMA, 0, 0); /* EMIFF or SDRC */ omap_set_dma_dest_burst_mode(ep->lch, -- cgit v1.2.3 From 49cd2480baeb377f91e66ba682f81cac2a1feaa1 Mon Sep 17 00:00:00 2001 From: Filip Joelsson Date: Sun, 31 Aug 2008 08:22:16 +0200 Subject: USB: Fixing Nokia 3310c in storage mode I had trouble connecting my cell phone as a storage device - so I added it to the unusual_devs.h list. I had trouble with the bcdDeviceMin and Max values - so after some experimenting I made it pretty inclusive. From: Filip Joelsson Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 37f45c6c8f7..b311300cf78 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -160,6 +160,13 @@ UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), +/* Reported by Filip Joelsson */ +UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, + "Nokia", + "Nokia 3110c", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Mario Rettig */ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, "Nokia", -- cgit v1.2.3 From 0590d5875e3a5dc6586fb16354037f115628896d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 30 Aug 2008 19:42:02 +0300 Subject: usb: musb: fix include path headers were moved, fixing. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 4 ++-- drivers/usb/musb/omap2430.c | 4 ++-- drivers/usb/musb/omap2430.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c5b8f0296fc..128e949db47 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -100,8 +100,8 @@ #include #ifdef CONFIG_ARM -#include -#include +#include +#include #include #endif diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 298b22e6ad0..9d2dcb121c5 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -35,8 +35,8 @@ #include #include -#include -#include +#include +#include #include "musb_core.h" #include "omap2430.h" diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h index 786a62071f7..dc7670718cd 100644 --- a/drivers/usb/musb/omap2430.h +++ b/drivers/usb/musb/omap2430.h @@ -11,8 +11,8 @@ #define __MUSB_OMAP243X_H__ #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) -#include -#include +#include +#include /* * OMAP2430-specific definitions -- cgit v1.2.3 From 01c17142659c02d8cd4c67acdd8358180c5c4fb6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 26 Aug 2008 23:35:04 -0700 Subject: USB: fix EHCI periodic transfers As noted by Stefan Neis , we had a recent regression with EHCI periodic transfers, in some (seemingly not all that common) cases. The root cause was that the schedule activation was only loosely coupled to the addition or removal of transfers, so two different execution contexts could both think they had to deactivate (or conversely activate) the schedule. So this fix tightens that coupling, managing it more like a refcount. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b7853c8bac0..4a0c5a78b2e 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -437,6 +437,9 @@ static int enable_periodic (struct ehci_hcd *ehci) u32 cmd; int status; + if (ehci->periodic_sched++) + return 0; + /* did clearing PSE did take effect yet? * takes effect only at frame boundaries... */ @@ -461,6 +464,9 @@ static int disable_periodic (struct ehci_hcd *ehci) u32 cmd; int status; + if (--ehci->periodic_sched) + return 0; + /* did setting PSE not take effect yet? * takes effect only at frame boundaries... */ @@ -544,13 +550,10 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) : (qh->usecs * 8); /* maybe enable periodic schedule processing */ - if (!ehci->periodic_sched++) - return enable_periodic (ehci); - - return 0; + return enable_periodic(ehci); } -static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) +static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) { unsigned i; unsigned period; @@ -586,9 +589,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) qh_put (qh); /* maybe turn off periodic schedule */ - ehci->periodic_sched--; - if (!ehci->periodic_sched) - (void) disable_periodic (ehci); + return disable_periodic(ehci); } static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) @@ -1562,9 +1563,7 @@ itd_link_urb ( urb->hcpriv = NULL; timer_action (ehci, TIMER_IO_WATCHDOG); - if (unlikely (!ehci->periodic_sched++)) - return enable_periodic (ehci); - return 0; + return enable_periodic(ehci); } #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) @@ -1642,7 +1641,7 @@ itd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - ehci->periodic_sched--; + (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (unlikely (list_empty (&stream->td_list))) { @@ -1951,9 +1950,7 @@ sitd_link_urb ( urb->hcpriv = NULL; timer_action (ehci, TIMER_IO_WATCHDOG); - if (!ehci->periodic_sched++) - return enable_periodic (ehci); - return 0; + return enable_periodic(ehci); } /*-------------------------------------------------------------------------*/ @@ -2019,7 +2016,7 @@ sitd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - ehci->periodic_sched--; + (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (list_empty (&stream->td_list)) { @@ -2243,8 +2240,7 @@ restart: if (unlikely (modified)) { if (likely(ehci->periodic_sched > 0)) goto restart; - /* maybe we can short-circuit this scan! */ - disable_periodic(ehci); + /* short-circuit this scan */ now_uframe = clock; break; } -- cgit v1.2.3 From ce816cf9c917435cd2e3b68acc7cfe2c1f4a814f Mon Sep 17 00:00:00 2001 From: Andreas Bombe Date: Sun, 14 Sep 2008 01:58:55 +0200 Subject: usb-serial: Add Siemens EF81 to PL-2303 hack triggers This hardware needs the pl2303 hack in order to work properly :( Signed-off-by: Andreas Bombe Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index b157c48e8b7..4f7f9e3ae0a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -733,7 +733,9 @@ int usb_serial_probe(struct usb_interface *interface, ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) || ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) && - (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) { + (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) || + ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && + (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) { if (interface != dev->actconfig->interface[0]) { /* check out the endpoints of the other interface*/ iface_desc = dev->actconfig->interface[0]->cur_altsetting; -- cgit v1.2.3 From ba0f332c413796925ce322d311d75269689a9e5d Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 4 Sep 2008 21:28:21 +0100 Subject: USB: SERIAL CP2101 add device IDs Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 442cba69cce..1279553381e 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -72,6 +72,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ @@ -83,6 +84,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ @@ -93,6 +95,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { } /* Terminating Entry */ }; -- cgit v1.2.3 From fe1926a0f549741ed0ca778aa1c7d3e208895dee Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 4 Sep 2008 09:56:35 -0400 Subject: USB: unusual_devs addition for RockChip MP3 player This patch (as1136) adds an unusual_devs entry for a version of the RockChip MP3 player which can't handle the MODE SENSE command used for write-protect detection. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b311300cf78..4d9ca02ac67 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1001,6 +1001,13 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Adrian Pilchowiec */ +UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, + "RockChip", + "MP3", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), + /* Reported by Massimiliano Ghilardi * This USB MP3/AVI player device fails and disconnects if more than 128 * sectors (64kB) are read/written in a single command, and may be present -- cgit v1.2.3 From 6ef65a7fb609a7aca72730dfb9890f30fcd723bf Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Mon, 8 Sep 2008 10:08:59 +0200 Subject: USB: fsl_usb2_udc: fix VDBG() format string Fixes: drivers/usb/gadget/fsl_usb2_udc.c: In function 'dr_controller_setup': drivers/usb/gadget/fsl_usb2_udc.c:229: warning: format '%p' expects type 'void *', but argument 3 has type 'int' Signed-off-by: Peter Korsgaard Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_usb2_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 1cfccf102a2..45ad556169f 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -223,7 +223,7 @@ static int dr_controller_setup(struct fsl_udc *udc) fsl_writel(tmp, &dr_regs->endpointlistaddr); VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x", - (int)udc->ep_qh, (int)tmp, + udc->ep_qh, (int)tmp, fsl_readl(&dr_regs->endpointlistaddr)); /* Config PHY interface */ -- cgit v1.2.3 From 2bcbe4c199ec012169f938d2c6b543f50c4925ed Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Wed, 10 Sep 2008 14:11:38 -0700 Subject: usb serial: ti_usb_3410_5052 obviously broken by firmware changes While making some other changes to ti_usb_3410_5052, I noticed that the changes made to move the firmware loading to a separate function are broken (in ti_download_firmware(), status is set to -ENOMEM and never changed). This means the driver will never initialize the device properly. It looks like status was supposed to get the result of ti_do_download(). Signed-off-by: Chris Adams Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index e39c779e416..9a3e495c769 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1744,7 +1744,7 @@ static int ti_download_firmware(struct ti_device *tdev, int type) if (buffer) { memcpy(buffer, fw_p->data, fw_p->size); memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size); - ti_do_download(dev, pipe, buffer, fw_p->size); + status = ti_do_download(dev, pipe, buffer, fw_p->size); kfree(buffer); } release_firmware(fw_p); -- cgit v1.2.3 From a18f80b4e2fdbc7b88d412c3deb533b9f1f30c30 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 16 Sep 2008 15:46:50 +0200 Subject: USB: ftdi_sio: Add 0x5050/0x0900 USB IDs (Papouch Quido USB 4/4) USB: ftdi_sio: Add 0x5050/0x0900 USB IDs (Papouch Quido USB 4/4) Signed-off-by: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 984f6eff4c4..8ff8d0a1bae 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -654,6 +654,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 382265bba96..ad41287ac2c 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -750,6 +750,7 @@ #define PAPOUCH_VID 0x5050 /* Vendor ID */ #define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ /* * ACG Identification Technologies GmbH products (http://www.acg.de/). -- cgit v1.2.3 From 884579d03a3e1e9ac8b7f32a1c36387cac3eb80b Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 17 Sep 2008 14:40:46 -0300 Subject: USB: serial: add ZTE CDMA Tech id to option driver Signed-off-by: Otavio Salvador Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9f9cd36455f..73f8277f88f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -218,6 +218,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 #define ZTE_PRODUCT_MF628 0x0015 +#define ZTE_PRODUCT_CDMA_TECH 0xfffe static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, @@ -347,6 +348,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From b77a5c7040643e658622148bb7d7dad63e8d0158 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Wed, 17 Sep 2008 09:03:38 -0700 Subject: USB Serial: Sierra: Add MC8785 VID/PID Add another MC8785 VID/PID Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index eb87640f362..ea1a103c99b 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -186,6 +186,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ + { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */ { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */ -- cgit v1.2.3 From 09fa14aa9273ca5cf5459b2057eb79e83e81e6be Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 22 Sep 2008 15:00:08 -0700 Subject: USB: drivers/usb/musb/: disable it on SuperH In file included from drivers/usb/musb/musb_core.h:59, from drivers/usb/musb/musb_core.c:108: drivers/usb/musb/musb_io.h:42: error: conflicting types for '__raw_readsl' /usr/src/devel/arch/sh/include/asm/io.h:112: error: previous declaration of '__raw_readsl' was here drivers/usb/musb/musb_io.h:42: error: conflicting types for '__raw_readsl' /usr/src/devel/arch/sh/include/asm/io.h:112: error: previous declaration of '__raw_readsl' was here drivers/usb/musb/musb_io.h:44: error: conflicting types for 'readsw' /usr/src/devel/arch/sh/include/asm/io.h:164: error: previous definition of 'readsw' was here drivers/usb/musb/musb_io.h:46: error: conflicting types for 'readsb' /usr/src/devel/arch/sh/include/asm/io.h:163: error: previous definition of 'readsb' was here drivers/usb/musb/musb_io.h:49: error: conflicting types for '__raw_writesl' /usr/src/devel/arch/sh/include/asm/io.h:111: error: previous declaration of '__raw_writesl' was here drivers/usb/musb/musb_io.h:49: error: conflicting types for '__raw_writesl' /usr/src/devel/arch/sh/include/asm/io.h:111: error: previous declaration of '__raw_writesl' was here drivers/usb/musb/musb_io.h:51: error: conflicting types for 'writesw' /usr/src/devel/arch/sh/include/asm/io.h:164: error: previous definition of 'writesw' was here drivers/usb/musb/musb_io.h:53: error: conflicting types for 'writesb' /usr/src/devel/arch/sh/include/asm/io.h:163: error: previous definition of 'writesb' was here Cc: Karsten Keil Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index a0017486ad4..58b2b8fc943 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -9,6 +9,7 @@ comment "Enable Host or Gadget support to see Inventra options" # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC depends on (USB || USB_GADGET) && HAVE_CLK + depends on !SUPERH select TWL4030_USB if MACH_OMAP_3430SDP tristate 'Inventra Highspeed Dual Role Controller (TI, ...)' help -- cgit v1.2.3 From 96285cb885b445b03b22849f2536af23c7454a11 Mon Sep 17 00:00:00 2001 From: Gaetan Carlier Date: Mon, 22 Sep 2008 15:00:09 -0700 Subject: usb: ftdi_sio: add support for Domintell devices Support for Domintell devices (FTDI FT232BM based) : DGQG and DUSB01 module. PIDs were missing. Signed-off-by: Gaetan Carlier Cc: Greg Kroah-Hartman Cc: Ian Abbott Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8ff8d0a1bae..3dc93b542b3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -655,6 +655,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index ad41287ac2c..8a5b6df3a97 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -839,6 +839,10 @@ /* Rig Expert Ukraine devices */ #define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ +/* Domintell products http://www.domintell.com */ +#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ +#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -- cgit v1.2.3 From af747c460b663a4b7795dc3f6897b5506fde6888 Mon Sep 17 00:00:00 2001 From: David Almaroad Date: Mon, 22 Sep 2008 15:00:11 -0700 Subject: usb: unusual devs patch for Nokia 5310 Music Xpress The Nokia 5310 Music Xpress phone reports one too many sectors in usb-storage mode. This patch resolves that. Signed-off-by: David Almaroad Cc: Matthew Dharm Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 4d9ca02ac67..cd155475cb6 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -246,6 +246,13 @@ UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Patch for Nokia 5310 capacity */ +UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, + "Nokia", + "5310", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From 5257d97a219e17abf8188f136e1189da3b3af33c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 22 Sep 2008 14:43:08 -0400 Subject: USB: revert recovery from transient errors This patch (as1135) essentially reverts the major parts of two earlier patches to usbcore, because they ended up causing a regression. Trying to recover from transient communication errors can lead to other problems, because operations that failed during the error period are not always retried. The simplest example is the initial Set-Config request sent after device enumeration; if it gets lost then it will not be retried and the device will remain unconfigured. This patch restores the old behavior in which any port disconnect or port disable causes the entire device structure to be removed, fixing a reported regression. Signed-off-by: Alan Stern Tested-by: Frans Pop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6a5cb018383..d99963873e3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2683,35 +2683,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, USB_PORT_STAT_C_ENABLE); #endif - /* Try to use the debounce delay for protection against - * port-enable changes caused, for example, by EMI. - */ - if (portchange & (USB_PORT_STAT_C_CONNECTION | - USB_PORT_STAT_C_ENABLE)) { - status = hub_port_debounce(hub, port1); - if (status < 0) { - if (printk_ratelimit()) - dev_err (hub_dev, "connect-debounce failed, " - "port %d disabled\n", port1); - portstatus &= ~USB_PORT_STAT_CONNECTION; - } else { - portstatus = status; - } - } - /* Try to resuscitate an existing device */ udev = hdev->children[port1-1]; if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && udev->state != USB_STATE_NOTATTACHED) { - usb_lock_device(udev); if (portstatus & USB_PORT_STAT_ENABLE) { status = 0; /* Nothing to do */ - } else if (!udev->persist_enabled) { - status = -ENODEV; /* Mustn't resuscitate */ #ifdef CONFIG_USB_SUSPEND - } else if (udev->state == USB_STATE_SUSPENDED) { + } else if (udev->state == USB_STATE_SUSPENDED && + udev->persist_enabled) { /* For a suspended device, treat this as a * remote wakeup event. */ @@ -2726,7 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, #endif } else { - status = usb_reset_device(udev); + status = -ENODEV; /* Don't resuscitate */ } usb_unlock_device(udev); @@ -2741,6 +2723,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, usb_disconnect(&hdev->children[port1-1]); clear_bit(port1, hub->change_bits); + if (portchange & (USB_PORT_STAT_C_CONNECTION | + USB_PORT_STAT_C_ENABLE)) { + status = hub_port_debounce(hub, port1); + if (status < 0) { + if (printk_ratelimit()) + dev_err(hub_dev, "connect-debounce failed, " + "port %d disabled\n", port1); + portstatus &= ~USB_PORT_STAT_CONNECTION; + } else { + portstatus = status; + } + } + /* Return now if debouncing failed or nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { @@ -2748,7 +2743,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 && !(portstatus & (1 << USB_PORT_FEAT_POWER))) set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); - + if (portstatus & USB_PORT_STAT_ENABLE) goto done; return; -- cgit v1.2.3 From e5d2304802a63304a54cff010209c4a717a2509f Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 23 Sep 2008 14:53:14 -0700 Subject: can: Add documentation for virtual CAN driver usage This patch adds a usage documentation for the virtual CAN driver (vcan). Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- Documentation/networking/can.txt | 44 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt index 297ba7b1cca..2035bc4932f 100644 --- a/Documentation/networking/can.txt +++ b/Documentation/networking/can.txt @@ -35,8 +35,9 @@ This file contains 6.1 general settings 6.2 local loopback of sent frames 6.3 CAN controller hardware filters - 6.4 currently supported CAN hardware - 6.5 todo + 6.4 The virtual CAN driver (vcan) + 6.5 currently supported CAN hardware + 6.6 todo 7 Credits @@ -584,7 +585,42 @@ solution for a couple of reasons: @133MHz with four SJA1000 CAN controllers from 2002 under heavy bus load without any problems ... - 6.4 currently supported CAN hardware (September 2007) + 6.4 The virtual CAN driver (vcan) + + Similar to the network loopback devices, vcan offers a virtual local + CAN interface. A full qualified address on CAN consists of + + - a unique CAN Identifier (CAN ID) + - the CAN bus this CAN ID is transmitted on (e.g. can0) + + so in common use cases more than one virtual CAN interface is needed. + + The virtual CAN interfaces allow the transmission and reception of CAN + frames without real CAN controller hardware. Virtual CAN network + devices are usually named 'vcanX', like vcan0 vcan1 vcan2 ... + When compiled as a module the virtual CAN driver module is called vcan.ko + + Since Linux Kernel version 2.6.24 the vcan driver supports the Kernel + netlink interface to create vcan network devices. The creation and + removal of vcan network devices can be managed with the ip(8) tool: + + - Create a virtual CAN network interface: + ip link add type vcan + + - Create a virtual CAN network interface with a specific name 'vcan42': + ip link add dev vcan42 type vcan + + - Remove a (virtual CAN) network interface 'vcan42': + ip link del vcan42 + + The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete. + + Virtual CAN network device creation in older Kernels: + In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan + netdevices at module load time by default. This value can be changed + with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8' + + 6.5 currently supported CAN hardware On the project website http://developer.berlios.de/projects/socketcan there are different drivers available: @@ -603,7 +639,7 @@ solution for a couple of reasons: Please check the Mailing Lists on the berlios OSS project website. - 6.5 todo (September 2007) + 6.6 todo The configuration interface for CAN network drivers is still an open issue that has not been finalized in the socketcan project. Also the -- cgit v1.2.3 From 44ce17192a01218b242e032237e1d2e52ef50429 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Tue, 23 Sep 2008 19:48:36 +0200 Subject: [MIPS] au1000: Fix gpio direction When setting the direction of one GPIO pin we have to keep the state of the other pins, hence use binary OR. Also gpio_direction_output() wants to set an initial value, so add that too. This fixes a problem with the USB power switch on mtx-1 boards. Signed-off-by: Bruno Randolf Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/gpio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c index b485d94ce8a..1f058434b72 100644 --- a/arch/mips/au1000/common/gpio.c +++ b/arch/mips/au1000/common/gpio.c @@ -61,7 +61,8 @@ static int au1xxx_gpio2_direction_input(unsigned gpio) static int au1xxx_gpio2_direction_output(unsigned gpio, int value) { gpio -= AU1XXX_GPIO_BASE; - gpio2->dir = (0x01 << gpio) | (value << gpio); + gpio2->dir |= 0x01 << gpio; + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio); return 0; } @@ -90,6 +91,7 @@ static int au1xxx_gpio1_direction_input(unsigned gpio) static int au1xxx_gpio1_direction_output(unsigned gpio, int value) { gpio1->trioutclr = (0x01 & gpio); + au1xxx_gpio1_write(gpio, value); return 0; } -- cgit v1.2.3 From 5291925a9a65ea334f6e887d0f01dd119b8e2b2e Mon Sep 17 00:00:00 2001 From: Jack Tan Date: Tue, 23 Sep 2008 22:52:34 +0800 Subject: [MIPS] Fixe the definition of PTRS_PER_PGD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we use > 4KB's page size the original definition is not consistent with PGDIR_SIZE. For exeample, if we use 16KB page size the PGDIR_SHIFT is (14-2) + 14 = 26, PGDIR_SIZE is 2^26,so the PTRS_PER_PGD should be: 2^32/2^26 = 2^6 but the original definition of PTRS_PER_PGD is 4096 (PGDIR_ORDER = 0). So, this definition needs to be consistent with the PGDIR_SIZE. And the new definition is consistent with the PGD init in pagetable_init(). Signed-off-by: Dajie Tan Signed-off-by: Ralf Baechle --- include/asm-mips/pgtable-32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h index 4396e9ffd41..55813d6150c 100644 --- a/include/asm-mips/pgtable-32.h +++ b/include/asm-mips/pgtable-32.h @@ -57,7 +57,7 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, #define PMD_ORDER 1 #define PTE_ORDER 0 -#define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#define PTRS_PER_PGD (USER_PTRS_PER_PGD * 2) #define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) #define USER_PTRS_PER_PGD (0x80000000UL/PGDIR_SIZE) -- cgit v1.2.3 From d87798450a7635ab1bcc80271a13ce4a53b016a9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 Sep 2008 20:47:22 -0700 Subject: aoe: Fix OOPS after SKB queue changes. Reported by Thomas Graf. If we don't unlink the SKB from the queue when we send it out in aoenet_xmit(), dev_hard_start_xmit() will see skb->next as non-NULL and interpret this to mean the SKB is part of a GSO segment list. Add __skb_unlink() call to fix that. Signed-off-by: David S. Miller --- drivers/block/aoe/aoenet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 8fb26030eba..9157d64270c 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -99,8 +99,10 @@ aoenet_xmit(struct sk_buff_head *queue) { struct sk_buff *skb, *tmp; - skb_queue_walk_safe(queue, skb, tmp) + skb_queue_walk_safe(queue, skb, tmp) { + __skb_unlink(skb, queue); dev_queue_xmit(skb); + } } /* -- cgit v1.2.3 From 96ca4a2cc1454cf633a1e0796b7ef39d937b87ec Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 23 Sep 2008 21:23:19 -0700 Subject: net: remove ifalias on empty given alias This patch removes the potentially allocated ifalias when the (new) given alias is empty. E.g. when setting echo "" > /sys/class/net/eth0/ifalias Signed-off-by: Oliver Hartkopp Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index e9139053399..a90737fe247 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -967,6 +967,14 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) if (len >= IFALIASZ) return -EINVAL; + if (!len) { + if (dev->ifalias) { + kfree(dev->ifalias); + dev->ifalias = NULL; + } + return 0; + } + dev->ifalias = krealloc(dev->ifalias, len+1, GFP_KERNEL); if (!dev->ifalias) return -ENOMEM; -- cgit v1.2.3 From 1eda81495a49a4ee91d8863b0a441a624375efea Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Tue, 23 Sep 2008 22:40:02 -0400 Subject: x86: prevent stale state of c1e_mask across CPU offline/online, fix Fix build error introduced by commit 4faac97d44ac27 ("x86: prevent stale state of c1e_mask across CPU offline/online"). process_32.c needs to include idle.h to get the prototype for c1e_remove_cpu() Signed-off-by: Marc Dionne Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 4b3cfdf5421..31f40b24bf5 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -55,6 +55,7 @@ #include #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -- cgit v1.2.3 From 77a9a768b7374cd23d1f400097eede9f1547f508 Mon Sep 17 00:00:00 2001 From: Jeremy Katz Date: Tue, 23 Sep 2008 21:54:00 -0400 Subject: x86: disable apm on the olpc The OLPC doesn't support APM but also doesn't have DMI, so we can't detect and disable it based on DMI data. So, just disable based on machine_is_olpc() Signed-off-by: Jeremy Katz Signed-off-by: Ingo Molnar --- arch/x86/kernel/apm_32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 9ee24e6bc4b..732d1f4e10e 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -234,6 +234,7 @@ #include #include #include +#include #include #include @@ -2217,7 +2218,7 @@ static int __init apm_init(void) dmi_check_system(apm_dmi_table); - if (apm_info.bios.version == 0 || paravirt_enabled()) { + if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) { printk(KERN_INFO "apm: BIOS not found.\n"); return -ENODEV; } -- cgit v1.2.3 From 4ebb52d34fac2904e541ccfa8e32126db836fa92 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-Koenig Date: Wed, 24 Sep 2008 13:39:21 +0200 Subject: i2c-powermac: Fix section for probe and remove functions __devexit for i2c_powermac_probe is obviously wrong. In the definition of struct platform_driver i2c_powermac_driver the remove function i2c_powermac_remove is wrapped in __devexit_p, so it should be defined using __devexit. Signed-off-by: Uwe Kleine-Koenig Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-powermac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 22f6d5c00d8..0e7b1c6724a 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -180,7 +180,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = { }; -static int i2c_powermac_remove(struct platform_device *dev) +static int __devexit i2c_powermac_remove(struct platform_device *dev) { struct i2c_adapter *adapter = platform_get_drvdata(dev); struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter); @@ -200,7 +200,7 @@ static int i2c_powermac_remove(struct platform_device *dev) } -static int __devexit i2c_powermac_probe(struct platform_device *dev) +static int __devinit i2c_powermac_probe(struct platform_device *dev) { struct pmac_i2c_bus *bus = dev->dev.platform_data; struct device_node *parent = NULL; -- cgit v1.2.3 From e74783ec3cb981211689bd2cfd3248f8dc48ec01 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Wed, 24 Sep 2008 13:39:21 +0200 Subject: i2c-dev: Return correct error code on class_create() failure We need to convert the error pointer from class_create(), else we'll return the successful return code from register_chrdev() on failure. Signed-off-by: Sven Wegener Signed-off-by: Jean Delvare --- drivers/i2c/i2c-dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index af4491fa7e3..307d976c9b6 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -583,8 +583,10 @@ static int __init i2c_dev_init(void) goto out; i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); - if (IS_ERR(i2c_dev_class)) + if (IS_ERR(i2c_dev_class)) { + res = PTR_ERR(i2c_dev_class); goto out_unreg_chrdev; + } res = i2c_add_driver(&i2cdev_driver); if (res) -- cgit v1.2.3 From 17a172fe112a15dc9cd694d84983c51e1dc6bf34 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 24 Sep 2008 13:39:22 +0200 Subject: i2c: Fix mailing lists in two MAINTAINERS entries Two MAINTAINER entries (I2C/SMBUS STUB DRIVER and SIS 96X I2C/SMBUS DRIVER) were improperly pointing to the lm-sensors mailing list instead of the i2c mailing list. Fix them. Signed-off-by: Jean Delvare Cc: Mark M. Hoffman --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 42ebbfdc350..3596d178226 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1984,7 +1984,7 @@ S: Maintained I2C/SMBUS STUB DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com -L: lm-sensors@lm-sensors.org +L: i2c@lm-sensors.org S: Maintained I2C SUBSYSTEM @@ -3726,7 +3726,7 @@ S: Maintained SIS 96X I2C/SMBUS DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com -L: lm-sensors@lm-sensors.org +L: i2c@lm-sensors.org S: Maintained SIS FRAMEBUFFER DRIVER -- cgit v1.2.3 From 92cccc2cda9a744326bbd9f16c635187af7f8a09 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Sep 2008 14:28:16 -0700 Subject: ath9k: disable MIB interrupts to fix interrupt storm Enabling the MIB interrupts has proven to cause an interrupt storm after 7 hours of run. We will make use of the MIB interrupt once we have ANI supported added so for now to cure this we disable the interrupt. The interrupt storm can be seen as follows after 7 hours of run as reported by Steven Noonan : 18:28:38 sum 1106.00 18:28:39 sum 1037.62 18:28:40 sum 1069.00 18:28:41 sum 1167.00 18:28:42 sum 1155.00 18:28:43 sum 1339.00 18:28:44 sum 18355.00 18:28:45 sum 17845.45 18:28:46 sum 15285.00 18:28:47 sum 17511.00 18:28:48 sum 17568.69 18:28:49 sum 17704.04 18:28:50 sum 18566.67 18:28:51 sum 18913.13 at 18:28:44 the MIB interrupt kicked off and caused huge latency which can be seen even on a video he submitted: http://www.youtube.com/watch?v=4GeCx1gZMpA Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index c04959357bd..87e37bc3914 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c @@ -795,6 +795,12 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) sc->sc_imask |= ATH9K_INT_CST; + /* Note: We disable MIB interrupts for now as we don't yet + * handle processing ANI, otherwise you will get an interrupt + * storm after about 7 hours of usage making the system unusable + * with huge latency. Once we do have ANI processing included + * we can re-enable this interrupt. */ +#if 0 /* * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. @@ -802,6 +808,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) if (ath9k_hw_phycounters(ah) && ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) sc->sc_imask |= ATH9K_INT_MIB; +#endif /* * Some hardware processes the TIM IE and fires an * interrupt when the TIM bit is set. For hardware -- cgit v1.2.3 From 9930ccee16addda9fa7d9af00cd03cd5a10c8965 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 13 Sep 2008 12:22:05 +0100 Subject: wireless: Read scan flags correctly on x86-64 The SIOCSIWSCAN handler is passed data in an iw_point structure. Some drivers erronously use an iw_param instead. On 32 bit architectures the difference isn't noticed as the flags parameter tends to be the only one used by scan handlers and is at the same offset. On 64 bit architectures the pointer in the iw_point structure means the flag parameter is at different offsets in these structures. Thanks to Jean Tourrilhes for tracking this down for orinoco, and Pavel Roskin for confirming the fix and identifying other suspect handlers. Signed-off-by: David Kilroy Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 +- drivers/net/wireless/atmel.c | 2 +- drivers/net/wireless/orinoco.c | 2 +- drivers/net/wireless/rndis_wlan.c | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index ae58a12befd..370133e492d 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -7107,7 +7107,7 @@ static int airo_get_aplist(struct net_device *dev, */ static int airo_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + struct iw_point *dwrq, char *extra) { struct airo_info *ai = dev->priv; diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index bd65c485098..ecb02bdaab5 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -2258,7 +2258,7 @@ static int atmel_get_freq(struct net_device *dev, static int atmel_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + struct iw_point *dwrq, char *extra) { struct atmel_private *priv = netdev_priv(dev); diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 9a2fcc0163d..50904771f29 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -5291,7 +5291,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev, /* Trigger a scan (look for other cells in the vicinity) */ static int orinoco_ioctl_setscan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *srq, + struct iw_point *srq, char *extra) { struct orinoco_private *priv = netdev_priv(dev); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 00e965b9da7..2b414899dfa 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1627,7 +1627,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, static int rndis_iw_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct iw_param *param = &wrqu->param; struct usbnet *usbdev = dev->priv; union iwreq_data evt; int ret = -EINVAL; @@ -1635,7 +1634,7 @@ static int rndis_iw_set_scan(struct net_device *dev, devdbg(usbdev, "SIOCSIWSCAN"); - if (param->flags == 0) { + if (wrqu->data.flags == 0) { tmp = ccpu2(1); ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, sizeof(tmp)); -- cgit v1.2.3 From 762af43bda3d8281a2738d3920ae5ded170aaf39 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Sep 2008 10:30:34 +0200 Subject: cfg80211: fix static regdomains When Luis added the static regdomains back he used +/-20 of the centre frequencies to account for 40MHz bandwidth neglecting the fact that 40MHz bandwidth cannot be used on the channels close to the allowed band edges. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index a910cd2d0fd..59e4d7debf0 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -41,7 +41,7 @@ const struct ieee80211_regdomain world_regdom = { .n_reg_rules = 1, .alpha2 = "00", .reg_rules = { - REG_RULE(2402, 2472, 40, 6, 20, + REG_RULE(2412-10, 2462+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), } @@ -64,17 +64,17 @@ const struct ieee80211_regdomain us_regdom = { .alpha2 = "US", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), + REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), + REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), + REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), + REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), + REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), /* IEEE 802.11a, channels 149..165, outdoor */ - REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), + REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), } }; @@ -83,12 +83,12 @@ const struct ieee80211_regdomain jp_regdom = { .alpha2 = "JP", .reg_rules = { /* IEEE 802.11b/g, channels 1..14 */ - REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), + REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), /* IEEE 802.11a, channels 34..48 */ - REG_RULE(5170-20, 5240+20, 40, 6, 20, + REG_RULE(5170-10, 5240+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN), /* IEEE 802.11a, channels 52..64 */ - REG_RULE(5260-20, 5320+20, 40, 6, 20, + REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_NO_IBSS | NL80211_RRF_DFS), } @@ -101,22 +101,22 @@ const struct ieee80211_regdomain eu_regdom = { .alpha2 = "EU", .reg_rules = { /* IEEE 802.11b/g, channels 1..13 */ - REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), + REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-20, 5180+20, 40, 6, 23, + REG_RULE(5180-10, 5180+10, 40, 6, 23, NL80211_RRF_PASSIVE_SCAN), /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-20, 5200+20, 40, 6, 23, + REG_RULE(5200-10, 5200+10, 40, 6, 23, NL80211_RRF_PASSIVE_SCAN), /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-20, 5220+20, 40, 6, 23, + REG_RULE(5220-10, 5220+10, 40, 6, 23, NL80211_RRF_PASSIVE_SCAN), /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-20, 5320+20, 40, 6, 20, + REG_RULE(5240-10, 5320+10, 40, 6, 20, NL80211_RRF_NO_IBSS | NL80211_RRF_DFS), /* IEEE 802.11a, channels 100..140 */ - REG_RULE(5500-20, 5700+20, 40, 6, 30, + REG_RULE(5500-10, 5700+10, 40, 6, 30, NL80211_RRF_NO_IBSS | NL80211_RRF_DFS), } -- cgit v1.2.3 From 734366deaee05b1a5842d977960b4cc574d7551d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Sep 2008 10:56:48 +0200 Subject: cfg80211: clean up regulatory mess The recent code from Luis is an #ifdef hell and contains lots of code that's stuffed into the wrong file making a whole bunch of things needlessly non-static, and besides, what is it doing in core.c?? Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 144 ----------------------------- net/wireless/reg.c | 254 +++++++++++++++++++++++++++++++++++++++++----------- net/wireless/reg.h | 35 +------- 3 files changed, 203 insertions(+), 230 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 59e4d7debf0..88cb7339486 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -29,107 +29,6 @@ MODULE_AUTHOR("Johannes Berg"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); -struct list_head regulatory_requests; - -/* Central wireless core regulatory domains, we only need two, - * the current one and a world regulatory domain in case we have no - * information to give us an alpha2 */ -struct ieee80211_regdomain *cfg80211_regdomain; - -/* We keep a static world regulatory domain in case of the absence of CRDA */ -const struct ieee80211_regdomain world_regdom = { - .n_reg_rules = 1, - .alpha2 = "00", - .reg_rules = { - REG_RULE(2412-10, 2462+10, 40, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), - } -}; - -#ifdef CONFIG_WIRELESS_OLD_REGULATORY -/* All this fucking static junk will be removed soon, so - * don't fucking count on it !@#$ */ - -static char *ieee80211_regdom = "US"; -module_param(ieee80211_regdom, charp, 0444); -MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); - -/* We assume 40 MHz bandwidth for the old regulatory work. - * We make emphasis we are using the exact same frequencies - * as before */ - -const struct ieee80211_regdomain us_regdom = { - .n_reg_rules = 6, - .alpha2 = "US", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), - /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), - /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), - /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), - /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), - /* IEEE 802.11a, channels 149..165, outdoor */ - REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), - } -}; - -const struct ieee80211_regdomain jp_regdom = { - .n_reg_rules = 3, - .alpha2 = "JP", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..14 */ - REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), - /* IEEE 802.11a, channels 34..48 */ - REG_RULE(5170-10, 5240+10, 40, 6, 20, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channels 52..64 */ - REG_RULE(5260-10, 5320+10, 40, 6, 20, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), - } -}; - -const struct ieee80211_regdomain eu_regdom = { - .n_reg_rules = 6, - /* This alpha2 is bogus, we leave it here just for stupid - * backward compatibility */ - .alpha2 = "EU", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..13 */ - REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), - /* IEEE 802.11a, channel 36 */ - REG_RULE(5180-10, 5180+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channel 40 */ - REG_RULE(5200-10, 5200+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channel 44 */ - REG_RULE(5220-10, 5220+10, 40, 6, 23, - NL80211_RRF_PASSIVE_SCAN), - /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5240-10, 5320+10, 40, 6, 20, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), - /* IEEE 802.11a, channels 100..140 */ - REG_RULE(5500-10, 5700+10, 40, 6, 30, - NL80211_RRF_NO_IBSS | - NL80211_RRF_DFS), - } -}; - -#endif - -struct ieee80211_regdomain *cfg80211_world_regdom = - (struct ieee80211_regdomain *) &world_regdom; - -LIST_HEAD(regulatory_requests); -DEFINE_MUTEX(cfg80211_reg_mutex); - /* RCU might be appropriate here since we usually * only read the list, and that can happen quite * often because we need to do it for each command */ @@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = { .notifier_call = cfg80211_netdev_notifier_call, }; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY -const struct ieee80211_regdomain *static_regdom(char *alpha2) -{ - if (alpha2[0] == 'U' && alpha2[1] == 'S') - return &us_regdom; - if (alpha2[0] == 'J' && alpha2[1] == 'P') - return &jp_regdom; - if (alpha2[0] == 'E' && alpha2[1] == 'U') - return &eu_regdom; - /* Default, as per the old rules */ - return &us_regdom; -} -#endif - static int cfg80211_init(void) { int err; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - cfg80211_regdomain = - (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); - /* Used during reset_regdomains_static() */ - cfg80211_world_regdom = cfg80211_regdomain; -#else - cfg80211_regdomain = - (struct ieee80211_regdomain *) cfg80211_world_regdom; -#endif - err = wiphy_sysfs_init(); if (err) goto out_fail_sysfs; @@ -560,25 +435,6 @@ static int cfg80211_init(void) if (err) goto out_fail_reg; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); - print_regdomain_info(cfg80211_regdomain); - /* The old code still requests for a new regdomain and if - * you have CRDA you get it updated, otherwise you get - * stuck with the static values. We ignore "EU" code as - * that is not a valid ISO / IEC 3166 alpha2 */ - if (ieee80211_regdom[0] != 'E' && - ieee80211_regdom[1] != 'U') - err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, - ieee80211_regdom, NULL); -#else - err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); - if (err) - printk(KERN_ERR "cfg80211: calling CRDA failed - " - "unable to update world regulatory domain, " - "using static definition\n"); -#endif - return 0; out_fail_reg: diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 592b2e391d4..5fbeab50996 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -42,6 +42,18 @@ #include "core.h" #include "reg.h" +/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ +struct regulatory_request { + struct list_head list; + struct wiphy *wiphy; + int granted; + enum reg_set_by initiator; + char alpha2[2]; +}; + +static LIST_HEAD(regulatory_requests); +DEFINE_MUTEX(cfg80211_reg_mutex); + /* To trigger userspace events */ static struct platform_device *reg_pdev; @@ -51,6 +63,161 @@ static u32 supported_bandwidths[] = { MHZ_TO_KHZ(20), }; +static struct list_head regulatory_requests; + +/* Central wireless core regulatory domains, we only need two, + * the current one and a world regulatory domain in case we have no + * information to give us an alpha2 */ +static struct ieee80211_regdomain *cfg80211_regdomain; + +/* We keep a static world regulatory domain in case of the absence of CRDA */ +static const struct ieee80211_regdomain world_regdom = { + .n_reg_rules = 1, + .alpha2 = "00", + .reg_rules = { + REG_RULE(2412-10, 2462+10, 40, 6, 20, + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS), + } +}; + +static struct ieee80211_regdomain *cfg80211_world_regdom = + (struct ieee80211_regdomain *) &world_regdom; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY +static char *ieee80211_regdom = "US"; +module_param(ieee80211_regdom, charp, 0444); +MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); + +/* We assume 40 MHz bandwidth for the old regulatory work. + * We make emphasis we are using the exact same frequencies + * as before */ + +static const struct ieee80211_regdomain us_regdom = { + .n_reg_rules = 6, + .alpha2 = "US", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..11 */ + REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), + /* IEEE 802.11a, channel 36 */ + REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), + /* IEEE 802.11a, channel 40 */ + REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), + /* IEEE 802.11a, channel 44 */ + REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), + /* IEEE 802.11a, channels 48..64 */ + REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), + /* IEEE 802.11a, channels 149..165, outdoor */ + REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), + } +}; + +static const struct ieee80211_regdomain jp_regdom = { + .n_reg_rules = 3, + .alpha2 = "JP", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..14 */ + REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), + /* IEEE 802.11a, channels 34..48 */ + REG_RULE(5170-10, 5240+10, 40, 6, 20, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channels 52..64 */ + REG_RULE(5260-10, 5320+10, 40, 6, 20, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + +static const struct ieee80211_regdomain eu_regdom = { + .n_reg_rules = 6, + /* This alpha2 is bogus, we leave it here just for stupid + * backward compatibility */ + .alpha2 = "EU", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..13 */ + REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), + /* IEEE 802.11a, channel 36 */ + REG_RULE(5180-10, 5180+10, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channel 40 */ + REG_RULE(5200-10, 5200+10, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channel 44 */ + REG_RULE(5220-10, 5220+10, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channels 48..64 */ + REG_RULE(5240-10, 5320+10, 40, 6, 20, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + /* IEEE 802.11a, channels 100..140 */ + REG_RULE(5500-10, 5700+10, 40, 6, 30, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + +static const struct ieee80211_regdomain *static_regdom(char *alpha2) +{ + if (alpha2[0] == 'U' && alpha2[1] == 'S') + return &us_regdom; + if (alpha2[0] == 'J' && alpha2[1] == 'P') + return &jp_regdom; + if (alpha2[0] == 'E' && alpha2[1] == 'U') + return &eu_regdom; + /* Default, as per the old rules */ + return &us_regdom; +} + +static bool is_old_static_regdom(struct ieee80211_regdomain *rd) +{ + if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) + return true; + return false; +} + +/* The old crap never deals with a world regulatory domain, it only + * deals with the static regulatory domain passed and if possible + * an updated "US" or "JP" regulatory domain. We do however store the + * old static regulatory domain in cfg80211_world_regdom for convenience + * of use here */ +static void reset_regdomains_static(void) +{ + if (!is_old_static_regdom(cfg80211_regdomain)) + kfree(cfg80211_regdomain); + /* This is setting the regdom to the old static regdom */ + cfg80211_regdomain = + (struct ieee80211_regdomain *) cfg80211_world_regdom; +} +#else +static void reset_regdomains(void) +{ + if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { + if (cfg80211_world_regdom == cfg80211_regdomain) { + kfree(cfg80211_regdomain); + } else { + kfree(cfg80211_world_regdom); + kfree(cfg80211_regdomain); + } + } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) + kfree(cfg80211_regdomain); + + cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; + cfg80211_regdomain = NULL; +} + +/* Dynamic world regulatory domain requested by the wireless + * core upon initialization */ +static void update_world_regdomain(struct ieee80211_regdomain *rd) +{ + BUG_ON(list_empty(®ulatory_requests)); + + reset_regdomains(); + + cfg80211_world_regdom = rd; + cfg80211_regdomain = rd; +} +#endif + bool is_world_regdom(char *alpha2) { if (!alpha2) @@ -555,58 +722,6 @@ void print_regdomain_info(struct ieee80211_regdomain *rd) print_rd_rules(rd); } -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - -static bool is_old_static_regdom(struct ieee80211_regdomain *rd) -{ - if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) - return true; - return false; -} - -/* The old crap never deals with a world regulatory domain, it only - * deals with the static regulatory domain passed and if possible - * an updated "US" or "JP" regulatory domain. We do however store the - * old static regulatory domain in cfg80211_world_regdom for convenience - * of use here */ -static void reset_regdomains_static(void) -{ - if (!is_old_static_regdom(cfg80211_regdomain)) - kfree(cfg80211_regdomain); - /* This is setting the regdom to the old static regdom */ - cfg80211_regdomain = - (struct ieee80211_regdomain *) cfg80211_world_regdom; -} -#else -static void reset_regdomains(void) -{ - if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { - if (cfg80211_world_regdom == cfg80211_regdomain) { - kfree(cfg80211_regdomain); - } else { - kfree(cfg80211_world_regdom); - kfree(cfg80211_regdomain); - } - } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) - kfree(cfg80211_regdomain); - - cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; - cfg80211_regdomain = NULL; -} - -/* Dynamic world regulatory domain requested by the wireless - * core upon initialization */ -static void update_world_regdomain(struct ieee80211_regdomain *rd) -{ - BUG_ON(list_empty(®ulatory_requests)); - - reset_regdomains(); - - cfg80211_world_regdom = rd; - cfg80211_regdomain = rd; -} -#endif - static int __set_regdom(struct ieee80211_regdomain *rd) { struct regulatory_request *request = NULL; @@ -615,7 +730,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) #ifdef CONFIG_WIRELESS_OLD_REGULATORY /* We ignore the world regdom with the old static regdomains setup - * as there is no point to it with satic regulatory definitions :( + * as there is no point to it with static regulatory definitions :( * Don't worry this shit will be removed soon... */ if (is_world_regdom(rd->alpha2)) return -EINVAL; @@ -735,25 +850,58 @@ int set_regdom(struct ieee80211_regdomain *rd) int regulatory_init(void) { + int err; + reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); if (IS_ERR(reg_pdev)) return PTR_ERR(reg_pdev); + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + cfg80211_regdomain = + (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); + /* Used during reset_regdomains_static() */ + cfg80211_world_regdom = cfg80211_regdomain; + + printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); + print_regdomain_info(cfg80211_regdomain); + /* The old code still requests for a new regdomain and if + * you have CRDA you get it updated, otherwise you get + * stuck with the static values. We ignore "EU" code as + * that is not a valid ISO / IEC 3166 alpha2 */ + if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') + err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, + ieee80211_regdom, NULL); +#else + cfg80211_regdomain = + (struct ieee80211_regdomain *) cfg80211_world_regdom; + + err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); + if (err) + printk(KERN_ERR "cfg80211: calling CRDA failed - " + "unable to update world regulatory domain, " + "using static definition\n"); +#endif + return 0; } void regulatory_exit(void) { struct regulatory_request *req, *req_tmp; + mutex_lock(&cfg80211_drv_mutex); + #ifdef CONFIG_WIRELESS_OLD_REGULATORY reset_regdomains_static(); #else reset_regdomains(); #endif + list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { list_del(&req->list); kfree(req); } platform_device_unregister(reg_pdev); + mutex_unlock(&cfg80211_drv_mutex); } diff --git a/net/wireless/reg.h b/net/wireless/reg.h index d75fd023297..b169815987f 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -1,44 +1,13 @@ #ifndef __NET_WIRELESS_REG_H #define __NET_WIRELESS_REG_H -extern const struct ieee80211_regdomain world_regdom; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY -extern const struct ieee80211_regdomain us_regdom; -extern const struct ieee80211_regdomain jp_regdom; -extern const struct ieee80211_regdomain eu_regdom; -#endif - -extern struct ieee80211_regdomain *cfg80211_regdomain; -extern struct ieee80211_regdomain *cfg80211_world_regdom; -extern struct list_head regulatory_requests; - -struct regdom_last_setby { - struct wiphy *wiphy; - u8 initiator; -}; - -/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ -struct regulatory_request { - struct list_head list; - struct wiphy *wiphy; - int granted; - enum reg_set_by initiator; - char alpha2[2]; -}; - +extern struct mutex cfg80211_reg_mutex; bool is_world_regdom(char *alpha2); bool reg_is_valid_request(char *alpha2); -int set_regdom(struct ieee80211_regdomain *rd); -int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by, - const char *alpha2); - int regulatory_init(void); void regulatory_exit(void); -void print_regdomain_info(struct ieee80211_regdomain *); - -/* If a char is A-Z */ -#define IS_ALPHA(letter) (letter >= 65 && letter <= 90) +int set_regdom(struct ieee80211_regdomain *rd); #endif /* __NET_WIRELESS_REG_H */ -- cgit v1.2.3 From a3d2eaf0dcad6dfdf44f3093aef688dfca714b6c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Sep 2008 11:10:52 +0200 Subject: cfg80211: fix regulatory code const A few pointers and structures in the regulatory code are const, but because it wasn't done properly a whole bunch of bogus casts were needed to compile without warning. Mark everything const properly to avoid that kind of junk code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 58 ++++++++++++++++++++++++++---------------------------- net/wireless/reg.h | 6 +++--- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5fbeab50996..7aba46efc7d 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -68,7 +68,7 @@ static struct list_head regulatory_requests; /* Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no * information to give us an alpha2 */ -static struct ieee80211_regdomain *cfg80211_regdomain; +static const struct ieee80211_regdomain *cfg80211_regdomain; /* We keep a static world regulatory domain in case of the absence of CRDA */ static const struct ieee80211_regdomain world_regdom = { @@ -81,8 +81,8 @@ static const struct ieee80211_regdomain world_regdom = { } }; -static struct ieee80211_regdomain *cfg80211_world_regdom = - (struct ieee80211_regdomain *) &world_regdom; +static const struct ieee80211_regdomain *cfg80211_world_regdom = + &world_regdom; #ifdef CONFIG_WIRELESS_OLD_REGULATORY static char *ieee80211_regdom = "US"; @@ -168,7 +168,7 @@ static const struct ieee80211_regdomain *static_regdom(char *alpha2) return &us_regdom; } -static bool is_old_static_regdom(struct ieee80211_regdomain *rd) +static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) { if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) return true; @@ -201,13 +201,13 @@ static void reset_regdomains(void) } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) kfree(cfg80211_regdomain); - cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; + cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; } /* Dynamic world regulatory domain requested by the wireless * core upon initialization */ -static void update_world_regdomain(struct ieee80211_regdomain *rd) +static void update_world_regdomain(const struct ieee80211_regdomain *rd) { BUG_ON(list_empty(®ulatory_requests)); @@ -218,7 +218,7 @@ static void update_world_regdomain(struct ieee80211_regdomain *rd) } #endif -bool is_world_regdom(char *alpha2) +bool is_world_regdom(const char *alpha2) { if (!alpha2) return false; @@ -227,7 +227,7 @@ bool is_world_regdom(char *alpha2) return false; } -static bool is_alpha2_set(char *alpha2) +static bool is_alpha2_set(const char *alpha2) { if (!alpha2) return false; @@ -244,7 +244,7 @@ static bool is_alpha_upper(char letter) return false; } -static bool is_unknown_alpha2(char *alpha2) +static bool is_unknown_alpha2(const char *alpha2) { if (!alpha2) return false; @@ -255,7 +255,7 @@ static bool is_unknown_alpha2(char *alpha2) return false; } -static bool is_an_alpha2(char *alpha2) +static bool is_an_alpha2(const char *alpha2) { if (!alpha2) return false; @@ -264,7 +264,7 @@ static bool is_an_alpha2(char *alpha2) return false; } -static bool alpha2_equal(char *alpha2_x, char *alpha2_y) +static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) { if (!alpha2_x || !alpha2_y) return false; @@ -274,7 +274,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y) return false; } -static bool regdom_changed(char *alpha2) +static bool regdom_changed(const char *alpha2) { if (!cfg80211_regdomain) return true; @@ -405,7 +405,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, } } -static bool __reg_is_valid_request(char *alpha2, +static bool __reg_is_valid_request(const char *alpha2, struct regulatory_request **request) { struct regulatory_request *req; @@ -421,16 +421,16 @@ static bool __reg_is_valid_request(char *alpha2, } /* Used by nl80211 before kmalloc'ing our regulatory domain */ -bool reg_is_valid_request(char *alpha2) +bool reg_is_valid_request(const char *alpha2) { struct regulatory_request *request = NULL; return __reg_is_valid_request(alpha2, &request); } /* Sanity check on a regulatory rule */ -static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) +static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) { - struct ieee80211_freq_range *freq_range = &rule->freq_range; + const struct ieee80211_freq_range *freq_range = &rule->freq_range; u32 freq_diff; if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) @@ -447,9 +447,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) return true; } -static bool is_valid_rd(struct ieee80211_regdomain *rd) +static bool is_valid_rd(const struct ieee80211_regdomain *rd) { - struct ieee80211_reg_rule *reg_rule = NULL; + const struct ieee80211_reg_rule *reg_rule = NULL; unsigned int i; if (!rd->n_reg_rules) @@ -661,12 +661,12 @@ unlock_and_exit: EXPORT_SYMBOL(regulatory_hint); -static void print_rd_rules(struct ieee80211_regdomain *rd) +static void print_rd_rules(const struct ieee80211_regdomain *rd) { unsigned int i; - struct ieee80211_reg_rule *reg_rule = NULL; - struct ieee80211_freq_range *freq_range = NULL; - struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_reg_rule *reg_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; + const struct ieee80211_power_rule *power_rule = NULL; printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " "(max_antenna_gain, max_eirp)\n"); @@ -696,7 +696,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd) } } -static void print_regdomain(struct ieee80211_regdomain *rd) +static void print_regdomain(const struct ieee80211_regdomain *rd) { if (is_world_regdom(rd->alpha2)) @@ -715,14 +715,14 @@ static void print_regdomain(struct ieee80211_regdomain *rd) print_rd_rules(rd); } -void print_regdomain_info(struct ieee80211_regdomain *rd) +void print_regdomain_info(const struct ieee80211_regdomain *rd) { printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]); print_rd_rules(rd); } -static int __set_regdom(struct ieee80211_regdomain *rd) +static int __set_regdom(const struct ieee80211_regdomain *rd) { struct regulatory_request *request = NULL; @@ -804,7 +804,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) * multiple drivers can be ironed out later. Caller must've already * kmalloc'd the rd structure. If this calls fails you should kfree() * the passed rd. Caller must hold cfg80211_drv_mutex */ -int set_regdom(struct ieee80211_regdomain *rd) +int set_regdom(const struct ieee80211_regdomain *rd) { struct regulatory_request *this_request = NULL, *prev_request = NULL; int r; @@ -857,8 +857,7 @@ int regulatory_init(void) return PTR_ERR(reg_pdev); #ifdef CONFIG_WIRELESS_OLD_REGULATORY - cfg80211_regdomain = - (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); + cfg80211_regdomain = static_regdom(ieee80211_regdom); /* Used during reset_regdomains_static() */ cfg80211_world_regdom = cfg80211_regdomain; @@ -872,8 +871,7 @@ int regulatory_init(void) err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, ieee80211_regdom, NULL); #else - cfg80211_regdomain = - (struct ieee80211_regdomain *) cfg80211_world_regdom; + cfg80211_regdomain = cfg80211_world_regdom; err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); if (err) diff --git a/net/wireless/reg.h b/net/wireless/reg.h index b169815987f..a33362872f3 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -2,12 +2,12 @@ #define __NET_WIRELESS_REG_H extern struct mutex cfg80211_reg_mutex; -bool is_world_regdom(char *alpha2); -bool reg_is_valid_request(char *alpha2); +bool is_world_regdom(const char *alpha2); +bool reg_is_valid_request(const char *alpha2); int regulatory_init(void); void regulatory_exit(void); -int set_regdom(struct ieee80211_regdomain *rd); +int set_regdom(const struct ieee80211_regdomain *rd); #endif /* __NET_WIRELESS_REG_H */ -- cgit v1.2.3 From 942b25cf9028e7c2f6446ee7c6618bd70dafec5f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Sep 2008 11:26:47 +0200 Subject: cfg80211: clean up static regdomain mess The statically defined regdomains are used in a very convoluted way, use them instead to prime the information we have and then continue operating normally. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 73 +++++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7aba46efc7d..626dbb68849 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -174,32 +174,27 @@ static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) return true; return false; } - -/* The old crap never deals with a world regulatory domain, it only - * deals with the static regulatory domain passed and if possible - * an updated "US" or "JP" regulatory domain. We do however store the - * old static regulatory domain in cfg80211_world_regdom for convenience - * of use here */ -static void reset_regdomains_static(void) +#else +static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) { - if (!is_old_static_regdom(cfg80211_regdomain)) - kfree(cfg80211_regdomain); - /* This is setting the regdom to the old static regdom */ - cfg80211_regdomain = - (struct ieee80211_regdomain *) cfg80211_world_regdom; + return false; } -#else +#endif + static void reset_regdomains(void) { - if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { - if (cfg80211_world_regdom == cfg80211_regdomain) { - kfree(cfg80211_regdomain); - } else { - kfree(cfg80211_world_regdom); - kfree(cfg80211_regdomain); - } - } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) - kfree(cfg80211_regdomain); + /* avoid freeing static information or freeing something twice */ + if (cfg80211_regdomain == cfg80211_world_regdom) + cfg80211_regdomain = NULL; + if (cfg80211_world_regdom == &world_regdom) + cfg80211_world_regdom = NULL; + if (cfg80211_regdomain == &world_regdom) + cfg80211_regdomain = NULL; + if (is_old_static_regdom(cfg80211_regdomain)) + cfg80211_regdomain = NULL; + + kfree(cfg80211_regdomain); + kfree(cfg80211_world_regdom); cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; @@ -216,7 +211,6 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) cfg80211_world_regdom = rd; cfg80211_regdomain = rd; } -#endif bool is_world_regdom(const char *alpha2) { @@ -297,12 +291,8 @@ static int call_crda(const char *alpha2) printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", alpha2[0], alpha2[1]); else -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - return -EINVAL; -#else printk(KERN_INFO "cfg80211: Calling CRDA to update world " "regulatory domain\n"); -#endif country_env[8] = alpha2[0]; country_env[9] = alpha2[1]; @@ -728,20 +718,12 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) /* Some basic sanity checks first */ -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - /* We ignore the world regdom with the old static regdomains setup - * as there is no point to it with static regulatory definitions :( - * Don't worry this shit will be removed soon... */ - if (is_world_regdom(rd->alpha2)) - return -EINVAL; -#else if (is_world_regdom(rd->alpha2)) { if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) return -EINVAL; update_world_regdomain(rd); return 0; } -#endif if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && !is_unknown_alpha2(rd->alpha2)) @@ -750,15 +732,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (list_empty(®ulatory_requests)) return -EINVAL; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - /* Static "US" and "JP" will be overridden, but just once */ + /* allow overriding the static definitions if CRDA is present */ if (!is_old_static_regdom(cfg80211_regdomain) && - !regdom_changed(rd->alpha2)) - return -EINVAL; -#else - if (!regdom_changed(rd->alpha2)) + !regdom_changed(rd->alpha2)) return -EINVAL; -#endif /* Now lets set the regulatory domain, update all driver channels * and finally inform them of what we have done, in case they want @@ -768,11 +745,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) return -EINVAL; -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - reset_regdomains_static(); -#else reset_regdomains(); -#endif /* Country IE parsing coming soon */ switch (request->initiator) { @@ -858,10 +831,8 @@ int regulatory_init(void) #ifdef CONFIG_WIRELESS_OLD_REGULATORY cfg80211_regdomain = static_regdom(ieee80211_regdom); - /* Used during reset_regdomains_static() */ - cfg80211_world_regdom = cfg80211_regdomain; - printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); + printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); print_regdomain_info(cfg80211_regdomain); /* The old code still requests for a new regdomain and if * you have CRDA you get it updated, otherwise you get @@ -889,11 +860,7 @@ void regulatory_exit(void) mutex_lock(&cfg80211_drv_mutex); -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - reset_regdomains_static(); -#else reset_regdomains(); -#endif list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { list_del(&req->list); -- cgit v1.2.3 From e07aa3783e9f66b03d72e7afd9f709d7f7059662 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Sep 2008 13:11:19 +0200 Subject: cfg80211: fix code ordering in header file Luis added the regulatory hint stuff to this file without observing that __ieee80211_get_channel and ieee80211_get_channel really belong together. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/wireless.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/net/wireless.h b/include/net/wireless.h index e4378cc6bf8..0de7fde9f33 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -328,6 +328,15 @@ extern int ieee80211_frequency_to_channel(int freq); */ extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, int freq); +/** + * ieee80211_get_channel - get channel struct from wiphy for specified frequency + */ +static inline struct ieee80211_channel * +ieee80211_get_channel(struct wiphy *wiphy, int freq) +{ + return __ieee80211_get_channel(wiphy, freq); +} + /** * __regulatory_hint - hint to the wireless core a regulatory domain * @wiphy: if a driver is providing the hint this is the driver's very @@ -380,13 +389,4 @@ extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, */ extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2, struct ieee80211_regdomain *rd); - -/** - * ieee80211_get_channel - get channel struct from wiphy for specified frequency - */ -static inline struct ieee80211_channel * -ieee80211_get_channel(struct wiphy *wiphy, int freq) -{ - return __ieee80211_get_channel(wiphy, freq); -} #endif /* __NET_WIRELESS_H */ -- cgit v1.2.3 From fdd1097488e3c1278996bd7c73d8429d410e725a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 16 Sep 2008 14:56:49 -0500 Subject: b43: Issue warning when RFKILL_INPUT is not enabled If the system is misconfigured with CONFIG_RFKILL set but CONFIG_RFKILL_INPUT not set, the built-in radio LEDs will not work. In the current code, no warning is issued. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/rfkill.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 7b9e99adb8c..96902da7d66 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -188,6 +188,11 @@ void b43_rfkill_init(struct b43_wldev *dev) "The built-in radio LED will not work.\n"); #endif /* CONFIG_RFKILL_INPUT */ +#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE) + b43warn(wl, "The rfkill-input subsystem is not available. " + "The built-in radio LED will not work.\n"); +#endif + err = input_register_polled_device(rfk->poll_dev); if (err) goto err_unreg_rfk; -- cgit v1.2.3 From 9ccacb86b5c613b25f41ca4227c3fb17bcd77de0 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 16 Sep 2008 14:01:03 +0800 Subject: iwlwifi: don't delay scan in IBSS mode Scan need to be delayed only after association to allow EAPOL exchange. We don't need the delay for IBSS mode. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 27376276976..970d0b32265 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2568,8 +2568,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) iwl_chain_noise_reset(priv); priv->start_calib = 1; - /* we have just associated, don't start scan too early */ - priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); @@ -3171,6 +3169,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, priv->power_data.dtim_period = bss_conf->dtim_period; priv->timestamp = bss_conf->timestamp; priv->assoc_capability = bss_conf->assoc_capability; + + /* we have just associated, don't start scan too early + * leave time for EAPOL exchange to complete + */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; mutex_lock(&priv->mutex); -- cgit v1.2.3 From 9e5e6c327defcef19dabad64335ee68bb55b2355 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 16 Sep 2008 14:01:04 +0800 Subject: iwlwifi: make PS use named constants This patch adds named constants for configuring MIMO power save chain settings. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d80184ee911..8203887ca00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -697,8 +697,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) } EXPORT_SYMBOL(iwl_set_rxon_ht); -/* - * Determine how many receiver/antenna chains to use. +#define IWL_NUM_RX_CHAINS_MULTIPLE 3 +#define IWL_NUM_RX_CHAINS_SINGLE 2 +#define IWL_NUM_IDLE_CHAINS_DUAL 2 +#define IWL_NUM_IDLE_CHAINS_SINGLE 1 + +/* Determine how many receiver/antenna chains to use. * More provides better reception via diversity. Fewer saves power. * MIMO (dual stream) requires at least 2, but works better with 3. * This does not determine *which* chains to use, just how many. @@ -711,9 +715,9 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) /* # of Rx chains to use when expecting MIMO. */ if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == WLAN_HT_CAP_SM_PS_STATIC))) - return 2; + return IWL_NUM_RX_CHAINS_SINGLE; else - return 3; + return IWL_NUM_RX_CHAINS_MULTIPLE; } static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) @@ -724,10 +728,11 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) switch (priv->current_ht_config.sm_ps) { case WLAN_HT_CAP_SM_PS_STATIC: case WLAN_HT_CAP_SM_PS_DYNAMIC: - idle_cnt = (is_cam) ? 2 : 1; + idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : + IWL_NUM_IDLE_CHAINS_SINGLE; break; case WLAN_HT_CAP_SM_PS_DISABLED: - idle_cnt = (is_cam) ? active_cnt : 1; + idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; break; case WLAN_HT_CAP_SM_PS_INVALID: default: @@ -796,7 +801,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); - if (!is_single && (active_rx_cnt >= 2) && is_cam) + if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; else priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; -- cgit v1.2.3 From 133b822638ff01eb1e32e1917b197c40ed095ddd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 14:18:59 +0200 Subject: mac80211: make master iface not wireless There's no need to register the master netdev with cfg80211, in fact, this is quite dangerous and lead to having to add checks for the master interface all over the config handlers. This patch removes the "ieee80211_ptr" from the master iface in favour of having a small netdev_priv() associated with the master interface that stores the ieee80211_local pointer. Because of this, a lot of code in the configuration handlers can go away. To make this patch easier to verify I have also removed a number of wiphy_priv() calls in favour of getting the sdata first and then the local pointer from that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 59 ---------------------------------------------- net/mac80211/debugfs_sta.c | 3 +-- net/mac80211/ieee80211_i.h | 4 ++++ net/mac80211/main.c | 19 ++++++++------- net/mac80211/mesh.c | 2 +- net/mac80211/rx.c | 25 ++++++++------------ net/mac80211/tx.c | 26 ++++++++++---------- 7 files changed, 39 insertions(+), 99 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4..a8501f14b16 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct net_device *dev; struct ieee80211_sub_if_data *sdata; int ret; @@ -95,9 +94,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (!nl80211_type_check(type)) return -EINVAL; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ret = ieee80211_if_change_type(sdata, type); @@ -120,16 +116,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr, struct key_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; enum ieee80211_key_alg alg; struct ieee80211_key *key; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); switch (params->cipher) { @@ -174,14 +166,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; int ret; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -222,7 +210,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, void (*callback)(void *cookie, struct key_params *params)) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; u8 seq[6] = {0}; @@ -232,9 +219,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, u16 iv16; int err = -ENOENT; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -310,12 +294,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - if (dev == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -496,13 +476,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -519,13 +495,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -541,13 +513,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -695,9 +663,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; int err; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - /* Prevent a race with changing the rate control algorithm */ if (!netif_running(dev)) return -ENETDOWN; @@ -752,9 +717,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (mac) { @@ -786,9 +748,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); /* XXX: get sta belonging to dev */ @@ -828,9 +787,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -884,9 +840,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, struct mesh_path *mpath; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -958,13 +911,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -986,13 +935,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -1015,13 +960,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; u32 changed = 0; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a..b9902e425f0 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sta_info *sta = file->private_data; - struct net_device *dev = sta->sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sta->sdata->local; struct ieee80211_hw *hw = &local->hw; u8 *da = sta->sta.addr; static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d..0b25b0f46b1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -573,6 +573,10 @@ enum { /* maximum number of hardware queues we support. */ #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) +struct ieee80211_master_priv { + struct ieee80211_local *local; +}; + struct ieee80211_local { /* embed the driver visible part. * don't cast (use the static inlines below), but we keep diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec0..7d2d5a041e2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { static int ieee80211_master_open(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; int res = -EOPNOTSUPP; @@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) static int ieee80211_master_stop(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; /* we hold the RTNL here so can safely walk the list */ @@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) static void ieee80211_master_set_multicast_list(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; ieee80211_configure_filter(local); } @@ -787,7 +790,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result; enum ieee80211_band band; struct net_device *mdev; - struct wireless_dev *mwdev; + struct ieee80211_master_priv *mpriv; /* * generic code guarantees at least one band, @@ -829,16 +832,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (hw->queues < 4) hw->ampdu_queues = 0; - mdev = alloc_netdev_mq(sizeof(struct wireless_dev), + mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), "wmaster%d", ether_setup, ieee80211_num_queues(hw)); if (!mdev) goto fail_mdev_alloc; - mwdev = netdev_priv(mdev); - mdev->ieee80211_ptr = mwdev; - mwdev->wiphy = local->hw.wiphy; - + mpriv = netdev_priv(mdev); + mpriv->local = local; local->mdev = mdev; ieee80211_rx_bss_list_init(local); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a..8013277924f 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; queue_work(local->hw.workqueue, &ifmsh->work); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e..3ab9670f180 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) return result; } -static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) +static void ap_sta_ps_start(struct sta_info *sta) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = sta->sdata; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_inc(&sdata->bss->num_sta_ps); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } -static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) +static int ap_sta_ps_end(struct sta_info *sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; int sent = 0; - struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_dec(&sdata->bss->num_sta_ps); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); @@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ @@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) sent++; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " - "since STA not sleeping anymore\n", dev->name, + "since STA not sleeping anymore\n", sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ info->flags |= IEEE80211_TX_CTL_REQUEUE; @@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) { struct sta_info *sta = rx->sta; - struct net_device *dev = rx->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; if (!sta) @@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) && !ieee80211_has_pm(hdr->frame_control)) - rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); + rx->sent_ps_buffered += ap_sta_ps_end(sta); else if (!test_sta_flags(sta, WLAN_STA_PS) && ieee80211_has_pm(hdr->frame_control)) - ap_sta_ps_start(dev, sta); + ap_sta_ps_start(sta); } /* Drop data::nullfunc frames silently, since they are used only to diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b4..00d798cc9e0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, return cpu_to_le16(dur); } -static int inline is_ieee80211_device(struct net_device *dev, - struct net_device *master) +static int inline is_ieee80211_device(struct ieee80211_local *local, + struct net_device *dev) { - return (wdev_priv(dev->ieee80211_ptr) == - wdev_priv(master->ieee80211_ptr)); + return local == wdev_priv(dev->ieee80211_ptr); } /* tx handlers */ @@ -1001,14 +1000,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* * NB: @tx is uninitialised when passed in here */ -static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, - struct sk_buff *skb, - struct net_device *mdev) +static int ieee80211_tx_prepare(struct ieee80211_local *local, + struct ieee80211_tx_data *tx, + struct sk_buff *skb) { struct net_device *dev; dev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { + if (unlikely(dev && !is_ieee80211_device(local, dev))) { dev_put(dev); dev = NULL; } @@ -1258,6 +1257,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct net_device *odev = NULL; @@ -1273,7 +1274,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (skb->iif) odev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(odev && !is_ieee80211_device(odev, dev))) { + if (unlikely(odev && !is_ieee80211_device(local, odev))) { dev_put(odev); odev = NULL; } @@ -1449,8 +1450,8 @@ fail: int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int ret = 1, head_need; u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; @@ -1462,7 +1463,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct sta_info *sta; u32 sta_flags = 0; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (unlikely(skb->len < ETH_HLEN)) { ret = 0; goto fail; @@ -2032,7 +2032,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, cpu_to_le16(IEEE80211_FCTL_MOREDATA); } - if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) + if (!ieee80211_tx_prepare(local, &tx, skb)) break; dev_kfree_skb_any(skb); } -- cgit v1.2.3 From 60719ffd721f6764b7d07ca188c0d944a4330b69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 14:55:09 +0200 Subject: cfg80211: show interface type This patch makes cfg80211 show the interface in the nl80211 information about a specific interface. API users are required to keep the type updated (everything else is fairly complicated) but you will get a warning if you fail to keep it updated. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 6 ++++-- include/net/wireless.h | 2 ++ net/mac80211/iface.c | 1 + net/wireless/core.c | 2 ++ net/wireless/nl80211.c | 6 +++++- 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9f40c4d417d..0e85ec39b63 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -363,11 +363,13 @@ struct wiphy; * wireless extensions but this is subject to reevaluation as soon as this * code is used more widely and we have a first user without wext. * - * @add_virtual_intf: create a new virtual interface with the given name + * @add_virtual_intf: create a new virtual interface with the given name, + * must set the struct wireless_dev's iftype. * * @del_virtual_intf: remove the virtual interface determined by ifindex. * - * @change_virtual_intf: change type of virtual interface + * @change_virtual_intf: change type/configuration of virtual interface, + * keep the struct wireless_dev's iftype updated. * * @add_key: add a key with the given parameters. @mac_addr will be %NULL * when adding a group key. diff --git a/include/net/wireless.h b/include/net/wireless.h index 0de7fde9f33..721efb363db 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -223,9 +223,11 @@ struct wiphy { * the netdev.) * * @wiphy: pointer to hardware description + * @iftype: interface type */ struct wireless_dev { struct wiphy *wiphy; + enum nl80211_iftype iftype; /* private to the generic wireless code */ struct list_head list; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a72fbebb8ea..b5cd91e8971 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -625,6 +625,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, /* and set some type-dependent values */ sdata->vif.type = type; sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; + sdata->wdev.iftype = type; /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; diff --git a/net/wireless/core.c b/net/wireless/core.c index 88cb7339486..d6940085d59 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -384,6 +384,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); + WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); + switch (state) { case NETDEV_REGISTER: mutex_lock(&rdev->devlist_mtx); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1221d726ed5..44771a690d5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); - /* TODO: interface type */ + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); return genlmsg_end(msg, hdr); nla_put_failure: @@ -453,6 +453,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) &flags); err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type, err ? NULL : &flags, ¶ms); + + dev = __dev_get_by_index(&init_net, ifindex); + WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); + rtnl_unlock(); unlock: -- cgit v1.2.3 From 723b038def23ce0606754c4f598cbb96bae9a102 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 20:22:09 +0200 Subject: cfg80211: allow set_interface without type Which then causes no type change. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 44771a690d5..a745932d137 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -422,19 +422,20 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) memset(¶ms, 0, sizeof(params)); - if (info->attrs[NL80211_ATTR_IFTYPE]) { - type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); - if (type > NL80211_IFTYPE_MAX) - return -EINVAL; - } else - return -EINVAL; - err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) return err; ifindex = dev->ifindex; + type = dev->ieee80211_ptr->iftype; dev_put(dev); + err = -EINVAL; + if (info->attrs[NL80211_ATTR_IFTYPE]) { + type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); + if (type > NL80211_IFTYPE_MAX) + goto unlock; + } + if (!drv->ops->change_virtual_intf || !(drv->wiphy.interface_modes & (1 << type))) { err = -EOPNOTSUPP; -- cgit v1.2.3 From f8b25cdad719cddceb9cf0d350065b3e59e74219 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 20:22:21 +0200 Subject: mac80211: allow interface settings changes only when down We currently allow monitor flags changes and mesh ID changes when the interface is up, which can lead to trouble. Change it to only allow when down. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a8501f14b16..89a183c2327 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -100,6 +100,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (ret) return ret; + if (netif_running(sdata->dev)) + return -EBUSY; + if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) ieee80211_sdata_set_mesh_id(sdata, params->mesh_id_len, -- cgit v1.2.3 From 92ffe055c3ea45856183bebed62f8880f75fef3b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 20:39:36 +0200 Subject: cfg80211: reject invalid configuration items Reject configuring mesh-id for non-mesh, monitor flags for non-monitor. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a745932d137..572793c8c7a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -418,7 +418,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) int err, ifindex; enum nl80211_iftype type; struct net_device *dev; - u32 flags; + u32 _flags, *flags = NULL; memset(¶ms, 0, sizeof(params)); @@ -442,18 +442,28 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) goto unlock; } - if (type == NL80211_IFTYPE_MESH_POINT && - info->attrs[NL80211_ATTR_MESH_ID]) { + if (info->attrs[NL80211_ATTR_MESH_ID]) { + if (type != NL80211_IFTYPE_MESH_POINT) { + err = -EINVAL; + goto unlock; + } params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); } + if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { + if (type != NL80211_IFTYPE_MONITOR) { + err = -EINVAL; + goto unlock; + } + err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], + &_flags); + if (!err) + flags = &_flags; + } rtnl_lock(); - err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? - info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, - &flags); err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, - type, err ? NULL : &flags, ¶ms); + type, flags, ¶ms); dev = __dev_get_by_index(&init_net, ifindex); WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); -- cgit v1.2.3 From 84e463fa0786a105c39281b90f8e3b6fe1444a05 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Wed, 17 Sep 2008 03:33:19 +0300 Subject: ath5k: Fix bad udelay calls on AR5210 code * Fix bad udelay calls (using > 2000us) in AR5210 code and clean up some bits on nic_reset (AR5210 support is still in bad shape) Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 2 +- drivers/net/wireless/ath5k/reg.h | 2 -- drivers/net/wireless/ath5k/reset.c | 20 +++++++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 1ea8ed962d2..e43f6563e61 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -2124,7 +2124,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); - udelay(2300); + mdelay(2); /* * Set the channel (with AGC turned off) diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index a9883236444..410f99a6d61 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -820,8 +820,6 @@ #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ -#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \ - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY) /* * Sleep control register diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index f5c3de890cd..953ba3b19ff 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -173,8 +173,10 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) udelay(15); if (ah->ah_version == AR5K_AR5210) { - val &= AR5K_RESET_CTL_CHIP; - mask &= AR5K_RESET_CTL_CHIP; + val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA + | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; + mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA + | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; } else { val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; @@ -361,16 +363,20 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; /* Reset chipset */ - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); + if (ah->ah_version == AR5K_AR5210) { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | + AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); + mdelay(2); + } else { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); + } if (ret) { ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); return -EIO; } - if (ah->ah_version == AR5K_AR5210) - udelay(2300); - /* ...wakeup again!*/ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { -- cgit v1.2.3 From 9c40fc510a3df3a74731f5f251b9481feffc0ed5 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 16 Sep 2008 18:08:39 -0700 Subject: libertas: Reduce the WPA key installation time (fixups) This patch addresses comments from Dan Williams about the patch committed as "libertas: Reduce the WPA key installation time." Signed-off-by: Javier Cardona Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/dev.h | 1 + drivers/net/wireless/libertas/wext.c | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index acb889e2590..f6f3753da30 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -58,6 +58,7 @@ struct lbs_802_11_security { u8 WPA2enabled; u8 wep_enabled; u8 auth_mode; + u32 key_mgmt; }; /** Current Basic Service Set State Structure */ diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 11297dcf9fc..6ebdd7f161f 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1598,8 +1598,20 @@ static int lbs_set_encodeext(struct net_device *dev, } out: - if (ret == 0) { /* key installation is time critical: postpone not! */ - lbs_do_association_work(priv); + if (ret == 0) { + /* 802.1x and WPA rekeying must happen as quickly as possible, + * especially during the 4-way handshake; thus if in + * infrastructure mode, and either (a) 802.1x is enabled or + * (b) WPA is being used, set the key right away. + */ + if (assoc_req->mode == IW_MODE_INFRA && + ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) || + (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) || + assoc_req->secinfo.WPAenabled || + assoc_req->secinfo.WPA2enabled)) { + lbs_do_association_work(priv); + } else + lbs_postpone_association_work(priv); } else { lbs_cancel_association_work(priv); } @@ -1707,13 +1719,17 @@ static int lbs_set_auth(struct net_device *dev, case IW_AUTH_TKIP_COUNTERMEASURES: case IW_AUTH_CIPHER_PAIRWISE: case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: case IW_AUTH_DROP_UNENCRYPTED: /* * libertas does not use these parameters */ break; + case IW_AUTH_KEY_MGMT: + assoc_req->secinfo.key_mgmt = dwrq->value; + updated = 1; + break; + case IW_AUTH_WPA_VERSION: if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { assoc_req->secinfo.WPAenabled = 0; @@ -1793,6 +1809,10 @@ static int lbs_get_auth(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); switch (dwrq->flags & IW_AUTH_INDEX) { + case IW_AUTH_KEY_MGMT: + dwrq->value = priv->secinfo.key_mgmt; + break; + case IW_AUTH_WPA_VERSION: dwrq->value = 0; if (priv->secinfo.WPAenabled) -- cgit v1.2.3 From 42eb7c644afcdbcd7eac4d862046230856fbf531 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 17 Sep 2008 10:10:05 +0800 Subject: iwlwifi: remove HT flags from RXON when not in HT anymore This patch removes the HT flags from RXON when moving from HT to legacy. This avoids keeping those flags set and possibly miss configuring firmware. If we are configured in HT, fat channel: channel 1 above, and move later to legacy channel 11, we need to clear the FAT channel control flags in RXON. If we don't, the firmware will understand this as channel 11 above which is not possible due to regulatory constraints, leading to firmware crash. Signed-off-by: Emmanuel Grumbach Reviewed-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 970d0b32265..d069549a01c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2504,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - if (priv->current_ht_config.is_ht) - iwl_set_rxon_ht(priv, &priv->current_ht_config); + iwl_set_rxon_ht(priv, &priv->current_ht_config); iwl_set_rxon_chain(priv); priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8203887ca00..4c312c55f90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -646,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) struct iwl_rxon_cmd *rxon = &priv->staging_rxon; u32 val; - if (!ht_info->is_ht) + if (!ht_info->is_ht) { + rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | + RXON_FLG_CHANNEL_MODE_PURE_40_MSK | + RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | + RXON_FLG_FAT_PROT_MSK | + RXON_FLG_HT_PROT_MSK); return; + } /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ if (iwl_is_fat_tx_allowed(priv, NULL)) -- cgit v1.2.3 From 980b24da6f1725c2d0b32c9484d06cd7d09d3c4b Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Sep 2008 10:15:09 +0530 Subject: ath9k: Whitespace cleanup Also, remove comments that are not relevant anymore. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 136 ++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 76 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index c43fd586116..f8d952ca3f8 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -26,7 +26,6 @@ * the operating mode of the station (AP or AdHoc). Parameters are AIFS * settings and channel width min/max */ - static int ath_beaconq_config(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; @@ -63,19 +62,18 @@ static int ath_beaconq_config(struct ath_softc *sc) * up all required antenna switch parameters, rate codes, and channel flags. * Beacons are always sent out at the lowest rate, and are not retried. */ - static void ath_beacon_setup(struct ath_softc *sc, - struct ath_vap *avp, struct ath_buf *bf) + struct ath_vap *avp, struct ath_buf *bf) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ath_hal *ah = sc->sc_ah; struct ath_desc *ds; - int flags, antenna; + struct ath9k_11n_rate_series series[4]; const struct ath9k_rate_table *rt; + int flags, antenna; u8 rix, rate; int ctsrate = 0; int ctsduration = 0; - struct ath9k_11n_rate_series series[4]; DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", __func__, skb, skb->len); @@ -115,20 +113,21 @@ static void ath_beacon_setup(struct ath_softc *sc, rate |= rt->info[rix].shortPreamble; ath9k_hw_set11n_txdesc(ah, ds, - skb->len + FCS_LEN, /* frame length */ - ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ + skb->len + FCS_LEN, /* frame length */ + ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ avp->av_btxctl.txpower, /* txpower XXX */ - ATH9K_TXKEYIX_INVALID, /* no encryption */ - ATH9K_KEY_TYPE_CLEAR, /* no encryption */ - flags /* no ack, veol for beacons */ + ATH9K_TXKEYIX_INVALID, /* no encryption */ + ATH9K_KEY_TYPE_CLEAR, /* no encryption */ + flags /* no ack, + veol for beacons */ ); /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), /* buffer length */ - true, /* first segment */ - true, /* last segment */ - ds /* first descriptor */ + true, /* first segment */ + true, /* last segment */ + ds /* first descriptor */ ); memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); @@ -153,22 +152,23 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) struct ath_buf *bf; struct ath_vap *avp; struct sk_buff *skb; - int cabq_depth; struct ath_txq *cabq; struct ieee80211_tx_info *info; + int cabq_depth; + avp = sc->sc_vaps[if_id]; + ASSERT(avp); cabq = sc->sc_cabq; - ASSERT(avp); - if (avp->av_bcbuf == NULL) { DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", __func__, avp, avp->av_bcbuf); return NULL; } + bf = avp->av_bcbuf; - skb = (struct sk_buff *) bf->bf_mpdu; + skb = (struct sk_buff *)bf->bf_mpdu; if (skb) { pci_unmap_single(sc->pdev, bf->bf_dmacontext, skb_end_pointer(skb) - skb->head, @@ -179,17 +179,19 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) bf->bf_mpdu = skb; if (skb == NULL) return NULL; + info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { /* * TODO: make sure the seq# gets assigned properly (vs. other * TX frames) */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; sc->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); } + bf->bf_buf_addr = bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, skb_end_pointer(skb) - skb->head, @@ -241,7 +243,6 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) * Startup beacon transmission for adhoc mode when they are sent entirely * by the hardware using the self-linked descriptor + veol trick. */ - static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) { struct ath_hal *ah = sc->sc_ah; @@ -278,7 +279,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) * min/max, and enable aifs). The info structure does not need to be * persistant. */ - int ath_beaconq_setup(struct ath_hal *ah) { struct ath9k_tx_queue_info qi; @@ -299,11 +299,10 @@ int ath_beaconq_setup(struct ath_hal *ah) * the ATH interface. This routine also calculates the beacon "slot" for * staggared beacons in the mBSSID case. */ - int ath_beacon_alloc(struct ath_softc *sc, int if_id) { struct ath_vap *avp; - struct ieee80211_hdr *wh; + struct ieee80211_hdr *hdr; struct ath_buf *bf; struct sk_buff *skb; @@ -312,13 +311,11 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) /* Allocate a beacon descriptor if we haven't done so. */ if (!avp->av_bcbuf) { - /* - * Allocate beacon state for hostap/ibss. We know - * a buffer is available. - */ + /* Allocate beacon state for hostap/ibss. We know + * a buffer is available. */ avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, - struct ath_buf, list); + struct ath_buf, list); list_del(&avp->av_bcbuf->list); if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || @@ -362,9 +359,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) } /* - * NB: the beacon data buffer must be 32-bit aligned; - * we assume the wbuf routines will return us something - * with this alignment (perhaps should assert). + * NB: the beacon data buffer must be 32-bit aligned. * FIXME: Fill avp->av_btxctl.txpower and * avp->av_btxctl.shortPreamble */ @@ -408,8 +403,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) __func__, "stagger", avp->av_bslot, intval, (unsigned long long)tsfadjust); - wh = (struct ieee80211_hdr *)skb->data; - memcpy(&wh[1], &val, sizeof(val)); + hdr = (struct ieee80211_hdr *)skb->data; + memcpy(&hdr[1], &val, sizeof(val)); } bf->bf_buf_addr = bf->bf_dmacontext = @@ -425,9 +420,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) * Reclaim beacon resources and return buffer to the pool. * * Checks the VAP to put the beacon frame buffer back to the ATH object - * queue, and de-allocates any wbuf frames that were sent as CAB traffic. + * queue, and de-allocates any skbs that were sent as CAB traffic. */ - void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) { if (avp->av_bcbuf != NULL) { @@ -459,10 +453,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame * contents are done as needed and the slot time is also adjusted based on * current state. - * - * This tasklet is not scheduled, it's called in ISR context. */ - void ath9k_beacon_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; @@ -490,6 +481,8 @@ void ath9k_beacon_tasklet(unsigned long data) * and wait for the next. Missed beacons indicate * a problem and should not occur. If we miss too * many consecutive beacons reset the device. + * + * FIXME: Clean up this mess !! */ if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { sc->sc_bmisscount++; @@ -505,19 +498,16 @@ void ath9k_beacon_tasklet(unsigned long data) __func__, sc->sc_bmisscount); if (show_cycles) { /* - * Display cycle counter stats - * from HW to aide in debug of - * stickiness. + * Display cycle counter stats from HW + * to aide in debug of stickiness. */ - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: busy times: rx_clear=%d, " "rx_frame=%d, tx_frame=%d\n", __func__, rx_clear, rx_frame, tx_frame); } else { - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: unable to obtain " "busy times\n", __func__); } @@ -529,8 +519,7 @@ void ath9k_beacon_tasklet(unsigned long data) } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { if (sc->sc_flags & SC_OP_NO_RESET) { if (sc->sc_bmisscount == BSTUCK_THRESH) { - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: beacon is officially " "stuck\n", __func__); ath9k_hw_dmaRegDump(ah); @@ -542,13 +531,12 @@ void ath9k_beacon_tasklet(unsigned long data) ath_bstuck_process(sc); } } - return; } + if (sc->sc_bmisscount != 0) { if (sc->sc_flags & SC_OP_NO_RESET) { - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: resume beacon xmit after %u misses\n", __func__, sc->sc_bmisscount); } else { @@ -572,10 +560,12 @@ void ath9k_beacon_tasklet(unsigned long data) tsftu = TSF_TO_TU(tsf>>32, tsf); slot = ((tsftu % intval) * ATH_BCBUF) / intval; if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; + DPRINTF(sc, ATH_DBG_BEACON, - "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", - __func__, slot, (unsigned long long) tsf, tsftu, - intval, if_id); + "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", + __func__, slot, (unsigned long long)tsf, tsftu, + intval, if_id); + bfaddr = 0; if (if_id != ATH_IF_ID_ANY) { bf = ath_beacon_generate(sc, if_id); @@ -632,9 +622,8 @@ void ath9k_beacon_tasklet(unsigned long data) * Tasklet for Beacon Stuck processing * * Processing for Beacon Stuck. - * Basically calls the ath_internal_reset function to reset the chip. + * Basically resets the chip. */ - void ath_bstuck_process(struct ath_softc *sc) { DPRINTF(sc, ATH_DBG_BEACON, @@ -658,13 +647,12 @@ void ath_bstuck_process(struct ath_softc *sc) * interrupt when we stop seeing beacons from the AP * we've associated with. */ - void ath_beacon_config(struct ath_softc *sc, int if_id) { struct ath_hal *ah = sc->sc_ah; - u32 nexttbtt, intval; struct ath_beacon_config conf; enum ath9k_opmode av_opmode; + u32 nexttbtt, intval; if (if_id != ATH_IF_ID_ANY) av_opmode = sc->sc_vaps[if_id]->av_opmode; @@ -673,12 +661,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) memzero(&conf, sizeof(struct ath_beacon_config)); - /* FIXME: Use default values for now - Sujith */ - /* Query beacon configuration first */ - /* - * Protocol stack doesn't support dynamic beacon configuration, - * use default configurations. - */ conf.beacon_interval = sc->hw->conf.beacon_int ? sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; conf.listen_interval = 1; @@ -704,12 +686,14 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; } - if (nexttbtt == 0) /* e.g. for ap mode */ + if (nexttbtt == 0) /* e.g. for ap mode */ nexttbtt = intval; - else if (intval) /* NB: can be 0 for monitor mode */ + else if (intval) /* NB: can be 0 for monitor mode */ nexttbtt = roundup(nexttbtt, intval); + DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", __func__, nexttbtt, intval, conf.beacon_interval); + /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { struct ath9k_beacon_state bs; @@ -723,19 +707,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * last beacon we received (which may be none). */ dtimperiod = conf.dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ + if (dtimperiod <= 0) /* NB: 0 if not known */ dtimperiod = 1; dtimcount = conf.dtim_count; - if (dtimcount >= dtimperiod) /* NB: sanity check */ - dtimcount = 0; /* XXX? */ - cfpperiod = 1; /* NB: no PCF support yet */ + if (dtimcount >= dtimperiod) /* NB: sanity check */ + dtimcount = 0; + cfpperiod = 1; /* NB: no PCF support yet */ cfpcount = 0; sleepduration = conf.listen_interval * intval; if (sleepduration <= 0) sleepduration = intval; -#define FUDGE 2 +#define FUDGE 2 /* * Pull nexttbtt forward to reflect the current * TSF and calculate dtim+cfp state for the result. @@ -759,6 +743,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; bs.bs_cfpmaxduration = 0; + /* * Calculate the number of consecutive beacons to miss * before taking a BMISS interrupt. The configuration @@ -767,9 +752,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * result to at most 15 beacons. */ if (sleepduration > intval) { - bs.bs_bmissthreshold = - conf.listen_interval * - ATH_DEFAULT_BMISS_LIMIT / 2; + bs.bs_bmissthreshold = conf.listen_interval * + ATH_DEFAULT_BMISS_LIMIT / 2; } else { bs.bs_bmissthreshold = DIV_ROUND_UP(conf.bmiss_timeout, intval); @@ -789,8 +773,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * XXX fixed at 100ms */ - bs.bs_sleepduration = - roundup(IEEE80211_MS_TO_TU(100), sleepduration); + bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), + sleepduration); if (bs.bs_sleepduration > bs.bs_dtimperiod) bs.bs_sleepduration = bs.bs_dtimperiod; @@ -834,9 +818,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { /* * Pull nexttbtt forward to reflect the current - * TSF . + * TSF */ -#define FUDGE 2 +#define FUDGE 2 if (!(intval & ATH9K_BEACON_RESET_TSF)) { tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU((u32)(tsf>>32), -- cgit v1.2.3 From 459f5f90f1bd959ced04761406415b178b315177 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Sep 2008 10:15:36 +0530 Subject: ath9k: Fix nexttbtt calculation nexttbtt has to be obtained from the timestamp of the beacon obtained from mac80211. Fix this. And is not needed anymore. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 9 ++++++--- drivers/net/wireless/ath9k/core.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index f8d952ca3f8..eedb465d25d 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -16,7 +16,6 @@ /* Implementation of beacon processing. */ -#include #include "core.h" /* @@ -305,6 +304,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) struct ieee80211_hdr *hdr; struct ath_buf *bf; struct sk_buff *skb; + __le64 tstamp; avp = sc->sc_vaps[if_id]; ASSERT(avp); @@ -370,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) return -ENOMEM; } + tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + sc->bc_tstamp = le64_to_cpu(tstamp); + /* * Calculate a TSF adjustment factor required for * staggered beacons. Note that we assume the format @@ -669,8 +672,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; /* extract tstamp from last beacon and convert to TU */ - nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), - get_unaligned_le32(conf.u.last_tstamp)); + nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp); + /* XXX conditionalize multi-bss support? */ if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { /* diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index b66de29cf66..6ff3befe39f 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -1001,6 +1001,7 @@ struct ath_softc { u32 sc_bhalq; u32 sc_bmisscount; u32 ast_be_xmit; /* beacons transmitted */ + u64 bc_tstamp; /* Rate */ struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; -- cgit v1.2.3 From 31e9ab2b180bccb3977b9a82ff357ac4c6ee3c83 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 17 Sep 2008 10:16:07 +0530 Subject: ath9k: Fix TSF Adjust usage TSF adjust is needed only for AP mode when staggered beacons are used. Since we support only a single interface in IBSS mode, disable setting the TSF adjust register. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index c262ef279ff..690f7c56af3 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c @@ -534,7 +534,8 @@ int ath_vap_attach(struct ath_softc *sc, avp->av_opmode = opmode; avp->av_bslot = -1; - ath9k_hw_set_tsfadjust(sc->sc_ah, 1); + if (opmode == ATH9K_M_HOSTAP) + ath9k_hw_set_tsfadjust(sc->sc_ah, 1); sc->sc_vaps[if_id] = avp; sc->sc_nvaps++; -- cgit v1.2.3 From 79617deeebb9cf089e2bc2aad19743b1209043f6 Mon Sep 17 00:00:00 2001 From: YanBo Date: Mon, 22 Sep 2008 13:30:32 +0800 Subject: mac80211: mesh portal functionality support Currently the mesh code doesn't support bridging mesh point interfaces with wired ethernet or AP to construct an MPP or MAP. This patch adds code to support the "6 address frame format packet" functionality to mesh point interfaces. Now the mesh network can be used as backhaul for end to end communication. Signed-off-by: Li YanBo Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 5 ++ net/mac80211/mesh.h | 4 ++ net/mac80211/mesh_pathtbl.c | 127 +++++++++++++++++++++++++++++++++++++++++++- net/mac80211/rx.c | 32 +++++++++-- net/mac80211/tx.c | 44 ++++++++++++--- 5 files changed, 201 insertions(+), 11 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index abc1abc63bf..14126bc3664 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -471,6 +471,11 @@ struct ieee80211s_hdr { u8 eaddr3[6]; } __attribute__ ((packed)); +/* Mesh flags */ +#define MESH_FLAGS_AE_A4 0x1 +#define MESH_FLAGS_AE_A5_A6 0x2 +#define MESH_FLAGS_PS_DEEP 0x4 + /** * struct ieee80211_quiet_ie * diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8ee414a0447..e10471c6ba4 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -71,6 +71,7 @@ enum mesh_path_flags { */ struct mesh_path { u8 dst[ETH_ALEN]; + u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ struct ieee80211_sub_if_data *sdata; struct sta_info *next_hop; struct timer_list timer; @@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb, void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata); +struct mesh_path *mpp_path_lookup(u8 *dst, + struct ieee80211_sub_if_data *sdata); +int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4fa2905fad..3c72557df45 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -36,6 +36,7 @@ struct mpath_node { }; static struct mesh_table *mesh_paths; +static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ /* This lock will have the grow table function as writer and add / delete nodes * as readers. When reading the table (i.e. doing lookups) we are well protected @@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) return NULL; } +struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) +{ + struct mesh_path *mpath; + struct hlist_node *n; + struct hlist_head *bucket; + struct mesh_table *tbl; + struct mpath_node *node; + + tbl = rcu_dereference(mpp_paths); + + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; + hlist_for_each_entry_rcu(node, n, bucket, list) { + mpath = node->mpath; + if (mpath->sdata == sdata && + memcmp(dst, mpath->dst, ETH_ALEN) == 0) { + if (MPATH_EXPIRED(mpath)) { + spin_lock_bh(&mpath->state_lock); + if (MPATH_EXPIRED(mpath)) + mpath->flags &= ~MESH_PATH_ACTIVE; + spin_unlock_bh(&mpath->state_lock); + } + return mpath; + } + } + return NULL; +} + + /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index * @idx: index @@ -226,6 +255,91 @@ err_path_alloc: } +int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) +{ + struct mesh_path *mpath, *new_mpath; + struct mpath_node *node, *new_node; + struct hlist_head *bucket; + struct hlist_node *n; + int grow = 0; + int err = 0; + u32 hash_idx; + + + if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) + /* never add ourselves as neighbours */ + return -ENOTSUPP; + + if (is_multicast_ether_addr(dst)) + return -ENOTSUPP; + + err = -ENOMEM; + new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); + if (!new_mpath) + goto err_path_alloc; + + new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); + if (!new_node) + goto err_node_alloc; + + read_lock(&pathtbl_resize_lock); + memcpy(new_mpath->dst, dst, ETH_ALEN); + memcpy(new_mpath->mpp, mpp, ETH_ALEN); + new_mpath->sdata = sdata; + new_mpath->flags = 0; + skb_queue_head_init(&new_mpath->frame_queue); + new_node->mpath = new_mpath; + new_mpath->exp_time = jiffies; + spin_lock_init(&new_mpath->state_lock); + + hash_idx = mesh_table_hash(dst, sdata, mpp_paths); + bucket = &mpp_paths->hash_buckets[hash_idx]; + + spin_lock(&mpp_paths->hashwlock[hash_idx]); + + err = -EEXIST; + hlist_for_each_entry(node, n, bucket, list) { + mpath = node->mpath; + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) + goto err_exists; + } + + hlist_add_head_rcu(&new_node->list, bucket); + if (atomic_inc_return(&mpp_paths->entries) >= + mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) + grow = 1; + + spin_unlock(&mpp_paths->hashwlock[hash_idx]); + read_unlock(&pathtbl_resize_lock); + if (grow) { + struct mesh_table *oldtbl, *newtbl; + + write_lock(&pathtbl_resize_lock); + oldtbl = mpp_paths; + newtbl = mesh_table_grow(mpp_paths); + if (!newtbl) { + write_unlock(&pathtbl_resize_lock); + return 0; + } + rcu_assign_pointer(mpp_paths, newtbl); + write_unlock(&pathtbl_resize_lock); + + synchronize_rcu(); + mesh_table_free(oldtbl, false); + } + return 0; + +err_exists: + spin_unlock(&mpp_paths->hashwlock[hash_idx]); + read_unlock(&pathtbl_resize_lock); + kfree(new_node); +err_node_alloc: + kfree(new_mpath); +err_path_alloc: + return err; +} + + /** * mesh_plink_broken - deactivates paths and sends perr when a link breaks * @@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) int mesh_pathtbl_init(void) { mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!mesh_paths) + return -ENOMEM; mesh_paths->free_node = &mesh_path_node_free; mesh_paths->copy_node = &mesh_path_node_copy; mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; - if (!mesh_paths) + + mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!mpp_paths) { + mesh_table_free(mesh_paths, true); return -ENOMEM; + } + mpp_paths->free_node = &mesh_path_node_free; + mpp_paths->copy_node = &mesh_path_node_copy; + mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; + return 0; } @@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) void mesh_pathtbl_unregister(void) { mesh_table_free(mesh_paths, true); + mesh_table_free(mpp_paths, true); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3ab9670f180..2efa4dd47b5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1107,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (ieee80211_vif_is_mesh(&sdata->vif)) - hdrlen += ieee80211_get_mesh_hdrlen( - (struct ieee80211s_hdr *) (skb->data + hdrlen)); - /* convert IEEE 802.11 header + possible LLC headers into Ethernet * header * IEEE 802.11 address fields: @@ -1134,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) return -1; + if (ieee80211_vif_is_mesh(&sdata->vif)) { + struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) + (skb->data + hdrlen); + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { + memcpy(dst, meshdr->eaddr1, ETH_ALEN); + memcpy(src, meshdr->eaddr2, ETH_ALEN); + } + } break; case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): if (sdata->vif.type != NL80211_IFTYPE_STATION || @@ -1393,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) /* illegal frame */ return RX_DROP_MONITOR; + if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ + struct ieee80211_sub_if_data *sdata; + struct mesh_path *mppath; + + sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + rcu_read_lock(); + mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); + if (!mppath) { + mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); + } else { + spin_lock_bh(&mppath->state_lock); + mppath->exp_time = jiffies; + if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) + memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); + spin_unlock_bh(&mppath->state_lock); + } + rcu_read_unlock(); + } + if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) return RX_CONTINUE; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 00d798cc9e0..00d96e63dce 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1498,18 +1498,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); - /* RA TA DA SA */ - memset(hdr.addr1, 0, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); - memcpy(hdr.addr3, skb->data, ETH_ALEN); - memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { /* Do not send frames with mesh_ttl == 0 */ sdata->u.mesh.mshstats.dropped_frames_ttl++; ret = 0; goto fail; } - meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); + memset(&mesh_hdr, 0, sizeof(mesh_hdr)); + + if (compare_ether_addr(dev->dev_addr, + skb->data + ETH_ALEN) == 0) { + /* RA TA DA SA */ + memset(hdr.addr1, 0, ETH_ALEN); + memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr3, skb->data, ETH_ALEN); + memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); + meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); + } else { + /* packet from other interface */ + struct mesh_path *mppath; + + memset(hdr.addr1, 0, ETH_ALEN); + memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); + + if (is_multicast_ether_addr(skb->data)) + memcpy(hdr.addr3, skb->data, ETH_ALEN); + else { + rcu_read_lock(); + mppath = mpp_path_lookup(skb->data, sdata); + if (mppath) + memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); + else + memset(hdr.addr3, 0xff, ETH_ALEN); + rcu_read_unlock(); + } + + mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; + mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; + put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); + memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); + memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); + sdata->u.mesh.mesh_seqnum++; + meshhdrlen = 18; + } hdrlen = 30; break; #endif -- cgit v1.2.3 From 2ff6a6d4e92270283432690adf53a7e5ab186d19 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Sep 2008 12:24:20 +0200 Subject: mac80211: fix mesh action frame handling When I split off the action frame handling I made the code drop all action frames we don't want to handle. This is wrong since some action frames are actually handled via rx_h_mgmt through being queued to the sta/mesh implementations. Thanks to Li YanBo for noticing the problem. Signed-off-by: Johannes Berg Cc: Li YanBo Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2efa4dd47b5..c489865761b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1557,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) */ if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_ADHOC) - return RX_DROP_MONITOR; + return RX_CONTINUE; switch (mgmt->u.action.category) { case WLAN_CATEGORY_BACK: -- cgit v1.2.3 From 4b7679a561e552eeda1e3567119bef2bca99b66e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Sep 2008 18:14:18 +0200 Subject: mac80211: clean up rate control API Long awaited, hard work. This patch totally cleans up the rate control API to remove the requirement to include internal headers outside of net/mac80211/. There's one internal use in the PID algorithm left for mesh networking, we'll have to figure out a way to clean that one up and decide how to do the peer link evaluation, possibly independent of the rate control algorithm or via new API. Additionally, ath9k is left using the cross-inclusion hack for now, we will add new API where necessary to make this work properly, but right now I'm not expert enough to do it. It's still off better than before. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 98 +++++++-------- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 182 ++++++---------------------- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 9 -- drivers/net/wireless/iwlwifi/iwl-3945.h | 4 + drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 146 +++++++++------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 +- include/net/mac80211.h | 68 +++++++++++ net/mac80211/cfg.c | 2 +- net/mac80211/ieee80211_i.h | 2 + net/mac80211/main.c | 4 +- net/mac80211/mlme.c | 4 +- net/mac80211/rate.c | 71 ++++++++--- net/mac80211/rate.h | 102 ++++------------ net/mac80211/rc80211_pid.h | 2 - net/mac80211/rc80211_pid_algo.c | 158 +++++++++--------------- net/mac80211/sta_info.c | 17 +-- net/mac80211/sta_info.h | 2 +- net/mac80211/tx.c | 5 +- 18 files changed, 373 insertions(+), 514 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 1cc9daf4455..cca2fc5b076 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -20,6 +20,7 @@ */ #include "core.h" +/* FIXME: remove this include! */ #include "../net/mac80211/rate.h" static u32 tx_triglevel_max; @@ -1812,20 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) } -static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) +static void ath_setup_rates(struct ath_softc *sc, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct ath_rate_node *rc_priv) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ath_softc *sc = hw->priv; - struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; int i, j = 0; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; for (i = 0; i < sband->n_bitrates; i++) { - if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) { + if (sta->supp_rates[sband->band] & BIT(i)) { rc_priv->neg_rates.rs_rates[j] = (sband->bitrates[i].bitrate * 2) / 10; j++; @@ -1852,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) } /* Rate Control callbacks */ -static void ath_tx_status(void *priv, struct net_device *dev, +static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { struct ath_softc *sc = priv; struct ath_tx_info_priv *tx_info_priv; struct ath_node *an; - struct sta_info *sta; - struct ieee80211_local *local; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr; __le16 fc; - local = hw_to_local(sc->hw); hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; @@ -1873,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev, an = ath_node_find(sc, hdr->addr1); spin_unlock_bh(&sc->node_lock); - sta = sta_info_get(local, hdr->addr1); - if (!an || !sta || !ieee80211_is_data(fc)) { + if (!an || !priv_sta || !ieee80211_is_data(fc)) { if (tx_info->driver_data[0] != NULL) { kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; @@ -1882,24 +1878,22 @@ static void ath_tx_status(void *priv, struct net_device *dev, return; } if (tx_info->driver_data[0] != NULL) { - ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv); + ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; } } static void ath_tx_aggr_resp(struct ath_softc *sc, - struct sta_info *sta, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, struct ath_node *an, u8 tidno) { - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_local *local; struct ath_atx_tid *txtid; - struct ieee80211_supported_band *sband; u16 buffersize = 0; int state; - DECLARE_MAC_BUF(mac); + struct sta_info *si; if (!(sc->sc_flags & SC_OP_TXAGGR)) return; @@ -1908,11 +1902,16 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, if (!txtid->paused) return; - local = hw_to_local(sc->hw); - sband = hw->wiphy->bands[hw->conf.channel->band]; + /* + * XXX: This is entirely busted, we aren't supposed to + * access the sta from here because it's internal + * to mac80211, and looking at the state without + * locking is wrong too. + */ + si = container_of(sta, struct sta_info, sta); buffersize = IEEE80211_MIN_AMPDU_BUF << sband->ht_info.ampdu_factor; /* FIXME */ - state = sta->ampdu_mlme.tid_state_tx[tidno]; + state = si->ampdu_mlme.tid_state_tx[tidno]; if (state & HT_ADDBA_RECEIVED_MSK) { txtid->addba_exchangecomplete = 1; @@ -1928,18 +1927,15 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, } } -static void ath_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sta_info *sta; - struct ath_softc *sc = (struct ath_softc *)priv; + struct ath_softc *sc = priv; struct ieee80211_hw *hw = sc->hw; struct ath_tx_info_priv *tx_info_priv; - struct ath_rate_node *ath_rc_priv; + struct ath_rate_node *ath_rc_priv = priv_sta; struct ath_node *an; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int is_probe = FALSE, chk, ret; @@ -1955,8 +1951,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, ASSERT(tx_info->driver_data[0] != NULL); tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; - sta = sta_info_get(local, hdr->addr1); - lowest_idx = rate_lowest_index(local, sband, sta); + lowest_idx = rate_lowest_index(sband, sta); tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; /* lowest rate for management and multicast/broadcast frames */ if (!ieee80211_is_data(fc) || @@ -1965,8 +1960,6 @@ static void ath_get_rate(void *priv, struct net_device *dev, return; } - ath_rc_priv = sta->rate_ctrl_priv; - /* Find tx rate for unicast frames */ ath_rate_findrate(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, @@ -1975,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, &is_probe, false); if (is_probe) - sel->probe_idx = ((struct ath_tx_ratectrl *) - sta->rate_ctrl_priv)->probe_rate; + sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; /* Ratecontrol sometimes returns invalid rate index */ if (tx_info_priv->rcs[0].rix != 0xff) @@ -2020,37 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev, __func__, print_mac(mac, hdr->addr1)); } else if (chk == AGGR_EXCHANGE_PROGRESS) - ath_tx_aggr_resp(sc, sta, an, tid); + ath_tx_aggr_resp(sc, sband, sta, an, tid); } } } -static void ath_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ieee80211_conf *conf = &local->hw.conf; - struct ath_softc *sc = hw->priv; + struct ath_softc *sc = priv; struct ath_rate_node *ath_rc_priv = priv_sta; int i, j = 0; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - ath_setup_rates(local, sta); - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + ath_setup_rates(sc, sband, sta, ath_rc_priv); + if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { for (i = 0; i < MCS_SET_SIZE; i++) { - if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) + if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; if (j == ATH_RATE_MAX) break; } ath_rc_priv->neg_ht_rates.rs_nrates = j; } - ath_rc_node_update(hw, priv_sta); + ath_rc_node_update(sc->hw, priv_sta); } static void ath_rate_clear(void *priv) @@ -2058,13 +2044,12 @@ static void ath_rate_clear(void *priv) return; } -static void *ath_rate_alloc(struct ieee80211_local *local) +static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - struct ieee80211_hw *hw = local_to_hw(local); struct ath_softc *sc = hw->priv; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - return local->hw.priv; + return hw->priv; } static void ath_rate_free(void *priv) @@ -2072,7 +2057,7 @@ static void ath_rate_free(void *priv) return; } -static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) +static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct ath_softc *sc = priv; struct ath_vap *avp = sc->sc_vaps[0]; @@ -2092,7 +2077,8 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) return rate_priv; } -static void ath_rate_free_sta(void *priv, void *priv_sta) +static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { struct ath_rate_node *rate_priv = priv_sta; struct ath_softc *sc = priv; @@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = { .alloc = ath_rate_alloc, .free = ath_rate_free, .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta + .free_sta = ath_rate_free_sta, }; int ath_rate_control_register(void) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a279bf1dc9b..6fc5e7361f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -36,8 +36,6 @@ #include -#include "../net/mac80211/rate.h" - #include "iwl-3945.h" #define RS_NAME "iwl-3945-rs" @@ -319,10 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, } } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, struct sta_info *sta) +static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { - struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv; + struct iwl3945_rs_sta *rs_sta = priv_sta; int i; IWL_DEBUG_RATE("enter\n"); @@ -333,22 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) { + if (sta->supp_rates[sband->band] & (1 << i)) { rs_sta->last_txrate_idx = i; break; } } /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ @@ -356,17 +354,24 @@ static void rs_free(void *priv) { return; } + static void rs_clear(void *priv) { return; } -static void *rs_alloc_sta(void *priv, gfp_t gfp) +static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; int i; + /* + * XXX: If it's using sta->drv_priv anyway, it might + * as well just put all the information there. + */ + IWL_DEBUG_RATE("enter\n"); rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); @@ -375,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return NULL; } + psta->rs_sta = rs_sta; + spin_lock_init(&rs_sta->lock); rs_sta->start_rate = IWL_RATE_INVALID; @@ -400,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return rs_sta; } -static void rs_free_sta(void *priv, void *priv_sta) +static void rs_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; + psta->rs_sta = NULL; + IWL_DEBUG_RATE("enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); kfree(rs_sta); @@ -445,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by * the hardware for each rate. */ -static void rs_tx_status(void *priv_rate, - struct net_device *dev, +static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { u8 retries, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; - struct sta_info *sta; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct iwl3945_rs_sta *rs_sta; - struct ieee80211_supported_band *sband; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - retries = info->status.retry_count; first_index = sband->bitrates[info->tx_rate_idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { @@ -472,17 +476,11 @@ static void rs_tx_status(void *priv_rate, return; } - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - if (!sta || !sta->rate_ctrl_priv) { - rcu_read_unlock(); + if (!priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); return; } - rs_sta = (void *)sta->rate_ctrl_priv; - rs_sta->tx_packets++; scale_rate_index = first_index; @@ -549,8 +547,6 @@ static void rs_tx_status(void *priv_rate, spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - IWL_DEBUG_RATE("leave\n"); return; @@ -634,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; int index; - struct iwl3945_rs_sta *rs_sta; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl3945_rate_scale_data *window = NULL; int current_tpt = IWL_INV_TPT; int low_tpt = IWL_INV_TPT; @@ -651,34 +646,25 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, u32 fail_count; s8 scale_action = 0; unsigned long flags; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; u16 fc, rate_mask; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; + struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; DECLARE_MAC_BUF(mac); IWL_DEBUG_RATE("enter\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { + !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(local, sband, sta); - rcu_read_unlock(); + sel->rate_idx = rate_lowest_index(sband, sta); return; } - rs_sta = (void *)sta->rate_ctrl_priv; - - rate_mask = sta->sta.supp_rates[sband->band]; + rate_mask = sta->supp_rates[sband->band]; index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) @@ -811,8 +797,6 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, else sel->rate_idx = rs_sta->last_txrate_idx; - rcu_read_unlock(); - IWL_DEBUG_RATE("leave: %d\n", index); } @@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = { .free_sta = rs_free_sta, }; -int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct iwl3945_priv *priv = hw->priv; - struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; - unsigned long flags; - int count = 0, i; - u32 samples = 0, success = 0, good = 0; - unsigned long now = jiffies; - u32 max_time = 0; - - rcu_read_lock(); - - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { - if (sta) - IWL_DEBUG_RATE("leave - no private rate data!\n"); - else - IWL_DEBUG_RATE("leave - no station!\n"); - rcu_read_unlock(); - return sprintf(buf, "station %d not found\n", sta_id); - } - - rs_sta = (void *)sta->rate_ctrl_priv; - spin_lock_irqsave(&rs_sta->lock, flags); - i = IWL_RATE_54M_INDEX; - while (1) { - u64 mask; - int j; - - count += - sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2); - - mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); - for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) - buf[count++] = - (rs_sta->win[i].data & mask) ? '1' : '0'; - - samples += rs_sta->win[i].counter; - good += rs_sta->win[i].success_counter; - success += rs_sta->win[i].success_counter * - iwl3945_rates[i].ieee; - - if (rs_sta->win[i].stamp) { - int delta = - jiffies_to_msecs(now - rs_sta->win[i].stamp); - - if (delta > max_time) - max_time = delta; - - count += sprintf(&buf[count], "%5dms\n", delta); - } else - buf[count++] = '\n'; - - j = iwl3945_get_prev_ieee_rate(i); - if (j == i) - break; - i = j; - } - spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - - /* Display the average rate of all samples taken. - * - * NOTE: We multiple # of samples by 2 since the IEEE measurement - * added from iwl3945_rates is actually 2X the rate */ - if (samples) - count += sprintf( - &buf[count], - "\nAverage rate is %3d.%02dMbs over last %4dms\n" - "%3d%% success (%d good packets over %d tries)\n", - success / (2 * samples), (success * 5 / samples) % 10, - max_time, good * 100 / samples, good, samples); - else - count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n"); - - return count; -} - void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { struct iwl3945_priv *priv = hw->priv; s32 rssi = 0; unsigned long flags; - struct ieee80211_local *local = hw_to_local(hw); struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; + struct ieee80211_sta *sta; + struct iwl3945_sta_priv *psta; IWL_DEBUG_RATE("enter\n"); - if (!local->rate_ctrl->ops->name || - strcmp(local->rate_ctrl->ops->name, RS_NAME)) { - IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n"); - IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n"); - return; - } - rcu_read_lock(); - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { + sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); + psta = (void *) sta->drv_priv; + if (!sta || !psta) { IWL_DEBUG_RATE("leave - no private rate data!\n"); rcu_read_unlock(); return; } - rs_sta = (void *)sta->rate_ctrl_priv; + rs_sta = psta->rs_sta; spin_lock_irqsave(&rs_sta->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index f085d330bdc..98b17ae6ef2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -175,15 +175,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) return rate; } -/** - * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation - * - * NOTE: This is provided as a quick mechanism for a user to visualize - * the performance of the rate control algorithm and is not meant to be - * parsed software. - */ -extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); - /** * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info * diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2a4933b5fb6..bdd32475b99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; extern int iwl3945_param_hwcrypto; extern int iwl3945_param_queues_num; +struct iwl3945_sta_priv { + struct iwl3945_rs_sta *rs_sta; +}; + enum iwl3945_antenna { IWL_ANTENNA_DIVERSITY, IWL_ANTENNA_MAIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8b57b390c8b..93944de923c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -35,8 +35,6 @@ #include -#include "../net/mac80211/rate.h" - #include "iwl-dev.h" #include "iwl-sta.h" #include "iwl-core.h" @@ -169,9 +167,9 @@ struct iwl_lq_sta { }; static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta); + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(const struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); @@ -357,20 +355,20 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl_lq_sta *lq_data, u8 tid, - struct sta_info *sta) + struct ieee80211_sta *sta) { DECLARE_MAC_BUF(mac); if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", - print_mac(mac, sta->sta.addr), tid); - ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid); + print_mac(mac, sta->addr), tid); + ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); } } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl_lq_sta *lq_data, - struct sta_info *sta) + struct ieee80211_sta *sta) { if ((tid < TID_MAX_LOAD_COUNT)) rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); @@ -770,7 +768,8 @@ out: /* * mac80211 sends us Tx status */ -static void rs_tx_status(void *priv_rate, struct net_device *dev, +static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { int status; @@ -778,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, int rs_index, index = 0; struct iwl_lq_sta *lq_sta; struct iwl_link_quality_cmd *table; - struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_rate_scale_data *window = NULL; struct iwl_rate_scale_data *search_win = NULL; @@ -808,15 +805,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if (retries > 15) retries = 15; - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - - if (!sta || !sta->rate_ctrl_priv) - goto out; - - - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)priv_sta; if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) @@ -962,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, } /* See if there's a better rate or modulation mode to try. */ - rs_rate_scale_perform(priv, dev, hdr, sta); + rs_rate_scale_perform(priv, hdr, sta, lq_sta); out: - rcu_read_unlock(); return; } @@ -1140,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, static int rs_switch_to_mimo2(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; @@ -1148,10 +1136,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, s8 is_green = lq_sta->is_green; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->sta.ht_info.ht_supported) + !sta->ht_info.ht_supported) return -1; - if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) == WLAN_HT_CAP_SM_PS_STATIC) return -1; @@ -1208,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, static int rs_switch_to_siso(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; @@ -1216,7 +1204,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, s32 rate; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->sta.ht_info.ht_supported) + !sta->ht_info.ht_supported) return -1; IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); @@ -1268,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, static int rs_move_legacy_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, int index) { struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1376,7 +1364,7 @@ out: static int rs_move_siso_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, int index) + struct ieee80211_sta *sta, int index) { u8 is_green = lq_sta->is_green; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1487,7 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, static int rs_move_mimo_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, int index) + struct ieee80211_sta *sta, int index) { s8 is_green = lq_sta->is_green; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1680,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) * Do rate scaling and search for new modulation mode. */ static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; int low = IWL_RATE_INVALID; int high = IWL_RATE_INVALID; @@ -1700,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, __le16 fc; u16 rate_mask; u8 update_lq = 0; - struct iwl_lq_sta *lq_sta; struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; u32 rate; @@ -1721,11 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, return; } - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) return; - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band]; + lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); @@ -2064,9 +2049,9 @@ out: static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct iwl_lq_sta *lq_sta; struct iwl_scale_tbl_info *tbl; int rate_idx; int i; @@ -2075,10 +2060,9 @@ static void rs_initialize_lq(struct iwl_priv *priv, u8 active_tbl = 0; u8 valid_tx_ant; - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) goto out; - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; i = lq_sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && @@ -2119,37 +2103,30 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { int i; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_conf *conf = &local->hw.conf; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; __le16 fc; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl_lq_sta *lq_sta; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + !sta || !priv_sta) { + sel->rate_idx = rate_lowest_index(sband, sta); + return; } - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)priv_sta; i = lq_sta->last_txrate_idx; if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && @@ -2167,23 +2144,22 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, lq_sta->lq.sta_id = sta_id; lq_sta->lq.rs_table[0].rate_n_flags = 0; lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + sel->rate_idx = rate_lowest_index(sband, sta); + return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; sel->rate_idx = i; -out: - rcu_read_unlock(); } -static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) +static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, + gfp_t gfp) { struct iwl_lq_sta *lq_sta; struct iwl_priv *priv; @@ -2206,20 +2182,16 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) return lq_sta; } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { int i, j; - struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_supported_band *sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; struct iwl_lq_sta *lq_sta = priv_sta; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->sta.supp_rates[sband->band]; + lq_sta->supp_rates = sta->supp_rates[sband->band]; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); @@ -2232,17 +2204,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->ibss_sta_added = 0; if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, sta->sta.addr); + u8 sta_id = iwl_find_station(priv, sta->addr); DECLARE_MAC_BUF(mac); /* for IBSS the call are from tasklet */ IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->sta.addr)); + print_mac(mac, sta->addr)); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->sta.addr)); - sta_id = iwl_add_station_flags(priv, sta->sta.addr, + print_mac(mac, sta->addr)); + sta_id = iwl_add_station_flags(priv, sta->addr, 0, CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { @@ -2256,11 +2228,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* Find highest tx rate supported by hardware and destination station */ lq_sta->last_txrate_idx = 3; for (i = 0; i < sband->n_bitrates; i++) - if (sta->sta.supp_rates[sband->band] & BIT(i)) + if (sta->supp_rates[sband->band] & BIT(i)) lq_sta->last_txrate_idx = i; /* For MODE_IEEE80211A, skip over cck rates in global rate table */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; @@ -2301,7 +2273,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; lq_sta->drv = priv; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } static void rs_fill_link_cmd(const struct iwl_priv *priv, @@ -2423,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ static void rs_free(void *priv_rate) @@ -2446,12 +2418,12 @@ static void rs_clear(void *priv_rate) #endif /* CONFIG_IWLWIFI_DEBUG */ } -static void rs_free_sta(void *priv_rate, void *priv_sta) +static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, + void *priv_sta) { struct iwl_lq_sta *lq_sta = priv_sta; - struct iwl_priv *priv; + struct iwl_priv *priv = priv_r; - priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("enter\n"); kfree(lq_sta); IWL_DEBUG_RATE("leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 62b26befddc..d15a2c99795 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7370,15 +7370,6 @@ static ssize_t show_temperature(struct device *d, static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); -static ssize_t show_rs_window(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct iwl3945_priv *priv = d->driver_data; - return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID); -} -static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); - static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { @@ -7840,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, @@ -7908,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e SET_IEEE80211_DEV(hw, &pdev->dev); hw->rate_control_algorithm = "iwl-3945-rs"; + hw->sta_data_size = sizeof(struct iwl3945_sta_priv); IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 003e4a03874..f5f5b1ff158 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1800,4 +1800,72 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr); + +/* Rate control API */ +/** + * struct rate_selection - rate information for/from rate control algorithms + * + * @rate_idx: selected transmission rate index + * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used + * @probe_idx: rate for probing (or -1) + * @max_rate_idx: maximum rate index that can be used, this is + * input to the algorithm and will be enforced + */ +struct rate_selection { + s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx; +}; + +struct rate_control_ops { + struct module *module; + const char *name; + void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); + void (*clear)(void *priv); + void (*free)(void *priv); + + void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); + void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta); + void (*free_sta)(void *priv, struct ieee80211_sta *sta, + void *priv_sta); + + void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb); + void (*get_rate)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, + struct rate_selection *sel); + + void (*add_sta_debugfs)(void *priv, void *priv_sta, + struct dentry *dir); + void (*remove_sta_debugfs)(void *priv, void *priv_sta); +}; + +static inline int rate_supported(struct ieee80211_sta *sta, + enum ieee80211_band band, + int index) +{ + return (sta == NULL || sta->supp_rates[band] & BIT(index)); +} + +static inline s8 +rate_lowest_index(struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta) +{ + int i; + + for (i = 0; i < sband->n_bitrates; i++) + if (rate_supported(sta, sband->band, i)) + return i; + + /* warn when we cannot find a rate. */ + WARN_ON(1); + + return 0; +} + + +int ieee80211_rate_control_register(struct rate_control_ops *ops); +void ieee80211_rate_control_unregister(struct rate_control_ops *ops); + #endif /* MAC80211_H */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 89a183c2327..855126a3039 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -693,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, sta_apply_parameters(local, sta, params); - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); rcu_read_lock(); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0b25b0f46b1..8025b294588 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -724,6 +724,8 @@ struct ieee80211_local { #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { + struct dentry *rcdir; + struct dentry *rcname; struct dentry *frequency; struct dentry *antenna_sel_tx; struct dentry *antenna_sel_rx; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7d2d5a041e2..d608c44047c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -542,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u16 frag, type; __le16 fc; + struct ieee80211_supported_band *sband; struct ieee80211_tx_status_rtap_hdr *rthdr; struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; @@ -588,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) sta->tx_retry_count += info->status.retry_count; } - rate_control_tx_status(local->mdev, skb); + sband = local->hw.wiphy->bands[info->band]; + rate_control_tx_status(local, sband, sta, skb); } rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8611a8318c9..109c3a7e63a 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); } - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); if (elems.wmm_param) { set_sta_flags(sta, WLAN_STA_WME); @@ -2342,7 +2342,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(local, band); - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); if (sta_info_insert(sta)) return NULL; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe..5d786720d93 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -12,6 +12,7 @@ #include #include "rate.h" #include "ieee80211_i.h" +#include "debugfs.h" struct rate_control_alg { struct list_head list; @@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) module_put(ops->module); } +#ifdef CONFIG_MAC80211_DEBUGFS +static ssize_t rcname_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct rate_control_ref *ref = file->private_data; + int len = strlen(ref->ops->name); + + return simple_read_from_buffer(userbuf, count, ppos, + ref->ops->name, len); +} + +static const struct file_operations rcname_ops = { + .read = rcname_read, + .open = mac80211_open_file_generic, +}; +#endif + struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local) { + struct dentry *debugfsdir = NULL; struct rate_control_ref *ref; ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); if (!ref) goto fail_ref; kref_init(&ref->kref); + ref->local = local; ref->ops = ieee80211_rate_control_ops_get(name); if (!ref->ops) goto fail_ops; - ref->priv = ref->ops->alloc(local); + +#ifdef CONFIG_MAC80211_DEBUGFS + debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); + local->debugfs.rcdir = debugfsdir; + local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, + ref, &rcname_ops); +#endif + + ref->priv = ref->ops->alloc(&local->hw, debugfsdir); if (!ref->priv) goto fail_priv; return ref; @@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) ctrl_ref = container_of(kref, struct rate_control_ref, kref); ctrl_ref->ops->free(ctrl_ref->priv); + +#ifdef CONFIG_MAC80211_DEBUGFS + debugfs_remove(ctrl_ref->local->debugfs.rcname); + ctrl_ref->local->debugfs.rcname = NULL; + debugfs_remove(ctrl_ref->local->debugfs.rcdir); + ctrl_ref->local->debugfs.rcdir = NULL; +#endif + ieee80211_rate_control_ops_put(ctrl_ref->ops); kfree(ctrl_ref); } -void rate_control_get_rate(struct net_device *dev, +void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, - struct sk_buff *skb, + struct sta_info *sta, struct sk_buff *skb, struct rate_selection *sel) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct rate_control_ref *ref = local->rate_ctrl; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct sta_info *sta; + struct rate_control_ref *ref = sdata->local->rate_ctrl; + void *priv_sta = NULL; + struct ieee80211_sta *ista = NULL; int i; - rcu_read_lock(); - sta = sta_info_get(local, hdr->addr1); - sel->rate_idx = -1; sel->nonerp_idx = -1; sel->probe_idx = -1; + sel->max_rate_idx = sdata->max_ratectrl_rateidx; + + if (sta) { + ista = &sta->sta; + priv_sta = sta->rate_ctrl_priv; + } + + if (sta && sdata->force_unicast_rateidx > -1) + sel->rate_idx = sdata->force_unicast_rateidx; + else + ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); - ref->ops->get_rate(ref->priv, dev, sband, skb, sel); + if (sdata->max_ratectrl_rateidx > -1 && + sel->rate_idx > sdata->max_ratectrl_rateidx) + sel->rate_idx = sdata->max_ratectrl_rateidx; BUG_ON(sel->rate_idx < 0); @@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) break; - if (rate_supported(sta, sband->band, i) && + if (rate_supported(ista, sband->band, i) && !(rate->flags & IEEE80211_RATE_ERP_G)) sel->nonerp_idx = i; } } - - rcu_read_unlock(); } struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5f18c27eb90..eb94e584d24 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -19,77 +19,48 @@ #include "ieee80211_i.h" #include "sta_info.h" -/** - * struct rate_selection - rate selection for rate control algos - * @rate: selected transmission rate index - * @nonerp: Non-ERP rate to use instead if ERP cannot be used - * @probe: rate for probing (or -1) - * - */ -struct rate_selection { - s8 rate_idx, nonerp_idx, probe_idx; -}; - -struct rate_control_ops { - struct module *module; - const char *name; - void (*tx_status)(void *priv, struct net_device *dev, - struct sk_buff *skb); - void (*get_rate)(void *priv, struct net_device *dev, - struct ieee80211_supported_band *band, - struct sk_buff *skb, - struct rate_selection *sel); - void (*rate_init)(void *priv, void *priv_sta, - struct ieee80211_local *local, struct sta_info *sta); - void (*clear)(void *priv); - - void *(*alloc)(struct ieee80211_local *local); - void (*free)(void *priv); - void *(*alloc_sta)(void *priv, gfp_t gfp); - void (*free_sta)(void *priv, void *priv_sta); - - int (*add_attrs)(void *priv, struct kobject *kobj); - void (*remove_attrs)(void *priv, struct kobject *kobj); - void (*add_sta_debugfs)(void *priv, void *priv_sta, - struct dentry *dir); - void (*remove_sta_debugfs)(void *priv, void *priv_sta); -}; - struct rate_control_ref { + struct ieee80211_local *local; struct rate_control_ops *ops; void *priv; struct kref kref; }; -int ieee80211_rate_control_register(struct rate_control_ops *ops); -void ieee80211_rate_control_unregister(struct rate_control_ops *ops); - /* Get a reference to the rate control algorithm. If `name' is NULL, get the * first available algorithm. */ struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local); -void rate_control_get_rate(struct net_device *dev, +void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, - struct sk_buff *skb, + struct sta_info *sta, struct sk_buff *skb, struct rate_selection *sel); struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); void rate_control_put(struct rate_control_ref *ref); -static inline void rate_control_tx_status(struct net_device *dev, +static inline void rate_control_tx_status(struct ieee80211_local *local, + struct ieee80211_supported_band *sband, + struct sta_info *sta, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct rate_control_ref *ref = local->rate_ctrl; + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; - ref->ops->tx_status(ref->priv, dev, skb); + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); } -static inline void rate_control_rate_init(struct sta_info *sta, - struct ieee80211_local *local) +static inline void rate_control_rate_init(struct sta_info *sta) { + struct ieee80211_local *local = sta->sdata->local; struct rate_control_ref *ref = sta->rate_ctrl; - ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + ref->ops->rate_init(ref->priv, sband, ista, priv_sta); } @@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) } static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, + struct ieee80211_sta *sta, gfp_t gfp) { - return ref->ops->alloc_sta(ref->priv, gfp); + return ref->ops->alloc_sta(ref->priv, sta, gfp); } -static inline void rate_control_free_sta(struct rate_control_ref *ref, - void *priv) +static inline void rate_control_free_sta(struct sta_info *sta) { - ref->ops->free_sta(ref->priv, priv); + struct rate_control_ref *ref = sta->rate_ctrl; + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; + + ref->ops->free_sta(ref->priv, ista, priv_sta); } static inline void rate_control_add_sta_debugfs(struct sta_info *sta) @@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) #endif } -static inline int rate_supported(struct sta_info *sta, - enum ieee80211_band band, - int index) -{ - return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); -} - -static inline s8 -rate_lowest_index(struct ieee80211_local *local, - struct ieee80211_supported_band *sband, - struct sta_info *sta) -{ - int i; - - for (i = 0; i < sband->n_bitrates; i++) - if (rate_supported(sta, sband->band, i)) - return i; - - /* warn when we cannot find a rate. */ - WARN_ON(1); - - return 0; -} - - /* functions for rate control related to a device */ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, const char *name); diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ffafc5da572..01d64d53f3b 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h @@ -124,7 +124,6 @@ struct rc_pid_events_file_info { * struct rc_pid_debugfs_entries - tunable parameters * * Algorithm parameters, tunable via debugfs. - * @dir: the debugfs directory for a specific phy * @target: target percentage for failed frames * @sampling_period: error sampling interval in milliseconds * @coeff_p: absolute value of the proportional coefficient @@ -143,7 +142,6 @@ struct rc_pid_events_file_info { * ordering of rates) */ struct rc_pid_debugfs_entries { - struct dentry *dir; struct dentry *target; struct dentry *sampling_period; struct dentry *coeff_p; diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa..86eb374e3b8 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -68,18 +68,14 @@ * exhibited a worse failed frames behaviour and we'll choose the highest rate * whose failed frames behaviour is not worse than the one of the original rate * target. While at it, check that the new rate is valid. */ -static void rate_control_pid_adjust_rate(struct ieee80211_local *local, - struct sta_info *sta, int adj, +static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct rc_pid_sta_info *spinfo, int adj, struct rc_pid_rateinfo *rinfo) { - struct ieee80211_sub_if_data *sdata; - struct ieee80211_supported_band *sband; int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; - struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; int cur = spinfo->txrate_idx; - sdata = sta->sdata; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; band = sband->band; n_bitrates = sband->n_bitrates; @@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) } static void rate_control_pid_sample(struct rc_pid_info *pinfo, - struct ieee80211_local *local, - struct sta_info *sta) + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct rc_pid_sta_info *spinfo) { - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; - struct ieee80211_supported_band *sband; u32 pf; s32 err_avg; u32 err_prop; @@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, int adj, i, j, tmp; unsigned long period; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - spinfo = sta->rate_ctrl_priv; - /* In case nothing happened during the previous control interval, turn * the sharpening factor on. */ period = (HZ * pinfo->sampling_period + 500) / 1000; @@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, if (unlikely(spinfo->tx_num_xmit == 0)) pf = spinfo->last_pf; else { + /* XXX: BAD HACK!!! */ + struct sta_info *si = container_of(sta, struct sta_info, sta); + pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; - if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) - mesh_plink_broken(sta); + + if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) + mesh_plink_broken(si); pf <<= RC_PID_ARITH_SHIFT; - sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) + si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) >> RC_PID_ARITH_SHIFT; } @@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, /* Change rate. */ if (adj) - rate_control_pid_adjust_rate(local, sta, adj, rinfo); + rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); } -static void rate_control_pid_tx_status(void *priv, struct net_device *dev, +static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sub_if_data *sdata; struct rc_pid_info *pinfo = priv; - struct sta_info *sta; - struct rc_pid_sta_info *spinfo; + struct rc_pid_sta_info *spinfo = priv_sta; unsigned long period; - struct ieee80211_supported_band *sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - if (!sta) - goto unlock; - - spinfo = sta->rate_ctrl_priv; - - /* Don't update the state if we're not controlling the rate. */ - sdata = sta->sdata; - if (sdata->force_unicast_rateidx > -1) { - spinfo->txrate_idx = sdata->max_ratectrl_rateidx; - goto unlock; - } + if (!spinfo) + return; /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ if (info->tx_rate_idx != spinfo->txrate_idx) - goto unlock; + return; spinfo->tx_num_xmit++; @@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, if (!period) period = 1; if (time_after(jiffies, spinfo->last_sample + period)) - rate_control_pid_sample(pinfo, local, sta); - - unlock: - rcu_read_unlock(); + rate_control_pid_sample(pinfo, sband, sta, spinfo); } -static void rate_control_pid_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void +rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, + struct rate_selection *sel) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sub_if_data *sdata; - struct rc_pid_sta_info *spinfo; - struct sta_info *sta; + struct rc_pid_sta_info *spinfo = priv_sta; int rateidx; u16 fc; - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); - if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - rcu_read_unlock(); + if (!sta || !spinfo || + (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || + is_multicast_ether_addr(hdr->addr1)) { + sel->rate_idx = rate_lowest_index(sband, sta); return; } - /* If a forced rate is in effect, select it. */ - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; - if (sdata->force_unicast_rateidx > -1) - spinfo->txrate_idx = sdata->force_unicast_rateidx; - rateidx = spinfo->txrate_idx; if (rateidx >= sband->n_bitrates) rateidx = sband->n_bitrates - 1; - rcu_read_unlock(); - sel->rate_idx = rateidx; #ifdef CONFIG_MAC80211_DEBUGFS - rate_control_pid_event_tx_rate( - &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, + rate_control_pid_event_tx_rate(&spinfo->events, rateidx, sband->bitrates[rateidx].bitrate); #endif } -static void rate_control_pid_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void +rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { + struct rc_pid_sta_info *spinfo = priv_sta; + struct sta_info *si; + /* TODO: This routine should consider using RSSI from previous packets * as we need to have IEEE 802.1X auth succeed immediately after assoc.. * Until that method is implemented, we will use the lowest supported * rate as a workaround. */ - struct ieee80211_supported_band *sband; - struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - spinfo->txrate_idx = rate_lowest_index(local, sband, sta); - sta->fail_avg = 0; + spinfo->txrate_idx = rate_lowest_index(sband, sta); + /* HACK */ + si = container_of(sta, struct sta_info, sta); + si->fail_avg = 0; } -static void *rate_control_pid_alloc(struct ieee80211_local *local) +static void *rate_control_pid_alloc(struct ieee80211_hw *hw, + struct dentry *debugfsdir) { struct rc_pid_info *pinfo; struct rc_pid_rateinfo *rinfo; @@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) struct rc_pid_debugfs_entries *de; #endif - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = hw->wiphy->bands[hw->conf.channel->band]; pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); if (!pinfo) @@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) #ifdef CONFIG_MAC80211_DEBUGFS de = &pinfo->dentries; - de->dir = debugfs_create_dir("rc80211_pid", - local->hw.wiphy->debugfsdir); de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, - de->dir, &pinfo->target); + debugfsdir, &pinfo->target); de->sampling_period = debugfs_create_u32("sampling_period", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sampling_period); de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_p); + debugfsdir, &pinfo->coeff_p); de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_i); + debugfsdir, &pinfo->coeff_i); de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_d); + debugfsdir, &pinfo->coeff_d); de->smoothing_shift = debugfs_create_u32("smoothing_shift", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->smoothing_shift); de->sharpen_factor = debugfs_create_u32("sharpen_factor", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sharpen_factor); de->sharpen_duration = debugfs_create_u32("sharpen_duration", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sharpen_duration); de->norm_offset = debugfs_create_u32("norm_offset", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->norm_offset); #endif @@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) debugfs_remove(de->coeff_p); debugfs_remove(de->sampling_period); debugfs_remove(de->target); - debugfs_remove(de->dir); #endif kfree(pinfo->rinfo); @@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) { } -static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) +static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, + gfp_t gfp) { struct rc_pid_sta_info *spinfo; @@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) return spinfo; } -static void rate_control_pid_free_sta(void *priv, void *priv_sta) +static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { - struct rc_pid_sta_info *spinfo = priv_sta; - kfree(spinfo); + kfree(priv_sta); } static struct rate_control_ops mac80211_rcpid = { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9774ac2e0f..9b72d15bc8d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, } /* protected by RCU */ -static struct sta_info *__sta_info_find(struct ieee80211_local *local, - const u8 *addr) +struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) { struct sta_info *sta; @@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local, return sta; } -struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) -{ - return __sta_info_find(local, addr); -} -EXPORT_SYMBOL(sta_info_get); - struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, struct net_device *dev) { @@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local, { DECLARE_MAC_BUF(mbuf); - rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); + rate_control_free_sta(sta); rate_control_put(sta->rate_ctrl); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->rate_ctrl = rate_control_get(local->rate_ctrl); sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, - gfp); + &sta->sta, gfp); if (!sta->rate_ctrl_priv) { rate_control_put(sta->rate_ctrl); kfree(sta); @@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta) spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (__sta_info_find(local, sta->sta.addr)) { + if (sta_info_get(local, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); err = -EEXIST; goto out_free; @@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr) { - struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); + struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); if (!sta) return NULL; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index daedfa9e1c6..c3f43696462 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -416,7 +416,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) /* * Get a STA info, must have be under RCU read lock. */ -struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); +struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); /* * Get STA info by index, BROKEN! */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 00d96e63dce..0cc2e23f082 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -446,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; if (likely(tx->rate_idx < 0)) { - rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); + rate_control_get_rate(tx->sdata, sband, tx->sta, + tx->skb, &rsel); if (tx->sta) tx->sta->last_txrate_idx = rsel.rate_idx; tx->rate_idx = rsel.rate_idx; @@ -1955,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, skb->do_not_encrypt = 1; info->band = band; - rate_control_get_rate(local->mdev, sband, skb, &rsel); + rate_control_get_rate(sdata, sband, NULL, skb, &rsel); if (unlikely(rsel.rate_idx < 0)) { if (net_ratelimit()) { -- cgit v1.2.3 From 4dfe51e10047a60e82734860cec0d9f660b102fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Sep 2008 05:10:34 +0200 Subject: mac80211: probe with correct SSID While associated, we should probe with the SSID we're associated to, not the scan SSID. Signed-off-by: Johannes Berg Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 109c3a7e63a..52a64813301 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, disassoc = 1; } else ieee80211_send_probe_req(sdata, ifsta->bssid, - local->scan_ssid, - local->scan_ssid_len); + ifsta->ssid, + ifsta->ssid_len); ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; } else { ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; -- cgit v1.2.3 From e6c948e8b8e565c7666ea482994e422c4f19ea44 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 22 Sep 2008 01:14:02 -0700 Subject: ath9k: Add a few comments about mibevents Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 0251e59f2f8..272c7581660 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2526,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah) } } +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ void ath9k_hw_procmibevent(struct ath_hal *ah, const struct ath9k_node_stats *stats) { @@ -2533,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, u32 phyCnt1, phyCnt2; DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n"); - + /* Reset these counters regardless */ REG_WRITE(ah, AR_FILT_OFDM, 0); REG_WRITE(ah, AR_FILT_CCK, 0); if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + /* Clear the mib counters and save them in the stats */ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); ahp->ah_stats.ast_nodestats = *stats; if (!DO_ANI(ah)) return; + /* NB: these are not reset-on-read */ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || @@ -2552,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, struct ar5416AniState *aniState = ahp->ah_curani; u32 ofdmPhyErrCnt, cckPhyErrCnt; + /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; ahp->ah_stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount; @@ -2562,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, cckPhyErrCnt - aniState->cckPhyErrCount; aniState->cckPhyErrCount = cckPhyErrCnt; + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) ath9k_hw_ani_ofdm_err_trigger(ah); if (aniState->cckPhyErrCount > aniState->cckTrigHigh) ath9k_hw_ani_cck_err_trigger(ah); - + /* NB: always restart to insure the h/w counters are reset */ ath9k_ani_restart(ah); } } -- cgit v1.2.3 From 4492bea656b70dad6a9ae7b59b1430fa38ba3345 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 22 Sep 2008 17:10:10 +0300 Subject: mac80211: fix led behavior in IBSS This patch fixes the led behavior in IBSS. After we joined an IBSS cell we need to inform the led that we got associated. Although there is no 802.11 association in IBSS mode, the semantic of "There is a link" is relevant. This allows the led to blink in IBSS mode (at least this solves a bug for iwlwifi). Signed-off-by: Emmanuel Grumbach Reviewed-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 52a64813301..e859a0ab616 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + ieee80211_led_assoc(local, true); + memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); -- cgit v1.2.3 From acaf908d408ccd49f13aeb46cbd4428a4db174d1 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 22 Sep 2008 19:40:04 +0200 Subject: rt2x00: Fix HW crypto key handling When a crypto key is being removed, rt2x00mac should not reset the key->hw_key_idx value because that will prevent the driver from removing the correct key from the hardware. Furthermore ffz() starts counting at 0 instead of 1, so we don't need to substract 1 from the resulting value. Signed-off-by: Stephen Blackheath Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 3 ++- drivers/net/wireless/rt2x00/rt61pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt73usb.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 485c40de5cc..2c6cc5c374f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -543,7 +543,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * provided but key 0 is not, then the key is not found * by the hardware during RX). */ - key->hw_key_idx = 0; + if (cmd == SET_KEY) + key->hw_key_idx = 0; if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) set_key = rt2x00dev->ops->lib->config_pairwise_key; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2c36b91ff4c..a461620b489 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -381,7 +381,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, if (reg && reg == mask) return -ENOSPC; - key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; + key->hw_key_idx += reg ? ffz(reg) : 0; /* * Upload key to hardware @@ -477,7 +477,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, return -ENOSPC; } - key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; + key->hw_key_idx += reg ? ffz(reg) : 0; /* * Upload key to hardware diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 27dde3e3460..934f8e03c5a 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -393,7 +393,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, if (reg && reg == mask) return -ENOSPC; - key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; + key->hw_key_idx += reg ? ffz(reg) : 0; /* * Upload key to hardware @@ -494,7 +494,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, return -ENOSPC; } - key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; + key->hw_key_idx += reg ? ffz(reg) : 0; /* * Upload key to hardware -- cgit v1.2.3 From 638af07386972861272ed9d0cff01cad528fdceb Mon Sep 17 00:00:00 2001 From: Denis ChengRq Date: Tue, 23 Sep 2008 02:35:37 +0800 Subject: wireless: a global static to local static improvement There are two improvements in this simple patch: 1. wiphy_counter is a static var only used in one function, so can use local static instead of global static; 2. wiphy_counter wrap handling killed one comparision; Signed-off-by: Denis ChengRq Signed-off-by: John W. Linville --- net/wireless/core.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index d6940085d59..5cadbeb76a1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -34,7 +34,6 @@ MODULE_DESCRIPTION("wireless configuration support"); * often because we need to do it for each command */ LIST_HEAD(cfg80211_drv_list); DEFINE_MUTEX(cfg80211_drv_mutex); -static int wiphy_counter; /* for debugfs */ static struct dentry *ieee80211_debugfs_dir; @@ -206,6 +205,8 @@ out_unlock: struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) { + static int wiphy_counter; + struct cfg80211_registered_device *drv; int alloc_size; @@ -222,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) mutex_lock(&cfg80211_drv_mutex); - drv->idx = wiphy_counter; - - /* now increase counter for the next device unless - * it has wrapped previously */ - if (wiphy_counter >= 0) - wiphy_counter++; - - mutex_unlock(&cfg80211_drv_mutex); + drv->idx = wiphy_counter++; if (unlikely(drv->idx < 0)) { + wiphy_counter--; + mutex_unlock(&cfg80211_drv_mutex); /* ugh, wrapped! */ kfree(drv); return NULL; } + mutex_unlock(&cfg80211_drv_mutex); + /* give it a proper name */ snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, PHY_NAME "%d", drv->idx); -- cgit v1.2.3 From 47cbb1107e4172f3632713d74dc8651a32ceb294 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 23 Sep 2008 13:53:09 +0100 Subject: pcmcia: Fix up legacy driver IRQs The PCMCIA layer obsoleted asking for per device private IRQS some years ago and all the drivers by inspection correctly use dev_id and handle shared interrupts [they get em anyway in most PCI bridged PCMCIA/Cardbus] so can be adjusted. This gets rid of the various bugs reported where there is spewage about conflicting irq types and sometimes the driver won't load. (Note I don't have all of these devices to test each one beyond by inspection) Signed-off-by: Alan Cox Signed-off-by: John W. Linville --- drivers/net/wireless/airo_cs.c | 2 +- drivers/net/wireless/atmel_cs.c | 2 +- drivers/net/wireless/netwave_cs.c | 2 +- drivers/net/wireless/orinoco_cs.c | 2 +- drivers/net/wireless/ray_cs.c | 2 +- drivers/net/wireless/spectrum_cs.c | 2 +- drivers/net/wireless/wavelan_cs.c | 2 +- drivers/net/wireless/wl3501_cs.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index f12355398fe..fd72e427cb2 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -147,7 +147,7 @@ static int airo_probe(struct pcmcia_device *p_dev) DEBUG(0, "airo_attach()\n"); /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = NULL; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 12617cd0b78..d2388e8d179 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -158,7 +158,7 @@ static int atmel_probe(struct pcmcia_device *p_dev) DEBUG(0, "atmel_attach()\n"); /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = NULL; diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index f479c1af678..25bae7933aa 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -398,7 +398,7 @@ static int netwave_probe(struct pcmcia_device *link) link->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &netwave_interrupt; diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 1ccf5a40cf0..9eaa252c243 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -121,7 +121,7 @@ orinoco_cs_probe(struct pcmcia_device *link) link->priv = dev; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = orinoco_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 963960dc30f..44da0d19b5c 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -325,7 +325,7 @@ static int ray_probe(struct pcmcia_device *p_dev) p_dev->io.IOAddrLines = 5; /* Interrupt setup. For PCMCIA, driver takes what's given */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = &ray_interrupt; diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index e368759d1d8..67b26d3c3cd 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -195,7 +195,7 @@ spectrum_cs_probe(struct pcmcia_device *link) link->priv = dev; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = orinoco_interrupt; link->irq.Instance = dev; diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 00a3559e5aa..b5de38a9b79 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4496,7 +4496,7 @@ wavelan_probe(struct pcmcia_device *p_dev) p_dev->io.IOAddrLines = 3; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = wavelan_interrupt; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index b6d4e04b8ab..74a5ad2f122 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1917,7 +1917,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = wl3501_interrupt; -- cgit v1.2.3 From 55d6a3cd0cc85ed90c39cf32e16f622bd003117b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 23 Sep 2008 19:18:43 +0200 Subject: iwlagn: downgrade BUG_ON in interrupt This BUG_ON really shouldn't trigger, but if it does, as on my machine, it leaves you wondering what happened because you won't see it. Let's instead leak a bit of state and memory and at least make it possible to report it to the kerneloops project to track it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e9feca4033f..907a53ebc6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1200,10 +1200,9 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (txq_id != IWL_CMD_QUEUE_NUM) - IWL_ERROR("Error wrong command queue %d command id 0x%X\n", - txq_id, pkt->hdr.cmd); - BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); + if (WARN(txq_id != IWL_CMD_QUEUE_NUM, + "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd)) + return; cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; -- cgit v1.2.3 From 8d09a5e1c36d0dec5728e6c8b0bb5412de09b27b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 24 Sep 2008 13:57:46 +0800 Subject: iwlwifi: don't fail if scan is issued too early This patch returns success and empty scan on scans requests that were rejected because issued too early. The cached bss list from previous scanning will be returned by mac80211. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 +++++++++++---- drivers/net/wireless/iwlwifi/iwl-scan.c | 8 +------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d069549a01c..7330890fd05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3190,9 +3190,9 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) { - int ret; unsigned long flags; struct iwl_priv *priv = hw->priv; + int ret; IWL_DEBUG_MAC80211("enter\n"); @@ -3211,20 +3211,27 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) goto out_unlock; } - /* we don't schedule scan within next_scan_jiffies period */ + /* We don't schedule scan within next_scan_jiffies period. + * Avoid scanning during possible EAPOL exchange, return + * success immediately. + */ if (priv->next_scan_jiffies && time_after(priv->next_scan_jiffies, jiffies)) { IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); - ret = -EAGAIN; + queue_work(priv->workqueue, &priv->scan_completed); + ret = 0; goto out_unlock; } + /* if we just finished scan ask for delay */ if (iwl_is_associated(priv) && priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); - ret = -EAGAIN; + queue_work(priv->workqueue, &priv->scan_completed); + ret = 0; goto out_unlock; } + if (ssid_len) { priv->one_direct_scan = 1; priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 09c264be049..bf855c35b0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -463,11 +463,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) int iwl_scan_initiate(struct iwl_priv *priv) { - if (priv->iw_mode == NL80211_IFTYPE_AP) { - IWL_ERROR("APs don't scan.\n"); - return 0; - } - if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); return -EIO; @@ -479,8 +474,7 @@ int iwl_scan_initiate(struct iwl_priv *priv) } if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN("Scan request while abort pending. " - "Queuing.\n"); + IWL_DEBUG_SCAN("Scan request while abort pending\n"); return -EAGAIN; } -- cgit v1.2.3 From 72029fe85d8d060b3f966f2dbc36b3c75b5a6532 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Sep 2008 16:22:23 -0500 Subject: 9p: implement proper trans module refcounting and unregistration 9p trans modules aren't refcounted nor were they unregistered properly. Fix it. * Add 9p_trans_module->owner and reference the module on each trans instance creation and put it on destruction. * Protect v9fs_trans_list with a spinlock. This isn't strictly necessary as the list is manipulated only during module loading / unloading but it's a good idea to make the API safe. * Unregister trans modules when the corresponding module is being unloaded. * While at it, kill unnecessary EXPORT_SYMBOL on p9_trans_fd_init(). Signed-off-by: Tejun Heo Signed-off-by: Eric Van Hensbergen --- include/net/9p/9p.h | 1 + include/net/9p/transport.h | 9 ++++- net/9p/client.c | 10 ++++- net/9p/mod.c | 92 +++++++++++++++++++++++++++++++++------------- net/9p/trans_fd.c | 11 +++++- net/9p/trans_virtio.c | 2 + 6 files changed, 95 insertions(+), 30 deletions(-) diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index b3d3e27c629..c3626c0ba9d 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -596,4 +596,5 @@ int p9_idpool_check(int id, struct p9_idpool *p); int p9_error_init(void); int p9_errstr2errno(char *, int); int p9_trans_fd_init(void); +void p9_trans_fd_exit(void); #endif /* NET_9P_H */ diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 0db3a4038dc..3ca737120a9 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -26,6 +26,8 @@ #ifndef NET_9P_TRANSPORT_H #define NET_9P_TRANSPORT_H +#include + /** * enum p9_trans_status - different states of underlying transports * @Connected: transport is connected and healthy @@ -91,9 +93,12 @@ struct p9_trans_module { int maxsize; /* max message size of transport */ int def; /* this transport should be default */ struct p9_trans * (*create)(const char *, char *, int, unsigned char); + struct module *owner; }; void v9fs_register_trans(struct p9_trans_module *m); -struct p9_trans_module *v9fs_match_trans(const substring_t *name); -struct p9_trans_module *v9fs_default_trans(void); +void v9fs_unregister_trans(struct p9_trans_module *m); +struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name); +struct p9_trans_module *v9fs_get_default_trans(void); +void v9fs_put_trans(struct p9_trans_module *m); #endif /* NET_9P_TRANSPORT_H */ diff --git a/net/9p/client.c b/net/9p/client.c index 2ffe40cf2f0..10e320307ec 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -75,7 +75,6 @@ static int parse_opts(char *opts, struct p9_client *clnt) int option; int ret = 0; - clnt->trans_mod = v9fs_default_trans(); clnt->dotu = 1; clnt->msize = 8192; @@ -108,7 +107,7 @@ static int parse_opts(char *opts, struct p9_client *clnt) clnt->msize = option; break; case Opt_trans: - clnt->trans_mod = v9fs_match_trans(&args[0]); + clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); break; case Opt_legacy: clnt->dotu = 0; @@ -117,6 +116,10 @@ static int parse_opts(char *opts, struct p9_client *clnt) continue; } } + + if (!clnt->trans_mod) + clnt->trans_mod = v9fs_get_default_trans(); + kfree(options); return ret; } @@ -150,6 +153,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) if (!clnt) return ERR_PTR(-ENOMEM); + clnt->trans_mod = NULL; clnt->trans = NULL; spin_lock_init(&clnt->lock); INIT_LIST_HEAD(&clnt->fidlist); @@ -235,6 +239,8 @@ void p9_client_destroy(struct p9_client *clnt) clnt->trans = NULL; } + v9fs_put_trans(clnt->trans_mod); + list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) p9_fid_destroy(fid); diff --git a/net/9p/mod.c b/net/9p/mod.c index bdee1fb7cc6..1084feb24cb 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_NET_9P_DEBUG unsigned int p9_debug_level = 0; /* feature-rific global debug level */ @@ -44,8 +45,8 @@ MODULE_PARM_DESC(debug, "9P debugging level"); * */ +static DEFINE_SPINLOCK(v9fs_trans_lock); static LIST_HEAD(v9fs_trans_list); -static struct p9_trans_module *v9fs_default_transport; /** * v9fs_register_trans - register a new transport with 9p @@ -54,48 +55,87 @@ static struct p9_trans_module *v9fs_default_transport; */ void v9fs_register_trans(struct p9_trans_module *m) { + spin_lock(&v9fs_trans_lock); list_add_tail(&m->list, &v9fs_trans_list); - if (m->def) - v9fs_default_transport = m; + spin_unlock(&v9fs_trans_lock); } EXPORT_SYMBOL(v9fs_register_trans); /** - * v9fs_match_trans - match transport versus registered transports + * v9fs_unregister_trans - unregister a 9p transport + * @m: the transport to remove + * + */ +void v9fs_unregister_trans(struct p9_trans_module *m) +{ + spin_lock(&v9fs_trans_lock); + list_del_init(&m->list); + spin_unlock(&v9fs_trans_lock); +} +EXPORT_SYMBOL(v9fs_unregister_trans); + +/** + * v9fs_get_trans_by_name - get transport with the matching name * @name: string identifying transport * */ -struct p9_trans_module *v9fs_match_trans(const substring_t *name) +struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name) { - struct list_head *p; - struct p9_trans_module *t = NULL; - - list_for_each(p, &v9fs_trans_list) { - t = list_entry(p, struct p9_trans_module, list); - if (strncmp(t->name, name->from, name->to-name->from) == 0) - return t; - } - return NULL; + struct p9_trans_module *t, *found = NULL; + + spin_lock(&v9fs_trans_lock); + + list_for_each_entry(t, &v9fs_trans_list, list) + if (strncmp(t->name, name->from, name->to-name->from) == 0 && + try_module_get(t->owner)) { + found = t; + break; + } + + spin_unlock(&v9fs_trans_lock); + return found; } -EXPORT_SYMBOL(v9fs_match_trans); +EXPORT_SYMBOL(v9fs_get_trans_by_name); /** - * v9fs_default_trans - returns pointer to default transport + * v9fs_get_default_trans - get the default transport * */ -struct p9_trans_module *v9fs_default_trans(void) +struct p9_trans_module *v9fs_get_default_trans(void) { - if (v9fs_default_transport) - return v9fs_default_transport; - else if (!list_empty(&v9fs_trans_list)) - return list_first_entry(&v9fs_trans_list, - struct p9_trans_module, list); - else - return NULL; + struct p9_trans_module *t, *found = NULL; + + spin_lock(&v9fs_trans_lock); + + list_for_each_entry(t, &v9fs_trans_list, list) + if (t->def && try_module_get(t->owner)) { + found = t; + break; + } + + if (!found) + list_for_each_entry(t, &v9fs_trans_list, list) + if (try_module_get(t->owner)) { + found = t; + break; + } + + spin_unlock(&v9fs_trans_lock); + return found; } -EXPORT_SYMBOL(v9fs_default_trans); +EXPORT_SYMBOL(v9fs_get_default_trans); +/** + * v9fs_put_trans - put trans + * @m: transport to put + * + */ +void v9fs_put_trans(struct p9_trans_module *m) +{ + if (m) + module_put(m->owner); +} /** * v9fs_init - Initialize module @@ -120,6 +160,8 @@ static int __init init_p9(void) static void __exit exit_p9(void) { printk(KERN_INFO "Unloading 9P2000 support\n"); + + p9_trans_fd_exit(); } module_init(init_p9) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index cdf137af7ad..6a32ffdb942 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1629,6 +1629,7 @@ static struct p9_trans_module p9_tcp_trans = { .maxsize = MAX_SOCK_BUF, .def = 1, .create = p9_trans_create_tcp, + .owner = THIS_MODULE, }; static struct p9_trans_module p9_unix_trans = { @@ -1636,6 +1637,7 @@ static struct p9_trans_module p9_unix_trans = { .maxsize = MAX_SOCK_BUF, .def = 0, .create = p9_trans_create_unix, + .owner = THIS_MODULE, }; static struct p9_trans_module p9_fd_trans = { @@ -1643,6 +1645,7 @@ static struct p9_trans_module p9_fd_trans = { .maxsize = MAX_SOCK_BUF, .def = 0, .create = p9_trans_create_fd, + .owner = THIS_MODULE, }; int p9_trans_fd_init(void) @@ -1659,4 +1662,10 @@ int p9_trans_fd_init(void) return 0; } -EXPORT_SYMBOL(p9_trans_fd_init); + +void p9_trans_fd_exit(void) +{ + v9fs_unregister_trans(&p9_tcp_trans); + v9fs_unregister_trans(&p9_unix_trans); + v9fs_unregister_trans(&p9_fd_trans); +} diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 42adc052b14..94912e077a5 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -528,6 +528,7 @@ static struct p9_trans_module p9_virtio_trans = { .create = p9_virtio_create, .maxsize = PAGE_SIZE*16, .def = 0, + .owner = THIS_MODULE, }; /* The standard init function */ @@ -545,6 +546,7 @@ static int __init p9_virtio_init(void) static void __exit p9_virtio_cleanup(void) { unregister_virtio_driver(&p9_virtio_drv); + v9fs_unregister_trans(&p9_virtio_trans); } module_init(p9_virtio_init); -- cgit v1.2.3 From 7dc5d24be06a5ed874af035d52a083a7b61ef1bd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Sep 2008 16:22:23 -0500 Subject: 9p-trans_fd: fix trans_fd::p9_conn_destroy() p9_conn_destroy() first kills all current requests by calling p9_conn_cancel(), then waits for the request list to be cleared by waiting on p9_conn->equeue. After that, polling is stopped and the trans is destroyed. This sequence has a few problems. * Read and write works were never cancelled and the p9_conn can be destroyed while the works are running as r/w works remove requests from the list and dereference the p9_conn from them. * The list emptiness wait using p9_conn->equeue wouldn't trigger because p9_conn_cancel() always clears all the lists and the only way the wait can be triggered is to have another task to issue a request between the slim window between p9_conn_cancel() and the wait, which isn't safe under the current implementation with or without the wait. This patch fixes the problem by first stopping poll, which can schedule r/w works, first and cancle r/w works which guarantees that r/w works are not and will not run from that point and then calling p9_conn_cancel() and do the rest of destruction. Signed-off-by: Tejun Heo Signed-off-by: Eric Van Hensbergen --- net/9p/trans_fd.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 6a32ffdb942..ee0d151da31 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -151,7 +151,6 @@ struct p9_mux_poll_task { * @trans: reference to transport instance for this connection * @tagpool: id accounting for transactions * @err: error state - * @equeue: event wait_q (?) * @req_list: accounting for requests which have been sent * @unsent_req_list: accounting for requests that haven't been sent * @rcall: current response &p9_fcall structure @@ -178,7 +177,6 @@ struct p9_conn { struct p9_trans *trans; struct p9_idpool *tagpool; int err; - wait_queue_head_t equeue; struct list_head req_list; struct list_head unsent_req_list; struct p9_fcall *rcall; @@ -430,7 +428,6 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) } m->err = 0; - init_waitqueue_head(&m->equeue); INIT_LIST_HEAD(&m->req_list); INIT_LIST_HEAD(&m->unsent_req_list); m->rcall = NULL; @@ -483,18 +480,13 @@ static void p9_conn_destroy(struct p9_conn *m) { P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, m->mux_list.prev, m->mux_list.next); - p9_conn_cancel(m, -ECONNRESET); - - if (!list_empty(&m->req_list)) { - /* wait until all processes waiting on this session exit */ - P9_DPRINTK(P9_DEBUG_MUX, - "mux %p waiting for empty request queue\n", m); - wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); - P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, - list_empty(&m->req_list)); - } p9_mux_poll_stop(m); + cancel_work_sync(&m->rq); + cancel_work_sync(&m->wq); + + p9_conn_cancel(m, -ECONNRESET); + m->trans = NULL; p9_idpool_destroy(m->tagpool); kfree(m); @@ -840,8 +832,6 @@ static void p9_read_work(struct work_struct *work) (*req->cb) (req, req->cba); else kfree(req->rcall); - - wake_up(&m->equeue); } } else { if (err >= 0 && rcall->id != P9_RFLUSH) @@ -984,8 +974,6 @@ static void p9_mux_flush_cb(struct p9_req *freq, void *a) (*req->cb) (req, req->cba); else kfree(req->rcall); - - wake_up(&m->equeue); } kfree(freq->tcall); @@ -1191,8 +1179,6 @@ void p9_conn_cancel(struct p9_conn *m, int err) else kfree(req->rcall); } - - wake_up(&m->equeue); } /** -- cgit v1.2.3 From 571ffeafffbfdd0b8f2f9d3b991028797ec87e42 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Sep 2008 16:22:23 -0500 Subject: 9p-trans_fd: clean up p9_conn_create() * Use kzalloc() to allocate p9_conn and remove 0/NULL initializations. * Clean up error return paths. Signed-off-by: Tejun Heo Signed-off-by: Eric Van Hensbergen --- net/9p/trans_fd.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index ee0d151da31..6c88e898375 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -407,11 +407,11 @@ static void p9_mux_poll_stop(struct p9_conn *m) static struct p9_conn *p9_conn_create(struct p9_trans *trans) { int i, n; - struct p9_conn *m, *mtmp; + struct p9_conn *m; P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, trans->msize); - m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); + m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); if (!m) return ERR_PTR(-ENOMEM); @@ -422,24 +422,14 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) m->trans = trans; m->tagpool = p9_idpool_create(); if (IS_ERR(m->tagpool)) { - mtmp = ERR_PTR(-ENOMEM); kfree(m); - return mtmp; + return ERR_PTR(-ENOMEM); } - m->err = 0; INIT_LIST_HEAD(&m->req_list); INIT_LIST_HEAD(&m->unsent_req_list); - m->rcall = NULL; - m->rpos = 0; - m->rbuf = NULL; - m->wpos = m->wsize = 0; - m->wbuf = NULL; INIT_WORK(&m->rq, p9_read_work); INIT_WORK(&m->wq, p9_write_work); - m->wsched = 0; - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); - m->poll_task = NULL; n = p9_mux_poll_start(m); if (n) { kfree(m); @@ -460,10 +450,8 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { if (IS_ERR(m->poll_waddr[i])) { p9_mux_poll_stop(m); - mtmp = (void *)m->poll_waddr; /* the error code */ kfree(m); - m = mtmp; - break; + return (void *)m->poll_waddr; /* the error code */ } } -- cgit v1.2.3 From ec3c68f232f6d98b4596c05c1c7551b44c617c5f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Sep 2008 16:22:23 -0500 Subject: 9p-trans_fd: don't do fs segment mangling in p9_fd_poll() p9_fd_poll() is never called with user pointers and f_op->poll() doesn't expect its arguments to be from userland. There's no need to set kernel ds before calling f_op->poll() from p9_fd_poll(). Remove it. Signed-off-by: Tejun Heo Signed-off-by: Eric Van Hensbergen --- net/9p/trans_fd.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 6c88e898375..f6d4af16cb1 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1344,7 +1344,6 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) { int ret, n; struct p9_trans_fd *ts = NULL; - mm_segment_t oldfs; if (trans && trans->status == Connected) ts = trans->priv; @@ -1358,24 +1357,17 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) if (!ts->wr->f_op || !ts->wr->f_op->poll) return -EIO; - oldfs = get_fs(); - set_fs(get_ds()); - ret = ts->rd->f_op->poll(ts->rd, pt); if (ret < 0) - goto end; + return ret; if (ts->rd != ts->wr) { n = ts->wr->f_op->poll(ts->wr, pt); - if (n < 0) { - ret = n; - goto end; - } + if (n < 0) + return n; ret = (ret & ~POLLOUT) | (n & ~POLLIN); } -end: - set_fs(oldfs); return ret; } -- cgit v1.2.3 From 206ca50de77033c6cc17d0e14fbb12d119a67b01 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Sep 2008 16:22:23 -0500 Subject: 9p-trans_fd: fix and clean up module init/exit paths trans_fd leaked p9_mux_wq on module unload. Fix it. While at it, collapse p9_mux_global_init() into p9_trans_fd_init(). It's easier to follow this way and the global poll_tasks array is about to removed anyway. Signed-off-by: Tejun Heo Signed-off-by: Eric Van Hensbergen --- net/9p/trans_fd.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index f6d4af16cb1..0b4eb5f7835 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -238,22 +238,6 @@ static int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, static void p9_conn_cancel(struct p9_conn *m, int err); -static int p9_mux_global_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) - p9_mux_poll_tasks[i].task = NULL; - - p9_mux_wq = create_workqueue("v9fs"); - if (!p9_mux_wq) { - printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); - return -ENOMEM; - } - - return 0; -} - static u16 p9_mux_get_tag(struct p9_conn *m) { int tag; @@ -1616,10 +1600,15 @@ static struct p9_trans_module p9_fd_trans = { int p9_trans_fd_init(void) { - int ret = p9_mux_global_init(); - if (ret) { - printk(KERN_WARNING "9p: starting mux failed\n"); - return ret; + int i; + + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) + p9_mux_poll_tasks[i].task = NULL; + + p9_mux_wq = create_workqueue("v9fs"); + if (!p9_mux_wq) { + printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); + return -ENOMEM; } v9fs_register_trans(&p9_tcp_trans); @@ -1634,4 +1623,6 @@ void p9_trans_fd_exit(void) v9fs_unregister_trans(&p9_tcp_trans); v9fs_unregister_trans(&p9_unix_trans); v9fs_unregister_trans(&p9_fd_trans); + + destroy_workqueue(p9_mux_wq); } -- cgit v1.2.3 From 620678244bc7b83287e2e283ed4fe6b959e94b7d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 24 Sep 2008 16:22:22 -0500 Subject: 9p: introduce missing kfree Error handling code following a kmalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,l; position p1,p2; expression *ptr != NULL; @@ ( if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S ) <... when != x when != if (...) { <+...x...+> } x->f = E ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Eric Van Hensbergen Signed-off-by: Andrew Morton --- net/9p/trans_fd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 0b4eb5f7835..d652baf5ff9 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -870,8 +870,10 @@ static struct p9_req *p9_send_request(struct p9_conn *m, else n = p9_mux_get_tag(m); - if (n < 0) + if (n < 0) { + kfree(req); return ERR_PTR(-ENOMEM); + } p9_set_tag(tc, n); -- cgit v1.2.3 From 62aa528e0299ffef8e138d9d92d13e631d06c5ff Mon Sep 17 00:00:00 2001 From: Julien Brunel Date: Wed, 24 Sep 2008 16:22:22 -0500 Subject: 9p: use an IS_ERR test rather than a NULL test In case of error, the function p9_client_walk returns an ERR pointer, but never returns a NULL pointer. So a NULL test that comes after an IS_ERR test should be deleted. The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @match_bad_null_test@ expression x, E; statement S1,S2; @@ x = p9_client_walk(...) ... when != x = E * if (x != NULL) S1 else S2 // Signed-off-by: Julien Brunel Signed-off-by: Julia Lawall Signed-off-by: Eric Van Hensbergen Signed-off-by: Andrew Morton --- fs/9p/vfs_inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c95295c6504..e83aa5ebe86 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -626,8 +626,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, return NULL; error: - if (fid) - p9_client_clunk(fid); + p9_client_clunk(fid); return ERR_PTR(result); } -- cgit v1.2.3 From 16ec4700127d479143c77fd9128dfa17ab572963 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 24 Sep 2008 16:22:22 -0500 Subject: 9p: fix put_data error handling Abhishek Kulkarni pointed out an inconsistency in the way errors are returned from p9_put_data. On deeper exploration it seems the error handling for this path was completely wrong. This patch adds checks for allocation problems and propagates errors correctly. Signed-off-by: Eric Van Hensbergen --- net/9p/conv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/9p/conv.c b/net/9p/conv.c index 44547201f5b..5ad3a3bd73b 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c @@ -451,8 +451,10 @@ p9_put_data(struct cbuf *bufp, const char *data, int count, unsigned char **pdata) { *pdata = buf_alloc(bufp, count); + if (*pdata == NULL) + return -ENOMEM; memmove(*pdata, data, count); - return count; + return 0; } static int @@ -460,6 +462,8 @@ p9_put_user_data(struct cbuf *bufp, const char __user *data, int count, unsigned char **pdata) { *pdata = buf_alloc(bufp, count); + if (*pdata == NULL) + return -ENOMEM; return copy_from_user(*pdata, data, count); } -- cgit v1.2.3 From 7c0965e614f076331bf4628fae005c844d2f1f69 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Sat, 13 Sep 2008 15:06:42 -0400 Subject: tulip: Fix dead 21041 ethernet after ifconfig down The de2104x did a pci_disable_device() in it's close function, but the open function never does a pci_enable_device() and assumes that the device is already enabled. Considering that downing the interface is just a temporary thing the pci_disable_device() isn't a pretty good idea and removing it from the close function just fixes the bug. Signed-off-by: Thomas Bogendoerfer Acked-by: Grant Grundler Signed-off-by: Jeff Garzik --- drivers/net/tulip/de2104x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 9281d06d5aa..f54c45049d5 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1418,7 +1418,6 @@ static int de_close (struct net_device *dev) de_free_rings(de); de_adapter_sleep(de); - pci_disable_device(de->pdev); return 0; } -- cgit v1.2.3 From e93dcb11dd6468000f2f018bd887e94b074ce931 Mon Sep 17 00:00:00 2001 From: Sebastien Dugue Date: Thu, 11 Sep 2008 15:34:39 +0200 Subject: ehea: fix phyp debugging typo Fix typo in ehea_h_query_ehea() which prevents building when DEBUG is on. Signed-off-by: Sebastien Dugue Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_phyp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c index 156eb6320b4..2a33a613d9e 100644 --- a/drivers/net/ehea/ehea_phyp.c +++ b/drivers/net/ehea/ehea_phyp.c @@ -535,7 +535,7 @@ u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr) cb_logaddr, /* R5 */ 0, 0, 0, 0, 0); /* R6-R10 */ #ifdef DEBUG - ehea_dmp(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea"); + ehea_dump(cb_addr, sizeof(struct hcp_query_ehea), "hcp_query_ehea"); #endif return hret; } -- cgit v1.2.3 From 523a609496dbc3897e530db2a2f27650d125ea00 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 10 Sep 2008 22:28:56 +0200 Subject: r8169: fix RxMissed register access - the register is defined for the 8169 chipset only and there is no 8169 beyond RTL_GIGA_MAC_VER_06. - only the lower 3 bytes of the register are valid Fixes: 1. http://bugzilla.kernel.org/show_bug.cgi?id=10180 2. http://bugzilla.kernel.org/show_bug.cgi?id=11062 (bits of) Tested by Hermann Gausterer and Adam Huffman. Signed-off-by: Francois Romieu Cc: Edward Hsu Signed-off-by: Jeff Garzik --- drivers/net/r8169.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 1822491f19c..f28c2022f3b 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2286,8 +2286,6 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_R8(IntrMask); - RTL_W32(RxMissed, 0); - rtl_set_rx_mode(dev); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -2412,8 +2410,6 @@ static void rtl_hw_start_8101(struct net_device *dev) RTL_R8(IntrMask); - RTL_W32(RxMissed, 0); - rtl_set_rx_mode(dev); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); @@ -3191,6 +3187,17 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) return work_done; } +static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + if (tp->mac_version > RTL_GIGA_MAC_VER_06) + return; + + dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); + RTL_W32(RxMissed, 0); +} + static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -3208,9 +3215,7 @@ core_down: rtl8169_asic_down(ioaddr); - /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); @@ -3332,8 +3337,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) if (netif_running(dev)) { spin_lock_irqsave(&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irqrestore(&tp->lock, flags); } @@ -3358,8 +3362,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) rtl8169_asic_down(ioaddr); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); - RTL_W32(RxMissed, 0); + rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); -- cgit v1.2.3 From d6bc372ea1196066b618908dc522b08cd28993df Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 8 Sep 2008 14:02:56 +0900 Subject: smc91x: fix nowait printout Commit c4f0e76747e80578a8f7fddd82fd0ce8127bd2f8 added nowait platform data support. The printout code was however not updated, so the value of SMC_NOWAIT is still used. This patch makes sure that nowait is printed accordingly to platform data. Signed-off-by: Magnus Damm Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 24768c10cad..53c2dda1dc8 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1961,7 +1961,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr, if (dev->dma != (unsigned char)-1) printk(" DMA %d", dev->dma); - printk("%s%s\n", nowait ? " [nowait]" : "", + printk("%s%s\n", + lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "", THROTTLE_TX_PKTS ? " [throttle_tx]" : ""); if (!is_valid_ether_addr(dev->dev_addr)) { -- cgit v1.2.3 From d1c5ea33c006e921f706f5075c09edc91e714263 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 8 Sep 2008 14:02:34 +0900 Subject: smc91x: SMC_IO_SHIFT platform data support for default case Commit 159198862adad7109bb347bb30a620f67beac45f added SMC_IO_SHIFT platform data support. After that ARM board support was added. The default case is still missing though, so on SuperH SMC_IO_SHIFT is constantly zero regardless of what you pass as platform data. Signed-off-by: Magnus Damm Test-by: Luca Santini Signed-off-by: Jeff Garzik --- drivers/net/smc91x.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 997e7f1d5c6..edea0732f14 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -446,6 +446,8 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #define SMC_CAN_USE_32BIT 1 #define SMC_NOWAIT 1 +#define SMC_IO_SHIFT (lp->io_shift) + #define SMC_inb(a, r) readb((a) + (r)) #define SMC_inw(a, r) readw((a) + (r)) #define SMC_inl(a, r) readl((a) + (r)) -- cgit v1.2.3 From c2d1eb085d2eb47a3b16726f79fcf0d53648ebc0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 5 Sep 2008 14:04:04 -0700 Subject: drivers/net/skfp/pmf.c: Use offsetof() macro Self-baked macros cause bunch of compile warnings like below: CC [M] drivers/net/skfp/pmf.o CC net/ipv4/fib_semantics.o drivers/net/skfp/pmf.c:86: warning: cast from pointer to integer of different size drivers/net/skfp/pmf.c:87: warning: cast from pointer to integer of different size ... Use the standard offsetof() macro instead. Signed-off-by: Takashi Iwai Acked-by: Alan Cox Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/skfp/pmf.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index ea85de91823..79e665e0853 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c @@ -44,17 +44,10 @@ static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, int set, int local); static int port_to_mib(struct s_smc *smc, int p); -#define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) -#define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) - -#define MOFFMS(e) ((int)&(((struct fddi_mib_m *)0)->e)) -#define MOFFMA(e) ((int) (((struct fddi_mib_m *)0)->e)) - -#define MOFFAS(e) ((int)&(((struct fddi_mib_a *)0)->e)) -#define MOFFAA(e) ((int) (((struct fddi_mib_a *)0)->e)) - -#define MOFFPS(e) ((int)&(((struct fddi_mib_p *)0)->e)) -#define MOFFPA(e) ((int) (((struct fddi_mib_p *)0)->e)) +#define MOFFSS(e) offsetof(struct fddi_mib, e) +#define MOFFMS(e) offsetof(struct fddi_mib_m, e) +#define MOFFAS(e) offsetof(struct fddi_mib_a, e) +#define MOFFPS(e) offsetof(struct fddi_mib_p, e) #define AC_G 0x01 /* Get */ @@ -87,8 +80,8 @@ static const struct s_p_tab { { SMT_P100D,AC_G, MOFFSS(fddiSMTOpVersionId), "S" } , { SMT_P100E,AC_G, MOFFSS(fddiSMTHiVersionId), "S" } , { SMT_P100F,AC_G, MOFFSS(fddiSMTLoVersionId), "S" } , - { SMT_P1010,AC_G, MOFFSA(fddiSMTManufacturerData), "D" } , - { SMT_P1011,AC_GR, MOFFSA(fddiSMTUserData), "D" } , + { SMT_P1010,AC_G, MOFFSS(fddiSMTManufacturerData), "D" } , + { SMT_P1011,AC_GR, MOFFSS(fddiSMTUserData), "D" } , { SMT_P1012,AC_G, MOFFSS(fddiSMTMIBVersionId), "S" } , /* StationConfigGrp */ @@ -103,7 +96,7 @@ static const struct s_p_tab { { SMT_P101D,AC_GR, MOFFSS(fddiSMTTT_Notify), "wS" } , { SMT_P101E,AC_GR, MOFFSS(fddiSMTStatRptPolicy), "bB" } , { SMT_P101F,AC_GR, MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } , - { SMT_P1020,AC_G, MOFFSA(fddiSMTPORTIndexes), "II" } , + { SMT_P1020,AC_G, MOFFSS(fddiSMTPORTIndexes), "II" } , { SMT_P1021,AC_G, MOFFSS(fddiSMTMACIndexes), "I" } , { SMT_P1022,AC_G, MOFFSS(fddiSMTBypassPresent), "F" } , @@ -117,8 +110,8 @@ static const struct s_p_tab { /* MIBOperationGrp */ { SMT_P1032,AC_GROUP } , - { SMT_P1033,AC_G, MOFFSA(fddiSMTTimeStamp),"P" } , - { SMT_P1034,AC_G, MOFFSA(fddiSMTTransitionTimeStamp),"P" } , + { SMT_P1033,AC_G, MOFFSS(fddiSMTTimeStamp),"P" } , + { SMT_P1034,AC_G, MOFFSS(fddiSMTTransitionTimeStamp),"P" } , /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */ { SMT_P1035,AC_G, MOFFSS(fddiSMTSetCount),"4P" } , { SMT_P1036,AC_G, MOFFSS(fddiSMTLastSetStationId),"8" } , @@ -129,7 +122,7 @@ static const struct s_p_tab { * PRIVATE EXTENSIONS * only accessible locally to get/set passwd */ - { SMT_P10F0,AC_GR, MOFFSA(fddiPRPMFPasswd), "8" } , + { SMT_P10F0,AC_GR, MOFFSS(fddiPRPMFPasswd), "8" } , { SMT_P10F1,AC_GR, MOFFSS(fddiPRPMFStation), "8" } , #ifdef ESS { SMT_P10F2,AC_GR, MOFFSS(fddiESSPayload), "lL" } , @@ -245,7 +238,7 @@ static const struct s_p_tab { { SMT_P400E,AC_GR, MOFFPS(fddiPORTConnectionPolicies),"bB" } , { SMT_P400F,AC_G, MOFFPS(fddiPORTMacIndicated), "2" } , { SMT_P4010,AC_G, MOFFPS(fddiPORTCurrentPath), "E" } , - { SMT_P4011,AC_GR, MOFFPA(fddiPORTRequestedPaths), "l4" } , + { SMT_P4011,AC_GR, MOFFPS(fddiPORTRequestedPaths), "l4" } , { SMT_P4012,AC_G, MOFFPS(fddiPORTMACPlacement), "S" } , { SMT_P4013,AC_G, MOFFPS(fddiPORTAvailablePaths), "B" } , { SMT_P4016,AC_G, MOFFPS(fddiPORTPMDClass), "E" } , -- cgit v1.2.3 From 6526128c18564697b301030a7bbf928209e49ae0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 5 Sep 2008 14:04:07 -0700 Subject: drivers/net/mlx4/alloc.c needs mm.h sparc32 allmodconfig with linux-next: drivers/net/mlx4/alloc.c: In function 'mlx4_buf_alloc': drivers/net/mlx4/alloc.c:164: error: 'PAGE_KERNEL' undeclared (first use in this function) drivers/net/mlx4/alloc.c:164: error: (Each undeclared identifier is reported only once drivers/net/mlx4/alloc.c:164: error: for each function it appears in.) this is due to some header shuffle in linux-next. I didn't look to see what it was. I'd sugges that this patch be merged ahead of a linux-next merge to avoid bisection breaks. We strictly only need asm/pgtable.h, but going direct to asm includes always seems grubby. Cc: Jeff Garzik Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/mlx4/alloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index 096bca54bcf..b411b79d72a 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 894d6276ed8dca0365a91b6d4858c37c58b962d7 Mon Sep 17 00:00:00 2001 From: Chris Snook Date: Tue, 9 Sep 2008 03:26:57 -0400 Subject: MAINTAINERS: add Atheros maintainer for atlx Jie Yang at Atheros is getting more directly involved with upstream work on the atl* drivers. This patch changes the ATL1 entry to ATLX (atl2 support posted to netdev today) and adds him as a maintainer. Signed-off-by: Jeff Garzik --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 106684e45e1..c29b420fc1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -750,11 +750,13 @@ P: Ville Syrjala M: syrjala@sci.fi S: Maintained -ATL1 ETHERNET DRIVER +ATLX ETHERNET DRIVERS P: Jay Cliburn M: jcliburn@gmail.com P: Chris Snook M: csnook@redhat.com +P: Jie Yang +M: jie.yang@atheros.com L: atl1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net -- cgit v1.2.3 From 533763d34862101090f8563aa9da202583b2423d Mon Sep 17 00:00:00 2001 From: Martin Gebert Date: Wed, 23 Jul 2008 09:40:09 +0200 Subject: [netdrvr] au1000_eth: Spinlock initialisation fix Seems like the spinlock for the AU1x00 ethernet device is initialised too late, as it is already used in enable_mac(), which is called via mii_probe() before the init takes place. The attached patch is working here for a Linux Au1100 2.6.22.6 kernel, and as far as I checked should also be applicable to the current head (just line numbers differ). Signed-off-by: Martin Gebert Signed-off-by: Jeff Garzik --- drivers/net/au1000_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 5ee1b0557a0..92c16c37ff2 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -653,6 +653,8 @@ static struct net_device * au1000_probe(int port_num) aup = dev->priv; + spin_lock_init(&aup->lock); + /* Allocate the data buffers */ /* Snooping works fine with eth on all au1xxx */ aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE * @@ -753,7 +755,6 @@ static struct net_device * au1000_probe(int port_num) aup->tx_db_inuse[i] = pDB; } - spin_lock_init(&aup->lock); dev->base_addr = base; dev->irq = irq; dev->open = au1000_open; -- cgit v1.2.3 From 539b06fc73b1d470b9ecb3fe7af6d5f439322c08 Mon Sep 17 00:00:00 2001 From: David Fries Date: Mon, 8 Sep 2008 22:01:14 -0500 Subject: [netdrvr] ne: Fix suspend and resume for ISA PnP cards. A call to pnp_stop_dev and pnp_start_dev now shuts down and initializes plug and play devices for suspend and resume. Signed-off-by: David Fries Cc: Atsushi Nemoto Cc: Paul Gortmaker Cc: Alan Cox Cc: Jeff Garzik Signed-off-by: Jeff Garzik --- drivers/net/ne.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ne.c b/drivers/net/ne.c index fa3ceca4e15..79599900c4b 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -844,8 +844,12 @@ static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state) { struct net_device *dev = platform_get_drvdata(pdev); - if (netif_running(dev)) + if (netif_running(dev)) { + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; netif_device_detach(dev); + if (idev) + pnp_stop_dev(idev); + } return 0; } @@ -854,6 +858,9 @@ static int ne_drv_resume(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); if (netif_running(dev)) { + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_start_dev(idev); ne_reset_8390(dev); NS8390p_init(dev, 1); netif_device_attach(dev); -- cgit v1.2.3 From 70666c71957b62c8e9ea5c0d999a4bfd214c80d2 Mon Sep 17 00:00:00 2001 From: Hannes Hering Date: Fri, 5 Sep 2008 16:36:26 +0200 Subject: ehea: Fix DLPAR memory handling The ehea busmap must be allocated only once in the first of many calls of the ehea_create_busmap_callback. Signed-off-by: Hannes Hering Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_qmr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 140f05baafd..db8a9257e68 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -595,7 +595,8 @@ static int ehea_create_busmap_callback(unsigned long pfn, end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE); mr_len = *(unsigned long *)arg; - ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL); + if (!ehea_bmap) + ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL); if (!ehea_bmap) return -ENOMEM; -- cgit v1.2.3 From f382a0a8e9403c6d7f8b2cfa21e41fefb5d0c9bd Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 12 Aug 2008 07:13:14 -0600 Subject: [netdrvr] atl1e: Don't take the mdio_lock in atl1e_probe Lockdep warns about the mdio_lock taken with interrupts enabled then later taken from interrupt context. Initially, I considered changing these to spin_lock_irq/spin_unlock_irq, but then I looked at atl1e_phy_init() and saw that it calls msleep(). Sleeping while holding a spinlock is not allowed either. In the probe path, we haven't registered the interrupt handler, so it can't poke at this card yet. It's before we call register_netdev(), so I don't think any other threads can reach this card either. If I'm right, we don't need a spinlock at all. Signed-off-by: Matthew Wilcox Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 7685b995ff9..9b603528143 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -2390,9 +2390,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, } /* Init GPHY as early as possible due to power saving issue */ - spin_lock(&adapter->mdio_lock); atl1e_phy_init(&adapter->hw); - spin_unlock(&adapter->mdio_lock); /* reset the controller to * put the device in a known good starting state */ err = atl1e_reset_hw(&adapter->hw); -- cgit v1.2.3 From 2d1ea19da0e84117d3ebbad981e4664bef03152e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 28 Aug 2008 15:38:41 -0400 Subject: bonding: Do not tx-balance some IPv6 packets on ALB/TLB bonds IPv6 all-node-multicasts and DAD probes should not be tx-balanced on ALB/TLB bonds. The all-node-multicast is an equivalent to IPv4 broadcasts. DAD probes have to be sent only on the primary so that we don't get false-positive detections. Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_alb.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 3d39278a63e..ade5f3f6693 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "bonding.h" #include "bond_alb.h" @@ -81,6 +82,7 @@ #define RLB_PROMISC_TIMEOUT 10*ALB_TIMER_TICKS_PER_SEC static const u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; +static const u8 mac_v6_allmcast[ETH_ALEN] = {0x33,0x33,0x00,0x00,0x00,0x01}; static const int alb_delta_in_ticks = HZ / ALB_TIMER_TICKS_PER_SEC; #pragma pack(1) @@ -1290,6 +1292,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) u32 hash_index = 0; const u8 *hash_start = NULL; int res = 1; + struct ipv6hdr *ip6hdr; skb_reset_mac_header(skb); eth_data = eth_hdr(skb); @@ -1319,11 +1322,32 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) } break; case ETH_P_IPV6: + /* IPv6 doesn't really use broadcast mac address, but leave + * that here just in case. + */ if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) { do_tx_balance = 0; break; } + /* IPv6 uses all-nodes multicast as an equivalent to + * broadcasts in IPv4. + */ + if (memcmp(eth_data->h_dest, mac_v6_allmcast, ETH_ALEN) == 0) { + do_tx_balance = 0; + break; + } + + /* Additianally, DAD probes should not be tx-balanced as that + * will lead to false positives for duplicate addresses and + * prevent address configuration from working. + */ + ip6hdr = ipv6_hdr(skb); + if (ipv6_addr_any(&ip6hdr->saddr)) { + do_tx_balance = 0; + break; + } + hash_start = (char *)&(ipv6_hdr(skb)->daddr); hash_size = sizeof(ipv6_hdr(skb)->daddr); break; -- cgit v1.2.3 From 54069511633ca9d5b4e5d45cf32ffea06697c88b Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Wed, 3 Sep 2008 18:21:56 +0200 Subject: wan/hdlc_x25.c: fix a NULL dereference WAN: fixes a NULL dereference in hdlc_x25. Reported-by: Adrian Bunk . Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/wan/hdlc_x25.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index 8b7e5d2e2ac..cbcbf6f0414 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -163,15 +163,17 @@ static void x25_close(struct net_device *dev) static int x25_rx(struct sk_buff *skb) { + struct net_device *dev = skb->dev; + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - skb->dev->stats.rx_dropped++; + dev->stats.rx_dropped++; return NET_RX_DROP; } - if (lapb_data_received(skb->dev, skb) == LAPB_OK) + if (lapb_data_received(dev, skb) == LAPB_OK) return NET_RX_SUCCESS; - skb->dev->stats.rx_errors++; + dev->stats.rx_errors++; dev_kfree_skb_any(skb); return NET_RX_DROP; } -- cgit v1.2.3 From e57b641dfafc10ce23d26cf271fd2638589fdb3f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 28 Aug 2008 01:02:37 +0300 Subject: [netdrvr/usb] hso_create_bulk_serial_device(): fix a double free hso_serial_common_free() mustn't be called if hso_serial_common_create() fails. Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6e42b5a8c22..8b2b947b675 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2211,14 +2211,14 @@ static struct hso_device *hso_create_bulk_serial_device( USB_DIR_IN); if (!serial->in_endp) { dev_err(&interface->dev, "Failed to find BULK IN ep\n"); - goto exit; + goto exit2; } if (! (serial->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT))) { dev_err(&interface->dev, "Failed to find BULK IN ep\n"); - goto exit; + goto exit2; } serial->write_data = hso_std_serial_write_data; @@ -2231,9 +2231,10 @@ static struct hso_device *hso_create_bulk_serial_device( /* done, return it */ return hso_dev; + +exit2: + hso_serial_common_free(serial); exit: - if (hso_dev && serial) - hso_serial_common_free(serial); kfree(serial); hso_free_device(hso_dev); return NULL; -- cgit v1.2.3 From 52845c3fd80c09f8ceac54513ae9cffac219cff7 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 25 Aug 2008 23:37:36 +0900 Subject: cs89x0: fix warning release_irq label release_irq label is only used when ALLOW_DMA is defined. drivers/net/cs89x0.c: In function 'net_open': drivers/net/cs89x0.c:1401: warning: label 'release_irq' defined but not used Signed-off-by: Yoichi Yuasa Signed-off-by: Jeff Garzik --- drivers/net/cs89x0.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index ea6144a9565..b0b66766ed2 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1397,9 +1397,7 @@ net_open(struct net_device *dev) release_dma: #if ALLOW_DMA free_dma(dev->dma); -#endif release_irq: -#if ALLOW_DMA release_dma_buff(lp); #endif writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON)); -- cgit v1.2.3 From cd0fce0322cd10ab39ace584be12f809988a1b9a Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 4 Sep 2008 17:52:54 -0300 Subject: s2io: Fix enabling VLAN tag stripping at driver initialization VLAN doesn't work except if you'd opened the interface in promiscuous mode before. This happens because VLAN tag stripping is not correctly marked as enabled at device startup Also, the vlan_strip_flag field was moved to the private network structure. Signed-off-by: Breno Leitao Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 18 ++++++++++-------- drivers/net/s2io.h | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 243db33042a..a2d50fad61a 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -371,9 +371,6 @@ static void s2io_vlan_rx_register(struct net_device *dev, flags[i]); } -/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */ -static int vlan_strip_flag; - /* Unregister the vlan */ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) { @@ -2303,7 +2300,7 @@ static int start_nic(struct s2io_nic *nic) val64 = readq(&bar0->rx_pa_cfg); val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG; writeq(val64, &bar0->rx_pa_cfg); - vlan_strip_flag = 0; + nic->vlan_strip_flag = 0; } /* @@ -5010,7 +5007,7 @@ static void s2io_set_multicast(struct net_device *dev) val64 = readq(&bar0->rx_pa_cfg); val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG; writeq(val64, &bar0->rx_pa_cfg); - vlan_strip_flag = 0; + sp->vlan_strip_flag = 0; } val64 = readq(&bar0->mac_cfg); @@ -5032,7 +5029,7 @@ static void s2io_set_multicast(struct net_device *dev) val64 = readq(&bar0->rx_pa_cfg); val64 |= RX_PA_CFG_STRIP_VLAN_TAG; writeq(val64, &bar0->rx_pa_cfg); - vlan_strip_flag = 1; + sp->vlan_strip_flag = 1; } val64 = readq(&bar0->mac_cfg); @@ -8206,6 +8203,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Initialize device name */ sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name); + if (vlan_tag_strip) + sp->vlan_strip_flag = 1; + else + sp->vlan_strip_flag = 0; + /* * Make Link state as off at this point, when the Link change * interrupt comes the state will be automatically changed to @@ -8311,7 +8313,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, * If vlan stripping is disabled and the frame is VLAN tagged, * shift the offset by the VLAN header size bytes. */ - if ((!vlan_strip_flag) && + if ((!sp->vlan_strip_flag) && (rxdp->Control_1 & RXD_FRAME_VLAN_TAG)) ip_off += HEADER_VLAN_SIZE; } else { @@ -8592,7 +8594,7 @@ static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag) skb->protocol = eth_type_trans(skb, dev); if (sp->vlgrp && vlan_tag - && (vlan_strip_flag)) { + && (sp->vlan_strip_flag)) { /* Queueing the vlan frame to the upper layer */ if (sp->config.napi) vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 6722a2f7d09..55cb943f23f 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -962,6 +962,7 @@ struct s2io_nic { int task_flag; unsigned long long start_time; struct vlan_group *vlgrp; + int vlan_strip_flag; #define MSIX_FLG 0xA5 int num_entries; struct msix_entry *entries; -- cgit v1.2.3 From da8de3929da9396977b3c9096f36b173f3d9085a Mon Sep 17 00:00:00 2001 From: Mats Erik Andersson Date: Thu, 17 Jul 2008 01:05:43 +0200 Subject: 8139too: [cosmetic] fix incorrect register for flash-rom I would like to submit a correction to the driver drivers/net/8139too.c, which in no way changes the compiled driver, but does change the value of a previously incorrect value for the configuration register address of Flash PROM on the network processor rtl8139C. This corrected value is in accordance with the datasheet for rtl8139C, and in addition this new value is indeed used in other functional drivers that use this adapter for programming a Flash memory chip in situ. But as said, the two new constants are never referenced in the driver maintained by you: they are only informational and correct! Mats Erik Andersson, meand@users.sourceforge.net Signed-off-by: Jeff Garzik --- drivers/net/8139too.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index f6ca99774cc..32e66f0d434 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -309,7 +309,7 @@ enum RTL8139_registers { Cfg9346 = 0x50, Config0 = 0x51, Config1 = 0x52, - FlashReg = 0x54, + TimerInt = 0x54, MediaStatus = 0x58, Config3 = 0x59, Config4 = 0x5A, /* absent on RTL-8139A */ @@ -325,6 +325,7 @@ enum RTL8139_registers { FIFOTMS = 0x70, /* FIFO Control and test. */ CSCR = 0x74, /* Chip Status and Configuration Register. */ PARA78 = 0x78, + FlashReg = 0xD4, /* Communication with Flash ROM, four bytes. */ PARA7c = 0x7c, /* Magic transceiver parameter register. */ Config5 = 0xD8, /* absent on RTL-8139A */ }; -- cgit v1.2.3 From 8ca31ce52a5cfd03b960fd81a49197ae85d25347 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Wed, 24 Sep 2008 15:53:39 -0700 Subject: netfilter: ip6t_{hbh,dst}: Rejects not-strict mode on rule insertion The current code ignores rules for internal options in HBH/DST options header in packet processing if 'Not strict' mode is specified (which is not implemented). Clearly it is not expected by user. Kernel should reject HBH/DST rule insertion with 'Not strict' mode in the first place. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6t_hbh.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 62e39ace058..26654b26d7f 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -97,8 +97,6 @@ hbh_mt6(const struct sk_buff *skb, const struct net_device *in, hdrlen -= 2; if (!(optinfo->flags & IP6T_OPTS_OPTS)) { return ret; - } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { - pr_debug("Not strict - not implemented"); } else { pr_debug("Strict "); pr_debug("#%d ", optinfo->optsnr); @@ -177,6 +175,12 @@ hbh_mt6_check(const char *tablename, const void *entry, pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); return false; } + + if (optsinfo->flags & IP6T_OPTS_NSTRICT) { + pr_debug("ip6t_opts: Not strict - not implemented"); + return false; + } + return true; } -- cgit v1.2.3 From 88c59425139c0cd9984ca8f1ef577959326446d3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Sep 2008 15:07:50 +0100 Subject: sfc: Add check for memory allocation failure in falcon_probe_nic() Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index e0c0b23f94e..636fe824b86 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -2758,6 +2758,8 @@ int falcon_probe_nic(struct efx_nic *efx) /* Allocate storage for hardware specific data */ nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); + if (!nic_data) + return -ENOMEM; efx->nic_data = nic_data; /* Determine number of ports etc. */ -- cgit v1.2.3 From e1074a0d966ac372bb0abd5eee926a0b57316582 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:49:15 +0100 Subject: sfc: Fix memory BAR release call on error path Match pci_request_region() with pci_release_region(), not release_mem_region(). From: Steve Hodgson Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/efx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 0d47d6ffe68..6d3eb823488 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -780,7 +780,7 @@ static int efx_init_io(struct efx_nic *efx) return 0; fail4: - release_mem_region(efx->membase_phys, efx->type->mem_map_size); + pci_release_region(efx->pci_dev, efx->type->mem_bar); fail3: efx->membase_phys = 0; fail2: -- cgit v1.2.3 From ef08af03ef85373901a2ca0241617e6e7e42685d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:49:20 +0100 Subject: sfc: Remove workaround for old firmware bug There was a bug in XAUI synchronisation in early 10Xpress firmware versions. This is fixed in released firmware and we do not need to work around it. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/efx.c | 1 - drivers/net/sfc/falcon_xmac.c | 88 +------------------------------------------ drivers/net/sfc/net_driver.h | 2 - drivers/net/sfc/sfe4001.c | 12 ------ drivers/net/sfc/tenxpress.c | 51 ------------------------- drivers/net/sfc/workarounds.h | 2 - drivers/net/sfc/xfp_phy.c | 1 - 7 files changed, 1 insertion(+), 156 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 6d3eb823488..f65e313c2be 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1750,7 +1750,6 @@ static struct efx_phy_operations efx_dummy_phy_operations = { .check_hw = efx_port_dummy_op_int, .fini = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void, - .reset_xaui = efx_port_dummy_op_void, }; static struct efx_board efx_dummy_board_info = { diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 0d9f68ff71e..d4012314dd0 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -78,79 +78,7 @@ static void falcon_setup_xaui(struct efx_nic *efx) falcon_write(efx, &txdrv, XX_TXDRV_CTL_REG); } -static void falcon_hold_xaui_in_rst(struct efx_nic *efx) -{ - efx_oword_t reg; - - EFX_ZERO_OWORD(reg); - EFX_SET_OWORD_FIELD(reg, XX_PWRDNA_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_PWRDNB_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_PWRDNC_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_PWRDND_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RSTPLLAB_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RSTPLLCD_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RESETA_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RESETB_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RESETC_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RESETD_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1); - EFX_SET_OWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); -} - -static int _falcon_reset_xaui_a(struct efx_nic *efx) -{ - efx_oword_t reg; - - falcon_hold_xaui_in_rst(efx); - falcon_read(efx, ®, XX_PWR_RST_REG); - - /* Follow the RAMBUS XAUI data reset sequencing - * Channels A and B first: power down, reset PLL, reset, clear - */ - EFX_SET_OWORD_FIELD(reg, XX_PWRDNA_EN, 0); - EFX_SET_OWORD_FIELD(reg, XX_PWRDNB_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - EFX_SET_OWORD_FIELD(reg, XX_RSTPLLAB_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - EFX_SET_OWORD_FIELD(reg, XX_RESETA_EN, 0); - EFX_SET_OWORD_FIELD(reg, XX_RESETB_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - /* Channels C and D: power down, reset PLL, reset, clear */ - EFX_SET_OWORD_FIELD(reg, XX_PWRDNC_EN, 0); - EFX_SET_OWORD_FIELD(reg, XX_PWRDND_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - EFX_SET_OWORD_FIELD(reg, XX_RSTPLLCD_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - EFX_SET_OWORD_FIELD(reg, XX_RESETC_EN, 0); - EFX_SET_OWORD_FIELD(reg, XX_RESETD_EN, 0); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - /* Setup XAUI */ - falcon_setup_xaui(efx); - udelay(10); - - /* Take XGXS out of reset */ - EFX_ZERO_OWORD(reg); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); - - return 0; -} - -static int _falcon_reset_xaui_b(struct efx_nic *efx) +int falcon_reset_xaui(struct efx_nic *efx) { efx_oword_t reg; int count; @@ -171,20 +99,6 @@ static int _falcon_reset_xaui_b(struct efx_nic *efx) return -ETIMEDOUT; } -int falcon_reset_xaui(struct efx_nic *efx) -{ - int rc; - - if (EFX_WORKAROUND_9388(efx)) { - falcon_hold_xaui_in_rst(efx); - efx->phy_op->reset_xaui(efx); - rc = _falcon_reset_xaui_a(efx); - } else { - rc = _falcon_reset_xaui_b(efx); - } - return rc; -} - static bool falcon_xgmii_status(struct efx_nic *efx) { efx_oword_t reg; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 567df00090f..be3d2ba3b74 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -503,7 +503,6 @@ enum efx_fc_type { * @clear_interrupt: Clear down interrupt * @blink: Blink LEDs * @check_hw: Check hardware - * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset) * @mmds: MMD presence mask * @loopbacks: Supported loopback modes mask */ @@ -513,7 +512,6 @@ struct efx_phy_operations { void (*reconfigure) (struct efx_nic *efx); void (*clear_interrupt) (struct efx_nic *efx); int (*check_hw) (struct efx_nic *efx); - void (*reset_xaui) (struct efx_nic *efx); int (*test) (struct efx_nic *efx); int mmds; unsigned loopbacks; diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index b7005da55d5..fe4e3fd2233 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -129,18 +129,6 @@ static int sfe4001_poweron(struct efx_nic *efx) unsigned int i, j; int rc; u8 out; - efx_oword_t reg; - - /* Ensure that XGXS and XAUI SerDes are held in reset */ - EFX_POPULATE_OWORD_7(reg, XX_PWRDNA_EN, 1, - XX_PWRDNB_EN, 1, - XX_RSTPLLAB_EN, 1, - XX_RESETA_EN, 1, - XX_RESETB_EN, 1, - XX_RSTXGXSRX_EN, 1, - XX_RSTXGXSTX_EN, 1); - falcon_write(efx, ®, XX_PWR_RST_REG); - udelay(10); /* Clear any previous over-temperature alert */ rc = i2c_smbus_read_byte_data(hwmon_client, RSL); diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 8412dbe1e8f..77e7f3a94b2 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -146,8 +146,6 @@ static int tenxpress_phy_check(struct efx_nic *efx) return 0; } -static void tenxpress_reset_xaui(struct efx_nic *efx); - static int tenxpress_init(struct efx_nic *efx) { int rc, reg; @@ -428,54 +426,6 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink) PMA_PMD_LED_OVERR_REG, reg); } -static void tenxpress_reset_xaui(struct efx_nic *efx) -{ - int phy = efx->mii.phy_id; - int clk_ctrl, test_select, soft_rst2; - - /* Real work is done on clock_ctrl other resets are thought to be - * optional but make the reset more reliable - */ - - /* Read */ - clk_ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS, - PCS_CLOCK_CTRL_REG); - test_select = mdio_clause45_read(efx, phy, MDIO_MMD_PCS, - PCS_TEST_SELECT_REG); - soft_rst2 = mdio_clause45_read(efx, phy, MDIO_MMD_PCS, - PCS_SOFT_RST2_REG); - - /* Put in reset */ - test_select &= ~(1 << CLK312_EN_LBN); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_TEST_SELECT_REG, test_select); - - soft_rst2 &= ~((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN)); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_SOFT_RST2_REG, soft_rst2); - - clk_ctrl &= ~(1 << PLL312_RST_N_LBN); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_CLOCK_CTRL_REG, clk_ctrl); - udelay(10); - - /* Remove reset */ - clk_ctrl |= (1 << PLL312_RST_N_LBN); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_CLOCK_CTRL_REG, clk_ctrl); - udelay(10); - - soft_rst2 |= ((1 << XGXS_RST_N_LBN) | (1 << SERDES_RST_N_LBN)); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_SOFT_RST2_REG, soft_rst2); - udelay(10); - - test_select |= (1 << CLK312_EN_LBN); - mdio_clause45_write(efx, phy, MDIO_MMD_PCS, - PCS_TEST_SELECT_REG, test_select); - udelay(10); -} - static int tenxpress_phy_test(struct efx_nic *efx) { /* BIST is automatically run after a special software reset */ @@ -488,7 +438,6 @@ struct efx_phy_operations falcon_tenxpress_phy_ops = { .check_hw = tenxpress_phy_check_hw, .fini = tenxpress_phy_fini, .clear_interrupt = tenxpress_phy_clear_interrupt, - .reset_xaui = tenxpress_reset_xaui, .test = tenxpress_phy_test, .mmds = TENXPRESS_REQUIRED_DEVS, .loopbacks = TENXPRESS_LOOPBACKS, diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index a824f5998c0..fa7b49d6928 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -24,8 +24,6 @@ #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS /* TX pkt parser problem with <= 16 byte TXes */ #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS -/* XGXS and XAUI reset sequencing in SW */ -#define EFX_WORKAROUND_9388 EFX_WORKAROUND_ALWAYS /* Low rate CRC errors require XAUI reset */ #define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS /* TX_EV_PKT_ERR can be caused by a dangling TX descriptor diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index f6edecc2e58..276151df3a7 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -165,7 +165,6 @@ struct efx_phy_operations falcon_xfp_phy_ops = { .check_hw = xfp_phy_check_hw, .fini = xfp_phy_fini, .clear_interrupt = xfp_phy_clear_interrupt, - .reset_xaui = efx_port_dummy_op_void, .mmds = XFP_REQUIRED_DEVS, .loopbacks = XFP_LOOPBACKS, }; -- cgit v1.2.3 From c8fcc49c542a2312c706ebf76dcfe5266b39ee13 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:49:25 +0100 Subject: sfc: Serialise tenxpress_special_reset() with statistics fetches On some boards 10Xpress feeds a 156 MHz clock to the Falcon XMAC. MAC statistics DMA can fail while this clock is stopped during a PHY reset. From: Steve Hodgson Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/tenxpress.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 77e7f3a94b2..2ad3d8d12f4 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -214,7 +214,10 @@ static int tenxpress_special_reset(struct efx_nic *efx) { int rc, reg; - EFX_TRACE(efx, "%s\n", __func__); + /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so + * a special software reset can glitch the XGMAC sufficiently for stats + * requests to fail. Since we don't ofen special_reset, just lock. */ + spin_lock(&efx->stats_lock); /* Initiate reset */ reg = mdio_clause45_read(efx, efx->mii.phy_id, @@ -223,20 +226,22 @@ static int tenxpress_special_reset(struct efx_nic *efx) mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG, reg); - msleep(200); + mdelay(200); /* Wait for the blocks to come out of reset */ rc = mdio_clause45_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) - return rc; + goto unlock; /* Try and reconfigure the device */ rc = tenxpress_init(efx); if (rc < 0) - return rc; + goto unlock; - return 0; +unlock: + spin_unlock(&efx->stats_lock); + return rc; } static void tenxpress_set_bad_lp(struct efx_nic *efx, bool bad_lp) -- cgit v1.2.3 From 92ade881b2fcfc2744d3de43d172d3ec8e13afd7 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Mon, 1 Sep 2008 12:49:29 +0100 Subject: sfc: Don't use EFX_OWORD_FIELD on an event (64-bit, quad-word) Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 636fe824b86..ad192f82c5e 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1007,7 +1007,7 @@ static void falcon_handle_global_event(struct efx_channel *channel, is_phy_event = true; if ((falcon_rev(efx) >= FALCON_REV_B0) && - EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0)) + EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) is_phy_event = true; if (is_phy_event) { -- cgit v1.2.3 From 6bc5d3a9334401d788e1adf8b71add211265bc8b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:49:37 +0100 Subject: sfc: Make queue flushes more reliable Increase the potential retry count for RX flushes from 5 to 100. Stop polling the RX_DESC_PTR_TBL to infer that a flush might have happened. Instead absolutely rely on the flush events, unless bug 7803 applies (Falcon rev A only). To keep things quick, request flushes for every TX and RX queue up front, and match up the events to requests. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/efx.c | 15 ++- drivers/net/sfc/falcon.c | 247 ++++++++++++++++++++++--------------------- drivers/net/sfc/falcon.h | 1 + drivers/net/sfc/net_driver.h | 4 + 4 files changed, 141 insertions(+), 126 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index f65e313c2be..06ea71c7e34 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -445,10 +445,17 @@ static void efx_fini_channels(struct efx_nic *efx) struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; + int rc; EFX_ASSERT_RESET_SERIALISED(efx); BUG_ON(efx->port_enabled); + rc = falcon_flush_queues(efx); + if (rc) + EFX_ERR(efx, "failed to flush queues\n"); + else + EFX_LOG(efx, "successfully flushed all queues\n"); + efx_for_each_channel(channel, efx) { EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); @@ -456,13 +463,6 @@ static void efx_fini_channels(struct efx_nic *efx) efx_fini_rx_queue(rx_queue); efx_for_each_channel_tx_queue(tx_queue, channel) efx_fini_tx_queue(tx_queue); - } - - /* Do the event queues last so that we can handle flush events - * for all DMA queues. */ - efx_for_each_channel(channel, efx) { - EFX_LOG(channel->efx, "shut down evq %d\n", channel->channel); - efx_fini_eventq(channel); } } @@ -1092,7 +1092,6 @@ static void efx_stop_all(struct efx_nic *efx) /* Isolate the MAC from the TX and RX engines, so that queue * flushes will complete in a timely fashion. */ - falcon_deconfigure_mac_wrapper(efx); falcon_drain_tx_fifo(efx); /* Stop the kernel transmit interface late, so the watchdog diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index ad192f82c5e..70c681ecdab 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -108,10 +108,10 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); /* Max number of internal errors. After this resets will not be performed */ #define FALCON_MAX_INT_ERRORS 4 -/* Maximum period that we wait for flush events. If the flush event - * doesn't arrive in this period of time then we check if the queue - * was disabled anyway. */ -#define FALCON_FLUSH_TIMEOUT 10 /* 10ms */ +/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times + */ +#define FALCON_FLUSH_INTERVAL 10 +#define FALCON_FLUSH_POLL_COUNT 100 /************************************************************************** * @@ -452,6 +452,8 @@ void falcon_init_tx(struct efx_tx_queue *tx_queue) efx_oword_t tx_desc_ptr; struct efx_nic *efx = tx_queue->efx; + tx_queue->flushed = false; + /* Pin TX descriptor ring */ falcon_init_special_buffer(efx, &tx_queue->txd); @@ -492,60 +494,16 @@ void falcon_init_tx(struct efx_tx_queue *tx_queue) } } -static int falcon_flush_tx_queue(struct efx_tx_queue *tx_queue) +static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue) { struct efx_nic *efx = tx_queue->efx; - struct efx_channel *channel = &efx->channel[0]; efx_oword_t tx_flush_descq; - unsigned int read_ptr, i; /* Post a flush command */ EFX_POPULATE_OWORD_2(tx_flush_descq, TX_FLUSH_DESCQ_CMD, 1, TX_FLUSH_DESCQ, tx_queue->queue); falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER); - msleep(FALCON_FLUSH_TIMEOUT); - - if (EFX_WORKAROUND_7803(efx)) - return 0; - - /* Look for a flush completed event */ - read_ptr = channel->eventq_read_ptr; - for (i = 0; i < FALCON_EVQ_SIZE; ++i) { - efx_qword_t *event = falcon_event(channel, read_ptr); - int ev_code, ev_sub_code, ev_queue; - if (!falcon_event_present(event)) - break; - - ev_code = EFX_QWORD_FIELD(*event, EV_CODE); - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID); - if ((ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) && - (ev_queue == tx_queue->queue)) { - EFX_LOG(efx, "tx queue %d flush command succesful\n", - tx_queue->queue); - return 0; - } - - read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - } - - if (EFX_WORKAROUND_11557(efx)) { - efx_oword_t reg; - bool enabled; - - falcon_read_table(efx, ®, efx->type->txd_ptr_tbl_base, - tx_queue->queue); - enabled = EFX_OWORD_FIELD(reg, TX_DESCQ_EN); - if (!enabled) { - EFX_LOG(efx, "tx queue %d disabled without a " - "flush event seen\n", tx_queue->queue); - return 0; - } - } - - EFX_ERR(efx, "tx queue %d flush command timed out\n", tx_queue->queue); - return -ETIMEDOUT; } void falcon_fini_tx(struct efx_tx_queue *tx_queue) @@ -553,9 +511,8 @@ void falcon_fini_tx(struct efx_tx_queue *tx_queue) struct efx_nic *efx = tx_queue->efx; efx_oword_t tx_desc_ptr; - /* Stop the hardware using the queue */ - if (falcon_flush_tx_queue(tx_queue)) - EFX_ERR(efx, "failed to flush tx queue %d\n", tx_queue->queue); + /* The queue should have been flushed */ + WARN_ON(!tx_queue->flushed); /* Remove TX descriptor ring from card */ EFX_ZERO_OWORD(tx_desc_ptr); @@ -643,6 +600,8 @@ void falcon_init_rx(struct efx_rx_queue *rx_queue) rx_queue->queue, rx_queue->rxd.index, rx_queue->rxd.index + rx_queue->rxd.entries - 1); + rx_queue->flushed = false; + /* Pin RX descriptor ring */ falcon_init_special_buffer(efx, &rx_queue->rxd); @@ -663,11 +622,9 @@ void falcon_init_rx(struct efx_rx_queue *rx_queue) rx_queue->queue); } -static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) +static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) { struct efx_nic *efx = rx_queue->efx; - struct efx_channel *channel = &efx->channel[0]; - unsigned int read_ptr, i; efx_oword_t rx_flush_descq; /* Post a flush command */ @@ -675,76 +632,15 @@ static int falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) RX_FLUSH_DESCQ_CMD, 1, RX_FLUSH_DESCQ, rx_queue->queue); falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER); - msleep(FALCON_FLUSH_TIMEOUT); - - if (EFX_WORKAROUND_7803(efx)) - return 0; - - /* Look for a flush completed event */ - read_ptr = channel->eventq_read_ptr; - for (i = 0; i < FALCON_EVQ_SIZE; ++i) { - efx_qword_t *event = falcon_event(channel, read_ptr); - int ev_code, ev_sub_code, ev_queue; - bool ev_failed; - if (!falcon_event_present(event)) - break; - - ev_code = EFX_QWORD_FIELD(*event, EV_CODE); - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID); - ev_failed = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_FLUSH_FAIL); - - if ((ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) && - (ev_queue == rx_queue->queue)) { - if (ev_failed) { - EFX_INFO(efx, "rx queue %d flush command " - "failed\n", rx_queue->queue); - return -EAGAIN; - } else { - EFX_LOG(efx, "rx queue %d flush command " - "succesful\n", rx_queue->queue); - return 0; - } - } - - read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - } - - if (EFX_WORKAROUND_11557(efx)) { - efx_oword_t reg; - bool enabled; - - falcon_read_table(efx, ®, efx->type->rxd_ptr_tbl_base, - rx_queue->queue); - enabled = EFX_OWORD_FIELD(reg, RX_DESCQ_EN); - if (!enabled) { - EFX_LOG(efx, "rx queue %d disabled without a " - "flush event seen\n", rx_queue->queue); - return 0; - } - } - - EFX_ERR(efx, "rx queue %d flush command timed out\n", rx_queue->queue); - return -ETIMEDOUT; } void falcon_fini_rx(struct efx_rx_queue *rx_queue) { efx_oword_t rx_desc_ptr; struct efx_nic *efx = rx_queue->efx; - int i, rc; - /* Try and flush the rx queue. This may need to be repeated */ - for (i = 0; i < 5; i++) { - rc = falcon_flush_rx_queue(rx_queue); - if (rc == -EAGAIN) - continue; - break; - } - if (rc) { - EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); - efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); - } + /* The queue should already have been flushed */ + WARN_ON(!rx_queue->flushed); /* Remove RX descriptor ring from card */ EFX_ZERO_OWORD(rx_desc_ptr); @@ -1255,6 +1151,121 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic) falcon_generate_event(channel, &test_event); } +/************************************************************************** + * + * Flush handling + * + **************************************************************************/ + + +static void falcon_poll_flush_events(struct efx_nic *efx) +{ + struct efx_channel *channel = &efx->channel[0]; + struct efx_tx_queue *tx_queue; + struct efx_rx_queue *rx_queue; + unsigned int read_ptr, i; + + read_ptr = channel->eventq_read_ptr; + for (i = 0; i < FALCON_EVQ_SIZE; ++i) { + efx_qword_t *event = falcon_event(channel, read_ptr); + int ev_code, ev_sub_code, ev_queue; + bool ev_failed; + if (!falcon_event_present(event)) + break; + + ev_code = EFX_QWORD_FIELD(*event, EV_CODE); + if (ev_code != DRIVER_EV_DECODE) + continue; + + ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); + switch (ev_sub_code) { + case TX_DESCQ_FLS_DONE_EV_DECODE: + ev_queue = EFX_QWORD_FIELD(*event, + DRIVER_EV_TX_DESCQ_ID); + if (ev_queue < EFX_TX_QUEUE_COUNT) { + tx_queue = efx->tx_queue + ev_queue; + tx_queue->flushed = true; + } + break; + case RX_DESCQ_FLS_DONE_EV_DECODE: + ev_queue = EFX_QWORD_FIELD(*event, + DRIVER_EV_RX_DESCQ_ID); + ev_failed = EFX_QWORD_FIELD(*event, + DRIVER_EV_RX_FLUSH_FAIL); + if (ev_queue < efx->n_rx_queues) { + rx_queue = efx->rx_queue + ev_queue; + + /* retry the rx flush */ + if (ev_failed) + falcon_flush_rx_queue(rx_queue); + else + rx_queue->flushed = true; + } + break; + } + + read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; + } +} + +/* Handle tx and rx flushes at the same time, since they run in + * parallel in the hardware and there's no reason for us to + * serialise them */ +int falcon_flush_queues(struct efx_nic *efx) +{ + struct efx_rx_queue *rx_queue; + struct efx_tx_queue *tx_queue; + int i; + bool outstanding; + + /* Issue flush requests */ + efx_for_each_tx_queue(tx_queue, efx) { + tx_queue->flushed = false; + falcon_flush_tx_queue(tx_queue); + } + efx_for_each_rx_queue(rx_queue, efx) { + rx_queue->flushed = false; + falcon_flush_rx_queue(rx_queue); + } + + /* Poll the evq looking for flush completions. Since we're not pushing + * any more rx or tx descriptors at this point, we're in no danger of + * overflowing the evq whilst we wait */ + for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) { + msleep(FALCON_FLUSH_INTERVAL); + falcon_poll_flush_events(efx); + + /* Check if every queue has been succesfully flushed */ + outstanding = false; + efx_for_each_tx_queue(tx_queue, efx) + outstanding |= !tx_queue->flushed; + efx_for_each_rx_queue(rx_queue, efx) + outstanding |= !rx_queue->flushed; + if (!outstanding) + return 0; + } + + /* Mark the queues as all flushed. We're going to return failure + * leading to a reset, or fake up success anyway. "flushed" now + * indicates that we tried to flush. */ + efx_for_each_tx_queue(tx_queue, efx) { + if (!tx_queue->flushed) + EFX_ERR(efx, "tx queue %d flush command timed out\n", + tx_queue->queue); + tx_queue->flushed = true; + } + efx_for_each_rx_queue(rx_queue, efx) { + if (!rx_queue->flushed) + EFX_ERR(efx, "rx queue %d flush command timed out\n", + rx_queue->queue); + rx_queue->flushed = true; + } + + if (EFX_WORKAROUND_7803(efx)) + return 0; + + return -ETIMEDOUT; +} /************************************************************************** * diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 30d61e48ac6..be025ba7a6c 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h @@ -86,6 +86,7 @@ extern void falcon_fini_interrupt(struct efx_nic *efx); extern int falcon_probe_nic(struct efx_nic *efx); extern int falcon_probe_resources(struct efx_nic *efx); extern int falcon_init_nic(struct efx_nic *efx); +extern int falcon_flush_queues(struct efx_nic *efx); extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); extern void falcon_remove_resources(struct efx_nic *efx); extern void falcon_remove_nic(struct efx_nic *efx); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index be3d2ba3b74..868ad1e703f 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -160,6 +160,7 @@ struct efx_tx_buffer { * @channel: The associated channel * @buffer: The software buffer ring * @txd: The hardware descriptor ring + * @flushed: Used when handling queue flushing * @read_count: Current read pointer. * This is the number of buffers that have been removed from both rings. * @stopped: Stopped count. @@ -192,6 +193,7 @@ struct efx_tx_queue { struct efx_nic *nic; struct efx_tx_buffer *buffer; struct efx_special_buffer txd; + bool flushed; /* Members used mainly on the completion path */ unsigned int read_count ____cacheline_aligned_in_smp; @@ -260,6 +262,7 @@ struct efx_rx_buffer { * the remaining space in the allocation. * @buf_dma_addr: Page's DMA address. * @buf_data: Page's host address. + * @flushed: Use when handling queue flushing */ struct efx_rx_queue { struct efx_nic *efx; @@ -285,6 +288,7 @@ struct efx_rx_queue { struct page *buf_page; dma_addr_t buf_dma_addr; char *buf_data; + bool flushed; }; /** -- cgit v1.2.3 From 94be0c5424b7871e0411b71c12c28b2fd8e8564c Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Mon, 1 Sep 2008 12:49:54 +0100 Subject: sfc: Don't include net_driver.h from falcon_io.h Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon_io.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h index 6670cdfc41a..c16da3149fa 100644 --- a/drivers/net/sfc/falcon_io.h +++ b/drivers/net/sfc/falcon_io.h @@ -13,7 +13,6 @@ #include #include -#include "net_driver.h" /************************************************************************** * -- cgit v1.2.3 From a620e134e989b7ce683574039fc7cb956aa58970 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:50:01 +0100 Subject: sfc: Stop generating bogus events in tenxpress_check_hw() mdio_clause45_links_ok() correctly checks efx_phy_mode_disabled(), so tenxpress_link_ok() doesn't need to. From: Steve Hodgson Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/tenxpress.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 2ad3d8d12f4..d507c93d666 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -377,8 +377,7 @@ static int tenxpress_phy_check_hw(struct efx_nic *efx) struct tenxpress_phy_data *phy_data = efx->phy_data; bool link_ok; - link_ok = (phy_data->phy_mode == PHY_MODE_NORMAL && - tenxpress_link_ok(efx, true)); + link_ok = tenxpress_link_ok(efx, true); if (link_ok != efx->link_up) falcon_xmac_sim_phy_event(efx); -- cgit v1.2.3 From 1d0680fd6235e0aa5baf14a8f1ff85eff9dc1fb3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:50:08 +0100 Subject: sfc: Insert read memory barrier after checking MAC statistics flag This prevents speculative reading of the statistics before the completion flag. From: Neil Turton Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 70c681ecdab..3a5289fe8d1 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1953,8 +1953,10 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) /* Wait for transfer to complete */ for (i = 0; i < 400; i++) { - if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) + if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) { + rmb(); /* Ensure the stats are valid. */ return 0; + } udelay(10); } -- cgit v1.2.3 From 0a62f1a681006719c226a682dbcfb4358c8b3d28 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:50:14 +0100 Subject: sfc: Disable interrupts after a fatal interrupt occurs until reset This should avoid an interrupt storm, which has been observed in the field with one faulty board. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 3a5289fe8d1..d30c938d0fb 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1374,10 +1374,11 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx) EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg)); } - /* Disable DMA bus mastering on both devices */ + /* Disable both devices */ pci_disable_device(efx->pci_dev); if (FALCON_IS_DUAL_FUNC(efx)) pci_disable_device(nic_data->pci_dev2); + falcon_disable_interrupts(efx); if (++n_int_errors < FALCON_MAX_INT_ERRORS) { EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n"); -- cgit v1.2.3 From 951f46a1a2c891479565f2c2c950a951f65fd59f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:50:18 +0100 Subject: sfc: Remove obsolete comment about PCI modes Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon_hwdefs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index e319fd64d07..5d584b0dbb5 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h @@ -117,7 +117,6 @@ #define SF_PRST_WIDTH 1 #define EE_PRST_LBN 8 #define EE_PRST_WIDTH 1 -/* See pic_mode_t for decoding of this field */ /* These bit definitions are extrapolated from the list of numerical * values for STRAP_PINS. */ -- cgit v1.2.3 From 13e9ab11430c4bdc4b6bb97e3d3821ebdc043712 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Sep 2008 12:50:28 +0100 Subject: sfc: Use CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS where appropriate For some buffers we use a starting offset of either NET_IP_ALIGN or 0 depending on whether we believe the architecture supports efficient access to unaligned words. There is now a config macro specifying whether this is the case, so check that rather than checking for specific architectures. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/net_driver.h | 2 +- drivers/net/sfc/tx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 868ad1e703f..cdb11fad605 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -474,7 +474,7 @@ enum nic_state { * This is the equivalent of NET_IP_ALIGN [which controls the alignment * of the skb->head for hardware DMA]. */ -#if defined(__i386__) || defined(__x86_64__) +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #define EFX_PAGE_IP_ALIGN 0 #else #define EFX_PAGE_IP_ALIGN NET_IP_ALIGN diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index cdee7c200d6..da3e9ff339f 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -516,7 +516,7 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) /* Number of bytes inserted at the start of a TSO header buffer, * similar to NET_IP_ALIGN. */ -#if defined(__i386__) || defined(__x86_64__) +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #define TSOH_OFFSET 0 #else #define TSOH_OFFSET NET_IP_ALIGN -- cgit v1.2.3 From 31b760202a0911384fa07796df9d1905e9e89a7f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Sep 2008 15:37:01 +0100 Subject: sfc: Fix type of FALCON_SPI_MAX_LEN FALCON_SPI_MAX_LEN has type size_t while other SPI lengths have type unsigned int. This results in warnings from min() on 64-bit architectures where they are different. Add a cast to make it match. From: Steve Hodgson Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d30c938d0fb..31ed1f49de0 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1605,7 +1605,7 @@ void falcon_fini_interrupt(struct efx_nic *efx) ************************************************************************** */ -#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t) +#define FALCON_SPI_MAX_LEN ((unsigned) sizeof(efx_oword_t)) /* Wait for SPI command completion */ static int falcon_spi_wait(struct efx_nic *efx) -- cgit v1.2.3 From c1d69937ee5818bcde3bed8c012c9f07d60e492e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 3 Sep 2008 16:50:03 +0200 Subject: r6040: fix bad usage of udelay This patch fixes the bad usage of udelay(5000), which in turns is a mdelay(5). It causes compilation for ARM where udelay maximum value is checked. Reported-by: Martin Michlmayr Signed-off-by: Florian Fainelli Signed-off-by: Jeff Garzik --- drivers/net/r6040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 5d86281d936..025f526558b 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -370,7 +370,7 @@ static void r6040_init_mac_regs(struct net_device *dev) /* Reset internal state machine */ iowrite16(2, ioaddr + MAC_SM); iowrite16(0, ioaddr + MAC_SM); - udelay(5000); + mdelay(5); /* MAC Bus Control Register */ iowrite16(MBCR_DEFAULT, ioaddr + MBCR); @@ -806,7 +806,7 @@ static void r6040_mac_address(struct net_device *dev) iowrite16(0x01, ioaddr + MCR1); /* Reset MAC */ iowrite16(2, ioaddr + MAC_SM); /* Reset internal state machine */ iowrite16(0, ioaddr + MAC_SM); - udelay(5000); + mdelay(5); /* Restore MAC Address */ adrp = (u16 *) dev->dev_addr; -- cgit v1.2.3 From 7fb614bcc7136875c436a8866072fae23bbd2a0c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 8 Sep 2008 14:03:16 +0900 Subject: smc911x: remove duplicate debug printout Remove duplicated debug printout. Signed-off-by: Magnus Damm Signed-off-by: Jeff Garzik --- drivers/net/smc911x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index c5871624f97..e15abc3606c 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1174,8 +1174,6 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&lp->lock, flags); - DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); - return IRQ_HANDLED; } -- cgit v1.2.3 From 330554cb9b666a9932785cc3391f3444293ef19b Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 12 Sep 2008 19:47:26 +0200 Subject: myri10ge: Stop scaring people when DCA is built but absent Stop scaring people with what looks like a fatal message when DCA support is compiled into their kernel, but the DCA device is not present. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index d6524db321a..a1d82b0b467 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1060,8 +1060,9 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp) } err = dca_add_requester(&pdev->dev); if (err) { - dev_err(&pdev->dev, - "dca_add_requester() failed, err=%d\n", err); + if (err != -ENODEV) + dev_err(&pdev->dev, + "dca_add_requester() failed, err=%d\n", err); return; } mgp->dca_enabled = 1; -- cgit v1.2.3 From 9a6b3b544082907760fa36f54f9300969f31870b Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 12 Sep 2008 19:48:06 +0200 Subject: myri10ge: Rename DCA-related firmware counters Rename the cryptic "dca_capable" to "dca_capable_firmware" and "dca_enabled" to "dca_device_present" in the firmware counters. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a1d82b0b467..ce9fc66e73b 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1688,7 +1688,7 @@ static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = { "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", "serial_number", "watchdog_resets", #ifdef CONFIG_DCA - "dca_capable", "dca_enabled", + "dca_capable_firmware", "dca_device_present", #endif "link_changes", "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered", -- cgit v1.2.3 From 040dec3b37e4b9ec15b359bf5744f1ceba39fe3e Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 12 Sep 2008 06:55:14 -0700 Subject: netxen: add pci ids Define old and new pci vendor and device ids. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 18 +++++++++--------- include/linux/pci_ids.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 008fd6618a5..0f8ea2c7728 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -77,18 +77,18 @@ static irqreturn_t netxen_msi_intr(int irq, void *data); /* PCI Device ID Table */ #define ENTRY(device) \ - {PCI_DEVICE(0x4040, (device)), \ + {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} static struct pci_device_id netxen_pci_tbl[] __devinitdata = { - ENTRY(0x0001), - ENTRY(0x0002), - ENTRY(0x0003), - ENTRY(0x0004), - ENTRY(0x0005), - ENTRY(0x0024), - ENTRY(0x0025), - ENTRY(0x0100), + ENTRY(PCI_DEVICE_ID_NX2031_10GXSR), + ENTRY(PCI_DEVICE_ID_NX2031_10GCX4), + ENTRY(PCI_DEVICE_ID_NX2031_4GCU), + ENTRY(PCI_DEVICE_ID_NX2031_IMEZ), + ENTRY(PCI_DEVICE_ID_NX2031_HMEZ), + ENTRY(PCI_DEVICE_ID_NX2031_XG_MGMT), + ENTRY(PCI_DEVICE_ID_NX2031_XG_MGMT2), + ENTRY(PCI_DEVICE_ID_NX3031), {0,} }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6f4276d461c..a65b082a888 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2247,6 +2247,16 @@ #define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2V 0x0009 +#define PCI_VENDOR_ID_NETXEN 0x4040 +#define PCI_DEVICE_ID_NX2031_10GXSR 0x0001 +#define PCI_DEVICE_ID_NX2031_10GCX4 0x0002 +#define PCI_DEVICE_ID_NX2031_4GCU 0x0003 +#define PCI_DEVICE_ID_NX2031_IMEZ 0x0004 +#define PCI_DEVICE_ID_NX2031_HMEZ 0x0005 +#define PCI_DEVICE_ID_NX2031_XG_MGMT 0x0024 +#define PCI_DEVICE_ID_NX2031_XG_MGMT2 0x0025 +#define PCI_DEVICE_ID_NX3031 0x0100 + #define PCI_VENDOR_ID_AKS 0x416c #define PCI_DEVICE_ID_AKS_ALADDINCARD 0x0100 -- cgit v1.2.3 From af72166f31662850e10d1d1c734654efb2ae4357 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:54:23 -0700 Subject: ixgbe: fix bug where using wake queue instead of start Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 362541aa946..c67211c91cb 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3377,7 +3377,7 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev, return -EBUSY; /* A reprieve! - use start_queue because it doesn't call schedule */ - netif_wake_subqueue(netdev, tx_ring->queue_index); + netif_start_subqueue(netdev, tx_ring->queue_index); ++adapter->restart_queue; return 0; } -- cgit v1.2.3 From a1f96ee7cce0dce583ff2f32de6376495ef51e4d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:54:48 -0700 Subject: ixgbe: fix dca defines to not have spaces Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c67211c91cb..904819586e2 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -80,7 +80,7 @@ static struct pci_device_id ixgbe_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static int ixgbe_notify_dca(struct notifier_block *, unsigned long event, void *p); static struct notifier_block dca_notifier = { @@ -309,7 +309,7 @@ done_cleaning: return (total_packets ? true : false); } -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring) { @@ -934,7 +934,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { tx_ring = &(adapter->tx_ring[r_idx]); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_tx_dca(adapter, tx_ring); #endif @@ -999,7 +999,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); rx_ring = &(adapter->rx_ring[r_idx]); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_rx_dca(adapter, rx_ring); #endif @@ -2102,7 +2102,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; dca_remove_requester(&adapter->pdev->dev); @@ -2114,7 +2114,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) /* since we reset the hardware DCA settings were cleared */ if (dca_add_requester(&adapter->pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; @@ -2178,7 +2178,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) struct ixgbe_adapter *adapter = q_vector->adapter; int tx_cleaned = 0, work_done = 0; -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { ixgbe_update_tx_dca(adapter, adapter->tx_ring); ixgbe_update_rx_dca(adapter, adapter->rx_ring); @@ -3754,7 +3754,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_register; -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; /* always use CB2 mode, difference is masked @@ -3804,7 +3804,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) flush_scheduled_work(); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; dca_remove_requester(&pdev->dev); @@ -3937,7 +3937,7 @@ static int __init ixgbe_init_module(void) printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright); -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) dca_register_notify(&dca_notifier); #endif @@ -3954,13 +3954,13 @@ module_init(ixgbe_init_module); **/ static void __exit ixgbe_exit_module(void) { -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) dca_unregister_notify(&dca_notifier); #endif pci_unregister_driver(&ixgbe_driver); } -#if defined(CONFIG_DCA) || defined (CONFIG_DCA_MODULE) +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event, void *p) { -- cgit v1.2.3 From ce94bf469edf84228771b58489944cf654aeb496 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:55:14 -0700 Subject: ixgbe: fix multicast address update after the most recent patches, the driver was not using the correct iterator for updating the receive address registers (RAR) Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 9c0d0a1964e..f5b2617111a 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -896,6 +896,7 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) { u32 rar_entries = hw->mac.num_rar_entries; + u32 rar; hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", mc_addr[0], mc_addr[1], mc_addr[2], @@ -906,8 +907,8 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) * else put it in the MTA */ if (hw->addr_ctrl.rar_used_count < rar_entries) { - ixgbe_set_rar(hw, hw->addr_ctrl.rar_used_count, - mc_addr, 0, IXGBE_RAH_AV); + rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; + ixgbe_set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); hw_dbg(hw, "Added a multicast address to RAR[%d]\n", hw->addr_ctrl.rar_used_count); hw->addr_ctrl.rar_used_count++; -- cgit v1.2.3 From cf8280ee7be3aaf44d32e389f15c725b850e5e32 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:55:32 -0700 Subject: ixgbe: Update watchdog thread to accomodate longerlink_up events This patch updates the link_up code and watchdog thread so that link_up doesn't cause stack overflows due to long waits in interrupt context. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 6 ++ drivers/net/ixgbe/ixgbe_82598.c | 29 +++++++-- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 129 +++++++++++++++++++++++++------------- drivers/net/ixgbe/ixgbe_type.h | 3 +- 5 files changed, 118 insertions(+), 51 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 90b53830196..2b827a67c9c 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -309,6 +309,12 @@ struct ixgbe_adapter { u64 lro_aggregated; u64 lro_flushed; u64 lro_no_desc; + + u32 link_speed; + bool link_up; + unsigned long link_check_timeout; + + struct work_struct watchdog_task; }; enum ixbge_state_t { diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index ba09063260d..1e014bcc72d 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -47,7 +47,8 @@ static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, - bool *link_up); + bool *link_up, + bool link_up_wait_to_complete); static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed, bool autoneg, bool autoneg_wait_to_complete); @@ -277,20 +278,36 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise + * @link_up_wait_to_complete: bool used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, - bool *link_up) + bool *link_up, + bool link_up_wait_to_complete) { u32 links_reg; + u32 i; links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); - if (links_reg & IXGBE_LINKS_UP) - *link_up = true; - else - *link_up = false; + if (link_up_wait_to_complete) { + for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + if (links_reg & IXGBE_LINKS_UP) { + *link_up = true; + break; + } else { + *link_up = false; + } + msleep(100); + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + } + } else { + if (links_reg & IXGBE_LINKS_UP) + *link_up = true; + else + *link_up = false; + } if (links_reg & IXGBE_LINKS_SPEED) *speed = IXGBE_LINK_SPEED_10GB_FULL; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 61c000e2309..8f0e3f93e6b 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -130,7 +130,7 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->port = PORT_FIBRE; } - adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up); + adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up, false); if (link_up) { ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? SPEED_10000 : SPEED_1000; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 904819586e2..036393e5383 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -902,6 +902,20 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) return; } + +static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + + adapter->lsc_int++; + adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); + schedule_work(&adapter->watchdog_task); + } +} + static irqreturn_t ixgbe_msix_lsc(int irq, void *data) { struct net_device *netdev = data; @@ -909,11 +923,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) struct ixgbe_hw *hw = &adapter->hw; u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR); - if (eicr & IXGBE_EICR_LSC) { - adapter->lsc_int++; - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies); - } + if (eicr & IXGBE_EICR_LSC) + ixgbe_check_lsc(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); @@ -1237,12 +1248,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) if (!eicr) return IRQ_NONE; /* Not our interrupt */ - if (eicr & IXGBE_EICR_LSC) { - adapter->lsc_int++; - if (!test_bit(__IXGBE_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies); - } - + if (eicr & IXGBE_EICR_LSC) + ixgbe_check_lsc(adapter); if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) { adapter->tx_ring[0].total_packets = 0; @@ -1897,6 +1904,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* bring the link up in the watchdog, this could race with our first * link up interrupt but shouldn't be a problem */ + adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; mod_timer(&adapter->watchdog_timer, jiffies); return 0; } @@ -2098,6 +2107,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_napi_disable_all(adapter); del_timer_sync(&adapter->watchdog_timer); + cancel_work_sync(&adapter->watchdog_task); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); @@ -3010,27 +3020,74 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) static void ixgbe_watchdog(unsigned long data) { struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; - struct net_device *netdev = adapter->netdev; - bool link_up; - u32 link_speed = 0; + struct ixgbe_hw *hw = &adapter->hw; + + /* Do the watchdog outside of interrupt context due to the lovely + * delays that some of the newer hardware requires */ + if (!test_bit(__IXGBE_DOWN, &adapter->state)) { + /* Cause software interrupt to ensure rx rings are cleaned */ + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + u32 eics = + (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1; + IXGBE_WRITE_REG(hw, IXGBE_EICS, eics); + } else { + /* For legacy and MSI interrupts don't set any bits that + * are enabled for EIAM, because this operation would + * set *both* EIMS and EICS for any bit in EIAM */ + IXGBE_WRITE_REG(hw, IXGBE_EICS, + (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); + } + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 2 * HZ)); + } - adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up); + schedule_work(&adapter->watchdog_task); +} + +/** + * ixgbe_watchdog_task - worker thread to bring link up + * @work: pointer to work_struct containing our data + **/ +static void ixgbe_watchdog_task(struct work_struct *work) +{ + struct ixgbe_adapter *adapter = container_of(work, + struct ixgbe_adapter, + watchdog_task); + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + u32 link_speed = adapter->link_speed; + bool link_up = adapter->link_up; + + adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; + + if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + if (link_up || + time_after(jiffies, (adapter->link_check_timeout + + IXGBE_TRY_LINK_TIMEOUT))) { + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); + adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; + } + adapter->link_up = link_up; + adapter->link_speed = link_speed; + } if (link_up) { if (!netif_carrier_ok(netdev)) { - u32 frctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - u32 rmcs = IXGBE_READ_REG(&adapter->hw, IXGBE_RMCS); + u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS); #define FLOW_RX (frctl & IXGBE_FCTRL_RFCE) #define FLOW_TX (rmcs & IXGBE_RMCS_TFCE_802_3X) DPRINTK(LINK, INFO, "NIC Link is Up %s, " - "Flow Control: %s\n", - (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? - "10 Gbps" : - (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? - "1 Gbps" : "unknown speed")), - ((FLOW_RX && FLOW_TX) ? "RX/TX" : - (FLOW_RX ? "RX" : - (FLOW_TX ? "TX" : "None")))); + "Flow Control: %s\n", + (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? + "10 Gbps" : + (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? + "1 Gbps" : "unknown speed")), + ((FLOW_RX && FLOW_TX) ? "RX/TX" : + (FLOW_RX ? "RX" : + (FLOW_TX ? "TX" : "None")))); netif_carrier_on(netdev); netif_tx_wake_all_queues(netdev); @@ -3039,6 +3096,8 @@ static void ixgbe_watchdog(unsigned long data) adapter->detect_tx_hung = true; } } else { + adapter->link_up = false; + adapter->link_speed = 0; if (netif_carrier_ok(netdev)) { DPRINTK(LINK, INFO, "NIC Link is Down\n"); netif_carrier_off(netdev); @@ -3047,24 +3106,7 @@ static void ixgbe_watchdog(unsigned long data) } ixgbe_update_stats(adapter); - - if (!test_bit(__IXGBE_DOWN, &adapter->state)) { - /* Cause software interrupt to ensure rx rings are cleaned */ - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - u32 eics = - (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics); - } else { - /* for legacy and MSI interrupts don't set any bits that - * are enabled for EIAM, because this operation would - * set *both* EIMS and EICS for any bit in EIAM */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, - (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER)); - } - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, - round_jiffies(jiffies + 2 * HZ)); - } + adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK; } static int ixgbe_tso(struct ixgbe_adapter *adapter, @@ -3707,6 +3749,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->reset_task, ixgbe_reset_task); + INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task); err = ixgbe_init_interrupt_scheme(adapter); if (err) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 3e9c483ad8e..172f766acde 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -703,6 +703,7 @@ #define IXGBE_LINKS_TL_FAULT 0x00001000 #define IXGBE_LINKS_SIGNAL 0x00000F00 +#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ /* SW Semaphore Register bitmasks */ @@ -1249,7 +1250,7 @@ struct ixgbe_mac_operations { s32 (*reset)(struct ixgbe_hw *); enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); s32 (*setup_link)(struct ixgbe_hw *); - s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *); + s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *, bool); s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool); s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *); }; -- cgit v1.2.3 From 41fb924866128fbb3fe15aafe7becc7d5ce4504f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:55:58 -0700 Subject: ixgbe: link change interrupt was not causing link event Upon review a buglet was found where link change was not causing an immediate link change event as it should. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 036393e5383..11bf86b9362 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -758,9 +758,9 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950); - /* set up to autoclear timer, lsc, and the vectors */ + /* set up to autoclear timer, and the vectors */ mask = IXGBE_EIMS_ENABLE_MASK; - mask &= ~IXGBE_EIMS_OTHER; + mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask); } -- cgit v1.2.3 From f47cf66e9cc778d21533c681e89b4034ed2d8666 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:56:14 -0700 Subject: ixgbe: fix bug with shared interrupts fix ixgbe bug reported with shared legacy interrupts Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 11bf86b9362..cfaa3ca28f5 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1245,8 +1245,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data) /* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read * therefore no explict interrupt disable is necessary */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); - if (!eicr) + if (!eicr) { + /* shared interrupt alert! + * make sure interrupts are enabled because the read will + * have disabled interrupts due to EIAM */ + ixgbe_irq_enable(adapter); return IRQ_NONE; /* Not our interrupt */ + } if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); -- cgit v1.2.3 From 42c783c5b1b755ae2ab2dec720ad58ffc2257a60 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:56:28 -0700 Subject: ixgbe: limit small mtu to minimum for ipv4 support Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cfaa3ca28f5..2c8895e9dae 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2839,8 +2839,8 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) struct ixgbe_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((max_frame < (ETH_ZLEN + ETH_FCS_LEN)) || - (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) + /* MTU < 68 is an error and causes problems on some kernels */ + if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) return -EINVAL; DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n", -- cgit v1.2.3 From 98c00a1c5de23295aebe7e46a61d85e05ee82855 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:56:41 -0700 Subject: ixgbe: fix ethtool register dump 1) reading some of the registers in our hardware causes them to clear, so don't read ICR in the ethtool register dump function. 2) several register iterators were not iterating Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_ethtool.c | 23 ++++++++++------------- drivers/net/ixgbe/ixgbe_type.h | 10 ++-------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 8f0e3f93e6b..64460b4c50c 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -315,7 +315,9 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC); /* Interrupt */ - regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICR); + /* don't read EICR because it can clear interrupt causes, instead + * read EICS which is a shadow but doesn't clear EICR */ + regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICS); regs_buff[19] = IXGBE_READ_REG(hw, IXGBE_EICS); regs_buff[20] = IXGBE_READ_REG(hw, IXGBE_EIMS); regs_buff[21] = IXGBE_READ_REG(hw, IXGBE_EIMC); @@ -419,7 +421,6 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM); regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT); - /* DCE */ regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS); regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS); regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS); @@ -539,21 +540,17 @@ static void ixgbe_get_regs(struct net_device *netdev, /* Diagnostic */ regs_buff[1071] = IXGBE_READ_REG(hw, IXGBE_RDSTATCTL); for (i = 0; i < 8; i++) - regs_buff[1072] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i)); + regs_buff[1072 + i] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i)); regs_buff[1080] = IXGBE_READ_REG(hw, IXGBE_RDHMPN); - regs_buff[1081] = IXGBE_READ_REG(hw, IXGBE_RIC_DW0); - regs_buff[1082] = IXGBE_READ_REG(hw, IXGBE_RIC_DW1); - regs_buff[1083] = IXGBE_READ_REG(hw, IXGBE_RIC_DW2); - regs_buff[1084] = IXGBE_READ_REG(hw, IXGBE_RIC_DW3); + for (i = 0; i < 4; i++) + regs_buff[1081 + i] = IXGBE_READ_REG(hw, IXGBE_RIC_DW(i)); regs_buff[1085] = IXGBE_READ_REG(hw, IXGBE_RDPROBE); regs_buff[1086] = IXGBE_READ_REG(hw, IXGBE_TDSTATCTL); for (i = 0; i < 8; i++) - regs_buff[1087] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i)); + regs_buff[1087 + i] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i)); regs_buff[1095] = IXGBE_READ_REG(hw, IXGBE_TDHMPN); - regs_buff[1096] = IXGBE_READ_REG(hw, IXGBE_TIC_DW0); - regs_buff[1097] = IXGBE_READ_REG(hw, IXGBE_TIC_DW1); - regs_buff[1098] = IXGBE_READ_REG(hw, IXGBE_TIC_DW2); - regs_buff[1099] = IXGBE_READ_REG(hw, IXGBE_TIC_DW3); + for (i = 0; i < 4; i++) + regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i)); regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE); regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL); regs_buff[1102] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA0); @@ -566,7 +563,7 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[1109] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA2); regs_buff[1110] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA3); for (i = 0; i < 8; i++) - regs_buff[1111] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i)); + regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i)); regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL); regs_buff[1120] = IXGBE_READ_REG(hw, IXGBE_MDFTC1); regs_buff[1121] = IXGBE_READ_REG(hw, IXGBE_MDFTC2); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 172f766acde..196841b344d 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -278,18 +278,12 @@ #define IXGBE_RDSTATCTL 0x02C20 #define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ #define IXGBE_RDHMPN 0x02F08 -#define IXGBE_RIC_DW0 0x02F10 -#define IXGBE_RIC_DW1 0x02F14 -#define IXGBE_RIC_DW2 0x02F18 -#define IXGBE_RIC_DW3 0x02F1C +#define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4)) #define IXGBE_RDPROBE 0x02F20 #define IXGBE_TDSTATCTL 0x07C20 #define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ #define IXGBE_TDHMPN 0x07F08 -#define IXGBE_TIC_DW0 0x07F10 -#define IXGBE_TIC_DW1 0x07F14 -#define IXGBE_TIC_DW2 0x07F18 -#define IXGBE_TIC_DW3 0x07F1C +#define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4)) #define IXGBE_TDPROBE 0x07F20 #define IXGBE_TXBUFCTRL 0x0C600 #define IXGBE_TXBUFDATA0 0x0C610 -- cgit v1.2.3 From 05857980cf15d96dd9eb47dd444b0634f436ba34 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 11 Sep 2008 19:57:00 -0700 Subject: ixgbe: fix pci_resource allocation as in other drivers Form: Jesse Brandeburg Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2c8895e9dae..0269115593e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3605,7 +3605,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, struct ixgbe_adapter *adapter = NULL; struct ixgbe_hw *hw; const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; - unsigned long mmio_start, mmio_len; static int cards_found; int i, err, pci_using_dac; u16 link_status, link_speed, link_width; @@ -3657,10 +3656,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->back = adapter; adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - - hw->hw_addr = ioremap(mmio_start, mmio_len); + hw->hw_addr = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); if (!hw->hw_addr) { err = -EIO; goto err_ioremap; @@ -3690,9 +3687,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, #endif strcpy(netdev->name, pci_name(pdev)); - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; - adapter->bd_number = cards_found; /* PCI config space info */ -- cgit v1.2.3 From 3d3d6d3cc2ad1e77516f3ad3f79d5988ebc361cf Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:57:17 -0700 Subject: ixgbe: fix ethtool disable csum for ipv6 ethtool was not disabling the correct netif flags when setting checksum disable. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 64460b4c50c..2506f9eae58 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -241,7 +241,7 @@ static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) if (data) netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); else - netdev->features &= ~NETIF_F_IP_CSUM; + netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); return 0; } -- cgit v1.2.3 From 30efa5a363d18f1c284455879cb67fb1bf547bdc Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:58:14 -0700 Subject: ixgbe: fix initial interrupt throttle settings ixgbe was incorrectly setting the throttle rate setting for all tx queues and the driver has been refreshed to better handle a dynamic interrupt mode as well as multiple queues. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 23 ++++------- drivers/net/ixgbe/ixgbe_ethtool.c | 86 +++++++++++++++++++++------------------ drivers/net/ixgbe/ixgbe_main.c | 80 ++++++++++++++++++++---------------- 3 files changed, 100 insertions(+), 89 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 2b827a67c9c..5ba03845c3e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -62,11 +62,6 @@ #define IXGBE_MAX_RXQ 1 #define IXGBE_MIN_RXQ 1 -#define IXGBE_DEFAULT_ITR_RX_USECS 125 /* 8k irqs/sec */ -#define IXGBE_DEFAULT_ITR_TX_USECS 250 /* 4k irqs/sec */ -#define IXGBE_MIN_ITR_USECS 100 /* 500k irqs/sec */ -#define IXGBE_MAX_ITR_USECS 10000 /* 100 irqs/sec */ - /* flow control */ #define IXGBE_DEFAULT_FCRTL 0x10000 #define IXGBE_MIN_FCRTL 0x40 @@ -161,10 +156,7 @@ struct ixgbe_ring { * vector array, can also be used for finding the bit in EICR * and friends that represents the vector for this ring */ - u32 eims_value; - u16 itr_register; - char name[IFNAMSIZ + 5]; u16 work_limit; /* max work per interrupt */ u16 rx_buf_len; }; @@ -191,8 +183,8 @@ struct ixgbe_q_vector { DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ u8 rxr_count; /* Rx ring count assigned to this vector */ u8 txr_count; /* Tx ring count assigned to this vector */ - u8 tx_eitr; - u8 rx_eitr; + u8 tx_itr; + u8 rx_itr; u32 eitr; }; @@ -240,7 +232,9 @@ struct ixgbe_adapter { /* TX */ struct ixgbe_ring *tx_ring; /* One per active queue */ + int num_tx_queues; u64 restart_queue; + u64 hw_csum_tx_good; u64 lsc_int; u64 hw_tso_ctxt; u64 hw_tso6_ctxt; @@ -249,12 +243,10 @@ struct ixgbe_adapter { /* RX */ struct ixgbe_ring *rx_ring; /* One per active queue */ - u64 hw_csum_tx_good; + int num_rx_queues; u64 hw_csum_rx_error; u64 hw_csum_rx_good; u64 non_eop_descs; - int num_tx_queues; - int num_rx_queues; int num_msix_vectors; struct ixgbe_ring_feature ring_feature[3]; struct msix_entry *msix_entries; @@ -301,14 +293,15 @@ struct ixgbe_adapter { struct ixgbe_hw_stats stats; /* Interrupt Throttle Rate */ - u32 rx_eitr; - u32 tx_eitr; + u32 eitr_param; unsigned long state; u64 tx_busy; u64 lro_aggregated; u64 lro_flushed; u64 lro_no_desc; + unsigned int tx_ring_count; + unsigned int rx_ring_count; u32 link_speed; bool link_up; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 2506f9eae58..f18e3daaf4f 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -880,17 +880,23 @@ static int ixgbe_get_coalesce(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); - if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS) - ec->rx_coalesce_usecs = adapter->rx_eitr; - else - ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr; - - if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS) - ec->tx_coalesce_usecs = adapter->tx_eitr; - else - ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr; - ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit; + + /* only valid if in constant ITR mode */ + switch (adapter->itr_setting) { + case 0: + /* throttling disabled */ + ec->rx_coalesce_usecs = 0; + break; + case 1: + /* dynamic ITR mode */ + ec->rx_coalesce_usecs = 1; + break; + default: + /* fixed interrupt rate mode */ + ec->rx_coalesce_usecs = 1000000/adapter->eitr_param; + break; + } return 0; } @@ -898,38 +904,40 @@ static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - - if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs != 0) && - (ec->rx_coalesce_usecs != 1) && - (ec->rx_coalesce_usecs != 3) && - (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS))) - return -EINVAL; - if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) || - ((ec->tx_coalesce_usecs != 0) && - (ec->tx_coalesce_usecs != 1) && - (ec->tx_coalesce_usecs != 3) && - (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS))) - return -EINVAL; - - /* convert to rate of irq's per second */ - if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS) - adapter->rx_eitr = ec->rx_coalesce_usecs; - else - adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs); - - if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS) - adapter->tx_eitr = ec->rx_coalesce_usecs; - else - adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs); + struct ixgbe_hw *hw = &adapter->hw; + int i; if (ec->tx_max_coalesced_frames_irq) - adapter->tx_ring[0].work_limit = - ec->tx_max_coalesced_frames_irq; + adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; + + if (ec->rx_coalesce_usecs > 1) { + /* store the value in ints/second */ + adapter->eitr_param = 1000000/ec->rx_coalesce_usecs; + + /* static value of interrupt rate */ + adapter->itr_setting = adapter->eitr_param; + /* clear the lower bit */ + adapter->itr_setting &= ~1; + } else if (ec->rx_coalesce_usecs == 1) { + /* 1 means dynamic mode */ + adapter->eitr_param = 20000; + adapter->itr_setting = 1; + } else { + /* any other value means disable eitr, which is best + * served by setting the interrupt rate very high */ + adapter->eitr_param = 3000000; + adapter->itr_setting = 0; + } - if (netif_running(netdev)) { - ixgbe_down(adapter); - ixgbe_up(adapter); + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { + struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; + if (q_vector->txr_count && !q_vector->rxr_count) + q_vector->eitr = (adapter->eitr_param >> 1); + else + /* rx only or mixed */ + q_vector->eitr = adapter->eitr_param; + IXGBE_WRITE_REG(hw, IXGBE_EITR(i), + EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); } return 0; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 0269115593e..ef965c99684 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -744,12 +744,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) r_idx + 1); } - /* if this is a tx only vector use half the irq (tx) rate */ + /* if this is a tx only vector halve the interrupt rate */ if (q_vector->txr_count && !q_vector->rxr_count) - q_vector->eitr = adapter->tx_eitr; + q_vector->eitr = (adapter->eitr_param >> 1); else - /* rx only or mixed */ - q_vector->eitr = adapter->rx_eitr; + /* rx only */ + q_vector->eitr = adapter->eitr_param; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); @@ -845,13 +845,13 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) for (i = 0; i < q_vector->txr_count; i++) { tx_ring = &(adapter->tx_ring[r_idx]); ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->tx_eitr, + q_vector->tx_itr, tx_ring->total_packets, tx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ - q_vector->tx_eitr = ((q_vector->tx_eitr > ret_itr) ? - q_vector->tx_eitr - 1 : ret_itr); + q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ? + q_vector->tx_itr - 1 : ret_itr); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, r_idx + 1); } @@ -860,18 +860,18 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) for (i = 0; i < q_vector->rxr_count; i++) { rx_ring = &(adapter->rx_ring[r_idx]); ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->rx_eitr, + q_vector->rx_itr, rx_ring->total_packets, rx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ - q_vector->rx_eitr = ((q_vector->rx_eitr > ret_itr) ? - q_vector->rx_eitr - 1 : ret_itr); + q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ? + q_vector->rx_itr - 1 : ret_itr); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, r_idx + 1); } - current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr); + current_itr = max(q_vector->rx_itr, q_vector->tx_itr); switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ @@ -970,16 +970,24 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_ring *rx_ring; int r_idx; + int i; r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring->total_bytes = 0; + rx_ring->total_packets = 0; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + if (!q_vector->rxr_count) return IRQ_HANDLED; + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); - rx_ring->total_bytes = 0; - rx_ring->total_packets = 0; netif_rx_schedule(adapter->netdev, &q_vector->napi); return IRQ_HANDLED; @@ -1020,7 +1028,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) /* If all Rx work done, exit the polling mode */ if (work_done < budget) { netif_rx_complete(adapter->netdev, napi); - if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS) + if (adapter->itr_setting & 3) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); @@ -1187,16 +1195,16 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) struct ixgbe_ring *rx_ring = &adapter->rx_ring[0]; struct ixgbe_ring *tx_ring = &adapter->tx_ring[0]; - q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr, - q_vector->tx_eitr, - tx_ring->total_packets, - tx_ring->total_bytes); - q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr, - q_vector->rx_eitr, - rx_ring->total_packets, - rx_ring->total_bytes); + q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr, + q_vector->tx_itr, + tx_ring->total_packets, + tx_ring->total_bytes); + q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr, + q_vector->rx_itr, + rx_ring->total_packets, + rx_ring->total_bytes); - current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr); + current_itr = max(q_vector->rx_itr, q_vector->tx_itr); switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ @@ -1371,7 +1379,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; IXGBE_WRITE_REG(hw, IXGBE_EITR(0), - EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr)); + EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param)); ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0); ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0); @@ -2209,7 +2217,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { netif_rx_complete(adapter->netdev, napi); - if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS) + if (adapter->itr_setting & 3) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable(adapter); @@ -2420,12 +2428,6 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter int err = 0; int vector, v_budget; - /* - * Set the default interrupt throttle rate. - */ - adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS); - adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS); - /* * It's easy to be greedy for MSI-X vectors, but it really * doesn't do us much good if we have a lot more vectors @@ -2567,10 +2569,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; - /* Enable Dynamic interrupt throttling by default */ - adapter->rx_eitr = 1; - adapter->tx_eitr = 1; - /* default flow control settings */ hw->fc.original_type = ixgbe_fc_none; hw->fc.type = ixgbe_fc_none; @@ -2591,6 +2589,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) return -EIO; } + /* enable itr by default in dynamic mode */ + adapter->itr_setting = 1; + adapter->eitr_param = 20000; + + /* set defaults for eitr in MegaBytes */ + adapter->eitr_low = 10; + adapter->eitr_high = 20; + + /* set default ring sizes */ + adapter->tx_ring_count = IXGBE_DEFAULT_TXD; + adapter->rx_ring_count = IXGBE_DEFAULT_RXD; + /* initialize eeprom parameters */ if (ixgbe_init_eeprom(hw)) { dev_err(&pdev->dev, "EEPROM initialization failed\n"); -- cgit v1.2.3 From ff819cfb5d95c4945811f5e33aa57274885c7527 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:58:29 -0700 Subject: ixgbe: fix bug with lots of tx queues when using more than 8 tx queues you can overrun the 8 bit v_idx field, so change it to 16 bits to represent the maximum number of queues (one for each bit) Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 5ba03845c3e..064af675a94 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -152,9 +152,9 @@ struct ixgbe_ring { struct net_lro_mgr lro_mgr; bool lro_used; struct ixgbe_queue_stats stats; - u8 v_idx; /* maps directly to the index for this ring in the hardware - * vector array, can also be used for finding the bit in EICR - * and friends that represents the vector for this ring */ + u16 v_idx; /* maps directly to the index for this ring in the hardware + * vector array, can also be used for finding the bit in EICR + * and friends that represents the vector for this ring */ u16 work_limit; /* max work per interrupt */ -- cgit v1.2.3 From 762f4c57105853d1cbad3b96ef18aa23beff3db2 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:58:43 -0700 Subject: ixgbe: recycle pages in packet split mode most of the time we only need 1500 bytes for a packet which means we don't need a whole 4k page for each packet. Share the allocation by using a reference count to the page and giving half to two receive descriptors. This can enable us to use packet split mode all the time due to the performance increase of allocating half the pages. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 1 + drivers/net/ixgbe/ixgbe_main.c | 49 ++++++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 064af675a94..71ddac6ac4f 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -114,6 +114,7 @@ struct ixgbe_rx_buffer { dma_addr_t dma; struct page *page; dma_addr_t page_dma; + unsigned int page_offset; }; struct ixgbe_queue_stats { diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ef965c99684..5858ab2b48f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -493,16 +493,24 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, while (cleaned_count--) { rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); - if (!bi->page && + if (!bi->page_dma && (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) { - bi->page = alloc_page(GFP_ATOMIC); if (!bi->page) { - adapter->alloc_rx_page_failed++; - goto no_buffers; + bi->page = alloc_page(GFP_ATOMIC); + if (!bi->page) { + adapter->alloc_rx_page_failed++; + goto no_buffers; + } + bi->page_offset = 0; + } else { + /* use a half page if we're re-using */ + bi->page_offset ^= (PAGE_SIZE / 2); } - bi->page_dma = pci_map_page(pdev, bi->page, 0, - PAGE_SIZE, - PCI_DMA_FROMDEVICE); + + bi->page_dma = pci_map_page(pdev, bi->page, + bi->page_offset, + (PAGE_SIZE / 2), + PCI_DMA_FROMDEVICE); } if (!bi->skb) { @@ -596,7 +604,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc)); len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> - IXGBE_RXDADV_HDRBUFLEN_SHIFT; + IXGBE_RXDADV_HDRBUFLEN_SHIFT; if (hdr_info & IXGBE_RXDADV_SPH) adapter->rx_hdr_split++; if (len > IXGBE_RX_HDR_SIZE) @@ -620,11 +628,18 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, if (upper_len) { pci_unmap_page(pdev, rx_buffer_info->page_dma, - PAGE_SIZE, PCI_DMA_FROMDEVICE); + PAGE_SIZE / 2, PCI_DMA_FROMDEVICE); rx_buffer_info->page_dma = 0; skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, - rx_buffer_info->page, 0, upper_len); - rx_buffer_info->page = NULL; + rx_buffer_info->page, + rx_buffer_info->page_offset, + upper_len); + + if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) || + (page_count(rx_buffer_info->page) != 1)) + rx_buffer_info->page = NULL; + else + get_page(rx_buffer_info->page); skb->len += upper_len; skb->data_len += upper_len; @@ -647,6 +662,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, rx_buffer_info->skb = next_buffer->skb; rx_buffer_info->dma = next_buffer->dma; next_buffer->skb = skb; + next_buffer->dma = 0; adapter->non_eop_descs++; goto next_desc; } @@ -1534,10 +1550,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) int rx_buf_len; /* Decide whether to use packet split mode or not */ - if (netdev->mtu > ETH_DATA_LEN) - adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; - else - adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { @@ -2018,12 +2031,12 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, } if (!rx_buffer_info->page) continue; - pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2, + PCI_DMA_FROMDEVICE); rx_buffer_info->page_dma = 0; - put_page(rx_buffer_info->page); rx_buffer_info->page = NULL; + rx_buffer_info->page_offset = 0; } size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count; -- cgit v1.2.3 From b95f5fcb8ba6073a652927d232a7a7cb552afe62 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:58:59 -0700 Subject: ixgbe: add device support for XF LR adapters Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_82598.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 1e014bcc72d..07261406cd6 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -196,6 +196,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + case IXGBE_DEV_ID_82598EB_XF_LR: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82598AT_DUAL_PORT: diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5858ab2b48f..3b0481a9979 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -74,6 +74,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR), + board_82598 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 196841b344d..7057aa3f393 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -40,6 +40,7 @@ #define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC +#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 /* General Registers */ #define IXGBE_CTRL 0x00000 -- cgit v1.2.3 From c431f97ef96026e6da7032a871a0789cf5a2eaea Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:59:16 -0700 Subject: ixgbe: fix ring reallocation in ethtool changing ring sizes in ethtool needs to be robust. If an allocation fails the driver must continue operation, with the previous settings. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 4 ++ drivers/net/ixgbe/ixgbe_ethtool.c | 95 +++++++++++++++++++-------------------- drivers/net/ixgbe/ixgbe_main.c | 10 ++--- 3 files changed, 56 insertions(+), 53 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 71ddac6ac4f..27db64f5c86 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -336,5 +336,9 @@ extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *rxdr); extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *txdr); +extern void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rxdr); +extern void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *txdr); #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index f18e3daaf4f..928b97cc170 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -654,12 +654,9 @@ static int ixgbe_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_tx_buffer *old_buf; - struct ixgbe_rx_buffer *old_rx_buf; - void *old_desc; + struct ixgbe_ring *temp_ring; int i, err; - u32 new_rx_count, new_tx_count, old_size; - dma_addr_t old_dma; + u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; @@ -678,6 +675,15 @@ static int ixgbe_set_ringparam(struct net_device *netdev, return 0; } + if (adapter->num_tx_queues > adapter->num_rx_queues) + temp_ring = vmalloc(adapter->num_tx_queues * + sizeof(struct ixgbe_ring)); + else + temp_ring = vmalloc(adapter->num_rx_queues * + sizeof(struct ixgbe_ring)); + if (!temp_ring) + return -ENOMEM; + while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) msleep(1); @@ -690,66 +696,59 @@ static int ixgbe_set_ringparam(struct net_device *netdev, * to the tx and rx ring structs. */ if (new_tx_count != adapter->tx_ring->count) { + memcpy(temp_ring, adapter->tx_ring, + adapter->num_tx_queues * sizeof(struct ixgbe_ring)); + for (i = 0; i < adapter->num_tx_queues; i++) { - /* Save existing descriptor ring */ - old_buf = adapter->tx_ring[i].tx_buffer_info; - old_desc = adapter->tx_ring[i].desc; - old_size = adapter->tx_ring[i].size; - old_dma = adapter->tx_ring[i].dma; - /* Try to allocate a new one */ - adapter->tx_ring[i].tx_buffer_info = NULL; - adapter->tx_ring[i].desc = NULL; - adapter->tx_ring[i].count = new_tx_count; - err = ixgbe_setup_tx_resources(adapter, - &adapter->tx_ring[i]); + temp_ring[i].count = new_tx_count; + err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]); if (err) { - /* Restore the old one so at least - the adapter still works, even if - we failed the request */ - adapter->tx_ring[i].tx_buffer_info = old_buf; - adapter->tx_ring[i].desc = old_desc; - adapter->tx_ring[i].size = old_size; - adapter->tx_ring[i].dma = old_dma; + while (i) { + i--; + ixgbe_free_tx_resources(adapter, &temp_ring[i]); + } goto err_setup; } - /* Free the old buffer manually */ - vfree(old_buf); - pci_free_consistent(adapter->pdev, old_size, - old_desc, old_dma); } + + for (i = 0; i < adapter->num_tx_queues; i++) + ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + + memcpy(adapter->tx_ring, temp_ring, + adapter->num_tx_queues * sizeof(struct ixgbe_ring)); + + adapter->tx_ring_count = new_tx_count; } if (new_rx_count != adapter->rx_ring->count) { - for (i = 0; i < adapter->num_rx_queues; i++) { + memcpy(temp_ring, adapter->rx_ring, + adapter->num_rx_queues * sizeof(struct ixgbe_ring)); - old_rx_buf = adapter->rx_ring[i].rx_buffer_info; - old_desc = adapter->rx_ring[i].desc; - old_size = adapter->rx_ring[i].size; - old_dma = adapter->rx_ring[i].dma; - - adapter->rx_ring[i].rx_buffer_info = NULL; - adapter->rx_ring[i].desc = NULL; - adapter->rx_ring[i].dma = 0; - adapter->rx_ring[i].count = new_rx_count; - err = ixgbe_setup_rx_resources(adapter, - &adapter->rx_ring[i]); + for (i = 0; i < adapter->num_rx_queues; i++) { + temp_ring[i].count = new_rx_count; + err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]); if (err) { - adapter->rx_ring[i].rx_buffer_info = old_rx_buf; - adapter->rx_ring[i].desc = old_desc; - adapter->rx_ring[i].size = old_size; - adapter->rx_ring[i].dma = old_dma; + while (i) { + i--; + ixgbe_free_rx_resources(adapter, &temp_ring[i]); + } goto err_setup; } - - vfree(old_rx_buf); - pci_free_consistent(adapter->pdev, old_size, old_desc, - old_dma); } + + for (i = 0; i < adapter->num_rx_queues; i++) + ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + + memcpy(adapter->rx_ring, temp_ring, + adapter->num_rx_queues * sizeof(struct ixgbe_ring)); + + adapter->rx_ring_count = new_rx_count; } + /* success! */ err = 0; err_setup: - if (netif_running(adapter->netdev)) + if (netif_running(netdev)) ixgbe_up(adapter); clear_bit(__IXGBE_RESETTING, &adapter->state); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3b0481a9979..cde5d5a5a9a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2731,8 +2731,8 @@ alloc_failed: * * Free all transmit software resources **/ -static void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) +void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring) { struct pci_dev *pdev = adapter->pdev; @@ -2761,14 +2761,14 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) } /** - * ixgbe_free_rx_resources - Free Rx Resources + * ixgbe_ree_rx_resources - Free Rx Resources * @adapter: board private structure * @rx_ring: ring to clean the resources from * * Free all receive software resources **/ -static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) +void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rx_ring) { struct pci_dev *pdev = adapter->pdev; -- cgit v1.2.3 From f6af803f0b7c8e46d72156b042e105b4d481b6c3 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:59:29 -0700 Subject: ixgbe: lro stats were not counted on first ethtool -Scall Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_ethtool.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 928b97cc170..4701abf3a59 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -774,6 +774,14 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, int j, k; int i; u64 aggregated = 0, flushed = 0, no_desc = 0; + for (i = 0; i < adapter->num_rx_queues; i++) { + aggregated += adapter->rx_ring[i].lro_mgr.stats.aggregated; + flushed += adapter->rx_ring[i].lro_mgr.stats.flushed; + no_desc += adapter->rx_ring[i].lro_mgr.stats.no_desc; + } + adapter->lro_aggregated = aggregated; + adapter->lro_flushed = flushed; + adapter->lro_no_desc = no_desc; ixgbe_update_stats(adapter); for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { @@ -788,17 +796,11 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, i += k; } for (j = 0; j < adapter->num_rx_queues; j++) { - aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated; - flushed += adapter->rx_ring[j].lro_mgr.stats.flushed; - no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc; queue_stat = (u64 *)&adapter->rx_ring[j].stats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; i += k; } - adapter->lro_aggregated = aggregated; - adapter->lro_flushed = flushed; - adapter->lro_no_desc = no_desc; } static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, -- cgit v1.2.3 From f08482766b7e3c0b2aaac4b68b30f33a91703aa3 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:59:42 -0700 Subject: ixgbe: add clean rx many routine in some configurations there can be more than one rx queue per vector in msi-x mode. Add functionality to be able to clean this without changing the performance path single-rx-queue cleanup. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 62 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cde5d5a5a9a..e18afa4e195 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1024,13 +1024,15 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) * @napi: napi struct with our devices info in it * @budget: amount of work driver is allowed to do this pass, in packets * + * This function is optimized for cleaning one queue only on a single + * q_vector!!! **/ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) { struct ixgbe_q_vector *q_vector = container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; - struct ixgbe_ring *rx_ring; + struct ixgbe_ring *rx_ring = NULL; int work_done = 0; long r_idx; @@ -1055,6 +1057,56 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) return work_done; } +/** + * ixgbe_clean_rxonly_many - msix (aka one shot) rx clean routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * This function will clean more than one rx queue associated with a + * q_vector. + **/ +static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) +{ + struct ixgbe_q_vector *q_vector = + container_of(napi, struct ixgbe_q_vector, napi); + struct ixgbe_adapter *adapter = q_vector->adapter; + struct net_device *netdev = adapter->netdev; + struct ixgbe_ring *rx_ring = NULL; + int work_done = 0, i; + long r_idx; + u16 enable_mask = 0; + + /* attempt to distribute budget to each queue fairly, but don't allow + * the budget to go below 1 because we'll exit polling */ + budget /= (q_vector->rxr_count ?: 1); + budget = max(budget, 1); + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + ixgbe_update_rx_dca(adapter, rx_ring); +#endif + ixgbe_clean_rx_irq(adapter, rx_ring, &work_done, budget); + enable_mask |= rx_ring->v_idx; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + /* If all Rx work done, exit the polling mode */ + if ((work_done == 0) || !netif_running(netdev)) { + netif_rx_complete(netdev, napi); + if (adapter->itr_setting & 3) + ixgbe_set_itr_msix(q_vector); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask); + return 0; + } + + return work_done; +} static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, int r_idx) { @@ -1813,10 +1865,16 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) q_vectors = 1; for (q_idx = 0; q_idx < q_vectors; q_idx++) { + struct napi_struct *napi; q_vector = &adapter->q_vector[q_idx]; if (!q_vector->rxr_count) continue; - napi_enable(&q_vector->napi); + napi = &q_vector->napi; + if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) && + (q_vector->rxr_count > 1)) + napi->poll = &ixgbe_clean_rxonly_many; + + napi_enable(napi); } } -- cgit v1.2.3 From c44ade9ef8ffd73cb8b026065ade78bc0040f0b4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 19:59:59 -0700 Subject: ixgbe: update to latest common code module This is a massive update that includes infrastructure for further patches where we will add support for more phy types and eeprom types. This code is shared as much as possible with other drivers, so the code may seem a little obtuse at times but wherever possible we keep to the linux style and methods. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 2 - drivers/net/ixgbe/ixgbe_82598.c | 600 +++++++++++++++++++++---- drivers/net/ixgbe/ixgbe_common.c | 914 +++++++++++++++++++++++++------------- drivers/net/ixgbe/ixgbe_common.h | 59 +-- drivers/net/ixgbe/ixgbe_ethtool.c | 20 +- drivers/net/ixgbe/ixgbe_main.c | 105 +++-- drivers/net/ixgbe/ixgbe_phy.c | 241 ++++------ drivers/net/ixgbe/ixgbe_phy.h | 60 ++- drivers/net/ixgbe/ixgbe_type.h | 513 +++++++++++++-------- 9 files changed, 1700 insertions(+), 814 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 27db64f5c86..2388af24672 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -41,8 +41,6 @@ #include #endif -#define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args) - #define PFX "ixgbe: " #define DPRINTK(nlevel, klevel, fmt, args...) \ ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 07261406cd6..a08a267f166 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -39,68 +39,80 @@ #define IXGBE_82598_MC_TBL_SIZE 128 #define IXGBE_82598_VFT_TBL_SIZE 128 -static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw); -static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, - bool *autoneg); -static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, - u32 *speed, bool *autoneg); +static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg); static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); +static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num); static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); -static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, - bool *link_up, - bool link_up_wait_to_complete); -static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed, - bool autoneg, - bool autoneg_wait_to_complete); +static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *link_up, bool link_up_wait_to_complete); +static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete); static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw); -static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, - bool autoneg, - bool autoneg_wait_to_complete); +static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete); static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); +static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, + u32 vind, bool vlan_on); +static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw); +static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index); +static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index); +static s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val); +static s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val); +static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); +static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw); - +/** + */ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) { - hw->mac.num_rx_queues = IXGBE_82598_MAX_RX_QUEUES; - hw->mac.num_tx_queues = IXGBE_82598_MAX_TX_QUEUES; - hw->mac.mcft_size = IXGBE_82598_MC_TBL_SIZE; - hw->mac.vft_size = IXGBE_82598_VFT_TBL_SIZE; - hw->mac.num_rar_entries = IXGBE_82598_RAR_ENTRIES; - - /* PHY ops are filled in by default properly for Fiber only */ - if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) { - hw->mac.ops.setup_link = &ixgbe_setup_copper_link_82598; - hw->mac.ops.setup_link_speed = &ixgbe_setup_copper_link_speed_82598; - hw->mac.ops.get_link_settings = - &ixgbe_get_copper_link_settings_82598; - - /* Call PHY identify routine to get the phy type */ - ixgbe_identify_phy(hw); - - switch (hw->phy.type) { - case ixgbe_phy_tn: - hw->phy.ops.setup_link = &ixgbe_setup_tnx_phy_link; - hw->phy.ops.check_link = &ixgbe_check_tnx_phy_link; - hw->phy.ops.setup_link_speed = - &ixgbe_setup_tnx_phy_link_speed; - break; - default: - break; - } + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_phy_info *phy = &hw->phy; + + /* Call PHY identify routine to get the phy type */ + ixgbe_identify_phy_generic(hw); + + /* PHY Init */ + switch (phy->type) { + default: + break; + } + + if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { + mac->ops.setup_link = &ixgbe_setup_copper_link_82598; + mac->ops.setup_link_speed = + &ixgbe_setup_copper_link_speed_82598; + mac->ops.get_link_capabilities = + &ixgbe_get_copper_link_capabilities_82598; } + mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; + mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; + mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; + mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; + return 0; } /** - * ixgbe_get_link_settings_82598 - Determines default link settings + * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * - * Determines the default link settings by reading the AUTOC register. + * Determines the link capabilities by reading the AUTOC register. **/ -static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, +static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, bool *autoneg) { s32 status = 0; @@ -150,15 +162,16 @@ static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, } /** - * ixgbe_get_copper_link_settings_82598 - Determines default link settings + * ixgbe_get_copper_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * - * Determines the default link settings by reading the AUTOC register. + * Determines the link capabilities by reading the AUTOC register. **/ -static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, - u32 *speed, bool *autoneg) +s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg) { s32 status = IXGBE_ERR_LINK_SETUP; u16 speed_ability; @@ -166,7 +179,7 @@ static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw, *speed = 0; *autoneg = true; - status = ixgbe_read_phy_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &speed_ability); @@ -199,9 +212,6 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598EB_XF_LR: media_type = ixgbe_media_type_fiber; break; - case IXGBE_DEV_ID_82598AT_DUAL_PORT: - media_type = ixgbe_media_type_copper; - break; default: media_type = ixgbe_media_type_unknown; break; @@ -210,6 +220,122 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) return media_type; } +/** + * ixgbe_setup_fc_82598 - Configure flow control settings + * @hw: pointer to hardware structure + * @packetbuf_num: packet buffer number (0-7) + * + * Configures the flow control settings based on SW configuration. This + * function is used for 802.3x flow control configuration only. + **/ +s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) +{ + u32 frctl_reg; + u32 rmcs_reg; + + if (packetbuf_num < 0 || packetbuf_num > 7) { + hw_dbg(hw, "Invalid packet buffer number [%d], expected range is" + " 0-7\n", packetbuf_num); + } + + frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); + frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); + + rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); + rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); + + /* + * 10 gig parts do not have a word in the EEPROM to determine the + * default flow control setting, so we explicitly set it to full. + */ + if (hw->fc.type == ixgbe_fc_default) + hw->fc.type = ixgbe_fc_full; + + /* + * We want to save off the original Flow Control configuration just in + * case we get disconnected and then reconnected into a different hub + * or switch with different Flow Control capabilities. + */ + hw->fc.original_type = hw->fc.type; + + /* + * The possible values of the "flow_control" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames but not + * send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but we do not + * support receiving pause frames) + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: Invalid. + */ + switch (hw->fc.type) { + case ixgbe_fc_none: + break; + case ixgbe_fc_rx_pause: + /* + * Rx Flow control is enabled, + * and Tx Flow control is disabled. + */ + frctl_reg |= IXGBE_FCTRL_RFCE; + break; + case ixgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is disabled, + * by a software over-ride. + */ + rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; + break; + case ixgbe_fc_full: + /* + * Flow control (both Rx and Tx) is enabled by a software + * over-ride. + */ + frctl_reg |= IXGBE_FCTRL_RFCE; + rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; + break; + default: + /* We should never get here. The value should be 0-3. */ + hw_dbg(hw, "Flow control param set incorrectly\n"); + break; + } + + /* Enable 802.3x based flow control settings. */ + IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); + IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); + + /* + * Check for invalid software configuration, zeros are completely + * invalid for all parameters used past this point, and if we enable + * flow control with zero water marks, we blast flow control packets. + */ + if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { + hw_dbg(hw, "Flow control structure initialized incorrectly\n"); + return IXGBE_ERR_INVALID_LINK_SETTINGS; + } + + /* + * We need to set up the Receive Threshold high and low water + * marks as well as (optionally) enabling the transmission of + * XON frames. + */ + if (hw->fc.type & ixgbe_fc_tx_pause) { + if (hw->fc.send_xon) { + IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), + (hw->fc.low_water | IXGBE_FCRTL_XONE)); + } else { + IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), + hw->fc.low_water); + } + IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), + (hw->fc.high_water)|IXGBE_FCRTH_FCEN); + } + + IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); + IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); + + return 0; +} + /** * ixgbe_setup_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure @@ -254,8 +380,7 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; - hw_dbg(hw, - "Autonegotiation did not complete.\n"); + hw_dbg(hw, "Autonegotiation did not complete.\n"); } } } @@ -265,8 +390,8 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) * case we get disconnected and then reconnected into a different hub * or switch with different Flow Control capabilities. */ - hw->fc.type = hw->fc.original_type; - ixgbe_setup_fc(hw, 0); + hw->fc.original_type = hw->fc.type; + ixgbe_setup_fc_82598(hw, 0); /* Add delay to filter out noises during initial link setup */ msleep(50); @@ -283,15 +408,13 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) * * Reads the links register to determine if link is up and the current speed **/ -static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, - bool *link_up, - bool link_up_wait_to_complete) +static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *link_up, bool link_up_wait_to_complete) { u32 links_reg; u32 i; links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); - if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { @@ -318,6 +441,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, return 0; } + /** * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed * @hw: pointer to hardware structure @@ -328,18 +452,18 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, - u32 speed, bool autoneg, + ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = 0; /* If speed is 10G, then check for CX4 or XAUI. */ if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && - (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) + (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) { hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; - else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) + } else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) { hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN; - else if (autoneg) { + } else if (autoneg) { /* BX mode - Autonegotiate 1G */ if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD)) hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN; @@ -358,7 +482,7 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, * ixgbe_hw This will write the AUTOC register based on the new * stored values */ - hw->mac.ops.setup_link(hw); + ixgbe_setup_mac_link_82598(hw); } return status; @@ -376,18 +500,17 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, **/ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) { - s32 status = 0; + s32 status; /* Restart autonegotiation on PHY */ - if (hw->phy.ops.setup_link) - status = hw->phy.ops.setup_link(hw); + status = hw->phy.ops.setup_link(hw); - /* Set MAC to KX/KX4 autoneg, which defaultis to Parallel detection */ + /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */ hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX); hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN; /* Set up MAC */ - hw->mac.ops.setup_link(hw); + ixgbe_setup_mac_link_82598(hw); return status; } @@ -401,14 +524,14 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) * * Sets the link speed in the AUTOC register in the MAC and restarts link. **/ -static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, +static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { - s32 status = 0; + s32 status; /* Setup the PHY according to input speed */ - if (hw->phy.ops.setup_link_speed) status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); @@ -417,7 +540,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN; /* Set up MAC */ - hw->mac.ops.setup_link(hw); + ixgbe_setup_mac_link_82598(hw); return status; } @@ -426,7 +549,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, u32 speed, * ixgbe_reset_hw_82598 - Performs hardware reset * @hw: pointer to hardware structure * - * Resets the hardware by reseting the transmit and receive units, masks and + * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/ @@ -440,35 +563,44 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) u8 analog_val; /* Call adapter stop to disable tx/rx and clear interrupts */ - ixgbe_stop_adapter(hw); + hw->mac.ops.stop_adapter(hw); /* - * Power up the Atlas TX lanes if they are currently powered down. - * Atlas TX lanes are powered down for MAC loopback tests, but + * Power up the Atlas Tx lanes if they are currently powered down. + * Atlas Tx lanes are powered down for MAC loopback tests, but * they are not automatically restored on reset. */ - ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { - /* Enable TX Atlas so packets can be transmitted again */ - ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); + /* Enable Tx Atlas so packets can be transmitted again */ + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, + &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; - ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, + analog_val); - ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, + &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; - ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, + analog_val); - ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, + &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; - ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, + analog_val); - ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); + hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, + &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; - ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); + hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, + analog_val); } /* Reset PHY */ - ixgbe_reset_phy(hw); + if (hw->phy.reset_disable == false) + hw->phy.ops.reset(hw); /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master @@ -527,23 +659,305 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) } /* Store the permanent mac address */ - ixgbe_get_mac_addr(hw, hw->mac.perm_addr); + hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); return status; } +/** + * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to associate with a VMDq index + * @vmdq: VMDq set index + **/ +s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 rar_high; + + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); + rar_high &= ~IXGBE_RAH_VIND_MASK; + rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); + IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); + return 0; +} + +/** + * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to associate with a VMDq index + * @vmdq: VMDq clear index (not used in 82598, but elsewhere) + **/ +static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 rar_high; + u32 rar_entries = hw->mac.num_rar_entries; + + if (rar < rar_entries) { + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); + if (rar_high & IXGBE_RAH_VIND_MASK) { + rar_high &= ~IXGBE_RAH_VIND_MASK; + IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); + } + } else { + hw_dbg(hw, "RAR index %d is out of range.\n", rar); + } + + return 0; +} + +/** + * ixgbe_set_vfta_82598 - Set VLAN filter table + * @hw: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFTA + * @vlan_on: boolean flag to turn on/off VLAN in VFTA + * + * Turn on/off specified VLAN in the VLAN filter table. + **/ +s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, + bool vlan_on) +{ + u32 regindex; + u32 bitindex; + u32 bits; + u32 vftabyte; + + if (vlan > 4095) + return IXGBE_ERR_PARAM; + + /* Determine 32-bit word position in array */ + regindex = (vlan >> 5) & 0x7F; /* upper seven bits */ + + /* Determine the location of the (VMD) queue index */ + vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ + bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ + + /* Set the nibble for VMD queue index */ + bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex)); + bits &= (~(0x0F << bitindex)); + bits |= (vind << bitindex); + IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits); + + /* Determine the location of the bit for this VLAN id */ + bitindex = vlan & 0x1F; /* lower five bits */ + + bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); + if (vlan_on) + /* Turn on this VLAN id */ + bits |= (1 << bitindex); + else + /* Turn off this VLAN id */ + bits &= ~(1 << bitindex); + IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); + + return 0; +} + +/** + * ixgbe_clear_vfta_82598 - Clear VLAN filter table + * @hw: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + **/ +static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) +{ + u32 offset; + u32 vlanbyte; + + for (offset = 0; offset < hw->mac.vft_size; offset++) + IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); + + for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) + for (offset = 0; offset < hw->mac.vft_size; offset++) + IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), + 0); + + return 0; +} + +/** + * ixgbe_blink_led_start_82598 - Blink LED based on index. + * @hw: pointer to hardware structure + * @index: led number to blink + **/ +static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index) +{ + ixgbe_link_speed speed = 0; + bool link_up = 0; + u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + + /* + * Link must be up to auto-blink the LEDs on the 82598EB MAC; + * force it if link is down. + */ + hw->mac.ops.check_link(hw, &speed, &link_up, false); + + if (!link_up) { + autoc_reg |= IXGBE_AUTOC_FLU; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + msleep(10); + } + + led_reg &= ~IXGBE_LED_MODE_MASK(index); + led_reg |= IXGBE_LED_BLINK(index); + IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); + IXGBE_WRITE_FLUSH(hw); + + return 0; +} + +/** + * ixgbe_blink_led_stop_82598 - Stop blinking LED based on index. + * @hw: pointer to hardware structure + * @index: led number to stop blinking + **/ +static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index) +{ + u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + + autoc_reg &= ~IXGBE_AUTOC_FLU; + autoc_reg |= IXGBE_AUTOC_AN_RESTART; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + + led_reg &= ~IXGBE_LED_MODE_MASK(index); + led_reg &= ~IXGBE_LED_BLINK(index); + led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); + IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); + IXGBE_WRITE_FLUSH(hw); + + return 0; +} + +/** + * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register + * @hw: pointer to hardware structure + * @reg: analog register to read + * @val: read value + * + * Performs read operation to Atlas analog register specified. + **/ +s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) +{ + u32 atlas_ctl; + + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, + IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); + IXGBE_WRITE_FLUSH(hw); + udelay(10); + atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); + *val = (u8)atlas_ctl; + + return 0; +} + +/** + * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register + * @hw: pointer to hardware structure + * @reg: atlas register to write + * @val: value to write + * + * Performs write operation to Atlas analog register specified. + **/ +s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) +{ + u32 atlas_ctl; + + atlas_ctl = (reg << 8) | val; + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); + IXGBE_WRITE_FLUSH(hw); + udelay(10); + + return 0; +} + +/** + * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type + * @hw: pointer to hardware structure + * + * Determines physical layer capabilities of the current configuration. + **/ +s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) +{ + s32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + + switch (hw->device_id) { + case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + break; + case IXGBE_DEV_ID_82598AF_DUAL_PORT: + case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + break; + case IXGBE_DEV_ID_82598EB_XF_LR: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + break; + + default: + physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + break; + } + + return physical_layer; +} + static struct ixgbe_mac_operations mac_ops_82598 = { - .reset = &ixgbe_reset_hw_82598, + .init_hw = &ixgbe_init_hw_generic, + .reset_hw = &ixgbe_reset_hw_82598, + .start_hw = &ixgbe_start_hw_generic, + .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, .get_media_type = &ixgbe_get_media_type_82598, + .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598, + .get_mac_addr = &ixgbe_get_mac_addr_generic, + .stop_adapter = &ixgbe_stop_adapter_generic, + .read_analog_reg8 = &ixgbe_read_analog_reg8_82598, + .write_analog_reg8 = &ixgbe_write_analog_reg8_82598, .setup_link = &ixgbe_setup_mac_link_82598, - .check_link = &ixgbe_check_mac_link_82598, .setup_link_speed = &ixgbe_setup_mac_link_speed_82598, - .get_link_settings = &ixgbe_get_link_settings_82598, + .check_link = &ixgbe_check_mac_link_82598, + .get_link_capabilities = &ixgbe_get_link_capabilities_82598, + .led_on = &ixgbe_led_on_generic, + .led_off = &ixgbe_led_off_generic, + .blink_led_start = &ixgbe_blink_led_start_82598, + .blink_led_stop = &ixgbe_blink_led_stop_82598, + .set_rar = &ixgbe_set_rar_generic, + .clear_rar = &ixgbe_clear_rar_generic, + .set_vmdq = &ixgbe_set_vmdq_82598, + .clear_vmdq = &ixgbe_clear_vmdq_82598, + .init_rx_addrs = &ixgbe_init_rx_addrs_generic, + .update_uc_addr_list = &ixgbe_update_uc_addr_list_generic, + .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, + .enable_mc = &ixgbe_enable_mc_generic, + .disable_mc = &ixgbe_disable_mc_generic, + .clear_vfta = &ixgbe_clear_vfta_82598, + .set_vfta = &ixgbe_set_vfta_82598, + .setup_fc = &ixgbe_setup_fc_82598, +}; + +static struct ixgbe_eeprom_operations eeprom_ops_82598 = { + .init_params = &ixgbe_init_eeprom_params_generic, + .read = &ixgbe_read_eeprom_generic, + .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, + .update_checksum = &ixgbe_update_eeprom_checksum_generic, +}; + +static struct ixgbe_phy_operations phy_ops_82598 = { + .identify = &ixgbe_identify_phy_generic, + /* .identify_sfp = &ixgbe_identify_sfp_module_generic, */ + .reset = &ixgbe_reset_phy_generic, + .read_reg = &ixgbe_read_phy_reg_generic, + .write_reg = &ixgbe_write_phy_reg_generic, + .setup_link = &ixgbe_setup_phy_link_generic, + .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, }; struct ixgbe_info ixgbe_82598_info = { .mac = ixgbe_mac_82598EB, .get_invariants = &ixgbe_get_invariants_82598, .mac_ops = &mac_ops_82598, + .eeprom_ops = &eeprom_ops_82598, + .phy_ops = &phy_ops_82598, }; diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index f5b2617111a..a11ff0db9d2 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -33,20 +33,28 @@ #include "ixgbe_common.h" #include "ixgbe_phy.h" -static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw); - static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw); +static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); +static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); +static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); +static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, + u16 count); +static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); +static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); +static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); +static void ixgbe_release_eeprom(struct ixgbe_hw *hw); static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); -static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw); -static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw); +static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); +static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); +static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); /** - * ixgbe_start_hw - Prepare hardware for TX/RX + * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears @@ -54,7 +62,7 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ -s32 ixgbe_start_hw(struct ixgbe_hw *hw) +s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) { u32 ctrl_ext; @@ -62,22 +70,22 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw) hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* Identify the PHY */ - ixgbe_identify_phy(hw); + hw->phy.ops.identify(hw); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ - ixgbe_init_rx_addrs(hw); + hw->mac.ops.init_rx_addrs(hw); /* Clear the VLAN filter table */ - ixgbe_clear_vfta(hw); + hw->mac.ops.clear_vfta(hw); /* Set up link */ hw->mac.ops.setup_link(hw); /* Clear statistics registers */ - ixgbe_clear_hw_cntrs(hw); + hw->mac.ops.clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); @@ -92,34 +100,34 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw) } /** - * ixgbe_init_hw - Generic hardware initialization + * ixgbe_init_hw_generic - Generic hardware initialization * @hw: pointer to hardware structure * - * Initialize the hardware by reseting the hardware, filling the bus info + * Initialize the hardware by resetting the hardware, filling the bus info * structure and media type, clears all on chip counters, initializes receive * address registers, multicast table, VLAN filter table, calls routine to set * up link and flow control settings, and leaves transmit and receive units * disabled and uninitialized **/ -s32 ixgbe_init_hw(struct ixgbe_hw *hw) +s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { /* Reset the hardware */ - hw->mac.ops.reset(hw); + hw->mac.ops.reset_hw(hw); /* Start the HW */ - ixgbe_start_hw(hw); + hw->mac.ops.start_hw(hw); return 0; } /** - * ixgbe_clear_hw_cntrs - Generic clear hardware counters + * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/ -static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw) +s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) { u16 i = 0; @@ -191,7 +199,36 @@ static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw) } /** - * ixgbe_get_mac_addr - Generic get MAC address + * ixgbe_read_pba_num_generic - Reads part number from EEPROM + * @hw: pointer to hardware structure + * @pba_num: stores the part number from the EEPROM + * + * Reads the part number from the EEPROM. + **/ +s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) +{ + s32 ret_val; + u16 data; + + ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); + if (ret_val) { + hw_dbg(hw, "NVM Read Error\n"); + return ret_val; + } + *pba_num = (u32)(data << 16); + + ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); + if (ret_val) { + hw_dbg(hw, "NVM Read Error\n"); + return ret_val; + } + *pba_num |= data; + + return 0; +} + +/** + * ixgbe_get_mac_addr_generic - Generic get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * @@ -199,7 +236,7 @@ static s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw) * A reset of the adapter must be performed prior to calling this function * in order for the MAC address to have been loaded from the EEPROM into RAR0 **/ -s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr) +s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) { u32 rar_high; u32 rar_low; @@ -217,30 +254,8 @@ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr) return 0; } -s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num) -{ - s32 ret_val; - u16 data; - - ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM0_PTR, &data); - if (ret_val) { - hw_dbg(hw, "NVM Read Error\n"); - return ret_val; - } - *part_num = (u32)(data << 16); - - ret_val = ixgbe_read_eeprom(hw, IXGBE_PBANUM1_PTR, &data); - if (ret_val) { - hw_dbg(hw, "NVM Read Error\n"); - return ret_val; - } - *part_num |= data; - - return 0; -} - /** - * ixgbe_stop_adapter - Generic stop TX/RX units + * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, @@ -248,7 +263,7 @@ s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num) * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ -s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) +s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) { u32 number_of_queues; u32 reg_val; @@ -264,6 +279,7 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); reg_val &= ~(IXGBE_RXCTRL_RXEN); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); + IXGBE_WRITE_FLUSH(hw); msleep(2); /* Clear interrupt mask to stop from interrupts being generated */ @@ -273,7 +289,7 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) IXGBE_READ_REG(hw, IXGBE_EICR); /* Disable the transmit unit. Each queue must be disabled. */ - number_of_queues = hw->mac.num_tx_queues; + number_of_queues = hw->mac.max_tx_queues; for (i = 0; i < number_of_queues; i++) { reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); if (reg_val & IXGBE_TXDCTL_ENABLE) { @@ -282,15 +298,22 @@ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) } } + /* + * Prevent the PCI-E bus from from hanging by disabling PCI-E master + * access and verify no pending requests + */ + if (ixgbe_disable_pcie_master(hw) != 0) + hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); + return 0; } /** - * ixgbe_led_on - Turns on the software controllable LEDs. + * ixgbe_led_on_generic - Turns on the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn on **/ -s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index) +s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); @@ -304,11 +327,11 @@ s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index) } /** - * ixgbe_led_off - Turns off the software controllable LEDs. + * ixgbe_led_off_generic - Turns off the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn off **/ -s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index) +s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); @@ -321,15 +344,14 @@ s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index) return 0; } - /** - * ixgbe_init_eeprom - Initialize EEPROM params + * ixgbe_init_eeprom_params_generic - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ -s32 ixgbe_init_eeprom(struct ixgbe_hw *hw) +s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; @@ -337,6 +359,9 @@ s32 ixgbe_init_eeprom(struct ixgbe_hw *hw) if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; + /* Set default semaphore delay to 10ms which is a well + * tested value */ + eeprom->semaphore_delay = 10; /* * Check for EEPROM present first. @@ -369,18 +394,85 @@ s32 ixgbe_init_eeprom(struct ixgbe_hw *hw) } /** - * ixgbe_read_eeprom - Read EEPROM word using EERD + * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be read + * @data: read 16 bit value from EEPROM + * + * Reads 16 bit value from EEPROM through bit-bang method + **/ +s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 *data) +{ + s32 status; + u16 word_in; + u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + + /* Prepare the EEPROM for reading */ + status = ixgbe_acquire_eeprom(hw); + + if (status == 0) { + if (ixgbe_ready_eeprom(hw) != 0) { + ixgbe_release_eeprom(hw); + status = IXGBE_ERR_EEPROM; + } + } + + if (status == 0) { + ixgbe_standby_eeprom(hw); + + /* + * Some SPI eeproms use the 8th address bit embedded in the + * opcode + */ + if ((hw->eeprom.address_bits == 8) && (offset >= 128)) + read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + ixgbe_shift_out_eeprom_bits(hw, read_opcode, + IXGBE_EEPROM_OPCODE_BITS); + ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), + hw->eeprom.address_bits); + + /* Read the data. */ + word_in = ixgbe_shift_in_eeprom_bits(hw, 16); + *data = (word_in >> 8) | (word_in << 8); + + /* End this read operation */ + ixgbe_release_eeprom(hw); + } + +out: + return status; +} + +/** + * ixgbe_read_eeprom_generic - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ -s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data) +s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { u32 eerd; s32 status; + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; + } + eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + IXGBE_EEPROM_READ_REG_START; @@ -393,6 +485,7 @@ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data) else hw_dbg(hw, "Eeprom read timed out\n"); +out: return status; } @@ -419,6 +512,58 @@ static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw) return status; } +/** + * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang + * @hw: pointer to hardware structure + * + * Prepares EEPROM for access using bit-bang method. This function should + * be called before issuing a command to the EEPROM. + **/ +static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) +{ + s32 status = 0; + u32 eec; + u32 i; + + if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0) + status = IXGBE_ERR_SWFW_SYNC; + + if (status == 0) { + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + /* Request EEPROM Access */ + eec |= IXGBE_EEC_REQ; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + + for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + if (eec & IXGBE_EEC_GNT) + break; + udelay(5); + } + + /* Release if grant not acquired */ + if (!(eec & IXGBE_EEC_GNT)) { + eec &= ~IXGBE_EEC_REQ; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + hw_dbg(hw, "Could not acquire EEPROM grant\n"); + + ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + status = IXGBE_ERR_EEPROM; + } + } + + /* Setup EEPROM for Read/Write */ + if (status == 0) { + /* Clear CS and SK */ + eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); + } + return status; +} + /** * ixgbe_get_eeprom_semaphore - Get hardware semaphore * @hw: pointer to hardware structure @@ -502,6 +647,217 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) IXGBE_WRITE_FLUSH(hw); } +/** + * ixgbe_ready_eeprom - Polls for EEPROM ready + * @hw: pointer to hardware structure + **/ +static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) +{ + s32 status = 0; + u16 i; + u8 spi_stat_reg; + + /* + * Read "Status Register" repeatedly until the LSB is cleared. The + * EEPROM will signal that the command has been completed by clearing + * bit 0 of the internal status register. If it's not cleared within + * 5 milliseconds, then error out. + */ + for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { + ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, + IXGBE_EEPROM_OPCODE_BITS); + spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); + if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) + break; + + udelay(5); + ixgbe_standby_eeprom(hw); + }; + + /* + * On some parts, SPI write time could vary from 0-20mSec on 3.3V + * devices (and only 0-5mSec on 5V devices) + */ + if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { + hw_dbg(hw, "SPI EEPROM Status error\n"); + status = IXGBE_ERR_EEPROM; + } + + return status; +} + +/** + * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state + * @hw: pointer to hardware structure + **/ +static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) +{ + u32 eec; + + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + /* Toggle CS to flush commands */ + eec |= IXGBE_EEC_CS; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); + eec &= ~IXGBE_EEC_CS; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); +} + +/** + * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. + * @hw: pointer to hardware structure + * @data: data to send to the EEPROM + * @count: number of bits to shift out + **/ +static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, + u16 count) +{ + u32 eec; + u32 mask; + u32 i; + + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + /* + * Mask is used to shift "count" bits of "data" out to the EEPROM + * one bit at a time. Determine the starting bit based on count + */ + mask = 0x01 << (count - 1); + + for (i = 0; i < count; i++) { + /* + * A "1" is shifted out to the EEPROM by setting bit "DI" to a + * "1", and then raising and then lowering the clock (the SK + * bit controls the clock input to the EEPROM). A "0" is + * shifted out to the EEPROM by setting "DI" to "0" and then + * raising and then lowering the clock. + */ + if (data & mask) + eec |= IXGBE_EEC_DI; + else + eec &= ~IXGBE_EEC_DI; + + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + + udelay(1); + + ixgbe_raise_eeprom_clk(hw, &eec); + ixgbe_lower_eeprom_clk(hw, &eec); + + /* + * Shift mask to signify next bit of data to shift in to the + * EEPROM + */ + mask = mask >> 1; + }; + + /* We leave the "DI" bit set to "0" when we leave this routine. */ + eec &= ~IXGBE_EEC_DI; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); +} + +/** + * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM + * @hw: pointer to hardware structure + **/ +static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) +{ + u32 eec; + u32 i; + u16 data = 0; + + /* + * In order to read a register from the EEPROM, we need to shift + * 'count' bits in from the EEPROM. Bits are "shifted in" by raising + * the clock input to the EEPROM (setting the SK bit), and then reading + * the value of the "DO" bit. During this "shifting in" process the + * "DI" bit should always be clear. + */ + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); + + for (i = 0; i < count; i++) { + data = data << 1; + ixgbe_raise_eeprom_clk(hw, &eec); + + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + eec &= ~(IXGBE_EEC_DI); + if (eec & IXGBE_EEC_DO) + data |= 1; + + ixgbe_lower_eeprom_clk(hw, &eec); + } + + return data; +} + +/** + * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. + * @hw: pointer to hardware structure + * @eec: EEC register's current value + **/ +static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) +{ + /* + * Raise the clock input to the EEPROM + * (setting the SK bit), then delay + */ + *eec = *eec | IXGBE_EEC_SK; + IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); +} + +/** + * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. + * @hw: pointer to hardware structure + * @eecd: EECD's current value + **/ +static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) +{ + /* + * Lower the clock input to the EEPROM (clearing the SK bit), then + * delay + */ + *eec = *eec & ~IXGBE_EEC_SK; + IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); +} + +/** + * ixgbe_release_eeprom - Release EEPROM, release semaphores + * @hw: pointer to hardware structure + **/ +static void ixgbe_release_eeprom(struct ixgbe_hw *hw) +{ + u32 eec; + + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + + eec |= IXGBE_EEC_CS; /* Pull CS high */ + eec &= ~IXGBE_EEC_SK; /* Lower SCK */ + + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + + udelay(1); + + /* Stop requesting EEPROM access */ + eec &= ~IXGBE_EEC_REQ; + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + + ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); +} + /** * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum * @hw: pointer to hardware structure @@ -517,7 +873,7 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { - if (ixgbe_read_eeprom(hw, i, &word) != 0) { + if (hw->eeprom.ops.read(hw, i, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } @@ -526,15 +882,15 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) /* Include all data from pointers except for the fw pointer */ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { - ixgbe_read_eeprom(hw, i, &pointer); + hw->eeprom.ops.read(hw, i, &pointer); /* Make sure the pointer seems valid */ if (pointer != 0xFFFF && pointer != 0) { - ixgbe_read_eeprom(hw, pointer, &length); + hw->eeprom.ops.read(hw, pointer, &length); if (length != 0xFFFF && length != 0) { for (j = pointer+1; j <= pointer+length; j++) { - ixgbe_read_eeprom(hw, j, &word); + hw->eeprom.ops.read(hw, j, &word); checksum += word; } } @@ -547,14 +903,15 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) } /** - * ixgbe_validate_eeprom_checksum - Validate EEPROM checksum + * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ -s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val) +s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, + u16 *checksum_val) { s32 status; u16 checksum; @@ -565,12 +922,12 @@ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val) * not continue or we could be in for a very long wait while every * EEPROM read fails */ - status = ixgbe_read_eeprom(hw, 0, &checksum); + status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == 0) { checksum = ixgbe_calc_eeprom_checksum(hw); - ixgbe_read_eeprom(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); + hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); /* * Verify read checksum from EEPROM is the same as @@ -589,6 +946,33 @@ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val) return status; } +/** + * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum + * @hw: pointer to hardware structure + **/ +s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) +{ + s32 status; + u16 checksum; + + /* + * Read the first word from the EEPROM. If this times out or fails, do + * not continue or we could be in for a very long wait while every + * EEPROM read fails + */ + status = hw->eeprom.ops.read(hw, 0, &checksum); + + if (status == 0) { + checksum = ixgbe_calc_eeprom_checksum(hw); + status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, + checksum); + } else { + hw_dbg(hw, "EEPROM read failed\n"); + } + + return status; +} + /** * ixgbe_validate_mac_addr - Validate MAC address * @mac_addr: pointer to MAC address. @@ -607,58 +991,137 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr) status = IXGBE_ERR_INVALID_MAC_ADDR; /* Reject the zero address */ else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && - mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) + mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) status = IXGBE_ERR_INVALID_MAC_ADDR; return status; } /** - * ixgbe_set_rar - Set RX address register + * ixgbe_set_rar_generic - Set Rx address register * @hw: pointer to hardware structure - * @addr: Address to put into receive address register * @index: Receive address register to write - * @vind: Vind to set RAR to + * @addr: Address to put into receive address register + * @vmdq: VMDq "set" or "pool" index * @enable_addr: set flag that address is active * * Puts an ethernet address into a receive address register. **/ -s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind, - u32 enable_addr) +s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr) { u32 rar_low, rar_high; + u32 rar_entries = hw->mac.num_rar_entries; + + /* setup VMDq pool selection before this RAR gets enabled */ + hw->mac.ops.set_vmdq(hw, index, vmdq); + /* Make sure we are using a valid rar index range */ + if (index < rar_entries) { /* - * HW expects these in little endian so we reverse the byte order from - * network order (big endian) to little endian + * HW expects these in little endian so we reverse the byte + * order from network order (big endian) to little endian */ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | - ((u32)addr[5] << 8) | - ((vind << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK)); + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); + rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + } else { + hw_dbg(hw, "RAR index %d is out of range.\n", index); + } + + return 0; +} + +/** + * ixgbe_clear_rar_generic - Remove Rx address register + * @hw: pointer to hardware structure + * @index: Receive address register to write + * + * Clears an ethernet address from a receive address register. + **/ +s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) +{ + u32 rar_high; + u32 rar_entries = hw->mac.num_rar_entries; + + /* Make sure we are using a valid rar index range */ + if (index < rar_entries) { + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); + + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + } else { + hw_dbg(hw, "RAR index %d is out of range.\n", index); + } + + /* clear VMDq pool/queue selection for this RAR */ + hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); return 0; } /** - * ixgbe_init_rx_addrs - Initializes receive address filters. + * ixgbe_enable_rar - Enable Rx address register + * @hw: pointer to hardware structure + * @index: index into the RAR table + * + * Enables the select receive address register. + **/ +static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index) +{ + u32 rar_high; + + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high |= IXGBE_RAH_AV; + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); +} + +/** + * ixgbe_disable_rar - Disable Rx address register + * @hw: pointer to hardware structure + * @index: index into the RAR table + * + * Disables the select receive address register. + **/ +static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index) +{ + u32 rar_high; + + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high &= (~IXGBE_RAH_AV); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); +} + +/** + * ixgbe_init_rx_addrs_generic - Initializes receive address filters. * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest - * of the receive addresss registers. Clears the multicast table. Assumes + * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ -static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) +s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) { u32 i; u32 rar_entries = hw->mac.num_rar_entries; @@ -671,7 +1134,7 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) if (ixgbe_validate_mac_addr(hw->mac.addr) == IXGBE_ERR_INVALID_MAC_ADDR) { /* Get the MAC address from the RAR0 for later reference */ - ixgbe_get_mac_addr(hw, hw->mac.addr); + hw->mac.ops.get_mac_addr(hw, hw->mac.addr); hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ", hw->mac.addr[0], hw->mac.addr[1], @@ -687,13 +1150,14 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], hw->mac.addr[4], hw->mac.addr[5]); - ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } + hw->addr_ctrl.overflow_promisc = 0; hw->addr_ctrl.rar_used_count = 1; /* Zero out the other receive addresses. */ - hw_dbg(hw, "Clearing RAR[1-15]\n"); + hw_dbg(hw, "Clearing RAR[1-%d]\n", rar_entries - 1); for (i = 1; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); @@ -708,6 +1172,9 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); + if (hw->mac.ops.init_uta_tables) + hw->mac.ops.init_uta_tables(hw); + return 0; } @@ -718,7 +1185,7 @@ static s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) * * Adds it to unused receive address register or goes into promiscuous mode. **/ -void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr) +static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { u32 rar_entries = hw->mac.num_rar_entries; u32 rar; @@ -733,7 +1200,7 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr) if (hw->addr_ctrl.rar_used_count < rar_entries) { rar = hw->addr_ctrl.rar_used_count - hw->addr_ctrl.mc_addr_in_rar_count; - ixgbe_set_rar(hw, rar, addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar); hw->addr_ctrl.rar_used_count++; } else { @@ -744,7 +1211,7 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr) } /** - * ixgbe_update_uc_addr_list - Updates MAC list of secondary addresses + * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses * @hw: pointer to hardware structure * @addr_list: the list of new addresses * @addr_count: number of addresses @@ -757,7 +1224,7 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr) * Drivers using secondary unicast addresses must set user_set_promisc when * manually putting the device into promiscuous mode. **/ -s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, +s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr next) { u8 *addr; @@ -787,7 +1254,7 @@ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, for (i = 0; i < addr_count; i++) { hw_dbg(hw, " Adding the secondary addresses:\n"); addr = next(hw, &addr_list, &vmdq); - ixgbe_add_uc_addr(hw, addr); + ixgbe_add_uc_addr(hw, addr, vmdq); } if (hw->addr_ctrl.overflow_promisc) { @@ -808,7 +1275,7 @@ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, } } - hw_dbg(hw, "ixgbe_update_uc_addr_list Complete\n"); + hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n"); return 0; } @@ -821,7 +1288,7 @@ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, * bit-vector to set in the multicast table. The hardware uses 12 bits, from * incoming rx multicast addresses, to determine the bit-vector to check in * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set - * by the MO field of the MCSTCTRL. The MO field is set during initalization + * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) @@ -907,10 +1374,10 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) * else put it in the MTA */ if (hw->addr_ctrl.rar_used_count < rar_entries) { + /* use RAR from the end up for multicast */ rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; - ixgbe_set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); - hw_dbg(hw, "Added a multicast address to RAR[%d]\n", - hw->addr_ctrl.rar_used_count); + hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); + hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar); hw->addr_ctrl.rar_used_count++; hw->addr_ctrl.mc_addr_in_rar_count++; } else { @@ -921,18 +1388,18 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) } /** - * ixgbe_update_mc_addr_list - Updates MAC list of multicast addresses + * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @next: iterator function to walk the multicast address list * * The given list replaces any existing list. Clears the MC addrs from receive - * address registers and the multicast table. Uses unsed receive address + * address registers and the multicast table. Uses unused receive address * registers for the first multicast addresses, and hashes the rest into the * multicast table. **/ -s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, +s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr next) { u32 i; @@ -949,7 +1416,8 @@ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, hw->addr_ctrl.mta_in_use = 0; /* Zero out the other receive addresses. */ - hw_dbg(hw, "Clearing RAR[1-15]\n"); + hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, + rar_entries - 1); for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); @@ -971,188 +1439,53 @@ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); - hw_dbg(hw, "ixgbe_update_mc_addr_list Complete\n"); + hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n"); return 0; } /** - * ixgbe_clear_vfta - Clear VLAN filter table + * ixgbe_enable_mc_generic - Enable multicast address in RAR * @hw: pointer to hardware structure * - * Clears the VLAN filer table, and the VMDq index associated with the filter + * Enables multicast address in RAR and the use of the multicast hash table. **/ -static s32 ixgbe_clear_vfta(struct ixgbe_hw *hw) +s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { - u32 offset; - u32 vlanbyte; + u32 i; + u32 rar_entries = hw->mac.num_rar_entries; + struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; - for (offset = 0; offset < hw->mac.vft_size; offset++) - IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); + if (a->mc_addr_in_rar_count > 0) + for (i = (rar_entries - a->mc_addr_in_rar_count); + i < rar_entries; i++) + ixgbe_enable_rar(hw, i); - for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) - for (offset = 0; offset < hw->mac.vft_size; offset++) - IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), - 0); + if (a->mta_in_use > 0) + IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | + hw->mac.mc_filter_type); return 0; } /** - * ixgbe_set_vfta - Set VLAN filter table + * ixgbe_disable_mc_generic - Disable multicast address in RAR * @hw: pointer to hardware structure - * @vlan: VLAN id to write to VLAN filter - * @vind: VMDq output index that maps queue to VLAN id in VFTA - * @vlan_on: boolean flag to turn on/off VLAN in VFTA * - * Turn on/off specified VLAN in the VLAN filter table. + * Disables multicast address in RAR and the use of the multicast hash table. **/ -s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, - bool vlan_on) +s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { - u32 VftaIndex; - u32 BitOffset; - u32 VftaReg; - u32 VftaByte; - - /* Determine 32-bit word position in array */ - VftaIndex = (vlan >> 5) & 0x7F; /* upper seven bits */ - - /* Determine the location of the (VMD) queue index */ - VftaByte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ - BitOffset = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ - - /* Set the nibble for VMD queue index */ - VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex)); - VftaReg &= (~(0x0F << BitOffset)); - VftaReg |= (vind << BitOffset); - IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(VftaByte, VftaIndex), VftaReg); - - /* Determine the location of the bit for this VLAN id */ - BitOffset = vlan & 0x1F; /* lower five bits */ - - VftaReg = IXGBE_READ_REG(hw, IXGBE_VFTA(VftaIndex)); - if (vlan_on) - /* Turn on this VLAN id */ - VftaReg |= (1 << BitOffset); - else - /* Turn off this VLAN id */ - VftaReg &= ~(1 << BitOffset); - IXGBE_WRITE_REG(hw, IXGBE_VFTA(VftaIndex), VftaReg); - - return 0; -} - -/** - * ixgbe_setup_fc - Configure flow control settings - * @hw: pointer to hardware structure - * @packetbuf_num: packet buffer number (0-7) - * - * Configures the flow control settings based on SW configuration. - * This function is used for 802.3x flow control configuration only. - **/ -s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) -{ - u32 frctl_reg; - u32 rmcs_reg; - - if (packetbuf_num < 0 || packetbuf_num > 7) - hw_dbg(hw, "Invalid packet buffer number [%d], expected range " - "is 0-7\n", packetbuf_num); - - frctl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); - frctl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); - - rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); - rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); - - /* - * 10 gig parts do not have a word in the EEPROM to determine the - * default flow control setting, so we explicitly set it to full. - */ - if (hw->fc.type == ixgbe_fc_default) - hw->fc.type = ixgbe_fc_full; - - /* - * We want to save off the original Flow Control configuration just in - * case we get disconnected and then reconnected into a different hub - * or switch with different Flow Control capabilities. - */ - hw->fc.type = hw->fc.original_type; - - /* - * The possible values of the "flow_control" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames but not - * send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do not - * support receiving pause frames) - * 3: Both Rx and TX flow control (symmetric) are enabled. - * other: Invalid. - */ - switch (hw->fc.type) { - case ixgbe_fc_none: - break; - case ixgbe_fc_rx_pause: - /* - * RX Flow control is enabled, - * and TX Flow control is disabled. - */ - frctl_reg |= IXGBE_FCTRL_RFCE; - break; - case ixgbe_fc_tx_pause: - /* - * TX Flow control is enabled, and RX Flow control is disabled, - * by a software over-ride. - */ - rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; - break; - case ixgbe_fc_full: - /* - * Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - frctl_reg |= IXGBE_FCTRL_RFCE; - rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; - break; - default: - /* We should never get here. The value should be 0-3. */ - hw_dbg(hw, "Flow control param set incorrectly\n"); - break; - } - - /* Enable 802.3x based flow control settings. */ - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, frctl_reg); - IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); - - /* - * Check for invalid software configuration, zeros are completely - * invalid for all parameters used past this point, and if we enable - * flow control with zero water marks, we blast flow control packets. - */ - if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { - hw_dbg(hw, "Flow control structure initialized incorrectly\n"); - return IXGBE_ERR_INVALID_LINK_SETTINGS; - } + u32 i; + u32 rar_entries = hw->mac.num_rar_entries; + struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - if (hw->fc.type & ixgbe_fc_tx_pause) { - if (hw->fc.send_xon) { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - (hw->fc.low_water | IXGBE_FCRTL_XONE)); - } else { - IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), - hw->fc.low_water); - } - IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), - (hw->fc.high_water)|IXGBE_FCRTH_FCEN); - } + if (a->mc_addr_in_rar_count > 0) + for (i = (rar_entries - a->mc_addr_in_rar_count); + i < rar_entries; i++) + ixgbe_disable_rar(hw, i); - IXGBE_WRITE_REG(hw, IXGBE_FCTTV(0), hw->fc.pause_time); - IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); + if (a->mta_in_use > 0) + IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); return 0; } @@ -1168,13 +1501,24 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) **/ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { - u32 ctrl; - s32 i; + u32 i; + u32 reg_val; + u32 number_of_queues; s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; - ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); - ctrl |= IXGBE_CTRL_GIO_DIS; - IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); + /* Disable the receive unit by stopping each queue */ + number_of_queues = hw->mac.max_rx_queues; + for (i = 0; i < number_of_queues; i++) { + reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); + if (reg_val & IXGBE_RXDCTL_ENABLE) { + reg_val &= ~IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); + } + } + + reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL); + reg_val |= IXGBE_CTRL_GIO_DIS; + IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { @@ -1189,11 +1533,11 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) /** - * ixgbe_acquire_swfw_sync - Aquire SWFW semaphore + * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure - * @mask: Mask to specify wich semaphore to acquire + * @mask: Mask to specify which semaphore to acquire * - * Aquires the SWFW semaphore throught the GSSR register for the specified + * Acquires the SWFW semaphore thought the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) @@ -1235,9 +1579,9 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) /** * ixgbe_release_swfw_sync - Release SWFW semaphore * @hw: pointer to hardware structure - * @mask: Mask to specify wich semaphore to release + * @mask: Mask to specify which semaphore to release * - * Releases the SWFW semaphore throught the GSSR register for the specified + * Releases the SWFW semaphore thought the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) @@ -1254,45 +1598,3 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) ixgbe_release_eeprom_semaphore(hw); } -/** - * ixgbe_read_analog_reg8 - Reads 8 bit Atlas analog register - * @hw: pointer to hardware structure - * @reg: analog register to read - * @val: read value - * - * Performs write operation to analog register specified. - **/ -s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val) -{ - u32 atlas_ctl; - - IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, - IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); - IXGBE_WRITE_FLUSH(hw); - udelay(10); - atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); - *val = (u8)atlas_ctl; - - return 0; -} - -/** - * ixgbe_write_analog_reg8 - Writes 8 bit Atlas analog register - * @hw: pointer to hardware structure - * @reg: atlas register to write - * @val: value to write - * - * Performs write operation to Atlas analog register specified. - **/ -s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val) -{ - u32 atlas_ctl; - - atlas_ctl = (reg << 8) | val; - IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); - IXGBE_WRITE_FLUSH(hw); - udelay(10); - - return 0; -} - diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index c75ecba9ccd..13ed8d2ff4a 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -31,36 +31,45 @@ #include "ixgbe_type.h" -s32 ixgbe_init_hw(struct ixgbe_hw *hw); -s32 ixgbe_start_hw(struct ixgbe_hw *hw); -s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr); -s32 ixgbe_stop_adapter(struct ixgbe_hw *hw); -s32 ixgbe_read_part_num(struct ixgbe_hw *hw, u32 *part_num); - -s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index); -s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index); - -s32 ixgbe_init_eeprom(struct ixgbe_hw *hw); -s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data); -s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val); - -s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind, - u32 enable_addr); -s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count, ixgbe_mc_addr_itr next); -s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *uc_addr_list, - u32 mc_addr_count, ixgbe_mc_addr_itr next); -s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); -s32 ixgbe_validate_mac_addr(u8 *mac_addr); - -s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packtetbuf_num); +s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); +s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); +s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); +s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw); +s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num); +s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr); +s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw); +s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw); + +s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); + +s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); +s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, + u16 *data); +s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, + u16 *checksum_val); +s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); + +s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, + u32 enable_addr); +s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw); +s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, + u32 mc_addr_count, + ixgbe_mc_addr_itr func); +s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, + u32 addr_count, ixgbe_mc_addr_itr func); +s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); +s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); +s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); -s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val); -s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val); +s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val); +s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val); #define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg))) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 4701abf3a59..ff4fac34a17 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -128,9 +128,10 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; + ecmd->autoneg = AUTONEG_DISABLE; } - adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up, false); + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) { ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? SPEED_10000 : SPEED_1000; @@ -327,7 +328,7 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[25] = IXGBE_READ_REG(hw, IXGBE_IVAR(0)); regs_buff[26] = IXGBE_READ_REG(hw, IXGBE_MSIXT); regs_buff[27] = IXGBE_READ_REG(hw, IXGBE_MSIXPBA); - regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL); + regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL(0)); regs_buff[29] = IXGBE_READ_REG(hw, IXGBE_GPIE); /* Flow Control */ @@ -373,7 +374,7 @@ static void ixgbe_get_regs(struct net_device *netdev, regs_buff[482 + i] = IXGBE_READ_REG(hw, IXGBE_RAL(i)); for (i = 0; i < 16; i++) regs_buff[498 + i] = IXGBE_READ_REG(hw, IXGBE_RAH(i)); - regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE); + regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)); regs_buff[515] = IXGBE_READ_REG(hw, IXGBE_FCTRL); regs_buff[516] = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); regs_buff[517] = IXGBE_READ_REG(hw, IXGBE_MCSTCTRL); @@ -605,8 +606,8 @@ static int ixgbe_get_eeprom(struct net_device *netdev, return -ENOMEM; for (i = 0; i < eeprom_len; i++) { - if ((ret_val = ixgbe_read_eeprom(hw, first_word + i, - &eeprom_buff[i]))) + if ((ret_val = hw->eeprom.ops.read(hw, first_word + i, + &eeprom_buff[i]))) break; } @@ -807,7 +808,7 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - u8 *p = data; + char *p = (char *)data; int i; switch (stringset) { @@ -857,16 +858,17 @@ static int ixgbe_nway_reset(struct net_device *netdev) static int ixgbe_phys_id(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - u32 led_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_LEDCTL); + struct ixgbe_hw *hw = &adapter->hw; + u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); u32 i; if (!data || data > 300) data = 300; for (i = 0; i < (data * 1000); i += 400) { - ixgbe_led_on(&adapter->hw, IXGBE_LED_ON); + hw->mac.ops.led_on(hw, IXGBE_LED_ON); msleep_interruptible(200); - ixgbe_led_off(&adapter->hw, IXGBE_LED_ON); + hw->mac.ops.led_off(hw, IXGBE_LED_ON); msleep_interruptible(200); } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e18afa4e195..df093ec830d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1749,14 +1749,16 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; /* add VID to filter table */ - ixgbe_set_vfta(&adapter->hw, vid, 0, true); + hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true); } static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_disable(adapter); @@ -1767,7 +1769,7 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ixgbe_irq_enable(adapter); /* remove VID from filter table */ - ixgbe_set_vfta(&adapter->hw, vid, 0, false); + hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false); } static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) @@ -1843,15 +1845,15 @@ static void ixgbe_set_rx_mode(struct net_device *netdev) addr_count = netdev->uc_count; if (addr_count) addr_list = netdev->uc_list->dmi_addr; - ixgbe_update_uc_addr_list(hw, addr_list, addr_count, - ixgbe_addr_list_itr); + hw->mac.ops.update_uc_addr_list(hw, addr_list, addr_count, + ixgbe_addr_list_itr); /* reprogram multicast list */ addr_count = netdev->mc_count; if (addr_count) addr_list = netdev->mc_list->dmi_addr; - ixgbe_update_mc_addr_list(hw, addr_list, addr_count, - ixgbe_addr_list_itr); + hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count, + ixgbe_addr_list_itr); } static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) @@ -2016,11 +2018,12 @@ int ixgbe_up(struct ixgbe_adapter *adapter) void ixgbe_reset(struct ixgbe_adapter *adapter) { - if (ixgbe_init_hw(&adapter->hw)) - DPRINTK(PROBE, ERR, "Hardware Error\n"); + struct ixgbe_hw *hw = &adapter->hw; + if (hw->mac.ops.init_hw(hw)) + dev_err(&adapter->pdev->dev, "Hardware Error\n"); /* reprogram the RAR[0] in case user changed it. */ - ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } @@ -2637,6 +2640,14 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) struct pci_dev *pdev = adapter->pdev; unsigned int rss; + /* PCI config space info */ + + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + hw->revision_id = pdev->revision; + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_device_id = pdev->subsystem_device; + /* Set capability flags */ rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus()); adapter->ring_feature[RING_F_RSS].indices = rss; @@ -2652,15 +2663,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* select 10G link by default */ hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; - if (hw->mac.ops.reset(hw)) { - dev_err(&pdev->dev, "HW Init failed\n"); - return -EIO; - } - if (hw->mac.ops.setup_link_speed(hw, IXGBE_LINK_SPEED_10GB_FULL, true, - false)) { - dev_err(&pdev->dev, "Link Speed setup failed\n"); - return -EIO; - } /* enable itr by default in dynamic mode */ adapter->itr_setting = 1; @@ -2675,7 +2677,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->rx_ring_count = IXGBE_DEFAULT_RXD; /* initialize eeprom parameters */ - if (ixgbe_init_eeprom(hw)) { + if (ixgbe_init_eeprom_params_generic(hw)) { dev_err(&pdev->dev, "EEPROM initialization failed\n"); return -EIO; } @@ -3622,7 +3624,7 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p) memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); - ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); + adapter->hw.mac.ops.set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); return 0; } @@ -3645,6 +3647,22 @@ static void ixgbe_netpoll(struct net_device *netdev) } #endif +/** + * ixgbe_link_config - set up initial link with default speed and duplex + * @hw: pointer to private hardware struct + * + * Returns 0 on success, negative on failure + **/ +static int ixgbe_link_config(struct ixgbe_hw *hw) +{ + u32 autoneg = IXGBE_LINK_SPEED_10GB_FULL; + + /* must always autoneg for both 1G and 10G link */ + hw->mac.autoneg = true; + + return hw->mac.ops.setup_link_speed(hw, autoneg, true, true); +} + /** * ixgbe_napi_add_all - prep napi structs for use * @adapter: private struct @@ -3691,7 +3709,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, static int cards_found; int i, err, pci_using_dac; u16 link_status, link_speed, link_width; - u32 part_num; + u32 part_num, eec; err = pci_enable_device(pdev); if (err) @@ -3705,8 +3723,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) { err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (err) { - dev_err(&pdev->dev, "No usable DMA " - "configuration, aborting\n"); + dev_err(&pdev->dev, "No usable DMA configuration, " + "aborting\n"); goto err_dma; } } @@ -3772,17 +3790,21 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, adapter->bd_number = cards_found; - /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->revision_id = pdev->revision; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_device_id = pdev->subsystem_device; - /* Setup hw api */ memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops)); hw->mac.type = ii->mac; + /* EEPROM */ + memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops)); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); + /* If EEPROM is valid (bit 8 = 1), use default otherwise use bit bang */ + if (!(eec & (1 << 8))) + hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic; + + /* PHY */ + memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops)); + /* phy->sfp_type = ixgbe_sfp_type_unknown; */ + err = ii->get_invariants(hw); if (err) goto err_hw_init; @@ -3792,6 +3814,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_sw_init; + /* reset_hw fills in the perm_addr as well */ + err = hw->mac.ops.reset_hw(hw); + if (err) { + dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); + goto err_sw_init; + } + netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | @@ -3812,7 +3841,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_HIGHDMA; /* make sure the EEPROM is good */ - if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) { + if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) { dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; @@ -3821,7 +3850,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len); memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len); - if (ixgbe_validate_mac_addr(netdev->dev_addr)) { + if (ixgbe_validate_mac_addr(netdev->perm_addr)) { + dev_err(&pdev->dev, "invalid MAC address\n"); err = -EIO; goto err_eeprom; } @@ -3853,7 +3883,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, "Unknown"), netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - ixgbe_read_part_num(hw, &part_num); + ixgbe_read_pba_num_generic(hw, &part_num); dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n", hw->mac.type, hw->phy.type, (part_num >> 8), (part_num & 0xff)); @@ -3867,7 +3897,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } /* reset the hardware with the new settings */ - ixgbe_start_hw(hw); + hw->mac.ops.start_hw(hw); + + /* link_config depends on start_hw being called at least once */ + err = ixgbe_link_config(hw); + if (err) { + dev_err(&pdev->dev, "setup_link_speed FAILED %d\n", err); + goto err_register; + } netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 8002931ae82..63a70176241 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -33,32 +33,36 @@ #include "ixgbe_common.h" #include "ixgbe_phy.h" +static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); -static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); -static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, - u32 device_type, u16 phy_data); /** - * ixgbe_identify_phy - Get physical layer module + * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ -s32 ixgbe_identify_phy(struct ixgbe_hw *hw) +s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 phy_addr; - for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { - if (ixgbe_validate_phy_addr(hw, phy_addr)) { - hw->phy.addr = phy_addr; - ixgbe_get_phy_id(hw); - hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); - status = 0; - break; + if (hw->phy.type == ixgbe_phy_unknown) { + for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { + if (ixgbe_validate_phy_addr(hw, phy_addr)) { + hw->phy.addr = phy_addr; + ixgbe_get_phy_id(hw); + hw->phy.type = + ixgbe_get_phy_type_from_id(hw->phy.id); + status = 0; + break; + } } + } else { + status = 0; } + return status; } @@ -73,10 +77,8 @@ static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) bool valid = false; hw->phy.addr = phy_addr; - ixgbe_read_phy_reg(hw, - IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, - &phy_id); + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); if (phy_id != 0xFFFF && phy_id != 0x0) valid = true; @@ -95,21 +97,18 @@ static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) u16 phy_id_high = 0; u16 phy_id_low = 0; - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, - &phy_id_high); + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + &phy_id_high); if (status == 0) { hw->phy.id = (u32)(phy_id_high << 16); - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_PHY_ID_LOW, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, - &phy_id_low); + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + &phy_id_low); hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK); hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); } - return status; } @@ -123,9 +122,6 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) enum ixgbe_phy_type phy_type; switch (phy_id) { - case TN1010_PHY_ID: - phy_type = ixgbe_phy_tn; - break; case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; @@ -138,32 +134,31 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) } /** - * ixgbe_reset_phy - Performs a PHY reset + * ixgbe_reset_phy_generic - Performs a PHY reset * @hw: pointer to hardware structure **/ -s32 ixgbe_reset_phy(struct ixgbe_hw *hw) +s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) { /* * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY */ - return ixgbe_write_phy_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, - IXGBE_MDIO_PHY_XS_RESET); + return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, + IXGBE_MDIO_PHY_XS_DEV_TYPE, + IXGBE_MDIO_PHY_XS_RESET); } /** - * ixgbe_read_phy_reg - Reads a value from a specified PHY register + * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register **/ -s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, - u32 device_type, u16 *phy_data) +s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data) { u32 command; u32 i; - u32 timeout = 10; u32 data; s32 status = 0; u16 gssr; @@ -179,9 +174,9 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, if (status == 0) { /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | - (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | - (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); + (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -190,7 +185,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * The MDI Command bit will clear when the operation is * complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -210,9 +205,9 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | - (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | - (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); + (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -221,7 +216,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * completed. The MDI Command bit will clear when the * operation is complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); @@ -231,8 +226,7 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { - hw_dbg(hw, - "PHY read command didn't complete\n"); + hw_dbg(hw, "PHY read command didn't complete\n"); status = IXGBE_ERR_PHY; } else { /* @@ -247,22 +241,22 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, ixgbe_release_swfw_sync(hw, gssr); } + return status; } /** - * ixgbe_write_phy_reg - Writes a value to specified PHY register + * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ -static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, - u32 device_type, u16 phy_data) +s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data) { u32 command; u32 i; - u32 timeout = 10; s32 status = 0; u16 gssr; @@ -280,9 +274,9 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | - (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | - (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); + (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -291,19 +285,19 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * The MDI Command bit will clear when the operation is * complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); - if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) { - hw_dbg(hw, "PHY address cmd didn't complete\n"); + if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; - } } - if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) + if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { + hw_dbg(hw, "PHY address cmd didn't complete\n"); status = IXGBE_ERR_PHY; + } if (status == 0) { /* @@ -311,9 +305,9 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | - (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | - (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); + (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -322,20 +316,19 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, * completed. The MDI Command bit will clear when the * operation is complete */ - for (i = 0; i < timeout; i++) { + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); - if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) { - hw_dbg(hw, "PHY write command did not " - "complete.\n"); + if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; - } } - if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) + if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { + hw_dbg(hw, "PHY address cmd didn't complete\n"); status = IXGBE_ERR_PHY; + } } ixgbe_release_swfw_sync(hw, gssr); @@ -345,67 +338,54 @@ static s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, } /** - * ixgbe_setup_tnx_phy_link - Set and restart autoneg + * ixgbe_setup_phy_link_generic - Set and restart autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ -s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw) +s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_NOT_IMPLEMENTED; u32 time_out; u32 max_time_out = 10; - u16 autoneg_speed_selection_register = 0x10; - u16 autoneg_restart_mask = 0x0200; - u16 autoneg_complete_mask = 0x0020; - u16 autoneg_reg = 0; + u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; /* * Set advertisement settings in PHY based on autoneg_advertised * settings. If autoneg_advertised = 0, then advertise default values - * txn devices cannot be "forced" to a autoneg 10G and fail. But can + * tnx devices cannot be "forced" to a autoneg 10G and fail. But can * for a 1G. */ - ixgbe_read_phy_reg(hw, - autoneg_speed_selection_register, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); + hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ else autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ - ixgbe_write_phy_reg(hw, - autoneg_speed_selection_register, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - autoneg_reg); - + hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); /* Restart PHY autonegotiation and wait for completion */ - ixgbe_read_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); + hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); - autoneg_reg |= autoneg_restart_mask; + autoneg_reg |= IXGBE_MII_RESTART; - ixgbe_write_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - autoneg_reg); + hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); /* Wait for autonegotiation to finish */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); /* Restart PHY autonegotiation and wait for completion */ - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, - &autoneg_reg); + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); - autoneg_reg &= autoneg_complete_mask; - if (autoneg_reg == autoneg_complete_mask) { + autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; + if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) { status = 0; break; } @@ -418,64 +398,17 @@ s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw) } /** - * ixgbe_check_tnx_phy_link - Determine link and speed status - * @hw: pointer to hardware structure - * - * Reads the VS1 register to determine if link is up and the current speed for - * the PHY. - **/ -s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, u32 *speed, - bool *link_up) -{ - s32 status = 0; - u32 time_out; - u32 max_time_out = 10; - u16 phy_link = 0; - u16 phy_speed = 0; - u16 phy_data = 0; - - /* Initialize speed and link to default case */ - *link_up = false; - *speed = IXGBE_LINK_SPEED_10GB_FULL; - - /* - * Check current speed and link status of the PHY register. - * This is a vendor specific register and may have to - * be changed for other copper PHYs. - */ - for (time_out = 0; time_out < max_time_out; time_out++) { - udelay(10); - if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { - *link_up = true; - if (phy_speed == - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) - *speed = IXGBE_LINK_SPEED_1GB_FULL; - break; - } else { - status = ixgbe_read_phy_reg(hw, - IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - &phy_data); - phy_link = phy_data & - IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; - phy_speed = phy_data & - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; - } - } - - return status; -} - -/** - * ixgbe_setup_tnx_phy_link_speed - Sets the auto advertised capabilities + * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled **/ -s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, - bool autoneg, - bool autoneg_wait_to_complete) +s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete) { + /* * Clear autoneg_advertised and set new values based on input link * speed. @@ -484,11 +417,13 @@ s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; /* Setup link based on the new speed settings */ - ixgbe_setup_tnx_phy_link(hw); + hw->phy.ops.setup_link(hw); return 0; } + diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index aa3ea72e678..f88c9131a01 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -30,20 +30,52 @@ #define _IXGBE_PHY_H_ #include "ixgbe_type.h" +#define IXGBE_I2C_EEPROM_DEV_ADDR 0xA0 -s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw); -s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, u32 *speed, bool *link_up); -s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, u32 speed, bool autoneg, - bool autoneg_wait_to_complete); -s32 ixgbe_identify_phy(struct ixgbe_hw *hw); -s32 ixgbe_reset_phy(struct ixgbe_hw *hw); -s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, - u32 device_type, u16 *phy_data); - -/* PHY specific */ -s32 ixgbe_setup_tnx_phy_link(struct ixgbe_hw *hw); -s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, u32 *speed, bool *link_up); -s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, bool autoneg, - bool autoneg_wait_to_complete); +/* EEPROM byte offsets */ +#define IXGBE_SFF_IDENTIFIER 0x0 +#define IXGBE_SFF_IDENTIFIER_SFP 0x3 +#define IXGBE_SFF_VENDOR_OUI_BYTE0 0x25 +#define IXGBE_SFF_VENDOR_OUI_BYTE1 0x26 +#define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27 +#define IXGBE_SFF_1GBE_COMP_CODES 0x6 +#define IXGBE_SFF_10GBE_COMP_CODES 0x3 +#define IXGBE_SFF_TRANSMISSION_MEDIA 0x9 + +/* Bitmasks */ +#define IXGBE_SFF_TWIN_AX_CAPABLE 0x80 +#define IXGBE_SFF_1GBASESX_CAPABLE 0x1 +#define IXGBE_SFF_10GBASESR_CAPABLE 0x10 +#define IXGBE_SFF_10GBASELR_CAPABLE 0x20 +#define IXGBE_I2C_EEPROM_READ_MASK 0x100 +#define IXGBE_I2C_EEPROM_STATUS_MASK 0x3 +#define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0 +#define IXGBE_I2C_EEPROM_STATUS_PASS 0x1 +#define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 +#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 + +/* Bit-shift macros */ +#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 12 +#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 8 +#define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 4 + +/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */ +#define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600 +#define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500 +#define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00 + + +s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); +s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw); +s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw); +s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data); +s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 phy_data); +s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw); +s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete); #endif /* _IXGBE_PHY_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 7057aa3f393..c76e30b94d8 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -37,7 +37,6 @@ /* Device IDs */ #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 -#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 @@ -71,11 +70,11 @@ #define IXGBE_EIMC 0x00888 #define IXGBE_EIAC 0x00810 #define IXGBE_EIAM 0x00890 -#define IXGBE_EITR(_i) (0x00820 + ((_i) * 4)) /* 0x820-0x86c */ -#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */ +#define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : (0x012300 + ((_i) * 4))) +#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */ #define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */ #define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */ -#define IXGBE_PBACL 0x11068 +#define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4))) #define IXGBE_GPIE 0x00898 /* Flow Control Registers */ @@ -87,20 +86,33 @@ #define IXGBE_TFCS 0x0CE00 /* Receive DMA Registers */ -#define IXGBE_RDBAL(_i) (0x01000 + ((_i) * 0x40)) /* 64 of each (0-63)*/ -#define IXGBE_RDBAH(_i) (0x01004 + ((_i) * 0x40)) -#define IXGBE_RDLEN(_i) (0x01008 + ((_i) * 0x40)) -#define IXGBE_RDH(_i) (0x01010 + ((_i) * 0x40)) -#define IXGBE_RDT(_i) (0x01018 + ((_i) * 0x40)) -#define IXGBE_RXDCTL(_i) (0x01028 + ((_i) * 0x40)) -#define IXGBE_RSCCTL(_i) (0x0102C + ((_i) * 0x40)) -#define IXGBE_SRRCTL(_i) (0x02100 + ((_i) * 4)) - /* array of 16 (0x02100-0x0213C) */ -#define IXGBE_DCA_RXCTRL(_i) (0x02200 + ((_i) * 4)) - /* array of 16 (0x02200-0x0223C) */ -#define IXGBE_RDRXCTL 0x02F00 +#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : (0x0D000 + ((_i - 64) * 0x40))) +#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : (0x0D004 + ((_i - 64) * 0x40))) +#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : (0x0D008 + ((_i - 64) * 0x40))) +#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : (0x0D010 + ((_i - 64) * 0x40))) +#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : (0x0D018 + ((_i - 64) * 0x40))) +#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : (0x0D028 + ((_i - 64) * 0x40))) +/* + * Split and Replication Receive Control Registers + * 00-15 : 0x02100 + n*4 + * 16-64 : 0x01014 + n*0x40 + * 64-127: 0x0D014 + (n-64)*0x40 + */ +#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \ + (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \ + (0x0D014 + ((_i - 64) * 0x40)))) +/* + * Rx DCA Control Register: + * 00-15 : 0x02200 + n*4 + * 16-64 : 0x0100C + n*0x40 + * 64-127: 0x0D00C + (n-64)*0x40 + */ +#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \ + (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \ + (0x0D00C + ((_i - 64) * 0x40)))) +#define IXGBE_RDRXCTL 0x02F00 #define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4)) - /* 8 of these 0x03C00 - 0x03C1C */ + /* 8 of these 0x03C00 - 0x03C1C */ #define IXGBE_RXCTRL 0x03000 #define IXGBE_DROPEN 0x03D04 #define IXGBE_RXPBSIZE_SHIFT 10 @@ -108,29 +120,32 @@ /* Receive Registers */ #define IXGBE_RXCSUM 0x05000 #define IXGBE_RFCTL 0x05008 +#define IXGBE_DRECCCTL 0x02F08 +#define IXGBE_DRECCCTL_DISABLE 0 +/* Multicast Table Array - 128 entries */ #define IXGBE_MTA(_i) (0x05200 + ((_i) * 4)) - /* Multicast Table Array - 128 entries */ -#define IXGBE_RAL(_i) (0x05400 + ((_i) * 8)) /* 16 of these (0-15) */ -#define IXGBE_RAH(_i) (0x05404 + ((_i) * 8)) /* 16 of these (0-15) */ -#define IXGBE_PSRTYPE 0x05480 - /* 0x5480-0x54BC Packet split receive type */ +#define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x0A200 + ((_i) * 8))) +#define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x0A204 + ((_i) * 8))) +/* Packet split receive type */ +#define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : (0x0EA00 + ((_i) * 4))) +/* array of 4096 1-bit vlan filters */ #define IXGBE_VFTA(_i) (0x0A000 + ((_i) * 4)) - /* array of 4096 1-bit vlan filters */ +/*array of 4096 4-bit vlan vmdq indices */ #define IXGBE_VFTAVIND(_j, _i) (0x0A200 + ((_j) * 0x200) + ((_i) * 4)) - /*array of 4096 4-bit vlan vmdq indicies */ #define IXGBE_FCTRL 0x05080 #define IXGBE_VLNCTRL 0x05088 #define IXGBE_MCSTCTRL 0x05090 #define IXGBE_MRQC 0x05818 -#define IXGBE_VMD_CTL 0x0581C #define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIRVP 0x05AC0 +#define IXGBE_VMD_CTL 0x0581C #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ + /* Transmit DMA registers */ -#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40))/* 32 of these (0-31)*/ +#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/ #define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40)) #define IXGBE_TDLEN(_i) (0x06008 + ((_i) * 0x40)) #define IXGBE_TDH(_i) (0x06010 + ((_i) * 0x40)) @@ -139,11 +154,10 @@ #define IXGBE_TDWBAL(_i) (0x06038 + ((_i) * 0x40)) #define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40)) #define IXGBE_DTXCTL 0x07E00 -#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) - /* there are 16 of these (0-15) */ + +#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */ #define IXGBE_TIPG 0x0CB00 -#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) *0x04)) - /* there are 8 of these */ +#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) * 4)) /* 8 of these */ #define IXGBE_MNGTXMAP 0x0CD10 #define IXGBE_TIPG_FIBER_DEFAULT 3 #define IXGBE_TXPBSIZE_SHIFT 10 @@ -155,6 +169,7 @@ #define IXGBE_IPAV 0x05838 #define IXGBE_IP4AT 0x05840 /* IPv4 table 0x5840-0x5858 */ #define IXGBE_IP6AT 0x05880 /* IPv6 table 0x5880-0x588F */ + #define IXGBE_WUPL 0x05900 #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ #define IXGBE_FHFT 0x09000 /* Flex host filter table 9000-93FC */ @@ -171,6 +186,8 @@ #define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ + + /* Stats registers */ #define IXGBE_CRCERRS 0x04000 #define IXGBE_ILLERRC 0x04004 @@ -225,7 +242,7 @@ #define IXGBE_XEC 0x04120 #define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4)) /* 16 of these */ -#define IXGBE_TQSMR(_i) (0x07300 + ((_i) * 4)) /* 8 of these */ +#define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : (0x08600 + ((_i) * 4))) #define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */ @@ -276,17 +293,17 @@ #define IXGBE_DCA_CTRL 0x11074 /* Diagnostic Registers */ -#define IXGBE_RDSTATCTL 0x02C20 -#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ -#define IXGBE_RDHMPN 0x02F08 +#define IXGBE_RDSTATCTL 0x02C20 +#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ +#define IXGBE_RDHMPN 0x02F08 #define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4)) -#define IXGBE_RDPROBE 0x02F20 -#define IXGBE_TDSTATCTL 0x07C20 -#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ -#define IXGBE_TDHMPN 0x07F08 +#define IXGBE_RDPROBE 0x02F20 +#define IXGBE_TDSTATCTL 0x07C20 +#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ +#define IXGBE_TDHMPN 0x07F08 #define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4)) -#define IXGBE_TDPROBE 0x07F20 -#define IXGBE_TXBUFCTRL 0x0C600 +#define IXGBE_TDPROBE 0x07F20 +#define IXGBE_TXBUFCTRL 0x0C600 #define IXGBE_TXBUFDATA0 0x0C610 #define IXGBE_TXBUFDATA1 0x0C614 #define IXGBE_TXBUFDATA2 0x0C618 @@ -387,7 +404,7 @@ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ -#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */ +#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ #define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */ /* MSCA Bit Masks */ @@ -411,10 +428,10 @@ #define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress enable */ /* MSRWD bit masks */ -#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF -#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 -#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 -#define IXGBE_MSRWD_READ_DATA_SHIFT 16 +#define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF +#define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 +#define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 +#define IXGBE_MSRWD_READ_DATA_SHIFT 16 /* Atlas registers */ #define IXGBE_ATLAS_PDN_LPBK 0x24 @@ -429,6 +446,7 @@ #define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0 #define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0 + /* Device Type definitions for new protocol MDIO commands */ #define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 #define IXGBE_MDIO_PCS_DEV_TYPE 0x3 @@ -436,6 +454,8 @@ #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ +#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ + #define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Control Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */ @@ -449,23 +469,39 @@ #define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */ #define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ #define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ -#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Abilty Reg */ +#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */ #define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */ #define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */ +#define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Address Reg */ +#define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ +#define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ + +/* MII clause 22/28 definitions */ +#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 + +#define IXGBE_MII_SPEED_SELECTION_REG 0x10 +#define IXGBE_MII_RESTART 0x200 +#define IXGBE_MII_AUTONEG_COMPLETE 0x20 +#define IXGBE_MII_AUTONEG_REG 0x0 + #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 /* PHY IDs*/ -#define TN1010_PHY_ID 0x00A19410 #define QT2022_PHY_ID 0x0043A400 +/* PHY Types */ +#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0 + /* General purpose Interrupt Enable */ -#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ -#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ -#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ -#define IXGBE_GPIE_EIAME 0x40000000 -#define IXGBE_GPIE_PBA_SUPPORT 0x80000000 +#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ +#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */ +#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ +#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ +#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ +#define IXGBE_GPIE_EIAME 0x40000000 +#define IXGBE_GPIE_PBA_SUPPORT 0x80000000 /* Transmit Flow Control status */ #define IXGBE_TFCS_TXOFF 0x00000001 @@ -526,7 +562,7 @@ #define IXGBE_PAP_TXPAUSECNT_MASK 0x0000FFFF /* Pause counter mask */ /* RMCS Bit Masks */ -#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recylce Mode enable */ +#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recycle Mode enable */ /* Receive Arbitration Control: 0 Round Robin, 1 DFP */ #define IXGBE_RMCS_RAC 0x00000004 #define IXGBE_RMCS_DFP IXGBE_RMCS_RAC /* Deficit Fixed Priority ena */ @@ -534,12 +570,15 @@ #define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority flow control ena */ #define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */ + /* Interrupt register bitmasks */ /* Extended Interrupt Cause Read */ #define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ #define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */ -#define IXGBE_EICR_MNG 0x00400000 /* Managability Event Interrupt */ +#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */ +#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ +#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */ #define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */ #define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */ #define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ @@ -547,11 +586,12 @@ /* Extended Interrupt Cause Set */ #define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ -#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */ -#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ -#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ -#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */ -#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */ +#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */ +#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ +#define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ +#define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ +#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ +#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */ #define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ @@ -559,7 +599,9 @@ #define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ -#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */ +#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ +#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ +#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */ #define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ @@ -568,18 +610,20 @@ #define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ -#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */ -#define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Error */ +#define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ +#define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ +#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ +#define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */ #define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ -#define IXGBE_EIMS_ENABLE_MASK (\ - IXGBE_EIMS_RTX_QUEUE | \ - IXGBE_EIMS_LSC | \ - IXGBE_EIMS_TCP_TIMER | \ - IXGBE_EIMS_OTHER) +#define IXGBE_EIMS_ENABLE_MASK ( \ + IXGBE_EIMS_RTX_QUEUE | \ + IXGBE_EIMS_LSC | \ + IXGBE_EIMS_TCP_TIMER | \ + IXGBE_EIMS_OTHER) -/* Immediate Interrupt RX (A.K.A. Low Latency Interrupt) */ +/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ #define IXGBE_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ #define IXGBE_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ #define IXGBE_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ @@ -616,6 +660,7 @@ #define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */ #define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */ + #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ /* STATUS Bit Masks */ @@ -663,16 +708,16 @@ #define IXGBE_AUTOC_AN_RESTART 0x00001000 #define IXGBE_AUTOC_FLU 0x00000001 #define IXGBE_AUTOC_LMS_SHIFT 13 -#define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) -#define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) - -#define IXGBE_AUTOC_1G_PMA_PMD 0x00000200 -#define IXGBE_AUTOC_10G_PMA_PMD 0x00000180 +#define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) +#define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) + +#define IXGBE_AUTOC_1G_PMA_PMD 0x00000200 +#define IXGBE_AUTOC_10G_PMA_PMD 0x00000180 #define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7 #define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9 #define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) @@ -753,6 +798,11 @@ #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 +/* Legacy EEPROM word offsets */ +#define IXGBE_ISCSI_BOOT_CAPS 0x0033 +#define IXGBE_ISCSI_SETUP_PORT_0 0x0030 +#define IXGBE_ISCSI_SETUP_PORT_1 0x0034 + /* EEPROM Commands - SPI */ #define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */ #define IXGBE_EEPROM_STATUS_RDY_SPI 0x01 @@ -760,7 +810,7 @@ #define IXGBE_EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ #define IXGBE_EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = addr bit-8 */ #define IXGBE_EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Ena latch */ -/* EEPROM reset Write Enbale latch */ +/* EEPROM reset Write Enable latch */ #define IXGBE_EEPROM_WRDI_OPCODE_SPI 0x04 #define IXGBE_EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status reg */ #define IXGBE_EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status reg */ @@ -799,22 +849,20 @@ /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 -/* PHY Types */ -#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0 - /* Check whether address is multicast. This is little-endian specific check.*/ #define IXGBE_IS_MULTICAST(Address) \ - (bool)(((u8 *)(Address))[0] & ((u8)0x01)) + (bool)(((u8 *)(Address))[0] & ((u8)0x01)) /* Check whether an address is broadcast. */ #define IXGBE_IS_BROADCAST(Address) \ - ((((u8 *)(Address))[0] == ((u8)0xff)) && \ - (((u8 *)(Address))[1] == ((u8)0xff))) + ((((u8 *)(Address))[0] == ((u8)0xff)) && \ + (((u8 *)(Address))[1] == ((u8)0xff))) /* RAH */ #define IXGBE_RAH_VIND_MASK 0x003C0000 #define IXGBE_RAH_VIND_SHIFT 18 #define IXGBE_RAH_AV 0x80000000 +#define IXGBE_CLEAR_VMDQ_ALL 0xFFFFFFFF /* Header split receive */ #define IXGBE_RFCTL_ISCSI_DIS 0x00000001 @@ -843,7 +891,7 @@ #define IXGBE_MAX_FRAME_SZ 0x40040000 #define IXGBE_TDWBAL_HEAD_WB_ENABLE 0x1 /* Tx head write-back enable */ -#define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq. # write-back enable */ +#define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq# write-back enable */ /* Receive Config masks */ #define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */ @@ -856,7 +904,7 @@ #define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */ #define IXGBE_FCTRL_PMCF 0x00001000 /* Pass MAC Control Frames */ #define IXGBE_FCTRL_DPF 0x00002000 /* Discard Pause Frame */ -/* Receive Priority Flow Control Enbale */ +/* Receive Priority Flow Control Enable */ #define IXGBE_FCTRL_RPFCE 0x00004000 #define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */ @@ -886,9 +934,8 @@ /* Receive Descriptor bit definitions */ #define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */ #define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */ -#define IXGBE_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */ +#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */ #define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ @@ -904,7 +951,7 @@ #define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */ #define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */ #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ -#define IXGBE_RXDADV_HBO 0x00800000 +#define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ #define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ #define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ #define IXGBE_RXDADV_ERR_PE 0x08000000 /* Packet Error */ @@ -918,15 +965,17 @@ #define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */ #define IXGBE_RXD_CFI_SHIFT 12 + /* SRRCTL bit definitions */ -#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ -#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F -#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 -#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 +#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ +#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F +#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 +#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 +#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 #define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000 #define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF @@ -960,21 +1009,20 @@ #define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ #define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ - /* Masks to determine if packets should be dropped due to frame errors */ -#define IXGBE_RXD_ERR_FRAME_ERR_MASK (\ - IXGBE_RXD_ERR_CE | \ - IXGBE_RXD_ERR_LE | \ - IXGBE_RXD_ERR_PE | \ - IXGBE_RXD_ERR_OSE | \ - IXGBE_RXD_ERR_USE) - -#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK (\ - IXGBE_RXDADV_ERR_CE | \ - IXGBE_RXDADV_ERR_LE | \ - IXGBE_RXDADV_ERR_PE | \ - IXGBE_RXDADV_ERR_OSE | \ - IXGBE_RXDADV_ERR_USE) +#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXD_ERR_CE | \ + IXGBE_RXD_ERR_LE | \ + IXGBE_RXD_ERR_PE | \ + IXGBE_RXD_ERR_OSE | \ + IXGBE_RXD_ERR_USE) + +#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXDADV_ERR_CE | \ + IXGBE_RXDADV_ERR_LE | \ + IXGBE_RXDADV_ERR_PE | \ + IXGBE_RXDADV_ERR_OSE | \ + IXGBE_RXDADV_ERR_USE) /* Multicast bit mask */ #define IXGBE_MCSTCTRL_MFE 0x4 @@ -990,6 +1038,7 @@ #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */ #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT + /* Transmit Descriptor - Legacy */ struct ixgbe_legacy_tx_desc { u64 buffer_addr; /* Address of the descriptor's data buffer */ @@ -1004,8 +1053,8 @@ struct ixgbe_legacy_tx_desc { union { __le32 data; struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ + u8 status; /* Descriptor status */ + u8 css; /* Checksum start */ __le16 vlan; } fields; } upper; @@ -1014,7 +1063,7 @@ struct ixgbe_legacy_tx_desc { /* Transmit Descriptor - Advanced */ union ixgbe_adv_tx_desc { struct { - __le64 buffer_addr; /* Address of descriptor's data buf */ + __le64 buffer_addr; /* Address of descriptor's data buf */ __le32 cmd_type_len; __le32 olinfo_status; } read; @@ -1046,8 +1095,8 @@ union ixgbe_adv_rx_desc { union { __le32 data; struct { - __le16 pkt_info; /* RSS type, Packet type */ - __le16 hdr_info; /* Split Header, header len */ + __le16 pkt_info; /* RSS, Pkt type */ + __le16 hdr_info; /* Splithdr, hdrlen */ } hs_rss; } lo_dword; union { @@ -1075,49 +1124,69 @@ struct ixgbe_adv_tx_context_desc { }; /* Adv Transmit Descriptor Config Masks */ -#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buffer length(bytes) */ +#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */ #define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */ #define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Desc */ #define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */ #define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */ -#define IXGBE_ADVTXD_DCMD_RDMA 0x04000000 /* RDMA */ #define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */ -#define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ +#define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext (1=Adv) */ #define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE /* VLAN pkt enable */ #define IXGBE_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD /* Descriptor Done */ -#define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */ +#define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED pres in WB */ #define IXGBE_ADVTXD_STAT_RSV 0x0000000C /* STA Reserved */ #define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ +#define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */ #define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */ #define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \ - IXGBE_ADVTXD_POPTS_SHIFT) + IXGBE_ADVTXD_POPTS_SHIFT) #define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \ - IXGBE_ADVTXD_POPTS_SHIFT) -#define IXGBE_ADVTXD_POPTS_EOM 0x00000400 /* Enable L bit-RDMA DDP hdr */ -#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ -#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ -#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ -#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/ -#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */ -#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ -#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ -#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ -#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ -#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ -#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ -#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ -#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */ -#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ -#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ - + IXGBE_ADVTXD_POPTS_SHIFT) +#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ +#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ +#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ +#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU */ +#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */ +#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ +#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ +#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ +#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ +#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ +#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ +#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ +#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ +#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /*Req requires Markers and CRC*/ +#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ +#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + +/* Autonegotiation advertised speeds */ +typedef u32 ixgbe_autoneg_advertised; /* Link speed */ +typedef u32 ixgbe_link_speed; #define IXGBE_LINK_SPEED_UNKNOWN 0 #define IXGBE_LINK_SPEED_100_FULL 0x0008 #define IXGBE_LINK_SPEED_1GB_FULL 0x0020 #define IXGBE_LINK_SPEED_10GB_FULL 0x0080 +#define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \ + IXGBE_LINK_SPEED_10GB_FULL) + +/* Physical layer type */ +typedef u32 ixgbe_physical_layer; +#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0 +#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001 +#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002 +#define IXGBE_PHYSICAL_LAYER_100BASE_T 0x0004 +#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008 +#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010 +#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020 +#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040 +#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080 +#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100 +#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200 +#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 enum ixgbe_eeprom_type { @@ -1134,16 +1203,38 @@ enum ixgbe_mac_type { enum ixgbe_phy_type { ixgbe_phy_unknown = 0, - ixgbe_phy_tn, ixgbe_phy_qt, - ixgbe_phy_xaui + ixgbe_phy_xaui, + ixgbe_phy_tw_tyco, + ixgbe_phy_tw_unknown, + ixgbe_phy_sfp_avago, + ixgbe_phy_sfp_ftl, + ixgbe_phy_sfp_unknown, + ixgbe_phy_generic +}; + +/* + * SFP+ module type IDs: + * + * ID Module Type + * ============= + * 0 SFP_DA_CU + * 1 SFP_SR + * 2 SFP_LR + */ +enum ixgbe_sfp_type { + ixgbe_sfp_type_da_cu = 0, + ixgbe_sfp_type_sr = 1, + ixgbe_sfp_type_lr = 2, + ixgbe_sfp_type_unknown = 0xFFFF }; enum ixgbe_media_type { ixgbe_media_type_unknown = 0, ixgbe_media_type_fiber, ixgbe_media_type_copper, - ixgbe_media_type_backplane + ixgbe_media_type_backplane, + ixgbe_media_type_virtual }; /* Flow Control Settings */ @@ -1241,59 +1332,114 @@ struct ixgbe_hw; typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq); +/* Function pointer table */ +struct ixgbe_eeprom_operations { + s32 (*init_params)(struct ixgbe_hw *); + s32 (*read)(struct ixgbe_hw *, u16, u16 *); + s32 (*write)(struct ixgbe_hw *, u16, u16); + s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); + s32 (*update_checksum)(struct ixgbe_hw *); +}; + struct ixgbe_mac_operations { - s32 (*reset)(struct ixgbe_hw *); + s32 (*init_hw)(struct ixgbe_hw *); + s32 (*reset_hw)(struct ixgbe_hw *); + s32 (*start_hw)(struct ixgbe_hw *); + s32 (*clear_hw_cntrs)(struct ixgbe_hw *); enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); + s32 (*get_supported_physical_layer)(struct ixgbe_hw *); + s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); + s32 (*stop_adapter)(struct ixgbe_hw *); + s32 (*get_bus_info)(struct ixgbe_hw *); + s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*); + s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8); + + /* Link */ s32 (*setup_link)(struct ixgbe_hw *); - s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *, bool); - s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool); - s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *); + s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, + bool); + s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); + s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, + bool *); + + /* LED */ + s32 (*led_on)(struct ixgbe_hw *, u32); + s32 (*led_off)(struct ixgbe_hw *, u32); + s32 (*blink_led_start)(struct ixgbe_hw *, u32); + s32 (*blink_led_stop)(struct ixgbe_hw *, u32); + + /* RAR, Multicast, VLAN */ + s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32); + s32 (*clear_rar)(struct ixgbe_hw *, u32); + s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32); + s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32); + s32 (*init_rx_addrs)(struct ixgbe_hw *); + s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32, + ixgbe_mc_addr_itr); + s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, + ixgbe_mc_addr_itr); + s32 (*enable_mc)(struct ixgbe_hw *); + s32 (*disable_mc)(struct ixgbe_hw *); + s32 (*clear_vfta)(struct ixgbe_hw *); + s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool); + s32 (*init_uta_tables)(struct ixgbe_hw *); + + /* Flow Control */ + s32 (*setup_fc)(struct ixgbe_hw *, s32); }; struct ixgbe_phy_operations { + s32 (*identify)(struct ixgbe_hw *); + s32 (*identify_sfp)(struct ixgbe_hw *); + s32 (*reset)(struct ixgbe_hw *); + s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *); + s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16); s32 (*setup_link)(struct ixgbe_hw *); - s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *); - s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool); -}; - -struct ixgbe_mac_info { - struct ixgbe_mac_operations ops; - enum ixgbe_mac_type type; - u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; - u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; - s32 mc_filter_type; - u32 mcft_size; - u32 vft_size; - u32 num_rar_entries; - u32 num_rx_queues; - u32 num_tx_queues; - u32 link_attach_type; - u32 link_mode_select; - bool link_settings_loaded; + s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, + bool); + s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *); + s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); + s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); + s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); }; struct ixgbe_eeprom_info { - enum ixgbe_eeprom_type type; - u16 word_size; - u16 address_bits; + struct ixgbe_eeprom_operations ops; + enum ixgbe_eeprom_type type; + u32 semaphore_delay; + u16 word_size; + u16 address_bits; }; -struct ixgbe_phy_info { - struct ixgbe_phy_operations ops; - - enum ixgbe_phy_type type; - u32 addr; - u32 id; - u32 revision; - enum ixgbe_media_type media_type; - u32 autoneg_advertised; - bool autoneg_wait_to_complete; +struct ixgbe_mac_info { + struct ixgbe_mac_operations ops; + enum ixgbe_mac_type type; + u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; + u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; + s32 mc_filter_type; + u32 mcft_size; + u32 vft_size; + u32 num_rar_entries; + u32 max_tx_queues; + u32 max_rx_queues; + u32 link_attach_type; + u32 link_mode_select; + bool link_settings_loaded; + bool autoneg; + bool autoneg_failed; }; -struct ixgbe_info { - enum ixgbe_mac_type mac; - s32 (*get_invariants)(struct ixgbe_hw *); - struct ixgbe_mac_operations *mac_ops; +struct ixgbe_phy_info { + struct ixgbe_phy_operations ops; + enum ixgbe_phy_type type; + u32 addr; + u32 id; + enum ixgbe_sfp_type sfp_type; + u32 revision; + enum ixgbe_media_type media_type; + bool reset_disable; + ixgbe_autoneg_advertised autoneg_advertised; + bool autoneg_wait_to_complete; }; struct ixgbe_hw { @@ -1312,6 +1458,15 @@ struct ixgbe_hw { bool adapter_stopped; }; +struct ixgbe_info { + enum ixgbe_mac_type mac; + s32 (*get_invariants)(struct ixgbe_hw *); + struct ixgbe_mac_operations *mac_ops; + struct ixgbe_eeprom_operations *eeprom_ops; + struct ixgbe_phy_operations *phy_ops; +}; + + /* Error Codes */ #define IXGBE_ERR_EEPROM -1 #define IXGBE_ERR_EEPROM_CHECKSUM -2 @@ -1330,6 +1485,8 @@ struct ixgbe_hw { #define IXGBE_ERR_RESET_FAILED -15 #define IXGBE_ERR_SWFW_SYNC -16 #define IXGBE_ERR_PHY_ADDR_INVALID -17 +#define IXGBE_ERR_I2C -18 +#define IXGBE_ERR_SFP_NOT_SUPPORTED -19 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #endif /* _IXGBE_TYPE_H_ */ -- cgit v1.2.3 From 7f8218752a76bb1f70b5e4e918f49bc5bf33275a Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:00:16 -0700 Subject: ixgbe: refresh the ixgbe_down function clean up the hardware shutdown sequence to prevent hardware from continuing to send when resetting or unloading. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index df093ec830d..cafb915bc82 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1096,7 +1096,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); rx_ring = &(adapter->rx_ring[r_idx]); /* If all Rx work done, exit the polling mode */ - if ((work_done == 0) || !netif_running(netdev)) { + if (work_done < budget) { netif_rx_complete(netdev, napi); if (adapter->itr_setting & 3) ixgbe_set_itr_msix(q_vector); @@ -2174,32 +2174,41 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter) void ixgbe_down(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; u32 rxctrl; + u32 txdctl; + int i, j; /* signal that we are down to the interrupt handler */ set_bit(__IXGBE_DOWN, &adapter->state); /* disable receives */ - rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, - rxctrl & ~IXGBE_RXCTRL_RXEN); + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); netif_tx_disable(netdev); - /* disable transmits in the hardware */ - - /* flush both disables */ - IXGBE_WRITE_FLUSH(&adapter->hw); + IXGBE_WRITE_FLUSH(hw); msleep(10); + netif_tx_stop_all_queues(netdev); + ixgbe_irq_disable(adapter); ixgbe_napi_disable_all(adapter); + del_timer_sync(&adapter->watchdog_timer); cancel_work_sync(&adapter->watchdog_task); + /* disable transmits in the hardware now that interrupts are off */ + for (i = 0; i < adapter->num_tx_queues; i++) { + j = adapter->tx_ring[i].reg_idx; + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), + (txdctl & ~IXGBE_TXDCTL_ENABLE)); + } + netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { @@ -2219,7 +2228,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) adapter->flags |= IXGBE_FLAG_DCA_ENABLED; /* always use CB2 mode, difference is masked * in the CB driver */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); + IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); ixgbe_setup_dca(adapter); } #endif -- cgit v1.2.3 From b9804972f52c2e6d60ddfa3a892c3628ed0aa846 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:00:29 -0700 Subject: ixgbe: move set_num_queues and call it after msix failure This is partial preparation for a future patch which will extend ixgbe_set_num_queues Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 88 +++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index ff4fac34a17..020b0c7c195 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -947,7 +947,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, } -static struct ethtool_ops ixgbe_ethtool_ops = { +static const struct ethtool_ops ixgbe_ethtool_ops = { .get_settings = ixgbe_get_settings, .set_settings = ixgbe_set_settings, .get_drvinfo = ixgbe_get_drvinfo, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cafb915bc82..257866b06f6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2333,6 +2333,46 @@ static void ixgbe_reset_task(struct work_struct *work) ixgbe_reinit_locked(adapter); } +static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) +{ + int nrq = 1, ntq = 1; + int feature_mask = 0, rss_i, rss_m; + + /* Number of supported queues */ + switch (adapter->hw.mac.type) { + case ixgbe_mac_82598EB: + rss_i = adapter->ring_feature[RING_F_RSS].indices; + rss_m = 0; + feature_mask |= IXGBE_FLAG_RSS_ENABLED; + + switch (adapter->flags & feature_mask) { + case (IXGBE_FLAG_RSS_ENABLED): + rss_m = 0xF; + nrq = rss_i; + ntq = rss_i; + break; + case 0: + default: + rss_i = 0; + rss_m = 0; + nrq = 1; + ntq = 1; + break; + } + + adapter->ring_feature[RING_F_RSS].indices = rss_i; + adapter->ring_feature[RING_F_RSS].mask = rss_m; + break; + default: + nrq = 1; + ntq = 1; + break; + } + + adapter->num_rx_queues = nrq; + adapter->num_tx_queues = ntq; +} + static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, int vectors) { @@ -2372,54 +2412,13 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, kfree(adapter->msix_entries); adapter->msix_entries = NULL; adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; + ixgbe_set_num_queues(adapter); } else { adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */ adapter->num_msix_vectors = vectors; } } -static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter) -{ - int nrq, ntq; - int feature_mask = 0, rss_i, rss_m; - - /* Number of supported queues */ - switch (adapter->hw.mac.type) { - case ixgbe_mac_82598EB: - rss_i = adapter->ring_feature[RING_F_RSS].indices; - rss_m = 0; - feature_mask |= IXGBE_FLAG_RSS_ENABLED; - - switch (adapter->flags & feature_mask) { - case (IXGBE_FLAG_RSS_ENABLED): - rss_m = 0xF; - nrq = rss_i; - ntq = rss_i; - break; - case 0: - default: - rss_i = 0; - rss_m = 0; - nrq = 1; - ntq = 1; - break; - } - - adapter->ring_feature[RING_F_RSS].indices = rss_i; - adapter->ring_feature[RING_F_RSS].mask = rss_m; - break; - default: - nrq = 1; - ntq = 1; - break; - } - - adapter->num_rx_queues = nrq; - adapter->num_tx_queues = ntq; -} - /** * ixgbe_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize @@ -2482,11 +2481,12 @@ static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter) goto err_rx_ring_allocation; for (i = 0; i < adapter->num_tx_queues; i++) { - adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD; + adapter->tx_ring[i].count = adapter->tx_ring_count; adapter->tx_ring[i].queue_index = i; } + for (i = 0; i < adapter->num_rx_queues; i++) { - adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD; + adapter->rx_ring[i].count = adapter->rx_ring_count; adapter->rx_ring[i].queue_index = i; } -- cgit v1.2.3 From 2adc0511a3126e392aa390cd203e8c3d4603e2c6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:03:00 -0700 Subject: ixgbe: cleanup defines Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 2388af24672..d69215e1b4e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -56,10 +56,6 @@ #define IXGBE_MAX_RXD 4096 #define IXGBE_MIN_RXD 64 -#define IXGBE_DEFAULT_RXQ 1 -#define IXGBE_MAX_RXQ 1 -#define IXGBE_MIN_RXQ 1 - /* flow control */ #define IXGBE_DEFAULT_FCRTL 0x10000 #define IXGBE_MIN_FCRTL 0x40 @@ -81,9 +77,6 @@ #define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) -/* How many Tx Descriptors do we need to call netif_wake_queue? */ -#define IXGBE_TX_QUEUE_WAKE 16 - /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */ -- cgit v1.2.3 From 74ce8dd29be934c30d7874276cdb3dfffbf2bc80 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:03:23 -0700 Subject: ixgbe: lower stack space usage some functions were un-necessarily using local variables. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 257866b06f6..a215350c196 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -482,7 +482,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring, int cleaned_count) { - struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; @@ -516,7 +515,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, } if (!bi->skb) { - struct sk_buff *skb = netdev_alloc_skb(netdev, bufsz); + struct sk_buff *skb = netdev_alloc_skb(adapter->netdev, + bufsz); if (!skb) { adapter->alloc_rx_buff_failed++; @@ -580,7 +580,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) { - struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; @@ -680,9 +679,9 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, total_rx_bytes += skb->len; total_rx_packets++; - skb->protocol = eth_type_trans(skb, netdev); + skb->protocol = eth_type_trans(skb, adapter->netdev); ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc); - netdev->last_rx = jiffies; + adapter->netdev->last_rx = jiffies; next_desc: rx_desc->wb.upper.status_error = 0; @@ -1070,7 +1069,6 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) struct ixgbe_q_vector *q_vector = container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; - struct net_device *netdev = adapter->netdev; struct ixgbe_ring *rx_ring = NULL; int work_done = 0, i; long r_idx; @@ -1097,7 +1095,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) rx_ring = &(adapter->rx_ring[r_idx]); /* If all Rx work done, exit the polling mode */ if (work_done < budget) { - netif_rx_complete(netdev, napi); + netif_rx_complete(adapter->netdev, napi); if (adapter->itr_setting & 3) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) @@ -2284,7 +2282,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) struct ixgbe_q_vector *q_vector = container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; - int tx_cleaned = 0, work_done = 0; + int tx_cleaned, work_done = 0; #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { @@ -2307,7 +2305,6 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable(adapter); } - return work_done; } -- cgit v1.2.3 From 9f8cdf4f06f81c7e21689b01bee0439fe9ae1966 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:03:35 -0700 Subject: ixgbe: xmit frame refactor ixgbe_xmit_frame can be refactored to use fewer locals and better utilize common kernel macros. also fixed minor buglet with internal to driver vlan flag variable being passed incorrectly. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a215350c196..41aede55233 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3213,8 +3213,8 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, unsigned int i; int err; struct ixgbe_tx_buffer *tx_buffer_info; - u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0; - u32 mss_l4len_idx = 0, l4len; + u32 vlan_macip_lens = 0, type_tucmd_mlhl; + u32 mss_l4len_idx, l4len; if (skb_is_gso(skb)) { if (skb_header_cloned(skb)) { @@ -3263,7 +3263,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, context_desc->seqnum_seed = 0; /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ - type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT | + type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT); if (skb->protocol == htons(ETH_P_IP)) @@ -3272,7 +3272,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl); /* MSS L4LEN IDX */ - mss_l4len_idx |= + mss_l4len_idx = (skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT); mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT); /* use index 1 for TSO */ @@ -3330,14 +3330,12 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; break; - case __constant_htons(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; break; - default: if (unlikely(net_ratelimit())) { DPRINTK(PROBE, WARNING, @@ -3354,6 +3352,7 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; + adapter->hw_csum_tx_good++; i++; if (i == tx_ring->count) @@ -3362,6 +3361,7 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, return true; } + return false; } @@ -3533,43 +3533,35 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *tx_ring; - unsigned int len = skb->len; unsigned int first; unsigned int tx_flags = 0; u8 hdr_len = 0; int r_idx = 0, tso; - unsigned int mss = 0; int count = 0; unsigned int f; - unsigned int nr_frags = skb_shinfo(skb)->nr_frags; - len -= skb->data_len; + r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping; tx_ring = &adapter->tx_ring[r_idx]; - - if (skb->len <= 0) { - dev_kfree_skb(skb); - return NETDEV_TX_OK; + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + tx_flags |= vlan_tx_tag_get(skb); + tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; + tx_flags |= IXGBE_TX_FLAGS_VLAN; } - mss = skb_shinfo(skb)->gso_size; - - if (mss) - count++; - else if (skb->ip_summed == CHECKSUM_PARTIAL) + /* three things can cause us to need a context descriptor */ + if (skb_is_gso(skb) || + (skb->ip_summed == CHECKSUM_PARTIAL) || + (tx_flags & IXGBE_TX_FLAGS_VLAN)) count++; - count += TXD_USE_COUNT(len); - for (f = 0; f < nr_frags; f++) + count += TXD_USE_COUNT(skb_headlen(skb)); + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) { adapter->tx_busy++; return NETDEV_TX_BUSY; } - if (adapter->vlgrp && vlan_tx_tag_present(skb)) { - tx_flags |= IXGBE_TX_FLAGS_VLAN; - tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT); - } if (skb->protocol == htons(ETH_P_IP)) tx_flags |= IXGBE_TX_FLAGS_IPV4; -- cgit v1.2.3 From 51ac6445b108abab5e5ebeb5e68665d4509a6f29 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 11 Sep 2008 20:03:55 -0700 Subject: ixgbe: bump version Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 41aede55233..b5139118090 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "1.3.18-k4" +#define DRV_VERSION "1.3.30-k2" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; -- cgit v1.2.3 From b46172402f39719e97b921cc3ca85141f3e8b1c2 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Date: Thu, 11 Sep 2008 20:04:46 -0700 Subject: ixgbe: Whitespace, copyright update and version number change patch This patch cleans up a bit of whitespace issues with the driver, updates the copyright information, and bumps the version number up. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe.h | 17 +- drivers/net/ixgbe/ixgbe_82598.c | 58 ++---- drivers/net/ixgbe/ixgbe_common.c | 57 +++--- drivers/net/ixgbe/ixgbe_common.h | 3 +- drivers/net/ixgbe/ixgbe_ethtool.c | 62 +++---- drivers/net/ixgbe/ixgbe_main.c | 360 +++++++++++++++++++------------------- drivers/net/ixgbe/ixgbe_phy.c | 3 +- drivers/net/ixgbe/ixgbe_phy.h | 3 +- drivers/net/ixgbe/ixgbe_type.h | 3 +- 9 files changed, 266 insertions(+), 300 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index d69215e1b4e..63f678931ad 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 @@ -321,15 +320,11 @@ extern int ixgbe_up(struct ixgbe_adapter *adapter); extern void ixgbe_down(struct ixgbe_adapter *adapter); extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); extern void ixgbe_reset(struct ixgbe_adapter *adapter); -extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern void ixgbe_set_ethtool_ops(struct net_device *netdev); -extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rxdr); -extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *txdr); -extern void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rxdr); -extern void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *txdr); +extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); +extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index a08a267f166..7cddcfba809 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 @@ -42,33 +41,11 @@ static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); -static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); -static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num); -static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); -static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete); -static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg, - bool autoneg_wait_to_complete); static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw); static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); -static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, - u32 vind, bool vlan_on); -static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw); -static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index); -static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index); -static s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val); -static s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val); -static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); -static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw); /** */ @@ -112,8 +89,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) * Determines the link capabilities by reading the AUTOC register. **/ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *autoneg) + ixgbe_link_speed *speed, + bool *autoneg) { s32 status = 0; s32 autoc_reg; @@ -180,8 +157,8 @@ s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, *autoneg = true; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, - &speed_ability); + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + &speed_ability); if (status == 0) { if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) @@ -408,8 +385,9 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) * * Reads the links register to determine if link is up and the current speed **/ -static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete) +static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, bool *link_up, + bool link_up_wait_to_complete) { u32 links_reg; u32 i; @@ -452,8 +430,8 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *spe * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, - ixgbe_link_speed speed, bool autoneg, - bool autoneg_wait_to_complete) + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete) { s32 status = 0; @@ -525,15 +503,15 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) * Sets the link speed in the AUTOC register in the MAC and restarts link. **/ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg, - bool autoneg_wait_to_complete) + ixgbe_link_speed speed, + bool autoneg, + bool autoneg_wait_to_complete) { s32 status; /* Setup the PHY according to input speed */ - status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, - autoneg_wait_to_complete); + status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, + autoneg_wait_to_complete); /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */ hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX); @@ -653,7 +631,7 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } else { hw->mac.link_attach_type = - (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); + (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); hw->mac.link_settings_loaded = true; } @@ -715,7 +693,7 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, - bool vlan_on) + bool vlan_on) { u32 regindex; u32 bitindex; @@ -770,7 +748,7 @@ static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), - 0); + 0); return 0; } diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index a11ff0db9d2..f67c68404bb 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 @@ -481,7 +480,7 @@ s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) if (status == 0) *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_READ_REG_DATA); + IXGBE_EEPROM_READ_REG_DATA); else hw_dbg(hw, "Eeprom read timed out\n"); @@ -620,7 +619,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) */ if (i >= timeout) { hw_dbg(hw, "Driver can't access the Eeprom - Semaphore " - "not granted.\n"); + "not granted.\n"); ixgbe_release_eeprom_semaphore(hw); status = IXGBE_ERR_EEPROM; } @@ -1018,14 +1017,14 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, /* Make sure we are using a valid rar index range */ if (index < rar_entries) { - /* + /* * HW expects these in little endian so we reverse the byte * order from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | - ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | - ((u32)addr[3] << 24)); + */ + rar_low = ((u32)addr[0] | + ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | + ((u32)addr[3] << 24)); /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part @@ -1035,11 +1034,11 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); - if (enable_addr != 0) - rar_high |= IXGBE_RAH_AV; + if (enable_addr != 0) + rar_high |= IXGBE_RAH_AV; - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); } else { hw_dbg(hw, "RAR index %d is out of range.\n", index); } @@ -1137,18 +1136,18 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) hw->mac.ops.get_mac_addr(hw, hw->mac.addr); hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw->mac.addr[4], hw->mac.addr[5]); } else { /* Setup the receive address. */ hw_dbg(hw, "Overriding MAC Address in RAR[0]\n"); hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); + hw->mac.addr[0], hw->mac.addr[1], + hw->mac.addr[2]); hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw->mac.addr[4], hw->mac.addr[5]); hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } @@ -1296,19 +1295,19 @@ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) u32 vector = 0; switch (hw->mac.mc_filter_type) { - case 0: /* use bits [47:36] of the address */ + case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); break; - case 1: /* use bits [46:35] of the address */ + case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); break; - case 2: /* use bits [45:34] of the address */ + case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); break; - case 3: /* use bits [43:32] of the address */ + case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); break; - default: /* Invalid mc_filter_type */ + default: /* Invalid mc_filter_type */ hw_dbg(hw, "MC filter type param set incorrectly\n"); break; } @@ -1366,8 +1365,8 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) u32 rar; hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", - mc_addr[0], mc_addr[1], mc_addr[2], - mc_addr[3], mc_addr[4], mc_addr[5]); + mc_addr[0], mc_addr[1], mc_addr[2], + mc_addr[3], mc_addr[4], mc_addr[5]); /* * Place this multicast address in the RAR if there is room, @@ -1400,7 +1399,7 @@ static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) * multicast table. **/ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count, ixgbe_mc_addr_itr next) + u32 mc_addr_count, ixgbe_mc_addr_itr next) { u32 i; u32 rar_entries = hw->mac.num_rar_entries; @@ -1437,7 +1436,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, /* Enable mta */ if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, - IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); + IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n"); return 0; diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 13ed8d2ff4a..192f8d01291 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 020b0c7c195..81a9c4b8672 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 @@ -48,7 +47,7 @@ struct ixgbe_stats { }; #define IXGBE_STAT(m) sizeof(((struct ixgbe_adapter *)0)->m), \ - offsetof(struct ixgbe_adapter, m) + offsetof(struct ixgbe_adapter, m) static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_packets", IXGBE_STAT(net_stats.rx_packets)}, {"tx_packets", IXGBE_STAT(net_stats.tx_packets)}, @@ -95,14 +94,15 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { }; #define IXGBE_QUEUE_STATS_LEN \ - ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \ - ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \ - (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) -#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) + ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \ + ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \ + (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) +#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) +#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) static int ixgbe_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) + struct ethtool_cmd *ecmd) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -114,7 +114,7 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->transceiver = XCVR_EXTERNAL; if (hw->phy.media_type == ixgbe_media_type_copper) { ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_TP | SUPPORTED_Autoneg); + SUPPORTED_TP | SUPPORTED_Autoneg); ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg); if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) @@ -126,7 +126,7 @@ static int ixgbe_get_settings(struct net_device *netdev, } else { ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising = (ADVERTISED_10000baseT_Full | - ADVERTISED_FIBRE); + ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; } @@ -134,7 +134,7 @@ static int ixgbe_get_settings(struct net_device *netdev, hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) { ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? - SPEED_10000 : SPEED_1000; + SPEED_10000 : SPEED_1000; ecmd->duplex = DUPLEX_FULL; } else { ecmd->speed = -1; @@ -145,7 +145,7 @@ static int ixgbe_get_settings(struct net_device *netdev, } static int ixgbe_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) + struct ethtool_cmd *ecmd) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -165,7 +165,7 @@ static int ixgbe_set_settings(struct net_device *netdev, } static void ixgbe_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -183,7 +183,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, } static int ixgbe_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -282,7 +282,7 @@ static int ixgbe_get_regs_len(struct net_device *netdev) #define IXGBE_GET_STAT(_A_, _R_) _A_->stats._R_ static void ixgbe_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) + struct ethtool_regs *regs, void *p) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -583,7 +583,7 @@ static int ixgbe_get_eeprom_len(struct net_device *netdev) } static int ixgbe_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) + struct ethtool_eeprom *eeprom, u8 *bytes) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -607,7 +607,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev, for (i = 0; i < eeprom_len; i++) { if ((ret_val = hw->eeprom.ops.read(hw, first_word + i, - &eeprom_buff[i]))) + &eeprom_buff[i]))) break; } @@ -622,7 +622,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev, } static void ixgbe_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) + struct ethtool_drvinfo *drvinfo) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -635,7 +635,7 @@ static void ixgbe_get_drvinfo(struct net_device *netdev, } static void ixgbe_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) + struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *tx_ring = adapter->tx_ring; @@ -652,7 +652,7 @@ static void ixgbe_get_ringparam(struct net_device *netdev, } static int ixgbe_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) + struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *temp_ring; @@ -706,7 +706,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, if (err) { while (i) { i--; - ixgbe_free_tx_resources(adapter, &temp_ring[i]); + ixgbe_free_tx_resources(adapter, + &temp_ring[i]); } goto err_setup; } @@ -731,7 +732,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, if (err) { while (i) { i--; - ixgbe_free_rx_resources(adapter, &temp_ring[i]); + ixgbe_free_rx_resources(adapter, + &temp_ring[i]); } goto err_setup; } @@ -767,7 +769,7 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset) } static void ixgbe_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) + struct ethtool_stats *stats, u64 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); u64 *queue_stat; @@ -788,7 +790,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { char *p = (char *)adapter + ixgbe_gstrings_stats[i].stat_offset; data[i] = (ixgbe_gstrings_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { queue_stat = (u64 *)&adapter->tx_ring[j].stats; @@ -805,7 +807,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, } static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, - u8 *data) + u8 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); char *p = (char *)data; @@ -830,14 +832,14 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, sprintf(p, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; } -/* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ + /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ break; } } static void ixgbe_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) + struct ethtool_wolinfo *wol) { wol->supported = 0; wol->wolopts = 0; @@ -879,7 +881,7 @@ static int ixgbe_phys_id(struct net_device *netdev, u32 data) } static int ixgbe_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) + struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -904,7 +906,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev, } static int ixgbe_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) + struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -974,7 +976,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .set_tso = ixgbe_set_tso, .get_strings = ixgbe_get_strings, .phys_id = ixgbe_phys_id, - .get_sset_count = ixgbe_get_sset_count, + .get_sset_count = ixgbe_get_sset_count, .get_ethtool_stats = ixgbe_get_ethtool_stats, .get_coalesce = ixgbe_get_coalesce, .set_coalesce = ixgbe_set_coalesce, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b5139118090..2980a373645 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 @@ -46,15 +45,14 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = - "Intel(R) 10 Gigabit PCI Express Network Driver"; + "Intel(R) 10 Gigabit PCI Express Network Driver"; #define DRV_VERSION "1.3.30-k2" const char ixgbe_driver_version[] = DRV_VERSION; -static const char ixgbe_copyright[] = - "Copyright (c) 1999-2007 Intel Corporation."; +static char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { - [board_82598] = &ixgbe_82598_info, + [board_82598] = &ixgbe_82598_info, }; /* ixgbe_pci_tbl - PCI Device ID Table @@ -84,7 +82,7 @@ MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl); #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static int ixgbe_notify_dca(struct notifier_block *, unsigned long event, - void *p); + void *p); static struct notifier_block dca_notifier = { .notifier_call = ixgbe_notify_dca, .next = NULL, @@ -106,7 +104,7 @@ static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter) /* Let firmware take over control of h/w */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, - ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); + ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); } static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) @@ -116,7 +114,7 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) /* Let firmware know the driver has taken over */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, - ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); + ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); } #ifdef DEBUG @@ -133,7 +131,7 @@ char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw) #endif static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry, - u8 msix_vector) + u8 msix_vector) { u32 ivar, index; @@ -146,12 +144,12 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry, } static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, - struct ixgbe_tx_buffer - *tx_buffer_info) + struct ixgbe_tx_buffer + *tx_buffer_info) { if (tx_buffer_info->dma) { pci_unmap_page(adapter->pdev, tx_buffer_info->dma, - tx_buffer_info->length, PCI_DMA_TODEVICE); + tx_buffer_info->length, PCI_DMA_TODEVICE); tx_buffer_info->dma = 0; } if (tx_buffer_info->skb) { @@ -162,8 +160,8 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, } static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, - unsigned int eop) + struct ixgbe_ring *tx_ring, + unsigned int eop) { struct ixgbe_hw *hw = &adapter->hw; u32 head, tail; @@ -198,14 +196,14 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, return false; } -#define IXGBE_MAX_TXD_PWR 14 -#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) +#define IXGBE_MAX_TXD_PWR 14 +#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) /* Tx Descriptors needed, worst case */ #define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ - MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ + MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ #define GET_TX_HEAD_FROM_RING(ring) (\ *(volatile u32 *) \ @@ -313,7 +311,7 @@ done_cleaning: #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) + struct ixgbe_ring *rx_ring) { u32 rxctrl; int cpu = get_cpu(); @@ -332,7 +330,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, } static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) + struct ixgbe_ring *tx_ring) { u32 txctrl; int cpu = get_cpu(); @@ -408,8 +406,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) * @rx_desc: rx descriptor **/ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, - struct sk_buff *skb, u8 status, - struct ixgbe_ring *ring, + struct sk_buff *skb, u8 status, + struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { bool is_vlan = (status & IXGBE_RXD_STAT_VP); @@ -577,8 +575,8 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) } static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring, - int *work_done, int work_to_do) + struct ixgbe_ring *rx_ring, + int *work_done, int work_to_do) { struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc, *next_rxd; @@ -622,8 +620,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, if (len && !skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, rx_buffer_info->dma, - rx_ring->rx_buf_len + NET_IP_ALIGN, - PCI_DMA_FROMDEVICE); + rx_ring->rx_buf_len + NET_IP_ALIGN, + PCI_DMA_FROMDEVICE); skb_put(skb, len); } @@ -741,24 +739,24 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) q_vector = &adapter->q_vector[v_idx]; /* XXX for_each_bit(...) */ r_idx = find_first_bit(q_vector->rxr_idx, - adapter->num_rx_queues); + adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { j = adapter->rx_ring[r_idx].reg_idx; ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(j), v_idx); r_idx = find_next_bit(q_vector->rxr_idx, - adapter->num_rx_queues, - r_idx + 1); + adapter->num_rx_queues, + r_idx + 1); } r_idx = find_first_bit(q_vector->txr_idx, - adapter->num_tx_queues); + adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { j = adapter->tx_ring[r_idx].reg_idx; ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(j), v_idx); r_idx = find_next_bit(q_vector->txr_idx, - adapter->num_tx_queues, - r_idx + 1); + adapter->num_tx_queues, + r_idx + 1); } /* if this is a tx only vector halve the interrupt rate */ @@ -769,7 +767,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) q_vector->eitr = adapter->eitr_param; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), - EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); + EITR_INTS_PER_SEC_TO_REG(q_vector->eitr)); } ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx); @@ -807,8 +805,8 @@ enum latency_range { * parameter (see ixgbe_param.c) **/ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter, - u32 eitr, u8 itr_setting, - int packets, int bytes) + u32 eitr, u8 itr_setting, + int packets, int bytes) { unsigned int retval = itr_setting; u32 timepassed_us; @@ -855,37 +853,37 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) u32 new_itr; u8 current_itr, ret_itr; int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) / - sizeof(struct ixgbe_q_vector); + sizeof(struct ixgbe_q_vector); struct ixgbe_ring *rx_ring, *tx_ring; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { tx_ring = &(adapter->tx_ring[r_idx]); ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->tx_itr, - tx_ring->total_packets, - tx_ring->total_bytes); + q_vector->tx_itr, + tx_ring->total_packets, + tx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ? - q_vector->tx_itr - 1 : ret_itr); + q_vector->tx_itr - 1 : ret_itr); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, - r_idx + 1); + r_idx + 1); } r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { rx_ring = &(adapter->rx_ring[r_idx]); ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, - q_vector->rx_itr, - rx_ring->total_packets, - rx_ring->total_bytes); + q_vector->rx_itr, + rx_ring->total_packets, + rx_ring->total_bytes); /* if the result for this queue would decrease interrupt * rate for this vector then use that result */ q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ? - q_vector->rx_itr - 1 : ret_itr); + q_vector->rx_itr - 1 : ret_itr); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, - r_idx + 1); + r_idx + 1); } current_itr = max(q_vector->rx_itr, q_vector->tx_itr); @@ -912,7 +910,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); /* must write high and low 16 bits to reset counter */ DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx, - itr_reg); + itr_reg); IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16); } @@ -970,7 +968,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) tx_ring->total_packets = 0; ixgbe_clean_tx_irq(adapter, tx_ring); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, - r_idx + 1); + r_idx + 1); } return IRQ_HANDLED; @@ -1029,7 +1027,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) { struct ixgbe_q_vector *q_vector = - container_of(napi, struct ixgbe_q_vector, napi); + container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_ring *rx_ring = NULL; int work_done = 0; @@ -1106,7 +1104,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) return work_done; } static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, - int r_idx) + int r_idx) { a->q_vector[v_idx].adapter = a; set_bit(r_idx, a->q_vector[v_idx].rxr_idx); @@ -1115,7 +1113,7 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, } static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, - int r_idx) + int r_idx) { a->q_vector[v_idx].adapter = a; set_bit(r_idx, a->q_vector[v_idx].txr_idx); @@ -1135,7 +1133,7 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, * mapping configurations in here. **/ static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter, - int vectors) + int vectors) { int v_start = 0; int rxr_idx = 0, txr_idx = 0; @@ -1212,28 +1210,28 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) goto out; #define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \ - (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \ - &ixgbe_msix_clean_many) + (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \ + &ixgbe_msix_clean_many) for (vector = 0; vector < q_vectors; vector++) { handler = SET_HANDLER(&adapter->q_vector[vector]); sprintf(adapter->name[vector], "%s:v%d-%s", - netdev->name, vector, - (handler == &ixgbe_msix_clean_rx) ? "Rx" : - ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx")); + netdev->name, vector, + (handler == &ixgbe_msix_clean_rx) ? "Rx" : + ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx")); err = request_irq(adapter->msix_entries[vector].vector, - handler, 0, adapter->name[vector], - &(adapter->q_vector[vector])); + handler, 0, adapter->name[vector], + &(adapter->q_vector[vector])); if (err) { DPRINTK(PROBE, ERR, - "request_irq failed for MSIX interrupt " - "Error: %d\n", err); + "request_irq failed for MSIX interrupt " + "Error: %d\n", err); goto free_queue_irqs; } } sprintf(adapter->name[vector], "%s:lsc", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, - &ixgbe_msix_lsc, 0, adapter->name[vector], netdev); + &ixgbe_msix_lsc, 0, adapter->name[vector], netdev); if (err) { DPRINTK(PROBE, ERR, "request_irq for msix_lsc failed: %d\n", err); @@ -1245,7 +1243,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) free_queue_irqs: for (i = vector - 1; i >= 0; i--) free_irq(adapter->msix_entries[--vector].vector, - &(adapter->q_vector[i])); + &(adapter->q_vector[i])); adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); @@ -1264,13 +1262,13 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) struct ixgbe_ring *tx_ring = &adapter->tx_ring[0]; q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr, - q_vector->tx_itr, - tx_ring->total_packets, - tx_ring->total_bytes); + q_vector->tx_itr, + tx_ring->total_packets, + tx_ring->total_bytes); q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr, - q_vector->rx_itr, - rx_ring->total_packets, - rx_ring->total_bytes); + q_vector->rx_itr, + rx_ring->total_packets, + rx_ring->total_bytes); current_itr = max(q_vector->rx_itr, q_vector->tx_itr); @@ -1373,10 +1371,10 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter) err = ixgbe_request_msix_irqs(adapter); } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { err = request_irq(adapter->pdev->irq, &ixgbe_intr, 0, - netdev->name, netdev); + netdev->name, netdev); } else { err = request_irq(adapter->pdev->irq, &ixgbe_intr, IRQF_SHARED, - netdev->name, netdev); + netdev->name, netdev); } if (err) @@ -1400,7 +1398,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) i--; for (; i >= 0; i--) { free_irq(adapter->msix_entries[i].vector, - &(adapter->q_vector[i])); + &(adapter->q_vector[i])); } ixgbe_reset_q_vectors(adapter); @@ -1533,8 +1531,8 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl |= IXGBE_RXBUFFER_2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; srrctl |= ((IXGBE_RX_HDR_SIZE << - IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & - IXGBE_SRRCTL_BSIZEHDR_MASK); + IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK); } else { srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; @@ -1551,7 +1549,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) /** * ixgbe_get_skb_hdr - helper function for LRO header processing * @skb: pointer to sk_buff to be added to LRO packet - * @iphdr: pointer to tcp header structure + * @iphdr: pointer to ip header structure * @tcph: pointer to tcp header structure * @hdr_flags: pointer to header flags * @priv: private data @@ -1576,7 +1574,7 @@ static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph, } #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ - (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) + (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) /** * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset @@ -1723,7 +1721,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) } static void ixgbe_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) + struct vlan_group *grp) { struct ixgbe_adapter *adapter = netdev_priv(netdev); u32 ctrl; @@ -1909,7 +1907,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_configure_rx(adapter); for (i = 0; i < adapter->num_rx_queues; i++) ixgbe_alloc_rx_buffers(adapter, &adapter->rx_ring[i], - (adapter->rx_ring[i].count - 1)); + (adapter->rx_ring[i].count - 1)); } static int ixgbe_up_complete(struct ixgbe_adapter *adapter) @@ -1927,7 +1925,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) { if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME | - IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD); + IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD); } else { /* MSI only */ gpie = 0; @@ -2037,7 +2035,7 @@ static int ixgbe_resume(struct pci_dev *pdev) err = pci_enable_device(pdev); if (err) { printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ - "suspend\n"); + "suspend\n"); return err; } pci_set_master(pdev); @@ -2068,7 +2066,7 @@ static int ixgbe_resume(struct pci_dev *pdev) * @rx_ring: ring to free buffers from **/ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) + struct ixgbe_ring *rx_ring) { struct pci_dev *pdev = adapter->pdev; unsigned long size; @@ -2082,8 +2080,8 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_buffer_info = &rx_ring->rx_buffer_info[i]; if (rx_buffer_info->dma) { pci_unmap_single(pdev, rx_buffer_info->dma, - rx_ring->rx_buf_len, - PCI_DMA_FROMDEVICE); + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); rx_buffer_info->dma = 0; } if (rx_buffer_info->skb) { @@ -2119,7 +2117,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, * @tx_ring: ring to be cleaned **/ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring) + struct ixgbe_ring *tx_ring) { struct ixgbe_tx_buffer *tx_buffer_info; unsigned long size; @@ -2226,7 +2224,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) adapter->flags |= IXGBE_FLAG_DCA_ENABLED; /* always use CB2 mode, difference is masked * in the CB driver */ - IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); + IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); ixgbe_setup_dca(adapter); } #endif @@ -2280,7 +2278,7 @@ static void ixgbe_shutdown(struct pci_dev *pdev) static int ixgbe_poll(struct napi_struct *napi, int budget) { struct ixgbe_q_vector *q_vector = container_of(napi, - struct ixgbe_q_vector, napi); + struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; int tx_cleaned, work_done = 0; @@ -2371,7 +2369,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) } static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, - int vectors) + int vectors) { int err, vector_threshold; @@ -2390,7 +2388,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, */ while (vectors >= vector_threshold) { err = pci_enable_msix(adapter->pdev, adapter->msix_entries, - vectors); + vectors); if (!err) /* Success in acquiring all requested vectors. */ break; else if (err < 0) @@ -2425,9 +2423,6 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, **/ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) { - /* TODO: Remove all uses of the indices in the cases where multiple - * features are OR'd together, if the feature set makes sense. - */ int feature_mask = 0, rss_i; int i, txr_idx, rxr_idx; @@ -2468,12 +2463,12 @@ static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter) int i; adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); + sizeof(struct ixgbe_ring), GFP_KERNEL); if (!adapter->tx_ring) goto err_tx_ring_allocation; adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); + sizeof(struct ixgbe_ring), GFP_KERNEL); if (!adapter->rx_ring) goto err_rx_ring_allocation; @@ -2505,7 +2500,7 @@ err_tx_ring_allocation: * capabilities of the hardware and the kernel. **/ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter - *adapter) + *adapter) { int err = 0; int vector, v_budget; @@ -2517,7 +2512,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter * (roughly) twice the number of vectors as there are CPU's. */ v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues, - (int)(num_online_cpus() * 2)) + NON_Q_VECTORS; + (int)(num_online_cpus() * 2)) + NON_Q_VECTORS; /* * At the same time, hardware can only support a maximum of @@ -2531,7 +2526,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter /* A failure in MSI-X entry allocation isn't fatal, but it does * mean we disable MSI-X capabilities of the adapter. */ adapter->msix_entries = kcalloc(v_budget, - sizeof(struct msix_entry), GFP_KERNEL); + sizeof(struct msix_entry), GFP_KERNEL); if (!adapter->msix_entries) { adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; ixgbe_set_num_queues(adapter); @@ -2540,7 +2535,7 @@ static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter err = ixgbe_alloc_queues(adapter); if (err) { DPRINTK(PROBE, ERR, "Unable to allocate memory " - "for queues\n"); + "for queues\n"); goto out; } @@ -2561,7 +2556,7 @@ try_msi: adapter->flags |= IXGBE_FLAG_MSI_ENABLED; } else { DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, " - "falling back to legacy. Error: %d\n", err); + "falling back to legacy. Error: %d\n", err); /* reset err */ err = 0; } @@ -2617,9 +2612,9 @@ static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) } DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, " - "Tx Queue count = %u\n", - (adapter->num_rx_queues > 1) ? "Enabled" : - "Disabled", adapter->num_rx_queues, adapter->num_tx_queues); + "Tx Queue count = %u\n", + (adapter->num_rx_queues > 1) ? "Enabled" : + "Disabled", adapter->num_rx_queues, adapter->num_tx_queues); set_bit(__IXGBE_DOWN, &adapter->state); @@ -2746,7 +2741,7 @@ err: * Returns 0 on success, negative on failure **/ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, - struct ixgbe_ring *rx_ring) + struct ixgbe_ring *rx_ring) { struct pci_dev *pdev = adapter->pdev; int size; @@ -2761,7 +2756,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, rx_ring->rx_buffer_info = vmalloc(size); if (!rx_ring->rx_buffer_info) { DPRINTK(PROBE, ERR, - "vmalloc allocation failed for the rx desc ring\n"); + "vmalloc allocation failed for the rx desc ring\n"); goto alloc_failed; } memset(rx_ring->rx_buffer_info, 0, size); @@ -2774,7 +2769,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, if (!rx_ring->desc) { DPRINTK(PROBE, ERR, - "Memory allocation failed for the rx desc ring\n"); + "Memory allocation failed for the rx desc ring\n"); vfree(rx_ring->rx_buffer_info); goto alloc_failed; } @@ -2827,7 +2822,7 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) } /** - * ixgbe_ree_rx_resources - Free Rx Resources + * ixgbe_free_rx_resources - Free Rx Resources * @adapter: board private structure * @rx_ring: ring to clean the resources from * @@ -2881,11 +2876,10 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_tx_queues; i++) { err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); - if (err) { - DPRINTK(PROBE, ERR, - "Allocation for Tx Queue %u failed\n", i); - break; - } + if (!err) + continue; + DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); + break; } return err; @@ -2908,11 +2902,10 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); - if (err) { - DPRINTK(PROBE, ERR, - "Allocation for Rx Queue %u failed\n", i); - break; - } + if (!err) + continue; + DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); + break; } return err; @@ -2935,7 +2928,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n", - netdev->mtu, new_mtu); + netdev->mtu, new_mtu); /* must set new MTU before calling down or up */ netdev->mtu = new_mtu; @@ -3102,7 +3095,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) /* Rx Errors */ adapter->net_stats.rx_errors = adapter->stats.crcerrs + - adapter->stats.rlec; + adapter->stats.rlec; adapter->net_stats.rx_dropped = 0; adapter->net_stats.rx_length_errors = adapter->stats.rlec; adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; @@ -3206,8 +3199,8 @@ static void ixgbe_watchdog_task(struct work_struct *work) } static int ixgbe_tso(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, struct sk_buff *skb, - u32 tx_flags, u8 *hdr_len) + struct ixgbe_ring *tx_ring, struct sk_buff *skb, + u32 tx_flags, u8 *hdr_len) { struct ixgbe_adv_tx_context_desc *context_desc; unsigned int i; @@ -3230,16 +3223,16 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, iph->tot_len = 0; iph->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); + iph->daddr, 0, + IPPROTO_TCP, + 0); adapter->hw_tso_ctxt++; } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0); adapter->hw_tso6_ctxt++; } @@ -3253,7 +3246,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK); vlan_macip_lens |= ((skb_network_offset(skb)) << - IXGBE_ADVTXD_MACLEN_SHIFT); + IXGBE_ADVTXD_MACLEN_SHIFT); *hdr_len += skb_network_offset(skb); vlan_macip_lens |= (skb_transport_header(skb) - skb_network_header(skb)); @@ -3264,7 +3257,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT | - IXGBE_ADVTXD_DTYP_CTXT); + IXGBE_ADVTXD_DTYP_CTXT); if (skb->protocol == htons(ETH_P_IP)) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; @@ -3293,8 +3286,8 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter, } static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, - struct sk_buff *skb, u32 tx_flags) + struct ixgbe_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags) { struct ixgbe_adv_tx_context_desc *context_desc; unsigned int i; @@ -3311,16 +3304,16 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK); vlan_macip_lens |= (skb_network_offset(skb) << - IXGBE_ADVTXD_MACLEN_SHIFT); + IXGBE_ADVTXD_MACLEN_SHIFT); if (skb->ip_summed == CHECKSUM_PARTIAL) vlan_macip_lens |= (skb_transport_header(skb) - - skb_network_header(skb)); + skb_network_header(skb)); context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); context_desc->seqnum_seed = 0; type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT | - IXGBE_ADVTXD_DTYP_CTXT); + IXGBE_ADVTXD_DTYP_CTXT); if (skb->ip_summed == CHECKSUM_PARTIAL) { switch (skb->protocol) { @@ -3328,13 +3321,13 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) type_tucmd_mlhl |= - IXGBE_ADVTXD_TUCMD_L4T_TCP; + IXGBE_ADVTXD_TUCMD_L4T_TCP; break; case __constant_htons(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) type_tucmd_mlhl |= - IXGBE_ADVTXD_TUCMD_L4T_TCP; + IXGBE_ADVTXD_TUCMD_L4T_TCP; break; default: if (unlikely(net_ratelimit())) { @@ -3366,8 +3359,8 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, } static int ixgbe_tx_map(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, - struct sk_buff *skb, unsigned int first) + struct ixgbe_ring *tx_ring, + struct sk_buff *skb, unsigned int first) { struct ixgbe_tx_buffer *tx_buffer_info; unsigned int len = skb->len; @@ -3385,8 +3378,8 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, tx_buffer_info->length = size; tx_buffer_info->dma = pci_map_single(adapter->pdev, - skb->data + offset, - size, PCI_DMA_TODEVICE); + skb->data + offset, + size, PCI_DMA_TODEVICE); tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; @@ -3411,9 +3404,10 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, tx_buffer_info->length = size; tx_buffer_info->dma = pci_map_page(adapter->pdev, - frag->page, - offset, - size, PCI_DMA_TODEVICE); + frag->page, + offset, + size, + PCI_DMA_TODEVICE); tx_buffer_info->time_stamp = jiffies; tx_buffer_info->next_to_watch = i; @@ -3436,8 +3430,8 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, } static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, - struct ixgbe_ring *tx_ring, - int tx_flags, int count, u32 paylen, u8 hdr_len) + struct ixgbe_ring *tx_ring, + int tx_flags, int count, u32 paylen, u8 hdr_len) { union ixgbe_adv_tx_desc *tx_desc = NULL; struct ixgbe_tx_buffer *tx_buffer_info; @@ -3456,17 +3450,17 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; olinfo_status |= IXGBE_TXD_POPTS_TXSM << - IXGBE_ADVTXD_POPTS_SHIFT; + IXGBE_ADVTXD_POPTS_SHIFT; /* use index 1 context for tso */ olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT); if (tx_flags & IXGBE_TX_FLAGS_IPV4) olinfo_status |= IXGBE_TXD_POPTS_IXSM << - IXGBE_ADVTXD_POPTS_SHIFT; + IXGBE_ADVTXD_POPTS_SHIFT; } else if (tx_flags & IXGBE_TX_FLAGS_CSUM) olinfo_status |= IXGBE_TXD_POPTS_TXSM << - IXGBE_ADVTXD_POPTS_SHIFT; + IXGBE_ADVTXD_POPTS_SHIFT; olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT); @@ -3476,7 +3470,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma); tx_desc->read.cmd_type_len = - cpu_to_le32(cmd_type_len | tx_buffer_info->length); + cpu_to_le32(cmd_type_len | tx_buffer_info->length); tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); i++; @@ -3499,7 +3493,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, } static int __ixgbe_maybe_stop_tx(struct net_device *netdev, - struct ixgbe_ring *tx_ring, int size) + struct ixgbe_ring *tx_ring, int size) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -3521,7 +3515,7 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev, } static int ixgbe_maybe_stop_tx(struct net_device *netdev, - struct ixgbe_ring *tx_ring, int size) + struct ixgbe_ring *tx_ring, int size) { if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size)) return 0; @@ -3575,12 +3569,12 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (tso) tx_flags |= IXGBE_TX_FLAGS_TSO; else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && - (skb->ip_summed == CHECKSUM_PARTIAL)) + (skb->ip_summed == CHECKSUM_PARTIAL)) tx_flags |= IXGBE_TX_FLAGS_CSUM; ixgbe_tx_queue(adapter, tx_ring, tx_flags, - ixgbe_tx_map(adapter, tx_ring, skb, first), - skb->len, hdr_len); + ixgbe_tx_map(adapter, tx_ring, skb, first), + skb->len, hdr_len); netdev->trans_start = jiffies; @@ -3614,15 +3608,16 @@ static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev) static int ixgbe_set_mac(struct net_device *netdev, void *p) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); - adapter->hw.mac.ops.set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); return 0; } @@ -3682,7 +3677,7 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) for (i = 0; i < q_vectors; i++) { struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; netif_napi_add(adapter->netdev, &q_vector->napi, - (*poll), 64); + (*poll), 64); } } @@ -3698,7 +3693,7 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) * and a hardware reset occur. **/ static int __devinit ixgbe_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { struct net_device *netdev; struct ixgbe_adapter *adapter = NULL; @@ -3721,8 +3716,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) { err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (err) { - dev_err(&pdev->dev, "No usable DMA configuration, " - "aborting\n"); + dev_err(&pdev->dev, "No usable DMA " + "configuration, aborting\n"); goto err_dma; } } @@ -3820,10 +3815,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } netdev->features = NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | - NETIF_F_HW_VLAN_FILTER; + NETIF_F_IP_CSUM | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; netdev->features |= NETIF_F_IPV6_CSUM; netdev->features |= NETIF_F_TSO; @@ -3870,28 +3865,28 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, link_speed = link_status & IXGBE_PCI_LINK_SPEED; link_width = link_status & IXGBE_PCI_LINK_WIDTH; dev_info(&pdev->dev, "(PCI Express:%s:%s) " - "%02x:%02x:%02x:%02x:%02x:%02x\n", - ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" : - (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" : - "Unknown"), - ((link_width == IXGBE_PCI_LINK_WIDTH_8) ? "Width x8" : - (link_width == IXGBE_PCI_LINK_WIDTH_4) ? "Width x4" : - (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" : - (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" : - "Unknown"), - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + "%02x:%02x:%02x:%02x:%02x:%02x\n", + ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" : + (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" : + "Unknown"), + ((link_width == IXGBE_PCI_LINK_WIDTH_8) ? "Width x8" : + (link_width == IXGBE_PCI_LINK_WIDTH_4) ? "Width x4" : + (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" : + (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" : + "Unknown"), + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); ixgbe_read_pba_num_generic(hw, &part_num); dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n", - hw->mac.type, hw->phy.type, - (part_num >> 8), (part_num & 0xff)); + hw->mac.type, hw->phy.type, + (part_num >> 8), (part_num & 0xff)); if (link_width <= IXGBE_PCI_LINK_WIDTH_4) { dev_warn(&pdev->dev, "PCI-Express bandwidth available for " - "this card is not sufficient for optimal " - "performance.\n"); + "this card is not sufficient for optimal " + "performance.\n"); dev_warn(&pdev->dev, "For optimal performance a x8 " - "PCI-Express slot is required.\n"); + "PCI-Express slot is required.\n"); } /* reset the hardware with the new settings */ @@ -3999,7 +3994,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) * this device has been detected. */ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) + pci_channel_state_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct ixgbe_adapter *adapter = netdev->priv; @@ -4010,7 +4005,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, ixgbe_down(adapter); pci_disable_device(pdev); - /* Request a slot slot reset. */ + /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } @@ -4027,7 +4022,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) if (pci_enable_device(pdev)) { DPRINTK(PROBE, ERR, - "Cannot re-enable PCI device after reset.\n"); + "Cannot re-enable PCI device after reset.\n"); return PCI_ERS_RESULT_DISCONNECT; } pci_set_master(pdev); @@ -4104,6 +4099,7 @@ static int __init ixgbe_init_module(void) ret = pci_register_driver(&ixgbe_driver); return ret; } + module_init(ixgbe_init_module); /** @@ -4122,12 +4118,12 @@ static void __exit ixgbe_exit_module(void) #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event, - void *p) + void *p) { int ret_val; ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event, - __ixgbe_notify_dca); + __ixgbe_notify_dca); return ret_val ? NOTIFY_BAD : NOTIFY_DONE; } diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 63a70176241..764035a8c9a 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index f88c9131a01..9bfe3f2b1d8 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index c76e30b94d8..c6f8fa1c4e5 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2007 Intel Corporation. + Copyright(c) 1999 - 2008 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -20,7 +20,6 @@ the file called "COPYING". Contact Information: - Linux NICS e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -- cgit v1.2.3 From b3c8b4ba619f3d461e01c27cdda02adcd48f02d4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 11 Sep 2008 20:04:56 -0700 Subject: ixgbe: correctly add and remove napi queues This patch corrects support for NAPI so that queues are correctly added and removed during suspend/resume in the event that the number of MSI-X vectors changes. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 230 +++++++++++++++++++++++------------------ 1 file changed, 130 insertions(+), 100 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2980a373645..a8edbad0335 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2023,43 +2023,6 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) } -#ifdef CONFIG_PM -static int ixgbe_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); - u32 err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ - "suspend\n"); - return err; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - if (netif_running(netdev)) { - err = ixgbe_request_irq(adapter); - if (err) - return err; - } - - ixgbe_reset(adapter); - - if (netif_running(netdev)) - ixgbe_up(adapter); - - netif_device_attach(netdev); - - return 0; -} -#endif - /** * ixgbe_clean_rx_ring - Free Rx Buffers per Queue * @adapter: board private structure @@ -2230,44 +2193,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) #endif } -static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev_priv(netdev); -#ifdef CONFIG_PM - int retval = 0; -#endif - - netif_device_detach(netdev); - - if (netif_running(netdev)) { - ixgbe_down(adapter); - ixgbe_free_irq(adapter); - } - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) - return retval; -#endif - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - ixgbe_release_hw_control(adapter); - - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static void ixgbe_shutdown(struct pci_dev *pdev) -{ - ixgbe_suspend(pdev, PMSG_SUSPEND); -} - /** * ixgbe_poll - NAPI Rx polling callback * @napi: structure for representing this polling device @@ -3022,6 +2947,135 @@ static int ixgbe_close(struct net_device *netdev) return 0; } +/** + * ixgbe_napi_add_all - prep napi structs for use + * @adapter: private struct + * helper function to napi_add each possible q_vector->napi + */ +static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) +{ + int q_idx, q_vectors; + int (*poll)(struct napi_struct *, int); + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + poll = &ixgbe_clean_rxonly; + /* Only enable as many vectors as we have rx queues. */ + q_vectors = adapter->num_rx_queues; + } else { + poll = &ixgbe_poll; + /* only one q_vector for legacy modes */ + q_vectors = 1; + } + + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; + netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); + } +} + +static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) +{ + int q_idx; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + /* legacy and MSI only use one vector */ + if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) + q_vectors = 1; + + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; + if (!q_vector->rxr_count) + continue; + netif_napi_del(&q_vector->napi); + } +} + +#ifdef CONFIG_PM +static int ixgbe_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbe_adapter *adapter = netdev_priv(netdev); + u32 err; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ + "suspend\n"); + return err; + } + pci_set_master(pdev); + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + err = ixgbe_init_interrupt_scheme(adapter); + if (err) { + printk(KERN_ERR "ixgbe: Cannot initialize interrupts for " + "device\n"); + return err; + } + + ixgbe_napi_add_all(adapter); + ixgbe_reset(adapter); + + if (netif_running(netdev)) { + err = ixgbe_open(adapter->netdev); + if (err) + return err; + } + + netif_device_attach(netdev); + + return 0; +} + +#endif /* CONFIG_PM */ +static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbe_adapter *adapter = netdev_priv(netdev); +#ifdef CONFIG_PM + int retval = 0; +#endif + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + ixgbe_down(adapter); + ixgbe_free_irq(adapter); + ixgbe_free_all_tx_resources(adapter); + ixgbe_free_all_rx_resources(adapter); + } + ixgbe_reset_interrupt_capability(adapter); + ixgbe_napi_del_all(adapter); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + +#ifdef CONFIG_PM + retval = pci_save_state(pdev); + if (retval) + return retval; +#endif + + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + ixgbe_release_hw_control(adapter); + + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static void ixgbe_shutdown(struct pci_dev *pdev) +{ + ixgbe_suspend(pdev, PMSG_SUSPEND); +} + /** * ixgbe_update_stats - Update the board statistics counters. * @adapter: board private structure @@ -3656,31 +3710,6 @@ static int ixgbe_link_config(struct ixgbe_hw *hw) return hw->mac.ops.setup_link_speed(hw, autoneg, true, true); } -/** - * ixgbe_napi_add_all - prep napi structs for use - * @adapter: private struct - * helper function to napi_add each possible q_vector->napi - */ -static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) -{ - int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - int (*poll)(struct napi_struct *, int); - - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - poll = &ixgbe_clean_rxonly; - } else { - poll = &ixgbe_poll; - /* only one q_vector for legacy modes */ - q_vectors = 1; - } - - for (i = 0; i < q_vectors; i++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; - netif_napi_add(adapter->netdev, &q_vector->napi, - (*poll), 64); - } -} - /** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -3977,6 +4006,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) pci_release_regions(pdev); DPRINTK(PROBE, INFO, "complete\n"); + ixgbe_napi_del_all(adapter); kfree(adapter->tx_ring); kfree(adapter->rx_ring); -- cgit v1.2.3 From 69888674738db42dd73430ebc59a691010c8fa2e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 11 Sep 2008 20:05:39 -0700 Subject: ixgbe: whitespace/formatting cleanup This patch cleans up some whitespace items, reorders a couple of functions, and removes some outdated comments. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 125 ++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 71 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a8edbad0335..ca17af4349d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -117,19 +117,6 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); } -#ifdef DEBUG -/** - * ixgbe_get_hw_dev_name - return device name string - * used by hardware layer to print debugging information - **/ -char *ixgbe_get_hw_dev_name(struct ixgbe_hw *hw) -{ - struct ixgbe_adapter *adapter = hw->back; - struct net_device *netdev = adapter->netdev; - return netdev->name; -} -#endif - static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, u16 int_alloc_entry, u8 msix_vector) { @@ -1315,7 +1302,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data) struct ixgbe_hw *hw = &adapter->hw; u32 eicr; - /* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read * therefore no explict interrupt disable is necessary */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); @@ -2658,6 +2644,31 @@ err: return -ENOMEM; } +/** + * ixgbe_setup_all_tx_resources - allocate all queues Tx resources + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or + * more of the rings is populated (while the rest are not). It is the + * callers duty to clean those orphaned rings. + * + * Return 0 on success, negative on failure + **/ +static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_tx_queues; i++) { + err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); + if (!err) + continue; + DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); + break; + } + + return err; +} + /** * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors) * @adapter: board private structure @@ -2710,6 +2721,32 @@ alloc_failed: return -ENOMEM; } +/** + * ixgbe_setup_all_rx_resources - allocate all queues Rx resources + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or + * more of the rings is populated (while the rest are not). It is the + * callers duty to clean those orphaned rings. + * + * Return 0 on success, negative on failure + **/ + +static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); + if (!err) + continue; + DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); + break; + } + + return err; +} + /** * ixgbe_free_tx_resources - Free Tx Resources per Queue * @adapter: board private structure @@ -2785,57 +2822,6 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]); } -/** - * ixgbe_setup_all_tx_resources - allocate all queues Tx resources - * @adapter: board private structure - * - * If this function returns with an error, then it's possible one or - * more of the rings is populated (while the rest are not). It is the - * callers duty to clean those orphaned rings. - * - * Return 0 on success, negative on failure - **/ -static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_tx_queues; i++) { - err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); - if (!err) - continue; - DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); - break; - } - - return err; -} - -/** - * ixgbe_setup_all_rx_resources - allocate all queues Rx resources - * @adapter: board private structure - * - * If this function returns with an error, then it's possible one or - * more of the rings is populated (while the rest are not). It is the - * callers duty to clean those orphaned rings. - * - * Return 0 on success, negative on failure - **/ - -static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_rx_queues; i++) { - err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); - if (!err) - continue; - DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); - break; - } - - return err; -} - /** * ixgbe_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure @@ -3001,7 +2987,7 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { - printk(KERN_ERR "ixgbe: Cannot enable PCI device from " \ + printk(KERN_ERR "ixgbe: Cannot enable PCI device from " "suspend\n"); return err; } @@ -3189,8 +3175,8 @@ static void ixgbe_watchdog(unsigned long data) } /** - * ixgbe_watchdog_task - worker thread to bring link up - * @work: pointer to work_struct containing our data + * ixgbe_watchdog_task - worker thread to bring link up + * @work: pointer to work_struct containing our data **/ static void ixgbe_watchdog_task(struct work_struct *work) { @@ -3526,7 +3512,6 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type_len | tx_buffer_info->length); tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); - i++; if (i == tx_ring->count) i = 0; @@ -3576,7 +3561,6 @@ static int ixgbe_maybe_stop_tx(struct net_device *netdev, return __ixgbe_maybe_stop_tx(netdev, tx_ring, size); } - static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -4086,7 +4070,6 @@ static void ixgbe_io_resume(struct pci_dev *pdev) } netif_device_attach(netdev); - } static struct pci_error_handlers ixgbe_err_handler = { -- cgit v1.2.3 From d100ba33f8d2c4dbb53b05f5ac49c39a0dd9dd76 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 11 Sep 2008 20:06:15 -0700 Subject: ixgbe: fix DCA dependency in Kconfig ixgbe can depend on dca IF it is enabled. So if we are compiled as IXGBE=y, and DCA is enabled, then we must force INTEL_IOATDMA and therefore DCA to be =y also. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 69c81da48eb..c25f0d6817a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2411,6 +2411,7 @@ config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI && INET select INET_LRO + select INTEL_IOATDMA ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go -- cgit v1.2.3 From 2eefbd63d0c85daa1317636474c226e236beba81 Mon Sep 17 00:00:00 2001 From: Sebastien Dugue Date: Thu, 11 Sep 2008 15:34:40 +0200 Subject: ehea: fix mutex and spinlock use Looks like to me that the ehea_fw_handles.lock mutex and the ehea_bcmc_regs.lock spinlock are taken much longer than necessary and could as well be pushed inside the functions that need them (ehea_update_firmware_handles() and ehea_update_bcmc_registrations()) rather than at each callsite. Signed-off-by: Sebastien Dugue Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_main.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index b70c5314f53..c765ec60946 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -219,9 +219,11 @@ static void ehea_update_firmware_handles(void) } out_update: + mutex_lock(&ehea_fw_handles.lock); kfree(ehea_fw_handles.arr); ehea_fw_handles.arr = arr; ehea_fw_handles.num_entries = i; + mutex_unlock(&ehea_fw_handles.lock); } static void ehea_update_bcmc_registrations(void) @@ -293,9 +295,11 @@ static void ehea_update_bcmc_registrations(void) } out_update: + spin_lock(&ehea_bcmc_regs.lock); kfree(ehea_bcmc_regs.arr); ehea_bcmc_regs.arr = arr; ehea_bcmc_regs.num_entries = i; + spin_unlock(&ehea_bcmc_regs.lock); } static struct net_device_stats *ehea_get_stats(struct net_device *dev) @@ -1770,8 +1774,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); - spin_lock(&ehea_bcmc_regs.lock); - /* Deregister old MAC in pHYP */ if (port->state == EHEA_PORT_UP) { ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -1792,7 +1794,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) out_upregs: ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); out_free: kfree(cb0); out: @@ -1954,8 +1955,6 @@ static void ehea_set_multicast_list(struct net_device *dev) } ehea_promiscuous(dev, 0); - spin_lock(&ehea_bcmc_regs.lock); - if (dev->flags & IFF_ALLMULTI) { ehea_allmulti(dev, 1); goto out; @@ -1985,7 +1984,6 @@ static void ehea_set_multicast_list(struct net_device *dev) } out: ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); return; } @@ -2466,8 +2464,6 @@ static int ehea_up(struct net_device *dev) if (port->state == EHEA_PORT_UP) return 0; - mutex_lock(&ehea_fw_handles.lock); - ret = ehea_port_res_setup(port, port->num_def_qps, port->num_add_tx_qps); if (ret) { @@ -2504,8 +2500,6 @@ static int ehea_up(struct net_device *dev) } } - spin_lock(&ehea_bcmc_regs.lock); - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); if (ret) { ret = -EIO; @@ -2527,10 +2521,8 @@ out: ehea_info("Failed starting %s. ret=%i", dev->name, ret); ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -2580,9 +2572,6 @@ static int ehea_down(struct net_device *dev) if (port->state == EHEA_PORT_DOWN) return 0; - mutex_lock(&ehea_fw_handles.lock); - - spin_lock(&ehea_bcmc_regs.lock); ehea_drop_multicast_list(dev); ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -2591,7 +2580,6 @@ static int ehea_down(struct net_device *dev) port->state = EHEA_PORT_DOWN; ehea_update_bcmc_registrations(); - spin_unlock(&ehea_bcmc_regs.lock); ret = ehea_clean_all_portres(port); if (ret) @@ -2599,7 +2587,6 @@ static int ehea_down(struct net_device *dev) dev->name, ret); ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -3378,7 +3365,6 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ehea_error("Invalid ibmebus device probed"); return -EINVAL; } - mutex_lock(&ehea_fw_handles.lock); adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { @@ -3462,7 +3448,6 @@ out_free_ad: out: ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -3481,8 +3466,6 @@ static int __devexit ehea_remove(struct of_device *dev) flush_scheduled_work(); - mutex_lock(&ehea_fw_handles.lock); - ibmebus_free_irq(adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); @@ -3492,7 +3475,6 @@ static int __devexit ehea_remove(struct of_device *dev) kfree(adapter); ehea_update_firmware_handles(); - mutex_unlock(&ehea_fw_handles.lock); return 0; } -- cgit v1.2.3 From b73724921d906d1642f9f6d054079c6b095903fe Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 13 Sep 2008 15:04:38 +0200 Subject: r8169: select MII in Kconfig drivers/built-in.o: In function `rtl8169_gset_xmii': r8169.c:(.text+0x82259): undefined reference to `mii_ethtool_gset' Signed-off-by: Hugh Dickins Acked-by: Francois Romieu Cc: Edward Hsu Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c25f0d6817a..8d222e47056 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2057,6 +2057,7 @@ config R8169 tristate "Realtek 8169 gigabit ethernet support" depends on PCI select CRC32 + select MII ---help--- Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. -- cgit v1.2.3 From 004f23b9d3874efc81d2d1cf18fd0fe48dc2f26f Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Thu, 4 Sep 2008 22:34:13 -0700 Subject: cxgb3 - remove duplicate tests in lro The generic lro code checks TCP flags/options. Remove duplicate tests done in the driver. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/sge.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 6990c0ddc85..89efd04be4e 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1937,38 +1937,6 @@ static inline int lro_frame_ok(const struct cpl_rx_pkt *p) eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); } -#define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\ - TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\ - TCP_FLAG_SYN | TCP_FLAG_FIN) -#define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\ - (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP) - -/** - * lro_segment_ok - check if a TCP segment is eligible for LRO - * @tcph: the TCP header of the packet - * - * Returns true if a TCP packet is eligible for LRO. This requires that - * the packet have only the ACK flag set and no TCP options besides - * time stamps. - */ -static inline int lro_segment_ok(const struct tcphdr *tcph) -{ - int optlen; - - if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK)) - return 0; - - optlen = (tcph->doff << 2) - sizeof(*tcph); - if (optlen) { - const u32 *opt = (const u32 *)(tcph + 1); - - if (optlen != TCPOLEN_TSTAMP_ALIGNED || - *opt != htonl(TSTAMP_WORD) || !opt[2]) - return 0; - } - return 1; -} - static int t3_get_lro_header(void **eh, void **iph, void **tcph, u64 *hdr_flags, void *priv) { @@ -1981,9 +1949,6 @@ static int t3_get_lro_header(void **eh, void **iph, void **tcph, *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); - if (!lro_segment_ok(*tcph)) - return -1; - *hdr_flags = LRO_IPV4 | LRO_TCP; return 0; } -- cgit v1.2.3 From ead7b9406c252014175bdf7c6c31894edfa0d1fa Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Sat, 13 Sep 2008 22:42:07 +0200 Subject: myri10ge: use DCA if DCA is compiled as a module Use DCA in myri10ge when CONFIG_DCA_MODULE is set as well. And thus force INTEL_IOATDMA to =y so that DCA=y if we are =y. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + drivers/net/myri10ge/myri10ge.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 8d222e47056..031b95b1f22 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2464,6 +2464,7 @@ config MYRI10GE select FW_LOADER select CRC32 select INET_LRO + select INTEL_IOATDMA ---help--- This driver supports Myricom Myri-10G Dual Protocol interface in Ethernet mode. If the eeprom on your board is not recent enough, diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ce9fc66e73b..005f2aa7501 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -183,7 +183,7 @@ struct myri10ge_slice_state { dma_addr_t fw_stats_bus; int watchdog_tx_done; int watchdog_tx_req; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) int cached_dca_tag; int cpu; __be32 __iomem *dca_tag; @@ -215,7 +215,7 @@ struct myri10ge_priv { int msi_enabled; int msix_enabled; struct msix_entry *msix_vectors; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) int dca_enabled; #endif u32 link_state; @@ -891,7 +891,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) struct myri10ge_slice_state *ss; int i, status; size_t bytes; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) unsigned long dca_tag_off; #endif @@ -986,7 +986,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) } put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_DCA_OFFSET, &cmd, 0); dca_tag_off = cmd.data0; for (i = 0; i < mgp->num_slices; i++) { @@ -1025,7 +1025,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) return status; } -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) static void myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag) { @@ -1458,7 +1458,7 @@ static int myri10ge_poll(struct napi_struct *napi, int budget) struct net_device *netdev = ss->mgp->dev; int work_done; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) if (ss->mgp->dca_enabled) myri10ge_update_dca(ss); #endif @@ -1687,7 +1687,7 @@ static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = { "tx_boundary", "WC", "irq", "MSI", "MSIX", "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", "serial_number", "watchdog_resets", -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) "dca_capable_firmware", "dca_device_present", #endif "link_changes", "link_up", "dropped_link_overflow", @@ -1766,7 +1766,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)mgp->read_write_dma; data[i++] = (unsigned int)mgp->serial_number; data[i++] = (unsigned int)mgp->watchdog_resets; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) data[i++] = (unsigned int)(mgp->ss[0].dca_tag != NULL); data[i++] = (unsigned int)(mgp->dca_enabled); #endif @@ -3764,7 +3764,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "failed reset\n"); goto abort_with_slices; } -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) myri10ge_setup_dca(mgp); #endif pci_set_drvdata(pdev, mgp); @@ -3867,7 +3867,7 @@ static void myri10ge_remove(struct pci_dev *pdev) netdev = mgp->dev; unregister_netdev(netdev); -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) myri10ge_teardown_dca(mgp); #endif myri10ge_dummy_rdma(mgp, 0); @@ -3912,7 +3912,7 @@ static struct pci_driver myri10ge_driver = { #endif }; -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) static int myri10ge_notify_dca(struct notifier_block *nb, unsigned long event, void *p) { @@ -3944,7 +3944,7 @@ static __init int myri10ge_init_module(void) myri10ge_driver.name, myri10ge_rss_hash); myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT; } -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) dca_register_notify(&myri10ge_dca_notifier); #endif @@ -3955,7 +3955,7 @@ module_init(myri10ge_init_module); static __exit void myri10ge_cleanup_module(void) { -#ifdef CONFIG_DCA +#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE) dca_unregister_notify(&myri10ge_dca_notifier); #endif pci_unregister_driver(&myri10ge_driver); -- cgit v1.2.3 From 8ef5ba63b94b04b182ac4a6009dbbf1406beb3c5 Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Fri, 5 Sep 2008 17:12:07 +0200 Subject: [netdrvr] usb/hso: throttle to prevent loss of serial data Patch to stop loss of characters on the hso modems, this patch throttles & unthrottles the modem by not putting out urbs until the tty/line discipline layer has enough space for newly received packets. serial ports. This is required for firmware diagnostics being done at Option. Signed-off-by: Denis Joseph Barrow Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 326 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 234 insertions(+), 92 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 8b2b947b675..1164c52e2c0 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -92,9 +92,6 @@ #define HSO_NET_TX_TIMEOUT (HZ*10) -/* Serial port defines and structs. */ -#define HSO_SERIAL_FLAG_RX_SENT 0 - #define HSO_SERIAL_MAGIC 0x48534f31 /* Number of ttys to handle */ @@ -179,6 +176,12 @@ struct hso_net { unsigned long flags; }; +enum rx_ctrl_state{ + RX_IDLE, + RX_SENT, + RX_PENDING +}; + struct hso_serial { struct hso_device *parent; int magic; @@ -205,7 +208,7 @@ struct hso_serial { struct usb_endpoint_descriptor *in_endp; struct usb_endpoint_descriptor *out_endp; - unsigned long flags; + enum rx_ctrl_state rx_state; u8 rts_state; u8 dtr_state; unsigned tx_urb_used:1; @@ -216,6 +219,15 @@ struct hso_serial { spinlock_t serial_lock; int (*write_data) (struct hso_serial *serial); + /* Hacks required to get flow control + * working on the serial receive buffers + * so as not to drop characters on the floor. + */ + int curr_rx_urb_idx; + u16 curr_rx_urb_offset; + u8 rx_urb_filled[MAX_RX_URBS]; + struct tasklet_struct unthrottle_tasklet; + struct work_struct retry_unthrottle_workqueue; }; struct hso_device { @@ -271,7 +283,7 @@ struct hso_device { static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void ctrl_callback(struct urb *urb); -static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial); +static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial); static void hso_kick_transmit(struct hso_serial *serial); /* Helper functions */ static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int, @@ -287,6 +299,8 @@ static int hso_start_net_device(struct hso_device *hso_dev); static void hso_free_shared_int(struct hso_shared_int *shared_int); static int hso_stop_net_device(struct hso_device *hso_dev); static void hso_serial_ref_free(struct kref *ref); +static void hso_std_serial_read_bulk_callback(struct urb *urb); +static int hso_mux_serial_read(struct hso_serial *serial); static void async_get_intf(struct work_struct *data); static void async_put_intf(struct work_struct *data); static int hso_put_activity(struct hso_device *hso_dev); @@ -458,6 +472,17 @@ static ssize_t hso_sysfs_show_porttype(struct device *dev, } static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL); +static int hso_urb_to_index(struct hso_serial *serial, struct urb *urb) +{ + int idx; + + for (idx = 0; idx < serial->num_rx_urbs; idx++) + if (serial->rx_urb[idx] == urb) + return idx; + dev_err(serial->parent->dev, "hso_urb_to_index failed\n"); + return -1; +} + /* converts mux value to a port spec value */ static u32 hso_mux_to_port(int mux) { @@ -1039,6 +1064,158 @@ static void _hso_serial_set_termios(struct tty_struct *tty, return; } +static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb) +{ + int result; +#ifdef CONFIG_HSO_AUTOPM + usb_mark_last_busy(urb->dev); +#endif + /* We are done with this URB, resubmit it. Prep the USB to wait for + * another frame */ + usb_fill_bulk_urb(urb, serial->parent->usb, + usb_rcvbulkpipe(serial->parent->usb, + serial->in_endp-> + bEndpointAddress & 0x7F), + urb->transfer_buffer, serial->rx_data_length, + hso_std_serial_read_bulk_callback, serial); + /* Give this to the USB subsystem so it can tell us when more data + * arrives. */ + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d\n", + __func__, result); + } +} + + + + +static void put_rxbuf_data_and_resubmit_bulk_urb(struct hso_serial *serial) +{ + int count; + struct urb *curr_urb; + + while (serial->rx_urb_filled[serial->curr_rx_urb_idx]) { + curr_urb = serial->rx_urb[serial->curr_rx_urb_idx]; + count = put_rxbuf_data(curr_urb, serial); + if (count == -1) + return; + if (count == 0) { + serial->curr_rx_urb_idx++; + if (serial->curr_rx_urb_idx >= serial->num_rx_urbs) + serial->curr_rx_urb_idx = 0; + hso_resubmit_rx_bulk_urb(serial, curr_urb); + } + } +} + +static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial) +{ + int count = 0; + struct urb *urb; + + urb = serial->rx_urb[0]; + if (serial->open_count > 0) { + count = put_rxbuf_data(urb, serial); + if (count == -1) + return; + } + /* Re issue a read as long as we receive data. */ + + if (count == 0 && ((urb->actual_length != 0) || + (serial->rx_state == RX_PENDING))) { + serial->rx_state = RX_SENT; + hso_mux_serial_read(serial); + } else + serial->rx_state = RX_IDLE; +} + + +/* read callback for Diag and CS port */ +static void hso_std_serial_read_bulk_callback(struct urb *urb) +{ + struct hso_serial *serial = urb->context; + int status = urb->status; + + /* sanity check */ + if (!serial) { + D1("serial == NULL"); + return; + } else if (status) { + log_usb_status(status, __func__); + return; + } + + D4("\n--- Got serial_read_bulk callback %02x ---", status); + D1("Actual length = %d\n", urb->actual_length); + DUMP1(urb->transfer_buffer, urb->actual_length); + + /* Anyone listening? */ + if (serial->open_count == 0) + return; + + if (status == 0) { + if (serial->parent->port_spec & HSO_INFO_CRC_BUG) { + u32 rest; + u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; + rest = + urb->actual_length % + serial->in_endp->wMaxPacketSize; + if (((rest == 5) || (rest == 6)) + && !memcmp(((u8 *) urb->transfer_buffer) + + urb->actual_length - 4, crc_check, 4)) { + urb->actual_length -= 4; + } + } + /* Valid data, handle RX data */ + spin_lock(&serial->serial_lock); + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; + put_rxbuf_data_and_resubmit_bulk_urb(serial); + spin_unlock(&serial->serial_lock); + } else if (status == -ENOENT || status == -ECONNRESET) { + /* Unlinked - check for throttled port. */ + D2("Port %d, successfully unlinked urb", serial->minor); + spin_lock(&serial->serial_lock); + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; + hso_resubmit_rx_bulk_urb(serial, urb); + spin_unlock(&serial->serial_lock); + } else { + D2("Port %d, status = %d for read urb", serial->minor, status); + return; + } +} + +/* + * This needs to be a tasklet otherwise we will + * end up recursively calling this function. + */ +void hso_unthrottle_tasklet(struct hso_serial *serial) +{ + unsigned long flags; + + spin_lock_irqsave(&serial->serial_lock, flags); + if ((serial->parent->port_spec & HSO_INTF_MUX)) + put_rxbuf_data_and_resubmit_ctrl_urb(serial); + else + put_rxbuf_data_and_resubmit_bulk_urb(serial); + spin_unlock_irqrestore(&serial->serial_lock, flags); +} + +static void hso_unthrottle(struct tty_struct *tty) +{ + struct hso_serial *serial = get_serial_by_tty(tty); + + tasklet_hi_schedule(&serial->unthrottle_tasklet); +} + +void hso_unthrottle_workfunc(struct work_struct *work) +{ + struct hso_serial *serial = + container_of(work, struct hso_serial, + retry_unthrottle_workqueue); + hso_unthrottle_tasklet(serial); +} + /* open the requested serial port */ static int hso_serial_open(struct tty_struct *tty, struct file *filp) { @@ -1064,13 +1241,18 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) tty->driver_data = serial; serial->tty = tty; - /* check for port allready opened, if not set the termios */ + /* check for port already opened, if not set the termios */ serial->open_count++; if (serial->open_count == 1) { tty->low_latency = 1; - serial->flags = 0; + serial->rx_state = RX_IDLE; /* Force default termio settings */ _hso_serial_set_termios(tty, NULL); + tasklet_init(&serial->unthrottle_tasklet, + (void (*)(unsigned long))hso_unthrottle_tasklet, + (unsigned long)serial); + INIT_WORK(&serial->retry_unthrottle_workqueue, + hso_unthrottle_workfunc); result = hso_start_serial_device(serial->parent, GFP_KERNEL); if (result) { hso_stop_serial_device(serial->parent); @@ -1117,9 +1299,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) } if (!usb_gone) hso_stop_serial_device(serial->parent); + tasklet_kill(&serial->unthrottle_tasklet); + cancel_work_sync(&serial->retry_unthrottle_workqueue); } + if (!usb_gone) usb_autopm_put_interface(serial->parent->interface); + mutex_unlock(&serial->parent->mutex); } @@ -1422,15 +1608,21 @@ static void intr_callback(struct urb *urb) (1 << i)); if (serial != NULL) { D1("Pending read interrupt on port %d\n", i); - if (!test_and_set_bit(HSO_SERIAL_FLAG_RX_SENT, - &serial->flags)) { + spin_lock(&serial->serial_lock); + if (serial->rx_state == RX_IDLE) { /* Setup and send a ctrl req read on * port i */ - hso_mux_serial_read(serial); + if (!serial->rx_urb_filled[0]) { + serial->rx_state = RX_SENT; + hso_mux_serial_read(serial); + } else + serial->rx_state = RX_PENDING; + } else { D1("Already pending a read on " "port %d\n", i); } + spin_unlock(&serial->serial_lock); } } } @@ -1532,16 +1724,10 @@ static void ctrl_callback(struct urb *urb) if (req->bRequestType == (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) { /* response to a read command */ - if (serial->open_count > 0) { - /* handle RX data the normal way */ - put_rxbuf_data(urb, serial); - } - - /* Re issue a read as long as we receive data. */ - if (urb->actual_length != 0) - hso_mux_serial_read(serial); - else - clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags); + serial->rx_urb_filled[0] = 1; + spin_lock(&serial->serial_lock); + put_rxbuf_data_and_resubmit_ctrl_urb(serial); + spin_unlock(&serial->serial_lock); } else { hso_put_activity(serial->parent); if (serial->tty) @@ -1552,91 +1738,42 @@ static void ctrl_callback(struct urb *urb) } /* handle RX data for serial port */ -static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial) +static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) { struct tty_struct *tty = serial->tty; - + int write_length_remaining = 0; + int curr_write_len; /* Sanity check */ if (urb == NULL || serial == NULL) { D1("serial = NULL"); - return; + return -2; } /* Push data to tty */ - if (tty && urb->actual_length) { + if (tty) { + write_length_remaining = urb->actual_length - + serial->curr_rx_urb_offset; D1("data to push to tty"); - tty_insert_flip_string(tty, urb->transfer_buffer, - urb->actual_length); - tty_flip_buffer_push(tty); - } -} - -/* read callback for Diag and CS port */ -static void hso_std_serial_read_bulk_callback(struct urb *urb) -{ - struct hso_serial *serial = urb->context; - int result; - int status = urb->status; - - /* sanity check */ - if (!serial) { - D1("serial == NULL"); - return; - } else if (status) { - log_usb_status(status, __func__); - return; - } - - D4("\n--- Got serial_read_bulk callback %02x ---", status); - D1("Actual length = %d\n", urb->actual_length); - DUMP1(urb->transfer_buffer, urb->actual_length); - - /* Anyone listening? */ - if (serial->open_count == 0) - return; - - if (status == 0) { - if (serial->parent->port_spec & HSO_INFO_CRC_BUG) { - u32 rest; - u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF }; - rest = - urb->actual_length % - serial->in_endp->wMaxPacketSize; - if (((rest == 5) || (rest == 6)) - && !memcmp(((u8 *) urb->transfer_buffer) + - urb->actual_length - 4, crc_check, 4)) { - urb->actual_length -= 4; - } + while (write_length_remaining) { + if (test_bit(TTY_THROTTLED, &tty->flags)) + return -1; + curr_write_len = tty_insert_flip_string + (tty, urb->transfer_buffer + + serial->curr_rx_urb_offset, + write_length_remaining); + serial->curr_rx_urb_offset += curr_write_len; + write_length_remaining -= curr_write_len; + tty_flip_buffer_push(tty); } - /* Valid data, handle RX data */ - put_rxbuf_data(urb, serial); - } else if (status == -ENOENT || status == -ECONNRESET) { - /* Unlinked - check for throttled port. */ - D2("Port %d, successfully unlinked urb", serial->minor); - } else { - D2("Port %d, status = %d for read urb", serial->minor, status); - return; } - - usb_mark_last_busy(urb->dev); - - /* We are done with this URB, resubmit it. Prep the USB to wait for - * another frame */ - usb_fill_bulk_urb(urb, serial->parent->usb, - usb_rcvbulkpipe(serial->parent->usb, - serial->in_endp-> - bEndpointAddress & 0x7F), - urb->transfer_buffer, serial->rx_data_length, - hso_std_serial_read_bulk_callback, serial); - /* Give this to the USB subsystem so it can tell us when more data - * arrives. */ - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) { - dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d", - __func__, result); + if (write_length_remaining == 0) { + serial->curr_rx_urb_offset = 0; + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; } + return write_length_remaining; } + /* Base driver functions */ static void hso_log_port(struct hso_device *hso_dev) @@ -1794,9 +1931,13 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) return -ENODEV; for (i = 0; i < serial->num_rx_urbs; i++) { - if (serial->rx_urb[i]) + if (serial->rx_urb[i]) { usb_kill_urb(serial->rx_urb[i]); + serial->rx_urb_filled[i] = 0; + } } + serial->curr_rx_urb_idx = 0; + serial->curr_rx_urb_offset = 0; if (serial->tx_urb) usb_kill_urb(serial->tx_urb); @@ -2741,6 +2882,7 @@ static const struct tty_operations hso_serial_ops = { .chars_in_buffer = hso_serial_chars_in_buffer, .tiocmget = hso_serial_tiocmget, .tiocmset = hso_serial_tiocmset, + .unthrottle = hso_unthrottle }; static struct usb_driver hso_driver = { -- cgit v1.2.3 From b514f6b6da3aedcf4eb6f0c69e910ae89ef4632f Mon Sep 17 00:00:00 2001 From: Hannes Hering Date: Fri, 5 Sep 2008 16:38:22 +0200 Subject: ehea: Enable DLPAR memory remove This patch adds the capability flag to the capability list for dynamic LPAR memory remove to enable this feature. Signed-off-by: Hannes Hering Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index e01926b7b5b..5524271eedc 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,13 +40,13 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0092" +#define DRV_VERSION "EHEA_0093" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 #define DLPAR_MEM_ADD 2 #define DLPAR_MEM_REM 4 -#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD) +#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM | DLPAR_MEM_ADD | DLPAR_MEM_REM) #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) -- cgit v1.2.3 From b39d66a81fb4f5ab555f86a2e49f3714f8369a3d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 20 Aug 2008 16:52:04 -0700 Subject: drivers/net: replace __FUNCTION__ with __func__ __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/3c505.c | 4 +- drivers/net/arcnet/arcnet.c | 18 +++--- drivers/net/arcnet/com20020.c | 16 +++--- drivers/net/ax88796.c | 14 ++--- drivers/net/bfin_mac.c | 8 +-- drivers/net/bonding/bonding.h | 2 +- drivers/net/cxgb3/cxgb3_offload.c | 8 +-- drivers/net/e100.c | 2 +- drivers/net/enc28j60.c | 56 +++++++++--------- drivers/net/ibm_newemac/phy.c | 2 +- drivers/net/ixgb/ixgb.h | 2 +- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/meth.c | 2 +- drivers/net/mipsnet.c | 2 +- drivers/net/netx-eth.c | 2 +- drivers/net/netxen/netxen_nic.h | 2 +- drivers/net/pci-skeleton.c | 4 +- drivers/net/r8169.c | 2 +- drivers/net/s2io.c | 40 ++++++------- drivers/net/smc911x.c | 66 +++++++++++----------- drivers/net/smc91x.c | 40 ++++++------- drivers/net/tehuti.h | 8 +-- drivers/net/tsi108_eth.c | 6 +- drivers/net/ucc_geth.c | 116 +++++++++++++++++++------------------- drivers/net/usb/mcs7830.c | 2 +- drivers/net/usb/pegasus.c | 20 +++---- drivers/net/via-velocity.h | 2 +- drivers/net/wan/cycx_drv.c | 6 +- drivers/net/wan/cycx_x25.c | 12 ++-- drivers/net/wan/dscc4.c | 2 +- drivers/net/wan/pc300_tty.c | 2 +- 31 files changed, 235 insertions(+), 235 deletions(-) diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index fdfb2b2cb73..a424869707a 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -130,12 +130,12 @@ static const char filename[] = __FILE__; static const char timeout_msg[] = "*** timeout at %s:%s (line %d) ***\n"; #define TIMEOUT_MSG(lineno) \ - printk(timeout_msg, filename,__FUNCTION__,(lineno)) + printk(timeout_msg, filename,__func__,(lineno)) static const char invalid_pcb_msg[] = "*** invalid pcb length %d at %s:%s (line %d) ***\n"; #define INVALID_PCB_MSG(len) \ - printk(invalid_pcb_msg, (len),filename,__FUNCTION__,__LINE__) + printk(invalid_pcb_msg, (len),filename,__func__,__LINE__) static char search_msg[] __initdata = KERN_INFO "%s: Looking for 3c505 adapter at address %#x..."; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index bdc4c0bb56d..a5b07691e46 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -442,24 +442,24 @@ static int arcnet_open(struct net_device *dev) BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " "DOS networking programs!\n"); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); if (ASTATUS() & RESETflag) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); netif_start_queue(dev); @@ -670,14 +670,14 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) freeskb = 0; } - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); lp->intmask |= TXFREEflag|EXCNAKflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) { @@ -798,7 +798,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) diagstatus = (status >> 8) & 0xFF; BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", - __FILE__,__LINE__,__FUNCTION__,status); + __FILE__,__LINE__,__func__,status); didsomething = 0; /* diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 8b51313b130..70124a944e7 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -238,15 +238,15 @@ static int com20020_reset(struct net_device *dev, int really_reset) u_char inbyte; BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", - __FILE__,__LINE__,__FUNCTION__,dev,lp,dev->name); + __FILE__,__LINE__,__func__,dev,lp,dev->name); BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); if (really_reset) { /* reset the card */ @@ -254,22 +254,22 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); if (inbyte != TESTvalue) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); /* done! return success. */ return 0; diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index a886a4b9f7e..4207d6efddc 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -153,7 +153,7 @@ static void ax_reset_8390(struct net_device *dev) while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) { if (jiffies - reset_start_time > 2*HZ/100) { dev_warn(&ax->dev->dev, "%s: %s did not complete.\n", - __FUNCTION__, dev->name); + __func__, dev->name); break; } } @@ -173,7 +173,7 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, if (ei_status.dmaing) { dev_err(&ax->dev->dev, "%s: DMAing conflict in %s " "[DMAstat:%d][irqlock:%d].\n", - dev->name, __FUNCTION__, + dev->name, __func__, ei_status.dmaing, ei_status.irqlock); return; } @@ -215,7 +215,7 @@ static void ax_block_input(struct net_device *dev, int count, dev_err(&ax->dev->dev, "%s: DMAing conflict in %s " "[DMAstat:%d][irqlock:%d].\n", - dev->name, __FUNCTION__, + dev->name, __func__, ei_status.dmaing, ei_status.irqlock); return; } @@ -260,7 +260,7 @@ static void ax_block_output(struct net_device *dev, int count, if (ei_status.dmaing) { dev_err(&ax->dev->dev, "%s: DMAing conflict in %s." "[DMAstat:%d][irqlock:%d]\n", - dev->name, __FUNCTION__, + dev->name, __func__, ei_status.dmaing, ei_status.irqlock); return; } @@ -396,7 +396,7 @@ ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc) { if (phy_debug) pr_debug("%s: dev %p, %04x, %04x, %d\n", - __FUNCTION__, dev, phy_addr, reg, opc); + __func__, dev, phy_addr, reg, opc); ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */ ax_mii_ei_outbits(dev, 1, 2); /* frame-start */ @@ -422,7 +422,7 @@ ax_phy_read(struct net_device *dev, int phy_addr, int reg) spin_unlock_irqrestore(&ei_local->page_lock, flags); if (phy_debug) - pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__, + pr_debug("%s: %04x.%04x => read %04x\n", __func__, phy_addr, reg, result); return result; @@ -436,7 +436,7 @@ ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) unsigned long flags; dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n", - __FUNCTION__, dev, phy_addr, reg, value); + __func__, dev, phy_addr, reg, value); spin_lock_irqsave(&ei->page_lock, flags); diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 3db7db1828e..df896e23e2c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -811,7 +811,7 @@ static void bfin_mac_enable(void) { u32 opmode; - pr_debug("%s: %s\n", DRV_NAME, __FUNCTION__); + pr_debug("%s: %s\n", DRV_NAME, __func__); /* Set RX DMA */ bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a)); @@ -847,7 +847,7 @@ static void bfin_mac_enable(void) /* Our watchdog timed out. Called by the networking layer */ static void bfin_mac_timeout(struct net_device *dev) { - pr_debug("%s: %s\n", dev->name, __FUNCTION__); + pr_debug("%s: %s\n", dev->name, __func__); bfin_mac_disable(); @@ -949,7 +949,7 @@ static int bfin_mac_open(struct net_device *dev) { struct bfin_mac_local *lp = netdev_priv(dev); int retval; - pr_debug("%s: %s\n", dev->name, __FUNCTION__); + pr_debug("%s: %s\n", dev->name, __func__); /* * Check that the address is valid. If its not, refuse @@ -989,7 +989,7 @@ static int bfin_mac_open(struct net_device *dev) static int bfin_mac_close(struct net_device *dev) { struct bfin_mac_local *lp = netdev_priv(dev); - pr_debug("%s: %s\n", dev->name, __FUNCTION__); + pr_debug("%s: %s\n", dev->name, __func__); netif_stop_queue(dev); netif_carrier_off(dev); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index fb730ec0396..f7b40edabfd 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -32,7 +32,7 @@ #ifdef BONDING_DEBUG #define dprintk(fmt, args...) \ printk(KERN_DEBUG \ - DRV_NAME ": %s() %d: " fmt, __FUNCTION__, __LINE__ , ## args ) + DRV_NAME ": %s() %d: " fmt, __func__, __LINE__ , ## args ) #else #define dprintk(fmt, args...) #endif /* BONDING_DEBUG */ diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index c5b3de1bb45..0f6fd63b284 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -1018,7 +1018,7 @@ static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e) skb = alloc_skb(sizeof(*req), GFP_ATOMIC); if (!skb) { - printk(KERN_ERR "%s: cannot allocate skb!\n", __FUNCTION__); + printk(KERN_ERR "%s: cannot allocate skb!\n", __func__); return; } skb->priority = CPL_PRIORITY_CONTROL; @@ -1049,14 +1049,14 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) return; if (!is_offloading(newdev)) { printk(KERN_WARNING "%s: Redirect to non-offload " - "device ignored.\n", __FUNCTION__); + "device ignored.\n", __func__); return; } tdev = dev2t3cdev(olddev); BUG_ON(!tdev); if (tdev != dev2t3cdev(newdev)) { printk(KERN_WARNING "%s: Redirect to different " - "offload device ignored.\n", __FUNCTION__); + "offload device ignored.\n", __func__); return; } @@ -1064,7 +1064,7 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) e = t3_l2t_get(tdev, new->neighbour, newdev); if (!e) { printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n", - __FUNCTION__); + __func__); return; } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 453115acaad..7d7dfa512bf 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -191,7 +191,7 @@ MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); #define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ - __FUNCTION__ , ## args)) + __func__ , ## args)) #define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index aa0bf6e1c69..e1b441effbb 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -110,7 +110,7 @@ spi_read_buf(struct enc28j60_net *priv, int len, u8 *data) } if (ret && netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n", - __FUNCTION__, ret); + __func__, ret); return ret; } @@ -131,7 +131,7 @@ static int spi_write_buf(struct enc28j60_net *priv, int len, ret = spi_write(priv->spi, priv->spi_transfer_buf, len + 1); if (ret && netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n", - __FUNCTION__, ret); + __func__, ret); } return ret; } @@ -156,7 +156,7 @@ static u8 spi_read_op(struct enc28j60_net *priv, u8 op, ret = spi_write_then_read(priv->spi, tx_buf, 1, rx_buf, slen); if (ret) printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n", - __FUNCTION__, ret); + __func__, ret); else val = rx_buf[slen - 1]; @@ -176,14 +176,14 @@ static int spi_write_op(struct enc28j60_net *priv, u8 op, ret = spi_write(priv->spi, priv->spi_transfer_buf, 2); if (ret && netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n", - __FUNCTION__, ret); + __func__, ret); return ret; } static void enc28j60_soft_reset(struct enc28j60_net *priv) { if (netif_msg_hw(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__); spi_write_op(priv, ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); /* Errata workaround #1, CLKRDY check is unreliable, @@ -357,7 +357,7 @@ static void enc28j60_mem_read(struct enc28j60_net *priv, reg = nolock_regw_read(priv, ERDPTL); if (reg != addr) printk(KERN_DEBUG DRV_NAME ": %s() error writing ERDPT " - "(0x%04x - 0x%04x)\n", __FUNCTION__, reg, addr); + "(0x%04x - 0x%04x)\n", __func__, reg, addr); } #endif spi_read_buf(priv, len, data); @@ -380,7 +380,7 @@ enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data) if (reg != TXSTART_INIT) printk(KERN_DEBUG DRV_NAME ": %s() ERWPT:0x%04x != 0x%04x\n", - __FUNCTION__, reg, TXSTART_INIT); + __func__, reg, TXSTART_INIT); } #endif /* Set the TXND pointer to correspond to the packet size given */ @@ -390,13 +390,13 @@ enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data) if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": %s() after control byte ERWPT:0x%04x\n", - __FUNCTION__, nolock_regw_read(priv, EWRPTL)); + __func__, nolock_regw_read(priv, EWRPTL)); /* copy the packet into the transmit buffer */ spi_write_buf(priv, len, data); if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": %s() after write packet ERWPT:0x%04x, len=%d\n", - __FUNCTION__, nolock_regw_read(priv, EWRPTL), len); + __func__, nolock_regw_read(priv, EWRPTL), len); mutex_unlock(&priv->lock); } @@ -495,7 +495,7 @@ static int enc28j60_set_hw_macaddr(struct net_device *ndev) if (netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() Hardware must be disabled to set " - "Mac address\n", __FUNCTION__); + "Mac address\n", __func__); ret = -EBUSY; } mutex_unlock(&priv->lock); @@ -575,7 +575,7 @@ static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end) if (start > 0x1FFF || end > 0x1FFF || start > end) { if (netif_msg_drv(priv)) printk(KERN_ERR DRV_NAME ": %s(%d, %d) RXFIFO " - "bad parameters!\n", __FUNCTION__, start, end); + "bad parameters!\n", __func__, start, end); return; } /* set receive buffer start + end */ @@ -591,7 +591,7 @@ static void nolock_txfifo_init(struct enc28j60_net *priv, u16 start, u16 end) if (start > 0x1FFF || end > 0x1FFF || start > end) { if (netif_msg_drv(priv)) printk(KERN_ERR DRV_NAME ": %s(%d, %d) TXFIFO " - "bad parameters!\n", __FUNCTION__, start, end); + "bad parameters!\n", __func__, start, end); return; } /* set transmit buffer start + end */ @@ -630,7 +630,7 @@ static int enc28j60_hw_init(struct enc28j60_net *priv) u8 reg; if (netif_msg_drv(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() - %s\n", __FUNCTION__, + printk(KERN_DEBUG DRV_NAME ": %s() - %s\n", __func__, priv->full_duplex ? "FullDuplex" : "HalfDuplex"); mutex_lock(&priv->lock); @@ -661,7 +661,7 @@ static int enc28j60_hw_init(struct enc28j60_net *priv) if (reg == 0x00 || reg == 0xff) { if (netif_msg_drv(priv)) printk(KERN_DEBUG DRV_NAME ": %s() Invalid RevId %d\n", - __FUNCTION__, reg); + __func__, reg); return 0; } @@ -724,7 +724,7 @@ static void enc28j60_hw_enable(struct enc28j60_net *priv) /* enable interrupts */ if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": %s() enabling interrupts.\n", - __FUNCTION__); + __func__); enc28j60_phy_write(priv, PHIE, PHIE_PGEIE | PHIE_PLNKIE); @@ -888,7 +888,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) if (netif_msg_rx_err(priv)) dev_err(&ndev->dev, "%s() Invalid packet address!! 0x%04x\n", - __FUNCTION__, priv->next_pk_ptr); + __func__, priv->next_pk_ptr); /* packet address corrupted: reset RX logic */ mutex_lock(&priv->lock); nolock_reg_bfclr(priv, ECON1, ECON1_RXEN); @@ -917,7 +917,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) rxstat |= rsv[4]; if (netif_msg_rx_status(priv)) - enc28j60_dump_rsv(priv, __FUNCTION__, next_packet, len, rxstat); + enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat); if (!RSV_GETBIT(rxstat, RSV_RXOK)) { if (netif_msg_rx_err(priv)) @@ -941,7 +941,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) enc28j60_mem_read(priv, priv->next_pk_ptr + sizeof(rsv), len, skb_put(skb, len)); if (netif_msg_pktdata(priv)) - dump_packet(__FUNCTION__, skb->len, skb->data); + dump_packet(__func__, skb->len, skb->data); skb->protocol = eth_type_trans(skb, ndev); /* update statistics */ ndev->stats.rx_packets++; @@ -958,7 +958,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) erxrdpt = erxrdpt_workaround(next_packet, RXSTART_INIT, RXEND_INIT); if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT:0x%04x\n", - __FUNCTION__, erxrdpt); + __func__, erxrdpt); mutex_lock(&priv->lock); nolock_regw_write(priv, ERXRDPTL, erxrdpt); @@ -968,7 +968,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) reg = nolock_regw_read(priv, ERXRDPTL); if (reg != erxrdpt) printk(KERN_DEBUG DRV_NAME ": %s() ERXRDPT verify " - "error (0x%04x - 0x%04x)\n", __FUNCTION__, + "error (0x%04x - 0x%04x)\n", __func__, reg, erxrdpt); } #endif @@ -1006,7 +1006,7 @@ static int enc28j60_get_free_rxfifo(struct enc28j60_net *priv) mutex_unlock(&priv->lock); if (netif_msg_rx_status(priv)) printk(KERN_DEBUG DRV_NAME ": %s() free_space = %d\n", - __FUNCTION__, free_space); + __func__, free_space); return free_space; } @@ -1022,7 +1022,7 @@ static void enc28j60_check_link_status(struct net_device *ndev) reg = enc28j60_phy_read(priv, PHSTAT2); if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": %s() PHSTAT1: %04x, " - "PHSTAT2: %04x\n", __FUNCTION__, + "PHSTAT2: %04x\n", __func__, enc28j60_phy_read(priv, PHSTAT1), reg); duplex = reg & PHSTAT2_DPXSTAT; @@ -1095,7 +1095,7 @@ static void enc28j60_irq_work_handler(struct work_struct *work) int intflags, loop; if (netif_msg_intr(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__); /* disable further interrupts */ locked_reg_bfclr(priv, EIE, EIE_INTIE); @@ -1198,7 +1198,7 @@ static void enc28j60_irq_work_handler(struct work_struct *work) /* re-enable interrupts */ locked_reg_bfset(priv, EIE, EIE_INTIE); if (netif_msg_intr(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() exit\n", __func__); } /* @@ -1213,7 +1213,7 @@ static void enc28j60_hw_tx(struct enc28j60_net *priv) ": Tx Packet Len:%d\n", priv->tx_skb->len); if (netif_msg_pktdata(priv)) - dump_packet(__FUNCTION__, + dump_packet(__func__, priv->tx_skb->len, priv->tx_skb->data); enc28j60_packet_write(priv, priv->tx_skb->len, priv->tx_skb->data); @@ -1254,7 +1254,7 @@ static int enc28j60_send_packet(struct sk_buff *skb, struct net_device *dev) struct enc28j60_net *priv = netdev_priv(dev); if (netif_msg_tx_queued(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__); /* If some error occurs while trying to transmit this * packet, you should return '1' from this function. @@ -1325,7 +1325,7 @@ static int enc28j60_net_open(struct net_device *dev) struct enc28j60_net *priv = netdev_priv(dev); if (netif_msg_drv(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__); if (!is_valid_ether_addr(dev->dev_addr)) { if (netif_msg_ifup(priv)) { @@ -1363,7 +1363,7 @@ static int enc28j60_net_close(struct net_device *dev) struct enc28j60_net *priv = netdev_priv(dev); if (netif_msg_drv(priv)) - printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __FUNCTION__); + printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__); enc28j60_hw_disable(priv); enc28j60_lowpower(priv, true); diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c index 37bfeea8788..9164abb72d9 100644 --- a/drivers/net/ibm_newemac/phy.c +++ b/drivers/net/ibm_newemac/phy.c @@ -321,7 +321,7 @@ static struct mii_phy_def bcm5248_phy_def = { static int m88e1111_init(struct mii_phy *phy) { - pr_debug("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__); + pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__); phy_write(phy, 0x14, 0x0ce3); phy_write(phy, 0x18, 0x4101); phy_write(phy, 0x09, 0x0e00); diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 804698fc6a8..d85717e3022 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -85,7 +85,7 @@ struct ixgb_adapter; #define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ - __FUNCTION__ , ## args)) + __func__ , ## args)) /* TX/RX descriptor defines */ diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 63f678931ad..2198b77c53e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -44,7 +44,7 @@ #define DPRINTK(nlevel, klevel, fmt, args...) \ ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ - __FUNCTION__ , ## args))) + __func__ , ## args))) /* TX/RX descriptor defines */ #define IXGBE_DEFAULT_TXD 1024 diff --git a/drivers/net/meth.c b/drivers/net/meth.c index 0a97c26df6a..a1e22ed1f6e 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -41,7 +41,7 @@ #endif #if MFE_DEBUG>=1 -#define DPRINTK(str,args...) printk(KERN_DEBUG "meth: %s: " str, __FUNCTION__ , ## args) +#define DPRINTK(str,args...) printk(KERN_DEBUG "meth: %s: " str, __func__ , ## args) #define MFE_RX_DEBUG 2 #else #define DPRINTK(str,args...) diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 6d343efb271..4e7a5faf035 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -203,7 +203,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) out_badirq: printk(KERN_INFO "%s: %s(): irq %d for unknown device\n", - dev->name, __FUNCTION__, irq); + dev->name, __func__, irq); return ret; } diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index 3f9af759cb9..b9bed82e1d2 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -189,7 +189,7 @@ netx_eth_interrupt(int irq, void *dev_id) if ((status & ISR_CON_HI) || (status & ISR_IND_HI)) printk("%s: unexpected status: 0x%08x\n", - __FUNCTION__, status); + __func__, status); fill_level = readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id))); diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 244ab49c433..f8e601c51da 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -742,7 +742,7 @@ extern char netxen_nic_driver_name[]; } while (0) #else #define DPRINTK(klevel, fmt, args...) do { \ - printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\ + printk(KERN_##klevel PFX "%s: %s: " fmt, __func__,\ (adapter != NULL && adapter->netdev != NULL) ? \ adapter->netdev->name : NULL, \ ## args); } while(0) diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 53451c3b2c0..0a575fef29e 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -119,7 +119,7 @@ KERN_INFO " Support available from http://foo.com/bar/baz.html\n"; #ifdef NETDRV_DEBUG /* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) #else # define DPRINTK(fmt, args...) #endif @@ -130,7 +130,7 @@ KERN_INFO " Support available from http://foo.com/bar/baz.html\n"; # define assert(expr) \ if(!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ + #expr,__FILE__,__func__,__LINE__); \ } #endif diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f28c2022f3b..fb899c675f4 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -36,7 +36,7 @@ #define assert(expr) \ if (!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ + #expr,__FILE__,__func__,__LINE__); \ } #define dprintk(fmt, args...) \ do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index a2d50fad61a..6a1375f9cbb 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3133,7 +3133,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) if (skb == NULL) { spin_unlock_irqrestore(&fifo_data->tx_lock, flags); DBG_PRINT(ERR_DBG, "%s: Null skb ", - __FUNCTION__); + __func__); DBG_PRINT(ERR_DBG, "in Tx Free Intr\n"); return; } @@ -3493,7 +3493,7 @@ static void s2io_reset(struct s2io_nic * sp) unsigned long long mem_alloc_cnt, mem_free_cnt, watchdog_cnt; DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n", - __FUNCTION__, sp->dev->name); + __func__, sp->dev->name); /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); @@ -3515,7 +3515,7 @@ static void s2io_reset(struct s2io_nic * sp) } if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) { - DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__); + DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __func__); } pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd); @@ -3765,7 +3765,7 @@ static void restore_xmsi_data(struct s2io_nic *nic) val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, msix_index)) { - DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); + DBG_PRINT(ERR_DBG, "failed in %s\n", __func__); continue; } } @@ -3786,7 +3786,7 @@ static void store_xmsi_data(struct s2io_nic *nic) val64 = (s2BIT(15) | vBIT(msix_index, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, msix_index)) { - DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); + DBG_PRINT(ERR_DBG, "failed in %s\n", __func__); continue; } addr = readq(&bar0->xmsi_address); @@ -3809,7 +3809,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) GFP_KERNEL); if (!nic->entries) { DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \ - __FUNCTION__); + __func__); nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; return -ENOMEM; } @@ -3823,7 +3823,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) GFP_KERNEL); if (!nic->s2io_entries) { DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", - __FUNCTION__); + __func__); nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; kfree(nic->entries); nic->mac_control.stats_info->sw_stat.mem_freed @@ -6743,7 +6743,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) ret = s2io_card_up(sp); if (ret) { DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", - __FUNCTION__); + __func__); return ret; } s2io_wake_all_tx_queue(sp); @@ -7527,7 +7527,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) default: DBG_PRINT(ERR_DBG, "%s: Samadhana!!\n", - __FUNCTION__); + __func__); BUG(); } } @@ -7778,7 +7778,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) return -ENOMEM; } if ((ret = pci_request_regions(pdev, s2io_driver_name))) { - DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __FUNCTION__, ret); + DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __func__, ret); pci_disable_device(pdev); return -ENODEV; } @@ -7995,7 +7995,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) if (sp->device_type & XFRAME_II_DEVICE) { mode = s2io_verify_pci_mode(sp); if (mode < 0) { - DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__); + DBG_PRINT(ERR_DBG, "%s: ", __func__); DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n"); ret = -EBADSLT; goto set_swap_failed; @@ -8301,7 +8301,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) { DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n", - __FUNCTION__); + __func__); return -1; } @@ -8332,7 +8332,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, static int check_for_socket_match(struct lro *lro, struct iphdr *ip, struct tcphdr *tcp) { - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__); if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) || (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest)) return -1; @@ -8347,7 +8347,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp) static void initiate_new_session(struct lro *lro, u8 *l2h, struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag) { - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__); lro->l2h = l2h; lro->iph = ip; lro->tcph = tcp; @@ -8377,7 +8377,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro) struct tcphdr *tcp = lro->tcph; __sum16 nchk; struct stat_block *statinfo = sp->mac_control.stats_info; - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__); /* Update L3 header */ ip->tot_len = htons(lro->total_len); @@ -8405,7 +8405,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro) static void aggregate_new_rx(struct lro *lro, struct iphdr *ip, struct tcphdr *tcp, u32 l4_pyld) { - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__); lro->total_len += l4_pyld; lro->frags_len += l4_pyld; lro->tcp_next_seq += l4_pyld; @@ -8429,7 +8429,7 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip, { u8 *ptr; - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); + DBG_PRINT(INFO_DBG,"%s: Been here...\n", __func__); if (!tcp_pyld_len) { /* Runt frame or a pure ack */ @@ -8511,7 +8511,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp, if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) { DBG_PRINT(INFO_DBG, "%s:Out of order. expected " - "0x%x, actual 0x%x\n", __FUNCTION__, + "0x%x, actual 0x%x\n", __func__, (*lro)->tcp_next_seq, ntohl(tcph->seq)); @@ -8551,7 +8551,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp, if (ret == 0) { /* sessions exceeded */ DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n", - __FUNCTION__); + __func__); *lro = NULL; return ret; } @@ -8573,7 +8573,7 @@ s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer, u8 **tcp, break; default: DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n", - __FUNCTION__); + __func__); break; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index e15abc3606c..02cc064c2c8 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -183,7 +183,7 @@ static void smc911x_reset(struct net_device *dev) unsigned int reg, timeout=0, resets=1; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* Take out of PM setting first */ if ((SMC_GET_PMT_CTRL(lp) & PMT_CTRL_READY_) == 0) { @@ -272,7 +272,7 @@ static void smc911x_enable(struct net_device *dev) unsigned mask, cfg, cr; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); SMC_SET_MAC_ADDR(lp, dev->dev_addr); @@ -329,7 +329,7 @@ static void smc911x_shutdown(struct net_device *dev) unsigned cr; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __func__); /* Disable IRQ's */ SMC_SET_INT_EN(lp, 0); @@ -348,7 +348,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev) struct smc911x_local *lp = netdev_priv(dev); unsigned int fifo_count, timeout, reg; - DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__); + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __func__); fifo_count = SMC_GET_RX_FIFO_INF(lp) & 0xFFFF; if (fifo_count <= 4) { /* Manually dump the packet data */ @@ -382,7 +382,7 @@ static inline void smc911x_rcv(struct net_device *dev) unsigned char *data; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", - dev->name, __FUNCTION__); + dev->name, __func__); status = SMC_GET_RX_STS_FIFO(lp); DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n", dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff); @@ -460,7 +460,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) unsigned char *buf; unsigned long flags; - DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __func__); BUG_ON(lp->pending_tx_skb == NULL); skb = lp->pending_tx_skb; @@ -524,7 +524,7 @@ static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", - dev->name, __FUNCTION__); + dev->name, __func__); BUG_ON(lp->pending_tx_skb != NULL); @@ -596,7 +596,7 @@ static void smc911x_tx(struct net_device *dev) unsigned int tx_status; DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", - dev->name, __FUNCTION__); + dev->name, __func__); /* Collect the TX status */ while (((SMC_GET_TX_FIFO_INF(lp) & TX_FIFO_INF_TSUSED_) >> 16) != 0) { @@ -647,7 +647,7 @@ static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) SMC_GET_MII(lp, phyreg, phyaddr, phydata); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); return phydata; } @@ -661,7 +661,7 @@ static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, struct smc911x_local *lp = netdev_priv(dev); DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); SMC_SET_MII(lp, phyreg, phyaddr, phydata); } @@ -676,7 +676,7 @@ static void smc911x_phy_detect(struct net_device *dev) int phyaddr; unsigned int cfg, id1, id2; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); lp->phy_type = 0; @@ -746,7 +746,7 @@ static int smc911x_phy_fixed(struct net_device *dev) int phyaddr = lp->mii.phy_id; int bmcr; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* Enter Link Disable state */ SMC_GET_PHY_BMCR(lp, phyaddr, bmcr); @@ -793,7 +793,7 @@ static int smc911x_phy_reset(struct net_device *dev, int phy) unsigned long flags; unsigned int reg; - DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); reg = SMC_GET_PMT_CTRL(lp); @@ -852,7 +852,7 @@ static void smc911x_phy_check_media(struct net_device *dev, int init) int phyaddr = lp->mii.phy_id; unsigned int bmcr, cr; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { /* duplex state has changed */ @@ -892,7 +892,7 @@ static void smc911x_phy_configure(struct work_struct *work) int status; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __func__); /* * We should not be called if phy_type is zero. @@ -985,7 +985,7 @@ static void smc911x_phy_interrupt(struct net_device *dev) int phyaddr = lp->mii.phy_id; int status; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); if (lp->phy_type == 0) return; @@ -1013,7 +1013,7 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) unsigned int rx_overrun=0, cr, pkts; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); @@ -1186,7 +1186,7 @@ smc911x_tx_dma_irq(int dma, void *data) struct sk_buff *skb = lp->current_tx_skb; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ @@ -1222,7 +1222,7 @@ smc911x_rx_dma_irq(int dma, void *data) unsigned long flags; unsigned int pkts; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ SMC_DMA_ACK_IRQ(dev, dma); @@ -1270,7 +1270,7 @@ static void smc911x_timeout(struct net_device *dev) int status, mask; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); status = SMC_GET_INT(lp); @@ -1308,7 +1308,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) unsigned int mcr, update_multicast = 0; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); spin_lock_irqsave(&lp->lock, flags); SMC_GET_MAC_CR(lp, mcr); @@ -1410,7 +1410,7 @@ smc911x_open(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* * Check that the address is valid. If its not, refuse @@ -1418,7 +1418,7 @@ smc911x_open(struct net_device *dev) * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */ if (!is_valid_ether_addr(dev->dev_addr)) { - PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); + PRINTK("%s: no valid ethernet hw addr\n", __func__); return -EINVAL; } @@ -1447,7 +1447,7 @@ static int smc911x_close(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); netif_stop_queue(dev); netif_carrier_off(dev); @@ -1481,7 +1481,7 @@ smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) int ret, status; unsigned long flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); cmd->maxtxpkt = 1; cmd->maxrxpkt = 1; @@ -1619,7 +1619,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) { if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) { PRINTK("%s: %s timeout waiting for EEPROM to respond\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -EFAULT; } mdelay(1); @@ -1627,7 +1627,7 @@ static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) } if (timeout == 0) { PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n", - dev->name, __FUNCTION__); + dev->name, __func__); return -ETIMEDOUT; } return 0; @@ -1740,7 +1740,7 @@ static int __init smc911x_findirq(struct net_device *dev) int timeout = 20; unsigned long cookie; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); cookie = probe_irq_on(); @@ -1806,7 +1806,7 @@ static int __init smc911x_probe(struct net_device *dev) const char *version_string; unsigned long irq_flags; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); /* First, see if the endian word is recognized */ val = SMC_GET_BYTE_TEST(lp); @@ -2056,7 +2056,7 @@ static int smc911x_drv_probe(struct platform_device *pdev) unsigned int *addr; int ret; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; @@ -2127,7 +2127,7 @@ static int smc911x_drv_remove(struct platform_device *pdev) struct smc911x_local *lp = netdev_priv(ndev); struct resource *res; - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); @@ -2157,7 +2157,7 @@ static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) struct net_device *ndev = platform_get_drvdata(dev); struct smc911x_local *lp = netdev_priv(ndev); - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); if (ndev) { if (netif_running(ndev)) { netif_device_detach(ndev); @@ -2175,7 +2175,7 @@ static int smc911x_drv_resume(struct platform_device *dev) { struct net_device *ndev = platform_get_drvdata(dev); - DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); if (ndev) { struct smc911x_local *lp = netdev_priv(ndev); diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 53c2dda1dc8..ef5ce8845c9 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -270,7 +270,7 @@ static void smc_reset(struct net_device *dev) unsigned int ctl, cfg; struct sk_buff *pending_skb; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); /* Disable all interrupts, block TX tasklet */ spin_lock_irq(&lp->lock); @@ -363,7 +363,7 @@ static void smc_enable(struct net_device *dev) void __iomem *ioaddr = lp->base; int mask; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); /* see the header file for options in TCR/RCR DEFAULT */ SMC_SELECT_BANK(lp, 0); @@ -397,7 +397,7 @@ static void smc_shutdown(struct net_device *dev) void __iomem *ioaddr = lp->base; struct sk_buff *pending_skb; - DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + DBG(2, "%s: %s\n", CARDNAME, __func__); /* no more interrupts for me */ spin_lock_irq(&lp->lock); @@ -430,7 +430,7 @@ static inline void smc_rcv(struct net_device *dev) void __iomem *ioaddr = lp->base; unsigned int packet_number, status, packet_len; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); packet_number = SMC_GET_RXFIFO(lp); if (unlikely(packet_number & RXFIFO_REMPTY)) { @@ -577,7 +577,7 @@ static void smc_hardware_send_pkt(unsigned long data) unsigned int packet_no, len; unsigned char *buf; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); if (!smc_special_trylock(&lp->lock)) { netif_stop_queue(dev); @@ -662,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) void __iomem *ioaddr = lp->base; unsigned int numPages, poll_count, status; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); BUG_ON(lp->pending_tx_skb != NULL); @@ -734,7 +734,7 @@ static void smc_tx(struct net_device *dev) void __iomem *ioaddr = lp->base; unsigned int saved_packet, packet_no, tx_status, pkt_len; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); /* If the TX FIFO is empty then nothing to do */ packet_no = SMC_GET_TXFIFO(lp); @@ -856,7 +856,7 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); return phydata; @@ -883,7 +883,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO)); DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", - __FUNCTION__, phyaddr, phyreg, phydata); + __func__, phyaddr, phyreg, phydata); SMC_SELECT_BANK(lp, 2); } @@ -896,7 +896,7 @@ static void smc_phy_detect(struct net_device *dev) struct smc_local *lp = netdev_priv(dev); int phyaddr; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); lp->phy_type = 0; @@ -935,7 +935,7 @@ static int smc_phy_fixed(struct net_device *dev) int phyaddr = lp->mii.phy_id; int bmcr, cfg1; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); /* Enter Link Disable state */ cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG); @@ -1168,7 +1168,7 @@ static void smc_phy_interrupt(struct net_device *dev) int phyaddr = lp->mii.phy_id; int phy18; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); if (lp->phy_type == 0) return; @@ -1236,7 +1236,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) int status, mask, timeout, card_stats; int saved_pointer; - DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + DBG(3, "%s: %s\n", dev->name, __func__); spin_lock(&lp->lock); @@ -1358,7 +1358,7 @@ static void smc_timeout(struct net_device *dev) void __iomem *ioaddr = lp->base; int status, mask, eph_st, meminfo, fifo; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); spin_lock_irq(&lp->lock); status = SMC_GET_INT(lp); @@ -1402,7 +1402,7 @@ static void smc_set_multicast_list(struct net_device *dev) unsigned char multicast_table[8]; int update_multicast = 0; - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); if (dev->flags & IFF_PROMISC) { DBG(2, "%s: RCR_PRMS\n", dev->name); @@ -1505,7 +1505,7 @@ smc_open(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); /* * Check that the address is valid. If its not, refuse @@ -1513,7 +1513,7 @@ smc_open(struct net_device *dev) * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */ if (!is_valid_ether_addr(dev->dev_addr)) { - PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); + PRINTK("%s: no valid ethernet hw addr\n", __func__); return -EINVAL; } @@ -1557,7 +1557,7 @@ static int smc_close(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); - DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + DBG(2, "%s: %s\n", dev->name, __func__); netif_stop_queue(dev); netif_carrier_off(dev); @@ -1700,7 +1700,7 @@ static int __init smc_findirq(struct smc_local *lp) int timeout = 20; unsigned long cookie; - DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + DBG(2, "%s: %s\n", CARDNAME, __func__); cookie = probe_irq_on(); @@ -1778,7 +1778,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr, const char *version_string; DECLARE_MAC_BUF(mac); - DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + DBG(2, "%s: %s\n", CARDNAME, __func__); /* First, see if the high byte is 0x33 */ val = SMC_CURRENT_BANK(lp); diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index 7db48f1cd94..efaf84d9757 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -539,22 +539,22 @@ struct txd_desc { #define ERR(fmt, args...) printk(KERN_ERR fmt, ## args) #define DBG2(fmt, args...) \ - printk(KERN_ERR "%s:%-5d: " fmt, __FUNCTION__, __LINE__, ## args) + printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args) #define BDX_ASSERT(x) BUG_ON(x) #ifdef DEBUG #define ENTER do { \ - printk(KERN_ERR "%s:%-5d: ENTER\n", __FUNCTION__, __LINE__); \ + printk(KERN_ERR "%s:%-5d: ENTER\n", __func__, __LINE__); \ } while (0) #define RET(args...) do { \ - printk(KERN_ERR "%s:%-5d: RETURN\n", __FUNCTION__, __LINE__); \ + printk(KERN_ERR "%s:%-5d: RETURN\n", __func__, __LINE__); \ return args; } while (0) #define DBG(fmt, args...) \ - printk(KERN_ERR "%s:%-5d: " fmt, __FUNCTION__, __LINE__, ## args) + printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args) #else #define ENTER do { } while (0) #define RET(args...) return args diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 43fde99b24a..eb1da6f0b08 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -263,7 +263,7 @@ static inline void tsi108_write_tbi(struct tsi108_prv_data *data, return; udelay(10); } - printk(KERN_ERR "%s function time out \n", __FUNCTION__); + printk(KERN_ERR "%s function time out \n", __func__); } static int mii_speed(struct mii_if_info *mii) @@ -1059,7 +1059,7 @@ static void tsi108_stop_ethernet(struct net_device *dev) return; udelay(10); } - printk(KERN_ERR "%s function time out \n", __FUNCTION__); + printk(KERN_ERR "%s function time out \n", __func__); } static void tsi108_reset_ether(struct tsi108_prv_data * data) @@ -1244,7 +1244,7 @@ static void tsi108_init_phy(struct net_device *dev) udelay(10); } if (i == 0) - printk(KERN_ERR "%s function time out \n", __FUNCTION__); + printk(KERN_ERR "%s function time out \n", __func__); if (data->phy_type == TSI108_PHY_BCM54XX) { tsi108_write_mii(data, 0x09, 0x0300); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8f944e57fd5..c87747bb24c 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -400,7 +400,7 @@ static struct enet_addr_container *get_enet_addr_container(void) enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL); if (!enet_addr_cont) { ugeth_err("%s: No memory for enet_addr_container object.", - __FUNCTION__); + __func__); return NULL; } @@ -427,7 +427,7 @@ static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth, struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illegal paddr_num.", __FUNCTION__); + ugeth_warn("%s: Illegal paddr_num.", __func__); return -EINVAL; } @@ -447,7 +447,7 @@ static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); + ugeth_warn("%s: Illagel paddr_num.", __func__); return -EINVAL; } @@ -1441,7 +1441,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) u32 upsmr, maccfg2, tbiBaseAddress; u16 value; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); ug_info = ugeth->ug_info; ug_regs = ugeth->ug_regs; @@ -1504,7 +1504,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) if (ret_val != 0) { if (netif_msg_probe(ugeth)) ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.", - __FUNCTION__); + __func__); return ret_val; } @@ -1744,7 +1744,7 @@ static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { if (netif_msg_probe(ugeth)) - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + ugeth_err("%s: ucc_num out of range.", __func__); return -EINVAL; } @@ -1773,7 +1773,7 @@ static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { if (netif_msg_probe(ugeth)) - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + ugeth_err("%s: ucc_num out of range.", __func__); return -EINVAL; } @@ -2062,7 +2062,7 @@ static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth ugeth_warn ("%s: multicast address added to paddr will have no " "effect - is this what you wanted?", - __FUNCTION__); + __func__); ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */ /* store address in our database */ @@ -2278,7 +2278,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) struct phy_device *phydev = ugeth->phydev; u32 tempval; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); /* Disable the controller */ ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); @@ -2315,7 +2315,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) (uf_info->bd_mem_part == MEM_PART_MURAM))) { if (netif_msg_probe(ugeth)) ugeth_err("%s: Bad memory partition value.", - __FUNCTION__); + __func__); return -EINVAL; } @@ -2327,7 +2327,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (netif_msg_probe(ugeth)) ugeth_err ("%s: Rx BD ring length must be multiple of 4, no smaller than 8.", - __FUNCTION__); + __func__); return -EINVAL; } } @@ -2338,7 +2338,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (netif_msg_probe(ugeth)) ugeth_err ("%s: Tx BD ring length must be no smaller than 2.", - __FUNCTION__); + __func__); return -EINVAL; } } @@ -2349,21 +2349,21 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (netif_msg_probe(ugeth)) ugeth_err ("%s: max_rx_buf_length must be non-zero multiple of 128.", - __FUNCTION__); + __func__); return -EINVAL; } /* num Tx queues */ if (ug_info->numQueuesTx > NUM_TX_QUEUES) { if (netif_msg_probe(ugeth)) - ugeth_err("%s: number of tx queues too large.", __FUNCTION__); + ugeth_err("%s: number of tx queues too large.", __func__); return -EINVAL; } /* num Rx queues */ if (ug_info->numQueuesRx > NUM_RX_QUEUES) { if (netif_msg_probe(ugeth)) - ugeth_err("%s: number of rx queues too large.", __FUNCTION__); + ugeth_err("%s: number of rx queues too large.", __func__); return -EINVAL; } @@ -2374,7 +2374,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) ugeth_err ("%s: VLAN priority table entry must not be" " larger than number of Rx queues.", - __FUNCTION__); + __func__); return -EINVAL; } } @@ -2386,7 +2386,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) ugeth_err ("%s: IP priority table entry must not be" " larger than number of Rx queues.", - __FUNCTION__); + __func__); return -EINVAL; } } @@ -2394,7 +2394,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (ug_info->cam && !ug_info->ecamptr) { if (netif_msg_probe(ugeth)) ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", - __FUNCTION__); + __func__); return -EINVAL; } @@ -2404,7 +2404,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (netif_msg_probe(ugeth)) ugeth_err("%s: Number of station addresses greater than 1 " "not allowed in extended parsing mode.", - __FUNCTION__); + __func__); return -EINVAL; } @@ -2418,7 +2418,7 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* Initialize the general fast UCC block. */ if (ucc_fast_init(uf_info, &ugeth->uccf)) { if (netif_msg_probe(ugeth)) - ugeth_err("%s: Failed to init uccf.", __FUNCTION__); + ugeth_err("%s: Failed to init uccf.", __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2448,7 +2448,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) u8 __iomem *endOfRing; u8 numThreadsRxNumerical, numThreadsTxNumerical; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); uccf = ugeth->uccf; ug_info = ugeth->ug_info; uf_info = &ug_info->uf_info; @@ -2474,7 +2474,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) default: if (netif_msg_ifup(ugeth)) ugeth_err("%s: Bad number of Rx threads value.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2499,7 +2499,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) default: if (netif_msg_ifup(ugeth)) ugeth_err("%s: Bad number of Tx threads value.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2553,7 +2553,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (ret_val != 0) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: IPGIFG initialization parameter too large.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return ret_val; } @@ -2571,7 +2571,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (ret_val != 0) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Half Duplex initialization parameter too large.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return ret_val; } @@ -2626,7 +2626,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate memory for Tx bd rings.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2662,7 +2662,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate memory for Rx bd rings.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2678,7 +2678,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (ugeth->tx_skbuff[j] == NULL) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Could not allocate tx_skbuff", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2710,7 +2710,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (ugeth->rx_skbuff[j] == NULL) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Could not allocate rx_skbuff", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2744,7 +2744,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2767,7 +2767,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2797,7 +2797,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2841,7 +2841,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_scheduler.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2892,7 +2892,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ugeth_err ("%s: Can not allocate DPRAM memory for" " p_tx_fw_statistics_pram.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2932,7 +2932,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2954,7 +2954,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2978,7 +2978,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for" - " p_rx_fw_statistics_pram.", __FUNCTION__); + " p_rx_fw_statistics_pram.", __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3001,7 +3001,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for" - " p_rx_irq_coalescing_tbl.", __FUNCTION__); + " p_rx_irq_coalescing_tbl.", __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3070,7 +3070,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3147,7 +3147,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (!ug_info->extendedFilteringChainPointer) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Null Extended Filtering Chain Pointer.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3161,7 +3161,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for" - " p_exf_glbl_param.", __FUNCTION__); + " p_exf_glbl_param.", __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3209,7 +3209,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate memory for" - " p_UccInitEnetParamShadows.", __FUNCTION__); + " p_UccInitEnetParamShadows.", __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3244,7 +3244,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Invalid largest External Lookup Key Size.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3271,7 +3271,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->riscRx, 1)) != 0) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3287,7 +3287,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->riscTx, 0)) != 0) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3297,7 +3297,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Can not fill Rx bds with buffers.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3309,7 +3309,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (netif_msg_ifup(ugeth)) ugeth_err ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", - __FUNCTION__); + __func__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3360,7 +3360,7 @@ static void ucc_geth_timeout(struct net_device *dev) { struct ucc_geth_private *ugeth = netdev_priv(dev); - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); dev->stats.tx_errors++; @@ -3386,7 +3386,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 bd_status; u8 txQ = 0; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); spin_lock_irq(&ugeth->lock); @@ -3459,7 +3459,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit u8 *bdBuffer; struct net_device *dev; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); dev = ugeth->dev; @@ -3481,7 +3481,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit (bd_status & R_ERRORS_FATAL)) { if (netif_msg_rx_err(ugeth)) ugeth_err("%s, %d: ERROR!!! skb - 0x%08x", - __FUNCTION__, __LINE__, (u32) skb); + __func__, __LINE__, (u32) skb); if (skb) dev_kfree_skb_any(skb); @@ -3507,7 +3507,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit skb = get_new_skb(ugeth, bd); if (!skb) { if (netif_msg_rx_err(ugeth)) - ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); + ugeth_warn("%s: No Rx Data Buffer", __func__); dev->stats.rx_dropped++; break; } @@ -3613,7 +3613,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) register u32 tx_mask; u8 i; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); uccf = ugeth->uccf; ug_info = ugeth->ug_info; @@ -3683,13 +3683,13 @@ static int ucc_geth_open(struct net_device *dev) struct ucc_geth_private *ugeth = netdev_priv(dev); int err; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); /* Test station address */ if (dev->dev_addr[0] & ENET_GROUP_ADDR) { if (netif_msg_ifup(ugeth)) ugeth_err("%s: Multicast address used for station address" - " - is this what you wanted?", __FUNCTION__); + " - is this what you wanted?", __func__); return -EINVAL; } @@ -3772,7 +3772,7 @@ static int ucc_geth_close(struct net_device *dev) { struct ucc_geth_private *ugeth = netdev_priv(dev); - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); napi_disable(&ugeth->napi); @@ -3840,7 +3840,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, }; - ugeth_vdbg("%s: IN", __FUNCTION__); + ugeth_vdbg("%s: IN", __func__); prop = of_get_property(np, "cell-index", NULL); if (!prop) { @@ -3857,7 +3857,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (ug_info == NULL) { if (netif_msg_probe(&debug)) ugeth_err("%s: [%d] Missing additional data!", - __FUNCTION__, ucc_num); + __func__, ucc_num); return -ENODEV; } diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index ca9d00c1194..b5143509e8b 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -118,7 +118,7 @@ static void mcs7830_async_cmd_callback(struct urb *urb) if (urb->status < 0) printk(KERN_DEBUG "%s() failed with %d\n", - __FUNCTION__, urb->status); + __func__, urb->status); kfree(req); usb_free_urb(urb); diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 8c19307e504..38b90e7a7ed 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -119,7 +119,7 @@ static void ctrl_callback(struct urb *urb) default: if (netif_msg_drv(pegasus) && printk_ratelimit()) dev_dbg(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, urb->status); + __func__, urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; wake_up(&pegasus->ctrl_wait); @@ -136,7 +136,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, if (!buffer) { if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __FUNCTION__); + __func__); return -ENOMEM; } add_wait_queue(&pegasus->ctrl_wait, &wait); @@ -224,7 +224,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); + __func__, ret); goto out; } @@ -246,7 +246,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) if (!tmp) { if (netif_msg_drv(pegasus)) dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __FUNCTION__); + __func__); return -ENOMEM; } memcpy(tmp, &data, 1); @@ -277,7 +277,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus) && printk_ratelimit()) dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); + __func__, ret); goto out; } @@ -310,7 +310,7 @@ static int update_eth_regs_async(pegasus_t * pegasus) netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); + __func__, ret); } return ret; @@ -341,7 +341,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) } fail: if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); + dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); return ret; } @@ -378,7 +378,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) fail: if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); + dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); return -ETIMEDOUT; } @@ -415,7 +415,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) fail: if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); + dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); return -ETIMEDOUT; } @@ -463,7 +463,7 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) return ret; fail: if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); + dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); return -ETIMEDOUT; } #endif /* PEGASUS_WRITE_EEPROM */ diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index 1b95b04c925..29a33090d3d 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1381,7 +1381,7 @@ enum velocity_msg_level { #define ASSERT(x) { \ if (!(x)) { \ printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\ - __FUNCTION__, __LINE__);\ + __func__, __LINE__);\ BUG(); \ }\ } diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c index d14e6678dee..a5ddc6c8963 100644 --- a/drivers/net/wan/cycx_drv.c +++ b/drivers/net/wan/cycx_drv.c @@ -407,7 +407,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) if (cfm->version != CFM_VERSION) { printk(KERN_ERR "%s:%s: firmware format %u rejected! " "Expecting %u.\n", - modname, __FUNCTION__, cfm->version, CFM_VERSION); + modname, __func__, cfm->version, CFM_VERSION); return -EINVAL; } @@ -420,7 +420,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) */ if (cksum != cfm->checksum) { printk(KERN_ERR "%s:%s: firmware corrupted!\n", - modname, __FUNCTION__); + modname, __func__); printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n", len - (int)sizeof(struct cycx_firmware) - 1, cfm->info.codesize); @@ -432,7 +432,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) /* If everything is ok, set reset, data and code pointers */ img_hdr = (struct cycx_fw_header *)&cfm->image; #ifdef FIRMWARE_DEBUG - printk(KERN_INFO "%s:%s: image sizes\n", __FUNCTION__, modname); + printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname); printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size); printk(KERN_INFO " data=%lu\n", img_hdr->data_size); printk(KERN_INFO " code=%lu\n", img_hdr->code_size); diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index d3b28b01b9f..5a7303dc096 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -874,7 +874,7 @@ static void cycx_x25_irq_connect(struct cycx_device *card, nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1); dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n", - __FUNCTION__, lcn, loc, rem); + __func__, lcn, loc, rem); dev = cycx_x25_get_dev_by_dte_addr(wandev, rem); if (!dev) { @@ -902,7 +902,7 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card, cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key)); dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n", - card->devname, __FUNCTION__, lcn, key); + card->devname, __func__, lcn, key); dev = cycx_x25_get_dev_by_lcn(wandev, -key); if (!dev) { @@ -929,7 +929,7 @@ static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card, cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); dprintk(1, KERN_INFO "%s: %s:lcn=%d\n", - card->devname, __FUNCTION__, lcn); + card->devname, __func__, lcn); dev = cycx_x25_get_dev_by_lcn(wandev, lcn); if (!dev) { /* Invalid channel, discard packet */ @@ -950,7 +950,7 @@ static void cycx_x25_irq_disconnect(struct cycx_device *card, u8 lcn; cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn)); - dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn); + dprintk(1, KERN_INFO "%s:lcn=%d\n", __func__, lcn); dev = cycx_x25_get_dev_by_lcn(wandev, lcn); if (dev) { @@ -1381,7 +1381,7 @@ static void cycx_x25_chan_timer(unsigned long d) cycx_x25_chan_disconnect(dev); else printk(KERN_ERR "%s: %s for svc (%s) not connected!\n", - chan->card->devname, __FUNCTION__, dev->name); + chan->card->devname, __func__, dev->name); } /* Set logical channel state. */ @@ -1485,7 +1485,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event) unsigned char *ptr; if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "%s: out of memory\n", __FUNCTION__); + printk(KERN_ERR "%s: out of memory\n", __func__); return; } diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index f5d55ad0226..5f1ccb2b08b 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -647,7 +647,7 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, skb = dpriv->rx_skbuff[dpriv->rx_current++%RX_RING_SIZE]; if (!skb) { - printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __FUNCTION__); + printk(KERN_DEBUG "%s: skb=0 (%s)\n", dev->name, __func__); goto refill; } pkt_len = TO_SIZE(le32_to_cpu(rx_fd->state2)); diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 4518d0aa248..4917a94943b 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -548,7 +548,7 @@ static int pc300_tiocmset(struct tty_struct *tty, struct file *file, { st_cpc_tty_area *cpc_tty; - CPC_TTY_DBG("%s: set:%x clear:%x\n", __FUNCTION__, set, clear); + CPC_TTY_DBG("%s: set:%x clear:%x\n", __func__, set, clear); if (!tty || !tty->driver_data ) { CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n"); -- cgit v1.2.3 From 5050015597efb5e52a0b21e30a8adb2f7d7b7fba Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Wed, 20 Aug 2008 16:51:59 -0700 Subject: sundance: set carrier status on link change events Check if the link is available when a changed interrupt has been received and set the carrier status appropriately. The code is copied nearly verbatim from the dl2k module. The link status could be used in more places in the driver, but this is enough to get the carrier status reported to userspace. Fixes kernel bug #7487: http://bugzilla.kernel.org/show_bug.cgi?id=7487 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Dan Nicholson Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 95 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 7d5561b8241..f860ea15039 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -409,6 +409,7 @@ static int change_mtu(struct net_device *dev, int new_mtu); static int eeprom_read(void __iomem *ioaddr, int location); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); +static int mdio_wait_link(struct net_device *dev, int wait); static int netdev_open(struct net_device *dev); static void check_duplex(struct net_device *dev); static void netdev_timer(unsigned long data); @@ -785,6 +786,24 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val return; } +static int mdio_wait_link(struct net_device *dev, int wait) +{ + int bmsr; + int phy_id; + struct netdev_private *np; + + np = netdev_priv(dev); + phy_id = np->phys[0]; + + do { + bmsr = mdio_read(dev, phy_id, MII_BMSR); + if (bmsr & 0x0004) + return 0; + mdelay(1); + } while (--wait > 0); + return -1; +} + static int netdev_open(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); @@ -1393,41 +1412,51 @@ static void netdev_error(struct net_device *dev, int intr_status) int speed; if (intr_status & LinkChange) { - if (np->an_enable) { - mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE); - mii_lpa= mdio_read (dev, np->phys[0], MII_LPA); - mii_advertise &= mii_lpa; - printk (KERN_INFO "%s: Link changed: ", dev->name); - if (mii_advertise & ADVERTISE_100FULL) { - np->speed = 100; - printk ("100Mbps, full duplex\n"); - } else if (mii_advertise & ADVERTISE_100HALF) { - np->speed = 100; - printk ("100Mbps, half duplex\n"); - } else if (mii_advertise & ADVERTISE_10FULL) { - np->speed = 10; - printk ("10Mbps, full duplex\n"); - } else if (mii_advertise & ADVERTISE_10HALF) { - np->speed = 10; - printk ("10Mbps, half duplex\n"); - } else - printk ("\n"); + if (mdio_wait_link(dev, 10) == 0) { + printk(KERN_INFO "%s: Link up\n", dev->name); + if (np->an_enable) { + mii_advertise = mdio_read(dev, np->phys[0], + MII_ADVERTISE); + mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); + mii_advertise &= mii_lpa; + printk(KERN_INFO "%s: Link changed: ", + dev->name); + if (mii_advertise & ADVERTISE_100FULL) { + np->speed = 100; + printk("100Mbps, full duplex\n"); + } else if (mii_advertise & ADVERTISE_100HALF) { + np->speed = 100; + printk("100Mbps, half duplex\n"); + } else if (mii_advertise & ADVERTISE_10FULL) { + np->speed = 10; + printk("10Mbps, full duplex\n"); + } else if (mii_advertise & ADVERTISE_10HALF) { + np->speed = 10; + printk("10Mbps, half duplex\n"); + } else + printk("\n"); + } else { + mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR); + speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; + np->speed = speed; + printk(KERN_INFO "%s: Link changed: %dMbps ,", + dev->name, speed); + printk("%s duplex.\n", + (mii_ctl & BMCR_FULLDPLX) ? + "full" : "half"); + } + check_duplex(dev); + if (np->flowctrl && np->mii_if.full_duplex) { + iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200, + ioaddr + MulticastFilter1+2); + iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl, + ioaddr + MACCtrl0); + } + netif_carrier_on(dev); } else { - mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR); - speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; - np->speed = speed; - printk (KERN_INFO "%s: Link changed: %dMbps ,", - dev->name, speed); - printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ? - "full" : "half"); - } - check_duplex (dev); - if (np->flowctrl && np->mii_if.full_duplex) { - iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200, - ioaddr + MulticastFilter1+2); - iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl, - ioaddr + MACCtrl0); + printk(KERN_INFO "%s: Link down\n", dev->name); + netif_carrier_off(dev); } } if (intr_status & StatsMax) { -- cgit v1.2.3 From ec68db6930635b25ef5ba4983053635f5b4bf35e Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 20 Aug 2008 13:52:48 -0700 Subject: netxen: enable msi-x for quad-gig boards NX3031 firmware now supports MSI-X interrupts on Quad GbE boards. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 0f8ea2c7728..6ef3f0d84bc 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -241,7 +241,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - adapter->msix_supported = 0; + adapter->msix_supported = !!use_msi_x; adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; break; -- cgit v1.2.3 From fa53ebac42d3de04619c813f5f6628ca2a7ce97f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 13 Sep 2008 21:17:09 -0400 Subject: bonding: add more ethtool support This patch allows reporting the link, checksum, and feature settings of bonded device by using generic hooks. Signed-off-by: Stephen Hemminger Acked-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index babe4610c39..8e2be24f3fe 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4493,6 +4493,12 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, static const struct ethtool_ops bond_ethtool_ops = { .get_drvinfo = bond_ethtool_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .get_tso = ethtool_op_get_tso, + .get_ufo = ethtool_op_get_ufo, + .get_flags = ethtool_op_get_flags, }; /* -- cgit v1.2.3 From b4f151ff899362fec952c45d166252c9912c041f Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 24 Sep 2008 17:48:26 +0100 Subject: MN10300: Move asm-arm/cnt32_to_63.h to include/linux/ Move asm-arm/cnt32_to_63.h to include/linux/ so that MN10300 can make use of it too. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/arm/mach-pxa/time.c | 2 +- arch/arm/mach-sa1100/generic.c | 2 +- arch/arm/mach-versatile/core.c | 2 +- include/linux/cnt32_to_63.h | 80 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 include/linux/cnt32_to_63.h diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 67e18509d7b..b0d6b32654c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -17,9 +17,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 1362994c78a..b422526f6d8 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -18,9 +18,9 @@ #include #include /* just for sched_clock() - funny that */ #include +#include #include -#include #include #include #include diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index d75e795c893..b638f10411e 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -28,8 +28,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/include/linux/cnt32_to_63.h b/include/linux/cnt32_to_63.h new file mode 100644 index 00000000000..8c0f9505b48 --- /dev/null +++ b/include/linux/cnt32_to_63.h @@ -0,0 +1,80 @@ +/* + * Extend a 32-bit counter to 63 bits + * + * Author: Nicolas Pitre + * Created: December 3, 2006 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#ifndef __LINUX_CNT32_TO_63_H__ +#define __LINUX_CNT32_TO_63_H__ + +#include +#include +#include + +/* this is used only to give gcc a clue about good code generation */ +union cnt32_to_63 { + struct { +#if defined(__LITTLE_ENDIAN) + u32 lo, hi; +#elif defined(__BIG_ENDIAN) + u32 hi, lo; +#endif + }; + u64 val; +}; + + +/** + * cnt32_to_63 - Expand a 32-bit counter to a 63-bit counter + * @cnt_lo: The low part of the counter + * + * Many hardware clock counters are only 32 bits wide and therefore have + * a relatively short period making wrap-arounds rather frequent. This + * is a problem when implementing sched_clock() for example, where a 64-bit + * non-wrapping monotonic value is expected to be returned. + * + * To overcome that limitation, let's extend a 32-bit counter to 63 bits + * in a completely lock free fashion. Bits 0 to 31 of the clock are provided + * by the hardware while bits 32 to 62 are stored in memory. The top bit in + * memory is used to synchronize with the hardware clock half-period. When + * the top bit of both counters (hardware and in memory) differ then the + * memory is updated with a new value, incrementing it when the hardware + * counter wraps around. + * + * Because a word store in memory is atomic then the incremented value will + * always be in synch with the top bit indicating to any potential concurrent + * reader if the value in memory is up to date or not with regards to the + * needed increment. And any race in updating the value in memory is harmless + * as the same value would simply be stored more than once. + * + * The only restriction for the algorithm to work properly is that this + * code must be executed at least once per each half period of the 32-bit + * counter to properly update the state bit in memory. This is usually not a + * problem in practice, but if it is then a kernel timer could be scheduled + * to manage for this code to be executed often enough. + * + * Note that the top bit (bit 63) in the returned value should be considered + * as garbage. It is not cleared here because callers are likely to use a + * multiplier on the returned value which can get rid of the top bit + * implicitly by making the multiplier even, therefore saving on a runtime + * clear-bit instruction. Otherwise caller must remember to clear the top + * bit explicitly. + */ +#define cnt32_to_63(cnt_lo) \ +({ \ + static volatile u32 __m_cnt_hi; \ + union cnt32_to_63 __x; \ + __x.hi = __m_cnt_hi; \ + __x.lo = (cnt_lo); \ + if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ + __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ + __x.val; \ +}) + +#endif -- cgit v1.2.3 From 08ec3c2d45bac41c782acb4e3331ac5881b2c68a Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 24 Sep 2008 17:48:31 +0100 Subject: MN10300: Make sched_clock() report time since boot Make sched_clock() report time since boot rather than time since last timer interrupt. Make sched_clock() expand and scale the 32-bit TSC value running at IOCLK speed (~33MHz) to a 64-bit nanosecond counter, using cnt32_to_63() acquired from the ARM arch and without using slow DIVU instructions every call. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/mn10300/kernel/time.c | 52 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index babb7c2ac37..e4606586f94 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -1,6 +1,6 @@ /* MN10300 Low level time management * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2007-2008 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * - Derived from arch/i386/kernel/time.c * @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,27 +41,54 @@ static struct irqaction timer_irq = { .name = "timer", }; +static unsigned long sched_clock_multiplier; + /* * scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) { union { - unsigned long long l; - u32 w[2]; - } quot; + unsigned long long ll; + unsigned l[2]; + } tsc64, result; + unsigned long tsc, tmp; + unsigned product[3]; /* 96-bit intermediate value */ + + /* read the TSC value + */ + tsc = 0 - get_cycles(); /* get_cycles() counts down */ - quot.w[0] = mn10300_last_tsc - get_cycles(); - quot.w[1] = 1000000000; + /* expand to 64-bits. + * - sched_clock() must be called once a minute or better or the + * following will go horribly wrong - see cnt32_to_63() + */ + tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; - asm("mulu %2,%3,%0,%1" - : "=r"(quot.w[1]), "=r"(quot.w[0]) - : "0"(quot.w[1]), "1"(quot.w[0]) + /* scale the 64-bit TSC value to a nanosecond value via a 96-bit + * intermediate + */ + asm("mulu %2,%0,%3,%0 \n" /* LSW * mult -> 0:%3:%0 */ + "mulu %2,%1,%2,%1 \n" /* MSW * mult -> %2:%1:0 */ + "add %3,%1 \n" + "addc 0,%2 \n" /* result in %2:%1:%0 */ + : "=r"(product[0]), "=r"(product[1]), "=r"(product[2]), "=r"(tmp) + : "0"(tsc64.l[0]), "1"(tsc64.l[1]), "2"(sched_clock_multiplier) : "cc"); - do_div(quot.l, MN10300_TSCCLK); + result.l[0] = product[1] << 16 | product[0] >> 16; + result.l[1] = product[2] << 16 | product[1] >> 16; - return quot.l; + return result.ll; +} + +/* + * initialise the scheduler clock + */ +static void __init mn10300_sched_clock_init(void) +{ + sched_clock_multiplier = + __muldiv64u(NSEC_PER_SEC, 1 << 16, MN10300_TSCCLK); } /* @@ -128,4 +156,6 @@ void __init time_init(void) /* start the watchdog timer */ watchdog_go(); #endif + + mn10300_sched_clock_init(); } -- cgit v1.2.3 From f1d58672de4e89478e0b02ea8fd1f60eb0626457 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 19 Sep 2008 12:56:02 +0200 Subject: qeth: use firmware MAC-address for layer2 hsi-devices Real HiperSocket devices in layer2 mode have a firmware-created MAC-address. This change enables the qeth driver to use this firmware MAC-address for layer2 HiperSocket devices. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_l2_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 3ac3cc1e03c..573b5e564ed 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -559,7 +559,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) "device %s: x%x\n", CARD_BUS_ID(card), rc); } - if (card->info.guestlan) { + if ((card->info.type == QETH_CARD_TYPE_IQD) || + (card->info.guestlan)) { rc = qeth_setadpparms_change_macaddr(card); if (rc) { QETH_DBF_MESSAGE(2, "couldn't get MAC address on " -- cgit v1.2.3 From 28a7e4c906bd86419eb8572b3b1343e619cd1470 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 19 Sep 2008 12:56:03 +0200 Subject: qeth: avoid qeth recovery problems Do not touch IFF_UP flag during qeth recovery, but invoke dev_close() in case of failing recovery. Cancel outstanding control commands in case of Data Checks or Channel Checks. Do not invoke qeth_l2_del_all_mc() in case of a hard stop to speed up removal of qeth devices. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_core_main.c | 4 +++- drivers/s390/net/qeth_l2_main.c | 11 +++++++---- drivers/s390/net/qeth_l3_main.c | 8 +++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c7ab1b86451..908f50b17e2 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -760,7 +760,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb) if (sense[SENSE_COMMAND_REJECT_BYTE] & SENSE_COMMAND_REJECT_FLAG) { QETH_DBF_TEXT(TRACE, 2, "CMDREJi"); - return 0; + return 1; } if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) { QETH_DBF_TEXT(TRACE, 2, "AFFE"); @@ -884,6 +884,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, } rc = qeth_get_problem(cdev, irb); if (rc) { + qeth_clear_ipacmd_list(card); qeth_schedule_recovery(card); goto out; } @@ -4147,6 +4148,7 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev) unsigned long flags; struct qeth_card *card = dev_get_drvdata(&gdev->dev); + QETH_DBF_TEXT(SETUP, 2, "removedv"); if (card->discipline.ccwgdriver) { card->discipline.ccwgdriver->remove(gdev); qeth_core_free_discipline(card); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 573b5e564ed..955ba7a31b9 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -395,7 +395,8 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) } if (card->state == CARD_STATE_SOFTSETUP) { qeth_l2_process_vlans(card, 1); - qeth_l2_del_all_mc(card); + if (!card->use_hard_stop) + qeth_l2_del_all_mc(card); qeth_clear_ipacmd_list(card); card->state = CARD_STATE_HARDSETUP; } @@ -826,7 +827,6 @@ static int qeth_l2_open(struct net_device *dev) } card->data.state = CH_STATE_UP; card->state = CARD_STATE_UP; - card->dev->flags |= IFF_UP; netif_start_queue(dev); if (!card->lan_online && netif_carrier_ok(dev)) @@ -841,7 +841,6 @@ static int qeth_l2_stop(struct net_device *dev) QETH_DBF_TEXT(TRACE, 4, "qethstop"); netif_tx_disable(dev); - card->dev->flags &= ~IFF_UP; if (card->state == CARD_STATE_UP) card->state = CARD_STATE_SOFTSETUP; return 0; @@ -1138,9 +1137,13 @@ static int qeth_l2_recover(void *ptr) if (!rc) PRINT_INFO("Device %s successfully recovered!\n", CARD_BUS_ID(card)); - else + else { + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); PRINT_INFO("Device %s could not be recovered!\n", CARD_BUS_ID(card)); + } return 0; } diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index dd72c3c2016..99547dea44d 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2795,7 +2795,6 @@ static int qeth_l3_open(struct net_device *dev) return -ENODEV; card->data.state = CH_STATE_UP; card->state = CARD_STATE_UP; - card->dev->flags |= IFF_UP; netif_start_queue(dev); if (!card->lan_online && netif_carrier_ok(dev)) @@ -2809,7 +2808,6 @@ static int qeth_l3_stop(struct net_device *dev) QETH_DBF_TEXT(TRACE, 4, "qethstop"); netif_tx_disable(dev); - card->dev->flags &= ~IFF_UP; if (card->state == CARD_STATE_UP) card->state = CARD_STATE_SOFTSETUP; return 0; @@ -3218,9 +3216,13 @@ static int qeth_l3_recover(void *ptr) if (!rc) PRINT_INFO("Device %s successfully recovered!\n", CARD_BUS_ID(card)); - else + else { + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); PRINT_INFO("Device %s could not be recovered!\n", CARD_BUS_ID(card)); + } return 0; } -- cgit v1.2.3 From 3b060be0582373be3c380629d7a6de5f06a311ed Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 24 Sep 2008 21:16:40 +0200 Subject: r6040: fix wrong assignment in r6040_free_txbufs This patch fixes a wrong assignment in r6040_free_txbufs on a receive skb pointer while we should actually do this on the transmit skb pointer. Signed-off-by: Florian Fainelli Signed-off-by: Jeff Garzik --- drivers/net/r6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 025f526558b..34fe7ef8e5e 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -265,7 +265,7 @@ static void r6040_free_txbufs(struct net_device *dev) le32_to_cpu(lp->tx_insert_ptr->buf), MAX_BUF_SIZE, PCI_DMA_TODEVICE); dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); - lp->rx_insert_ptr->skb_ptr = NULL; + lp->tx_insert_ptr->skb_ptr = NULL; } lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; } -- cgit v1.2.3 From d9c3c57ffc23b562a6ef8da794fc9702e1c3b328 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 24 Sep 2008 11:23:22 -0700 Subject: enic: Don't indicate IPv6 pkts using soft-LRO LRO is only applied to IPv4 pkts, so don't use the LRO indication functions for anything other IPv4 pkts. Every non-IPv4 pkt is indicated using non- LRO functions. Signed-off-by: Scott Feldman Signed-off-by: Jeff Garzik --- drivers/net/enic/enic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 4cf5ec76c99..e6d5f116ad7 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -941,7 +941,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, if (enic->vlan_group && vlan_stripped) { - if (ENIC_SETTING(enic, LRO)) + if (ENIC_SETTING(enic, LRO) && ipv4) lro_vlan_hwaccel_receive_skb(&enic->lro_mgr, skb, enic->vlan_group, vlan, cq_desc); @@ -951,7 +951,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, } else { - if (ENIC_SETTING(enic, LRO)) + if (ENIC_SETTING(enic, LRO) && ipv4) lro_receive_skb(&enic->lro_mgr, skb, cq_desc); else netif_receive_skb(skb); -- cgit v1.2.3 From 25f0a061d9e491c4b17976065443271e2ddd383f Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 24 Sep 2008 11:23:32 -0700 Subject: enic: fixes for review items from Ben Hutchings Fixes for review items from Ben Hutchings: - use netdev->net_stats rather than private net_stats - use ethtool op .get_sset_count rather than .get_stats_count - err out if setting Tx/Rx csum or TSO using ethtool and setting is not enabled for device. - pass in jiffies + constant to round_jiffies - return err if new MTU is out-of-bounds Signed-off-by: Scott Feldman Signed-off-by: Jeff Garzik --- drivers/net/enic/enic.h | 1 - drivers/net/enic/enic_main.c | 62 ++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index fb83c926da5..9e0d484deb2 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -75,7 +75,6 @@ struct enic { struct vnic_enet_config config; struct vnic_dev_bar bar0; struct vnic_dev *vdev; - struct net_device_stats net_stats; struct timer_list notify_timer; struct work_struct reset; struct msix_entry msix_entry[ENIC_MSIX_MAX]; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index e6d5f116ad7..03b646a5aec 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -43,7 +43,6 @@ #include "enic.h" #define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ) -#define ENIC_JUMBO_FIRST_BUF_SIZE 256 /* Supported devices */ static struct pci_device_id enic_id_table[] = { @@ -167,9 +166,14 @@ static void enic_get_strings(struct net_device *netdev, u32 stringset, u8 *data) } } -static int enic_get_stats_count(struct net_device *netdev) +static int enic_get_sset_count(struct net_device *netdev, int sset) { - return enic_n_tx_stats + enic_n_rx_stats; + switch (sset) { + case ETH_SS_STATS: + return enic_n_tx_stats + enic_n_rx_stats; + default: + return -EOPNOTSUPP; + } } static void enic_get_ethtool_stats(struct net_device *netdev, @@ -199,8 +203,10 @@ static int enic_set_rx_csum(struct net_device *netdev, u32 data) { struct enic *enic = netdev_priv(netdev); - enic->csum_rx_enabled = - (data && ENIC_SETTING(enic, RXCSUM)) ? 1 : 0; + if (data && !ENIC_SETTING(enic, RXCSUM)) + return -EINVAL; + + enic->csum_rx_enabled = !!data; return 0; } @@ -209,7 +215,10 @@ static int enic_set_tx_csum(struct net_device *netdev, u32 data) { struct enic *enic = netdev_priv(netdev); - if (data && ENIC_SETTING(enic, TXCSUM)) + if (data && !ENIC_SETTING(enic, TXCSUM)) + return -EINVAL; + + if (data) netdev->features |= NETIF_F_HW_CSUM; else netdev->features &= ~NETIF_F_HW_CSUM; @@ -221,7 +230,10 @@ static int enic_set_tso(struct net_device *netdev, u32 data) { struct enic *enic = netdev_priv(netdev); - if (data && ENIC_SETTING(enic, TSO)) + if (data && !ENIC_SETTING(enic, TSO)) + return -EINVAL; + + if (data) netdev->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN; else @@ -250,7 +262,7 @@ static struct ethtool_ops enic_ethtool_ops = { .set_msglevel = enic_set_msglevel, .get_link = ethtool_op_get_link, .get_strings = enic_get_strings, - .get_stats_count = enic_get_stats_count, + .get_sset_count = enic_get_sset_count, .get_ethtool_stats = enic_get_ethtool_stats, .get_rx_csum = enic_get_rx_csum, .set_rx_csum = enic_set_rx_csum, @@ -652,25 +664,26 @@ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) static struct net_device_stats *enic_get_stats(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); + struct net_device_stats *net_stats = &netdev->stats; struct vnic_stats *stats; spin_lock(&enic->devcmd_lock); vnic_dev_stats_dump(enic->vdev, &stats); spin_unlock(&enic->devcmd_lock); - enic->net_stats.tx_packets = stats->tx.tx_frames_ok; - enic->net_stats.tx_bytes = stats->tx.tx_bytes_ok; - enic->net_stats.tx_errors = stats->tx.tx_errors; - enic->net_stats.tx_dropped = stats->tx.tx_drops; + net_stats->tx_packets = stats->tx.tx_frames_ok; + net_stats->tx_bytes = stats->tx.tx_bytes_ok; + net_stats->tx_errors = stats->tx.tx_errors; + net_stats->tx_dropped = stats->tx.tx_drops; - enic->net_stats.rx_packets = stats->rx.rx_frames_ok; - enic->net_stats.rx_bytes = stats->rx.rx_bytes_ok; - enic->net_stats.rx_errors = stats->rx.rx_errors; - enic->net_stats.multicast = stats->rx.rx_multicast_frames_ok; - enic->net_stats.rx_crc_errors = stats->rx.rx_crc_errors; - enic->net_stats.rx_dropped = stats->rx.rx_no_bufs; + net_stats->rx_packets = stats->rx.rx_frames_ok; + net_stats->rx_bytes = stats->rx.rx_bytes_ok; + net_stats->rx_errors = stats->rx.rx_errors; + net_stats->multicast = stats->rx.rx_multicast_frames_ok; + net_stats->rx_crc_errors = stats->rx.rx_crc_errors; + net_stats->rx_dropped = stats->rx.rx_no_bufs; - return &enic->net_stats; + return net_stats; } static void enic_reset_mcaddrs(struct enic *enic) @@ -1109,7 +1122,8 @@ static void enic_notify_timer(unsigned long data) enic_notify_check(enic); - mod_timer(&enic->notify_timer, round_jiffies(ENIC_NOTIFY_TIMER_PERIOD)); + mod_timer(&enic->notify_timer, + round_jiffies(jiffies + ENIC_NOTIFY_TIMER_PERIOD)); } static void enic_free_intr(struct enic *enic) @@ -1313,14 +1327,12 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu) struct enic *enic = netdev_priv(netdev); int running = netif_running(netdev); + if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) + return -EINVAL; + if (running) enic_stop(netdev); - if (new_mtu < ENIC_MIN_MTU) - new_mtu = ENIC_MIN_MTU; - if (new_mtu > ENIC_MAX_MTU) - new_mtu = ENIC_MAX_MTU; - netdev->mtu = new_mtu; if (netdev->mtu > enic->port_mtu) -- cgit v1.2.3 From 8f4d248cb7c1873275608f267e525e08bcbd543b Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 24 Sep 2008 11:23:42 -0700 Subject: enic: Bug fix: Free MSI intr with correct data handle Bug fix: Free MSI intr with correct data handle Use davem proposed naming for MSI-X tx/rx vectors (ethX-tx-0, ethX-rx-0) Signed-off-by: Scott Feldman Signed-off-by: Jeff Garzik --- drivers/net/enic/enic_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 03b646a5aec..d403ce29a14 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1133,9 +1133,11 @@ static void enic_free_intr(struct enic *enic) switch (vnic_dev_get_intr_mode(enic->vdev)) { case VNIC_DEV_INTR_MODE_INTX: - case VNIC_DEV_INTR_MODE_MSI: free_irq(enic->pdev->irq, netdev); break; + case VNIC_DEV_INTR_MODE_MSI: + free_irq(enic->pdev->irq, enic); + break; case VNIC_DEV_INTR_MODE_MSIX: for (i = 0; i < ARRAY_SIZE(enic->msix); i++) if (enic->msix[i].requested) @@ -1170,12 +1172,12 @@ static int enic_request_intr(struct enic *enic) case VNIC_DEV_INTR_MODE_MSIX: sprintf(enic->msix[ENIC_MSIX_RQ].devname, - "%.11s-rx", netdev->name); + "%.11s-rx-0", netdev->name); enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq; enic->msix[ENIC_MSIX_RQ].devid = enic; sprintf(enic->msix[ENIC_MSIX_WQ].devname, - "%.11s-tx", netdev->name); + "%.11s-tx-0", netdev->name); enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq; enic->msix[ENIC_MSIX_WQ].devid = enic; -- cgit v1.2.3 From 4b75a442d2affb2ed20422054b1c640bd3b9c36a Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 24 Sep 2008 11:23:53 -0700 Subject: enic: bug fix: don't set netdev->name too early Bug fix: don't set netdev->name early before netdev registration. Setting netdev->name early with dev_alloc_name() would occasionally cause netdev registration to fail returning error that device was already registered. Since we're using netdev->name to name MSI-X vectors, we now need to move the request_irq after netdev registartion, so move it to ->open. Signed-off-by: Scott Feldman Signed-off-by: Jeff Garzik --- drivers/net/enic/enic.h | 2 +- drivers/net/enic/enic_main.c | 121 ++++++++++++++++--------------------------- 2 files changed, 47 insertions(+), 76 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 9e0d484deb2..7f677e89a78 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -33,7 +33,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" -#define DRV_VERSION "0.0.1.18163.472" +#define DRV_VERSION "0.0.1-18163.472-k1" #define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" #define PFX DRV_NAME ": " diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index d403ce29a14..f3a47a87dbb 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1250,13 +1250,28 @@ static int enic_open(struct net_device *netdev) unsigned int i; int err; + err = enic_request_intr(enic); + if (err) { + printk(KERN_ERR PFX "%s: Unable to request irq.\n", + netdev->name); + return err; + } + + err = enic_notify_set(enic); + if (err) { + printk(KERN_ERR PFX + "%s: Failed to alloc notify buffer, aborting.\n", + netdev->name); + goto err_out_free_intr; + } + for (i = 0; i < enic->rq_count; i++) { err = vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf); if (err) { printk(KERN_ERR PFX "%s: Unable to alloc receive buffers.\n", netdev->name); - return err; + goto err_out_notify_unset; } } @@ -1278,6 +1293,13 @@ static int enic_open(struct net_device *netdev) enic_notify_timer_start(enic); return 0; + +err_out_notify_unset: + vnic_dev_notify_unset(enic->vdev); +err_out_free_intr: + enic_free_intr(enic); + + return err; } /* rtnl lock is held, process context */ @@ -1307,6 +1329,9 @@ static int enic_stop(struct net_device *netdev) return err; } + vnic_dev_notify_unset(enic->vdev); + enic_free_intr(enic); + (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ], -1, enic_rq_service_drop, NULL); (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ], @@ -1592,18 +1617,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, return -ENOMEM; } - /* Set the netdev name early so intr vectors are properly - * named and any error msgs can include netdev->name - */ - - rtnl_lock(); - err = dev_alloc_name(netdev, netdev->name); - rtnl_unlock(); - if (err < 0) { - printk(KERN_ERR PFX "Unable to allocate netdev name.\n"); - goto err_out_free_netdev; - } - pci_set_drvdata(pdev, netdev); SET_NETDEV_DEV(netdev, &pdev->dev); @@ -1618,16 +1631,14 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) { printk(KERN_ERR PFX - "%s: Cannot enable PCI device, aborting.\n", - netdev->name); + "Cannot enable PCI device, aborting.\n"); goto err_out_free_netdev; } err = pci_request_regions(pdev, DRV_NAME); if (err) { printk(KERN_ERR PFX - "%s: Cannot request PCI regions, aborting.\n", - netdev->name); + "Cannot request PCI regions, aborting.\n"); goto err_out_disable_device; } @@ -1643,25 +1654,22 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) { printk(KERN_ERR PFX - "%s: No usable DMA configuration, aborting.\n", - netdev->name); + "No usable DMA configuration, aborting.\n"); goto err_out_release_regions; } err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (err) { printk(KERN_ERR PFX - "%s: Unable to obtain 32-bit DMA " - "for consistent allocations, aborting.\n", - netdev->name); + "Unable to obtain 32-bit DMA " + "for consistent allocations, aborting.\n"); goto err_out_release_regions; } } else { err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); if (err) { printk(KERN_ERR PFX - "%s: Unable to obtain 40-bit DMA " - "for consistent allocations, aborting.\n", - netdev->name); + "Unable to obtain 40-bit DMA " + "for consistent allocations, aborting.\n"); goto err_out_release_regions; } using_dac = 1; @@ -1672,8 +1680,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { printk(KERN_ERR PFX - "%s: BAR0 not memory-map'able, aborting.\n", - netdev->name); + "BAR0 not memory-map'able, aborting.\n"); err = -ENODEV; goto err_out_release_regions; } @@ -1684,8 +1691,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, if (!enic->bar0.vaddr) { printk(KERN_ERR PFX - "%s: Cannot memory-map BAR0 res hdr, aborting.\n", - netdev->name); + "Cannot memory-map BAR0 res hdr, aborting.\n"); err = -ENODEV; goto err_out_release_regions; } @@ -1696,8 +1702,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic->vdev = vnic_dev_register(NULL, enic, pdev, &enic->bar0); if (!enic->vdev) { printk(KERN_ERR PFX - "%s: vNIC registration failed, aborting.\n", - netdev->name); + "vNIC registration failed, aborting.\n"); err = -ENODEV; goto err_out_iounmap; } @@ -1708,8 +1713,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_dev_open(enic); if (err) { printk(KERN_ERR PFX - "%s: vNIC dev open failed, aborting.\n", - netdev->name); + "vNIC dev open failed, aborting.\n"); goto err_out_vnic_unregister; } @@ -1726,8 +1730,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = vnic_dev_init(enic->vdev, 0); if (err) { printk(KERN_ERR PFX - "%s: vNIC dev init failed, aborting.\n", - netdev->name); + "vNIC dev init failed, aborting.\n"); goto err_out_dev_close; } @@ -1737,8 +1740,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_get_vnic_config(enic); if (err) { printk(KERN_ERR PFX - "%s: Get vNIC configuration failed, aborting.\n", - netdev->name); + "Get vNIC configuration failed, aborting.\n"); goto err_out_dev_close; } @@ -1754,18 +1756,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_set_intr_mode(enic); if (err) { printk(KERN_ERR PFX - "%s: Failed to set intr mode, aborting.\n", - netdev->name); - goto err_out_dev_close; - } - - /* Request interrupt vector(s) - */ - - err = enic_request_intr(enic); - if (err) { - printk(KERN_ERR PFX "%s: Unable to request irq.\n", - netdev->name); + "Failed to set intr mode, aborting.\n"); goto err_out_dev_close; } @@ -1775,8 +1766,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_alloc_vnic_resources(enic); if (err) { printk(KERN_ERR PFX - "%s: Failed to alloc vNIC resources, aborting.\n", - netdev->name); + "Failed to alloc vNIC resources, aborting.\n"); goto err_out_free_vnic_resources; } @@ -1792,19 +1782,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, ig_vlan_strip_en); if (err) { printk(KERN_ERR PFX - "%s: Failed to config nic, aborting.\n", - netdev->name); - goto err_out_free_vnic_resources; - } - - /* Setup notification buffer area - */ - - err = enic_notify_set(enic); - if (err) { - printk(KERN_ERR PFX - "%s: Failed to alloc notify buffer, aborting.\n", - netdev->name); + "Failed to config nic, aborting.\n"); goto err_out_free_vnic_resources; } @@ -1831,9 +1809,8 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_set_mac_addr(netdev, enic->mac_addr); if (err) { printk(KERN_ERR PFX - "%s: Invalid MAC address, aborting.\n", - netdev->name); - goto err_out_notify_unset; + "Invalid MAC address, aborting.\n"); + goto err_out_free_vnic_resources; } netdev->open = enic_open; @@ -1887,18 +1864,14 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = register_netdev(netdev); if (err) { printk(KERN_ERR PFX - "%s: Cannot register net device, aborting.\n", - netdev->name); - goto err_out_notify_unset; + "Cannot register net device, aborting.\n"); + goto err_out_free_vnic_resources; } return 0; -err_out_notify_unset: - vnic_dev_notify_unset(enic->vdev); err_out_free_vnic_resources: enic_free_vnic_resources(enic); - enic_free_intr(enic); err_out_dev_close: vnic_dev_close(enic->vdev); err_out_vnic_unregister: @@ -1926,9 +1899,7 @@ static void __devexit enic_remove(struct pci_dev *pdev) flush_scheduled_work(); unregister_netdev(netdev); - vnic_dev_notify_unset(enic->vdev); enic_free_vnic_resources(enic); - enic_free_intr(enic); vnic_dev_close(enic->vdev); enic_clear_intr_mode(enic); vnic_dev_unregister(enic->vdev); -- cgit v1.2.3 From 2e2e8d53c3f34684af7a7475098b7524a6b854c2 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 23 Sep 2008 15:46:38 -0700 Subject: e1000e: remove failed request for sw/fw/hw flag When the driver fails to acquire the control flag used to serialize NVM and PHY accesses between the driver, firmware and hardware, remove the request for the flag otherwise the hardware might grant the flag when it becomes available but the driver will not release the flag. This could cause the firmware to prevent the driver getting the flag for all future attempts. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/ich8lan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 019b9c0bcdc..692251b6091 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -398,6 +398,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) if (!timeout) { hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + ew32(EXTCNF_CTRL, extcnf_ctrl); return -E1000_ERR_CONFIG; } -- cgit v1.2.3 From baac03d9bb7b8aa3c33a2dbf5f459ea6ce8abaf4 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 22 Sep 2008 10:03:56 -0700 Subject: gianfar: Fix error in mdio reset timeout The loop with the timeout used "while (... && timeout--)", which means than when the timeout occurs, "timeout" will be -1 after the loop has exited. The code that checks if the looped exited because of a timeout used "if (timeout <= 0)". Seems ok, except timeout is unsigned, and (unsigned)-1 isn't less than zero! Using "--timeout" in the loop fixes this problem, as now "timeout" will be 0 when the loop times out. This also fixes a bug in the existing code, where it will erroneously think a timeout occurred if the condition the loop was waiting for is satisfied on the final iteration before a timeout. Signed-off-by: Trent Piepho Acked-by: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar_mii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index ebcfb27a904..906aba2757e 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -136,12 +136,12 @@ static int gfar_mdio_reset(struct mii_bus *bus) /* Wait until the bus is free */ while ((gfar_read(®s->miimind) & MIIMIND_BUSY) && - timeout--) + --timeout) cpu_relax(); mutex_unlock(&bus->mdio_lock); - if(timeout <= 0) { + if(timeout == 0) { printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); return -EBUSY; -- cgit v1.2.3 From fbb80230bf1c1dcc81339e991b172006243333e9 Mon Sep 17 00:00:00 2001 From: David Fries Date: Mon, 22 Sep 2008 14:10:20 -0700 Subject: ne.c: fix rmmod, platform driver improvements Removing the module would cause a kernel oops as platform_driver_probe failed to detect a device and unregistered the platform driver on module init, and cleanup_module would unregister the already unregistered driver. The suspend and resume functions weren't being called. platform_driver support was added earlier, but without any platform_device_register* calls I don't think it was being used. Now all devices are registered using platform_device_register_simple and pointers are kept to unregister the ones that the probe failed for or unregister all devices on module shutdown. init_module no longer calls ne_init to reduce confusion (and multiple unregister paths that caused the rmmod oops). With the devices now registered they are added to the platform driver and get suspend and resume events. netif_device_detach(dev) was added before unregister_netdev(dev) when removing the region as occationally I would see a race condition where the device was still being used in unregister_netdev. Signed-off-by: David Fries Cc: Atsushi Nemoto Cc: Paul Gortmaker Cc: Alan Cox Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/ne.c | 272 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 164 insertions(+), 108 deletions(-) diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 79599900c4b..eb681c0d51b 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -64,6 +64,25 @@ static const char version2[] = /* Do we support clones that don't adhere to 14,15 of the SAprom ? */ #define SUPPORT_NE_BAD_CLONES +/* 0xbad = bad sig or no reset ack */ +#define BAD 0xbad + +#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ +static struct platform_device *pdev_ne[MAX_NE_CARDS]; +static int io[MAX_NE_CARDS]; +static int irq[MAX_NE_CARDS]; +static int bad[MAX_NE_CARDS]; + +#ifdef MODULE +module_param_array(io, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param_array(bad, int, NULL, 0); +MODULE_PARM_DESC(io, "I/O base address(es),required"); +MODULE_PARM_DESC(irq, "IRQ number(s)"); +MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); +MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver"); +MODULE_LICENSE("GPL"); +#endif /* MODULE */ /* Do we perform extra sanity checks on stuff ? */ /* #define NE_SANITY_CHECK */ @@ -74,6 +93,10 @@ static const char version2[] = /* Do we have a non std. amount of memory? (in units of 256 byte pages) */ /* #define PACKETBUF_MEMSIZE 0x40 */ +/* This is set up so that no ISA autoprobe takes place. We can't guarantee +that the ne2k probe is the last 8390 based probe to take place (as it +is at boot) and so the probe will get confused by any other 8390 cards. +ISA device autoprobes on a running machine are not recommended anyway. */ #if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R)) /* Do we need a portlist for the ISA auto-probe ? */ #define NEEDS_PORTLIST @@ -192,8 +215,13 @@ static int __init do_ne_probe(struct net_device *dev) #endif /* First check any supplied i/o locations. User knows best. */ - if (base_addr > 0x1ff) /* Check a single specified location. */ - return ne_probe1(dev, base_addr); + if (base_addr > 0x1ff) { /* Check a single specified location. */ + int ret = ne_probe1(dev, base_addr); + if (ret) + printk(KERN_WARNING "ne.c: No NE*000 card found at " + "i/o = %#lx\n", base_addr); + return ret; + } else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; @@ -214,28 +242,6 @@ static int __init do_ne_probe(struct net_device *dev) return -ENODEV; } -#ifndef MODULE -struct net_device * __init ne_probe(int unit) -{ - struct net_device *dev = alloc_eip_netdev(); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_ne_probe(dev); - if (err) - goto out; - return dev; -out: - free_netdev(dev); - return ERR_PTR(err); -} -#endif - static int __init ne_probe_isapnp(struct net_device *dev) { int i; @@ -329,7 +335,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) with an otherwise unused dev->mem_end value of "0xBAD" will cause the driver to skip these parts of the probe. */ - bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad)); + bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD)); /* Reset card. Who knows what dain-bramaged state it was left in. */ @@ -806,39 +812,84 @@ retry: static int __init ne_drv_probe(struct platform_device *pdev) { struct net_device *dev; + int err, this_dev = pdev->id; struct resource *res; - int err, irq; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - irq = platform_get_irq(pdev, 0); - if (!res || irq < 0) - return -ENODEV; dev = alloc_eip_netdev(); if (!dev) return -ENOMEM; - dev->irq = irq; - dev->base_addr = res->start; + + /* ne.c doesn't populate resources in platform_device, but + * rbtx4927_ne_init and rbtx4938_ne_init do register devices + * with resources. + */ + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (res) { + dev->base_addr = res->start; + dev->irq = platform_get_irq(pdev, 0); + } else { + if (this_dev < 0 || this_dev >= MAX_NE_CARDS) + return -EINVAL; + dev->base_addr = io[this_dev]; + dev->irq = irq[this_dev]; + dev->mem_end = bad[this_dev]; + } err = do_ne_probe(dev); if (err) { free_netdev(dev); return err; } platform_set_drvdata(pdev, dev); + + /* Update with any values found by probing, don't update if + * resources were specified. + */ + if (!res) { + io[this_dev] = dev->base_addr; + irq[this_dev] = dev->irq; + } return 0; } -static int __exit ne_drv_remove(struct platform_device *pdev) +static int ne_drv_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(dev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); - free_netdev(dev); + if (dev) { + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + netif_device_detach(dev); + unregister_netdev(dev); + if (idev) + pnp_device_detach(idev); + /* Careful ne_drv_remove can be called twice, once from + * the platform_driver.remove and again when the + * platform_device is being removed. + */ + ei_status.priv = 0; + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + } return 0; } +/* Remove unused devices or all if true. */ +static void ne_loop_rm_unreg(int all) +{ + int this_dev; + struct platform_device *pdev; + for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { + pdev = pdev_ne[this_dev]; + /* No network device == unused */ + if (pdev && (!platform_get_drvdata(pdev) || all)) { + ne_drv_remove(pdev); + platform_device_unregister(pdev); + pdev_ne[this_dev] = NULL; + } + } +} + #ifdef CONFIG_PM static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state) { @@ -873,7 +924,7 @@ static int ne_drv_resume(struct platform_device *pdev) #endif static struct platform_driver ne_driver = { - .remove = __exit_p(ne_drv_remove), + .remove = ne_drv_remove, .suspend = ne_drv_suspend, .resume = ne_drv_resume, .driver = { @@ -882,91 +933,96 @@ static struct platform_driver ne_driver = { }, }; -static int __init ne_init(void) +static void __init ne_add_devices(void) { - return platform_driver_probe(&ne_driver, ne_drv_probe); -} + int this_dev; + struct platform_device *pdev; -static void __exit ne_exit(void) -{ - platform_driver_unregister(&ne_driver); + for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { + if (pdev_ne[this_dev]) + continue; + pdev = platform_device_register_simple( + DRV_NAME, this_dev, NULL, 0); + if (IS_ERR(pdev)) + continue; + pdev_ne[this_dev] = pdev; + } } #ifdef MODULE -#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -static struct net_device *dev_ne[MAX_NE_CARDS]; -static int io[MAX_NE_CARDS]; -static int irq[MAX_NE_CARDS]; -static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ - -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param_array(bad, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O base address(es),required"); -MODULE_PARM_DESC(irq, "IRQ number(s)"); -MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); -MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver"); -MODULE_LICENSE("GPL"); - -/* This is set up so that no ISA autoprobe takes place. We can't guarantee -that the ne2k probe is the last 8390 based probe to take place (as it -is at boot) and so the probe will get confused by any other 8390 cards. -ISA device autoprobes on a running machine are not recommended anyway. */ - -int __init init_module(void) +int __init init_module() { - int this_dev, found = 0; - int plat_found = !ne_init(); - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_eip_netdev(); - if (!dev) - break; - dev->irq = irq[this_dev]; - dev->mem_end = bad[this_dev]; - dev->base_addr = io[this_dev]; - if (do_ne_probe(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - free_netdev(dev); - if (found || plat_found) - break; - if (io[this_dev] != 0) - printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); - else - printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); - return -ENXIO; + int retval; + ne_add_devices(); + retval = platform_driver_probe(&ne_driver, ne_drv_probe); + if (retval) { + if (io[0] == 0) + printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\"" + " value(s) for ISA cards.\n"); + ne_loop_rm_unreg(1); + return retval; } - if (found || plat_found) - return 0; - return -ENODEV; -} -static void cleanup_card(struct net_device *dev) + /* Unregister unused platform_devices. */ + ne_loop_rm_unreg(0); + return retval; +} +#else /* MODULE */ +static int __init ne_init(void) { - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); + int retval = platform_driver_probe(&ne_driver, ne_drv_probe); + + /* Unregister unused platform_devices. */ + ne_loop_rm_unreg(0); + return retval; } +module_init(ne_init); -void __exit cleanup_module(void) +struct net_device * __init ne_probe(int unit) { int this_dev; + struct net_device *dev; + + /* Find an empty slot, that is no net_device and zero io port. */ + this_dev = 0; + while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) || + io[this_dev]) { + if (++this_dev == MAX_NE_CARDS) + return ERR_PTR(-ENOMEM); + } + + /* Get irq, io from kernel command line */ + dev = alloc_eip_netdev(); + if (!dev) + return ERR_PTR(-ENOMEM); - ne_exit(); + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + io[this_dev] = dev->base_addr; + irq[this_dev] = dev->irq; + bad[this_dev] = dev->mem_end; + + free_netdev(dev); + + ne_add_devices(); + + /* return the first device found */ for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = dev_ne[this_dev]; - if (dev) { - unregister_netdev(dev); - cleanup_card(dev); - free_netdev(dev); + if (pdev_ne[this_dev]) { + dev = platform_get_drvdata(pdev_ne[this_dev]); + if (dev) + return dev; } } + + return ERR_PTR(-ENODEV); } -#else /* MODULE */ -module_init(ne_init); -module_exit(ne_exit); #endif /* MODULE */ + +static void __exit ne_exit(void) +{ + platform_driver_unregister(&ne_driver); + ne_loop_rm_unreg(1); +} +module_exit(ne_exit); -- cgit v1.2.3 From ac7198bb124e7007cfd48990d382678341886dba Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Mon, 22 Sep 2008 14:10:25 -0700 Subject: gianfar: free/iounmap memory after an error in mii bus initialization Recent changes to MII bus initialization code added exit points which didn't free or iounmap the bus before returning. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=11372. Signed-off-by: Andy Fleming Reported-by: Daniel Marjamki Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/gianfar_mii.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 906aba2757e..678f48c6911 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -211,19 +211,21 @@ static int gfar_mdio_probe(struct device *dev) gfar_write(&enet_regs->tbipa, 0); for (i = PHY_MAX_ADDR; i > 0; i--) { u32 phy_id; - int r; - r = get_phy_id(new_bus, i, &phy_id); - if (r) - return r; + err = get_phy_id(new_bus, i, &phy_id); + if (err) + goto bus_register_fail; if (phy_id == 0xffffffff) break; } /* The bus is full. We don't support using 31 PHYs, sorry */ - if (i == 0) - return -EBUSY; + if (i == 0) { + err = -EBUSY; + + goto bus_register_fail; + } gfar_write(&enet_regs->tbipa, i); -- cgit v1.2.3 From a4e77d063d61e4703db813470fefe90dac672b55 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 22 Sep 2008 14:52:25 -0700 Subject: atl1e: remove the unneeded (struct atl1e_adapter *) Remove the unneeded (struct atl1e_adapter *) casts, for hw->adapter already has type atl1e_adapter *. Signed-off-by: Jie Yang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_hw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c index 949e75358bf..8cbc1b59bd6 100644 --- a/drivers/net/atl1e/atl1e_hw.c +++ b/drivers/net/atl1e/atl1e_hw.c @@ -397,7 +397,7 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw) */ int atl1e_phy_commit(struct atl1e_hw *hw) { - struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter; + struct atl1e_adapter *adapter = hw->adapter; struct pci_dev *pdev = adapter->pdev; int ret_val; u16 phy_data; @@ -431,7 +431,7 @@ int atl1e_phy_commit(struct atl1e_hw *hw) int atl1e_phy_init(struct atl1e_hw *hw) { - struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter; + struct atl1e_adapter *adapter = hw->adapter; struct pci_dev *pdev = adapter->pdev; s32 ret_val; u16 phy_val; @@ -525,7 +525,7 @@ int atl1e_phy_init(struct atl1e_hw *hw) */ int atl1e_reset_hw(struct atl1e_hw *hw) { - struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter; + struct atl1e_adapter *adapter = hw->adapter; struct pci_dev *pdev = adapter->pdev; u32 idle_status_data = 0; -- cgit v1.2.3 From 6c2a9efadec464f848b18216e41783d3c01c7d10 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Mon, 22 Sep 2008 14:52:22 -0700 Subject: e1000e: avoid duplicated output of device name in kernel warning With 2.6.27-rc3 I noticed the following messages in my boot log: 0000:01:00.0: 0000:01:00.0: Warning: detected DSPD enabled in EEPROM 0000:01:00.0: eth0: (PCI Express:2.5GB/s:Width x1) 00:16:76:04:ff:09 The second seems correct, but the first has a silly repetition of the PCI device before the actual message. The message originates from e1000_eeprom_checks in e1000e/netdev.c. With this patch below the first message becomes e1000e 0000:01:00.0: Warning: detected DSPD enabled in EEPROM which makes it similar to directly preceding messages. Use dev_warn instead of e_warn in e1000_eeprom_checks() as the interface name has not yet been assigned at that point. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Frans Pop Signed-off-by: Jeff Kirsher Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000e/netdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 0925204cd2d..24d05cb7005 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4671,13 +4671,15 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); if (!(le16_to_cpu(buf) & (1 << 0))) { /* Deep Smart Power Down (DSPD) */ - e_warn("Warning: detected DSPD enabled in EEPROM\n"); + dev_warn(&adapter->pdev->dev, + "Warning: detected DSPD enabled in EEPROM\n"); } ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); if (le16_to_cpu(buf) & (3 << 2)) { /* ASPM enable */ - e_warn("Warning: detected ASPM enabled in EEPROM\n"); + dev_warn(&adapter->pdev->dev, + "Warning: detected ASPM enabled in EEPROM\n"); } } -- cgit v1.2.3 From 1545e205db6e797861d644e3459339109f7573ff Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Mon, 22 Sep 2008 09:55:35 -0400 Subject: forcedeth fix: take phy out of reset during power up This patch will add the phy reset bit into the power up mask which is used during power up. Certain BIOSes will place the phy in reset and therefore the driver must take the phy out of reset when it loads. Signed-off-by: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0b6ecef9a84..35e582d3fd2 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -337,7 +337,7 @@ enum { NvRegMSIXIrqStatus = 0x3f0, NvRegPowerState2 = 0x600, -#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 +#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15 #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 #define NVREG_POWERSTATE2_PHY_RESET 0x0004 }; -- cgit v1.2.3 From e2f092ff9bf2ab515c14d2208b5f08c7d389d5d2 Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Sat, 20 Sep 2008 17:37:05 -0500 Subject: atl2: add tx bytes statistic Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index d548a67da1e..5ab9c763100 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -522,8 +522,10 @@ static void atl2_intr_tx(struct atl2_adapter *adapter) atomic_set(&adapter->txd_read_ptr, (int)txd_read_ptr); /* tx statistics: */ - if (txs->ok) + if (txs->ok) { + adapter->net_stats.tx_bytes += txs->pkt_size; adapter->net_stats.tx_packets++; + } else adapter->net_stats.tx_errors++; -- cgit v1.2.3 From 83dad4c3773b2be110f9ab0c9031e6129bd2e294 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 22 Sep 2008 14:52:19 -0700 Subject: netdev: drop CONFIG_PPC_MERGE from Kconfig Now that arch/ppc is dead CONFIG_PPC_MERGE is always defined for all powerpc platforms so we don't need to depend on it. Signed-off-by: Kumar Gala Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Josh Boyer Cc: David Gibson Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 2 +- drivers/net/ibm_newemac/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 42b4eb703c2..f6fd0be9ef5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1813,7 +1813,7 @@ config FEC2 config FEC_MPC52xx tristate "MPC52xx FEC driver" - depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC + depends on PPC_MPC52xx && PPC_BESTCOMM_FEC select CRC32 select PHYLIB ---help--- diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig index 70a3272ee99..bcec7320895 100644 --- a/drivers/net/ibm_newemac/Kconfig +++ b/drivers/net/ibm_newemac/Kconfig @@ -1,6 +1,6 @@ config IBM_NEW_EMAC tristate "IBM EMAC Ethernet support" - depends on PPC_DCR && PPC_MERGE + depends on PPC_DCR select CRC32 help This driver supports the IBM EMAC family of Ethernet controllers -- cgit v1.2.3 From 315781408ef4a6ff831f8fd37c90d4bb7c234853 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 22 Sep 2008 14:52:18 -0700 Subject: fs-enet: remove code associated with !CONFIG_PPC_MERGE Now that arch/ppc is gone we don't need CONFIG_PPC_MERGE anymore remove the dead code associated with !CONFIG_PPC_MERGE. With this change the pre_request_irq() and post_free_irq() calls became nops so they have been removed. Also removed fs_request_irq() and fs_free_irq() and just called request_irq() and free_irq(). Signed-off-by: Kumar Gala Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jeff Garzik Cc: Scott Wood Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/fs_enet/fs_enet-main.c | 22 +++------------------- drivers/net/fs_enet/fs_enet.h | 2 -- drivers/net/fs_enet/mac-fcc.c | 12 ------------ drivers/net/fs_enet/mac-fec.c | 30 ------------------------------ drivers/net/fs_enet/mac-scc.c | 26 -------------------------- 5 files changed, 3 insertions(+), 89 deletions(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 9d461825bf4..cb51c1fb033 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -664,23 +664,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int fs_request_irq(struct net_device *dev, int irq, const char *name, - irq_handler_t irqf) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - (*fep->ops->pre_request_irq)(dev, irq); - return request_irq(irq, irqf, IRQF_SHARED, name, dev); -} - -static void fs_free_irq(struct net_device *dev, int irq) -{ - struct fs_enet_private *fep = netdev_priv(dev); - - free_irq(irq, dev); - (*fep->ops->post_free_irq)(dev, irq); -} - static void fs_timeout(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -800,7 +783,8 @@ static int fs_enet_open(struct net_device *dev) napi_enable(&fep->napi); /* Install our interrupt handler. */ - r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt); + r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, + "fs_enet-mac", dev); if (r != 0) { printk(KERN_ERR DRV_MODULE_NAME ": %s Could not allocate FS_ENET IRQ!", dev->name); @@ -842,7 +826,7 @@ static int fs_enet_close(struct net_device *dev) /* release any irqs */ phy_disconnect(fep->phydev); fep->phydev = NULL; - fs_free_irq(dev, fep->interrupt); + free_irq(fep->interrupt, dev); return 0; } diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index db46d2e7232..85a4bab7f63 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -34,8 +34,6 @@ struct fs_ops { void (*adjust_link)(struct net_device *dev); void (*restart)(struct net_device *dev); void (*stop)(struct net_device *dev); - void (*pre_request_irq)(struct net_device *dev, int irq); - void (*post_free_irq)(struct net_device *dev, int irq); void (*napi_clear_rx_event)(struct net_device *dev); void (*napi_enable_rx)(struct net_device *dev); void (*napi_disable_rx)(struct net_device *dev); diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 1c7ef812a8e..22e5a847a58 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -421,16 +421,6 @@ static void stop(struct net_device *dev) fs_cleanup_bds(dev); } -static void pre_request_irq(struct net_device *dev, int irq) -{ - /* nothing */ -} - -static void post_free_irq(struct net_device *dev, int irq) -{ - /* nothing */ -} - static void napi_clear_rx_event(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -540,8 +530,6 @@ const struct fs_ops fs_fcc_ops = { .set_multicast_list = set_multicast_list, .restart = restart, .stop = stop, - .pre_request_irq = pre_request_irq, - .post_free_irq = post_free_irq, .napi_clear_rx_event = napi_clear_rx_event, .napi_enable_rx = napi_enable_rx, .napi_disable_rx = napi_disable_rx, diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 0a7d1c5c652..14e575313c8 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -313,11 +313,7 @@ static void restart(struct net_device *dev) * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); -#ifndef CONFIG_PPC_MERGE - FW(fecp, ivec, (fep->interrupt / 2) << 29); -#else FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); -#endif /* * adjust to speed (only for DUET & RMII) @@ -413,30 +409,6 @@ static void stop(struct net_device *dev) } } -static void pre_request_irq(struct net_device *dev, int irq) -{ -#ifndef CONFIG_PPC_MERGE - immap_t *immap = fs_enet_immap; - u32 siel; - - /* SIU interrupt */ - if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) { - - siel = in_be32(&immap->im_siu_conf.sc_siel); - if ((irq & 1) == 0) - siel |= (0x80000000 >> irq); - else - siel &= ~(0x80000000 >> (irq & ~1)); - out_be32(&immap->im_siu_conf.sc_siel, siel); - } -#endif -} - -static void post_free_irq(struct net_device *dev, int irq) -{ - /* nothing */ -} - static void napi_clear_rx_event(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -529,8 +501,6 @@ const struct fs_ops fs_fec_ops = { .set_multicast_list = set_multicast_list, .restart = restart, .stop = stop, - .pre_request_irq = pre_request_irq, - .post_free_irq = post_free_irq, .napi_clear_rx_event = napi_clear_rx_event, .napi_enable_rx = napi_enable_rx, .napi_disable_rx = napi_disable_rx, diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 22f50dd8b27..008cdd9cc53 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -377,30 +377,6 @@ static void stop(struct net_device *dev) fs_cleanup_bds(dev); } -static void pre_request_irq(struct net_device *dev, int irq) -{ -#ifndef CONFIG_PPC_MERGE - immap_t *immap = fs_enet_immap; - u32 siel; - - /* SIU interrupt */ - if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) { - - siel = in_be32(&immap->im_siu_conf.sc_siel); - if ((irq & 1) == 0) - siel |= (0x80000000 >> irq); - else - siel &= ~(0x80000000 >> (irq & ~1)); - out_be32(&immap->im_siu_conf.sc_siel, siel); - } -#endif -} - -static void post_free_irq(struct net_device *dev, int irq) -{ - /* nothing */ -} - static void napi_clear_rx_event(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -494,8 +470,6 @@ const struct fs_ops fs_scc_ops = { .set_multicast_list = set_multicast_list, .restart = restart, .stop = stop, - .pre_request_irq = pre_request_irq, - .post_free_irq = post_free_irq, .napi_clear_rx_event = napi_clear_rx_event, .napi_enable_rx = napi_enable_rx, .napi_disable_rx = napi_disable_rx, -- cgit v1.2.3 From be61ea52900b97800effbb68478915d73b5d4df2 Mon Sep 17 00:00:00 2001 From: Weiwei Wang Date: Thu, 18 Sep 2008 08:23:48 +0800 Subject: [netdrvr] convert sbmac tx to spin_lock_irqsave to prevent early IRQ enable Netpoll will call the interrupt handler with interrupts disabled when using kgdboe, so spin_lock_irqsave() should be used instead of spin_lock_irq() to prevent interrupts from being incorrectly enabled. Signed-off-by: Weiwei Wang Signed-off-by: Jeff Garzik --- drivers/net/sb1250-mac.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index fe41e4ec21e..ce10cfa1ee5 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2069,9 +2069,10 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance) static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) { struct sbmac_softc *sc = netdev_priv(dev); + unsigned long flags; /* lock eth irq */ - spin_lock_irq (&sc->sbm_lock); + spin_lock_irqsave(&sc->sbm_lock, flags); /* * Put the buffer on the transmit ring. If we @@ -2081,14 +2082,14 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { /* XXX save skb that we could not send */ netif_stop_queue(dev); - spin_unlock_irq(&sc->sbm_lock); + spin_unlock_irqrestore(&sc->sbm_lock, flags); return 1; } dev->trans_start = jiffies; - spin_unlock_irq (&sc->sbm_lock); + spin_unlock_irqrestore(&sc->sbm_lock, flags); return 0; } @@ -2568,14 +2569,15 @@ static void sbmac_mii_poll(struct net_device *dev) static void sbmac_tx_timeout (struct net_device *dev) { struct sbmac_softc *sc = netdev_priv(dev); + unsigned long flags; - spin_lock_irq (&sc->sbm_lock); + spin_lock_irqsave(&sc->sbm_lock, flags); dev->trans_start = jiffies; dev->stats.tx_errors++; - spin_unlock_irq (&sc->sbm_lock); + spin_unlock_irqrestore(&sc->sbm_lock, flags); printk (KERN_WARNING "%s: Transmit timed out\n",dev->name); } -- cgit v1.2.3 From b22596726bd37c7a4df4a43406a9a60f617d3d02 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 14 Sep 2008 16:56:12 +0100 Subject: drivers/net/bonding: sparse fixes for exported tables The following sparse warnings are being generated because bonding.h is missing definitons for items declared in bond_main.c but also used in bond_sysfs.h Also export bond_dev_list as this is also declared in bond_main but used elsewhere in drivers/net/bonding. bond_main.c:105:20: warning: symbol 'bonding_defaults' was not declared. Should it be static? bond_main.c:148:1: warning: symbol 'bond_dev_list' was not declared. Should it be static? bond_main.c:162:22: warning: symbol 'bond_lacp_tbl' was not declared. Should it be static? bond_main.c:168:22: warning: symbol 'bond_mode_tbl' was not declared. Should it be static? bond_main.c:179:22: warning: symbol 'xmit_hashtype_tbl' was not declared. Should it be static? bond_main.c:186:22: warning: symbol 'arp_validate_tbl' was not declared. Should it be static? bond_main.c:194:22: warning: symbol 'fail_over_mac_tbl' was not declared. Should it be static? Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/bonding/bonding.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index f7b40edabfd..ffb668dd6d3 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -333,5 +333,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active); void bond_register_arp(struct bonding *); void bond_unregister_arp(struct bonding *); +/* exported from bond_main.c */ +extern struct list_head bond_dev_list; +extern struct bond_parm_tbl bond_lacp_tbl[]; +extern struct bond_parm_tbl bond_mode_tbl[]; +extern struct bond_parm_tbl xmit_hashtype_tbl[]; +extern struct bond_parm_tbl arp_validate_tbl[]; +extern struct bond_parm_tbl fail_over_mac_tbl[]; + #endif /* _LINUX_BONDING_H */ -- cgit v1.2.3 From 630b25cdf4e3f8c0a11eb04fc8436cc36653cd58 Mon Sep 17 00:00:00 2001 From: "Brandeburg, Jesse" Date: Tue, 16 Sep 2008 13:01:28 -0700 Subject: e1000: remove unused Kconfig option for disabling packet split Since the e1000/e1000e split, no hardware supported by e1000 supports packet split, just remove the Kconfig option and associated code from the driver. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 9 - drivers/net/e1000/e1000.h | 17 -- drivers/net/e1000/e1000_main.c | 416 +---------------------------------------- 3 files changed, 9 insertions(+), 433 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f6fd0be9ef5..2d6a060d92e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1938,15 +1938,6 @@ config E1000 To compile this driver as a module, choose M here. The module will be called e1000. -config E1000_DISABLE_PACKET_SPLIT - bool "Disable Packet Split for PCI express adapters" - depends on E1000 - help - Say Y here if you want to use the legacy receive path for PCI express - hardware. - - If in doubt, say N. - config E1000E tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support" depends on PCI && (!SPARC32 || BROKEN) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 19e317eaf5b..62f62970f97 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -155,8 +155,6 @@ do { \ #endif #define E1000_MNG_VLAN_NONE (-1) -/* Number of packet split data buffers (not including the header buffer) */ -#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ @@ -168,14 +166,6 @@ struct e1000_buffer { u16 next_to_watch; }; -struct e1000_ps_page { - struct page *ps_page[PS_PAGE_BUFFERS]; -}; - -struct e1000_ps_page_dma { - u64 ps_page_dma[PS_PAGE_BUFFERS]; -}; - struct e1000_tx_ring { /* pointer to the descriptor ring memory */ void *desc; @@ -213,9 +203,6 @@ struct e1000_rx_ring { unsigned int next_to_clean; /* array of buffer information structs */ struct e1000_buffer *buffer_info; - /* arrays of page information for packet split */ - struct e1000_ps_page *ps_page; - struct e1000_ps_page_dma *ps_page_dma; /* cpu for rx queue */ int cpu; @@ -228,8 +215,6 @@ struct e1000_rx_ring { ((((R)->next_to_clean > (R)->next_to_use) \ ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1) -#define E1000_RX_DESC_PS(R, i) \ - (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) #define E1000_RX_DESC_EXT(R, i) \ (&(((union e1000_rx_desc_extended *)((R).desc))[i])) #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) @@ -311,10 +296,8 @@ struct e1000_adapter { u32 rx_int_delay; u32 rx_abs_int_delay; bool rx_csum; - unsigned int rx_ps_pages; u32 gorcl; u64 gorcl_old; - u16 rx_ps_bsize0; /* OS defined structs */ struct net_device *netdev; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ad6da7b67e5..2ab44db29fa 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -137,15 +137,9 @@ static int e1000_clean(struct napi_struct *napi, int budget); static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring, int *work_done, int work_to_do); -static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring, int cleaned_count); -static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); @@ -1331,7 +1325,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - adapter->rx_ps_bsize0 = E1000_RXBUFFER_128; hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; @@ -1815,26 +1808,6 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, } memset(rxdr->buffer_info, 0, size); - rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct e1000_ps_page), - GFP_KERNEL); - if (!rxdr->ps_page) { - vfree(rxdr->buffer_info); - DPRINTK(PROBE, ERR, - "Unable to allocate memory for the receive descriptor ring\n"); - return -ENOMEM; - } - - rxdr->ps_page_dma = kcalloc(rxdr->count, - sizeof(struct e1000_ps_page_dma), - GFP_KERNEL); - if (!rxdr->ps_page_dma) { - vfree(rxdr->buffer_info); - kfree(rxdr->ps_page); - DPRINTK(PROBE, ERR, - "Unable to allocate memory for the receive descriptor ring\n"); - return -ENOMEM; - } - if (hw->mac_type <= e1000_82547_rev_2) desc_len = sizeof(struct e1000_rx_desc); else @@ -1852,8 +1825,6 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter, "Unable to allocate memory for the receive descriptor ring\n"); setup_rx_desc_die: vfree(rxdr->buffer_info); - kfree(rxdr->ps_page); - kfree(rxdr->ps_page_dma); return -ENOMEM; } @@ -1932,11 +1903,7 @@ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter) static void e1000_setup_rctl(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - u32 rctl, rfctl; - u32 psrctl = 0; -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT - u32 pages = 0; -#endif + u32 rctl; rctl = er32(RCTL); @@ -1988,55 +1955,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) break; } -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT - /* 82571 and greater support packet-split where the protocol - * header is placed in skb->data and the packet data is - * placed in pages hanging off of skb_shinfo(skb)->nr_frags. - * In the case of a non-split, skb->data is linearly filled, - * followed by the page buffers. Therefore, skb->data is - * sized to hold the largest protocol header. - */ - /* allocations using alloc_page take too long for regular MTU - * so only enable packet split for jumbo frames */ - pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if ((hw->mac_type >= e1000_82571) && (pages <= 3) && - PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE)) - adapter->rx_ps_pages = pages; - else - adapter->rx_ps_pages = 0; -#endif - if (adapter->rx_ps_pages) { - /* Configure extra packet-split registers */ - rfctl = er32(RFCTL); - rfctl |= E1000_RFCTL_EXTEN; - /* disable packet split support for IPv6 extension headers, - * because some malformed IPv6 headers can hang the RX */ - rfctl |= (E1000_RFCTL_IPV6_EX_DIS | - E1000_RFCTL_NEW_IPV6_EXT_DIS); - - ew32(RFCTL, rfctl); - - rctl |= E1000_RCTL_DTYP_PS; - - psrctl |= adapter->rx_ps_bsize0 >> - E1000_PSRCTL_BSIZE0_SHIFT; - - switch (adapter->rx_ps_pages) { - case 3: - psrctl |= PAGE_SIZE << - E1000_PSRCTL_BSIZE3_SHIFT; - case 2: - psrctl |= PAGE_SIZE << - E1000_PSRCTL_BSIZE2_SHIFT; - case 1: - psrctl |= PAGE_SIZE >> - E1000_PSRCTL_BSIZE1_SHIFT; - break; - } - - ew32(PSRCTL, psrctl); - } - ew32(RCTL, rctl); } @@ -2053,18 +1971,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 rdlen, rctl, rxcsum, ctrl_ext; - if (adapter->rx_ps_pages) { - /* this is a 32 byte descriptor */ - rdlen = adapter->rx_ring[0].count * - sizeof(union e1000_rx_desc_packet_split); - adapter->clean_rx = e1000_clean_rx_irq_ps; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; - } else { - rdlen = adapter->rx_ring[0].count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers; - } + rdlen = adapter->rx_ring[0].count * + sizeof(struct e1000_rx_desc); + adapter->clean_rx = e1000_clean_rx_irq; + adapter->alloc_rx_buf = e1000_alloc_rx_buffers; /* disable receives while setting up the descriptors */ rctl = er32(RCTL); @@ -2109,28 +2019,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) /* Enable 82543 Receive Checksum Offload for TCP and UDP */ if (hw->mac_type >= e1000_82543) { rxcsum = er32(RXCSUM); - if (adapter->rx_csum) { + if (adapter->rx_csum) rxcsum |= E1000_RXCSUM_TUOFL; - - /* Enable 82571 IPv4 payload checksum for UDP fragments - * Must be used in conjunction with packet-split. */ - if ((hw->mac_type >= e1000_82571) && - (adapter->rx_ps_pages)) { - rxcsum |= E1000_RXCSUM_IPPCSE; - } - } else { - rxcsum &= ~E1000_RXCSUM_TUOFL; + else /* don't need to clear IPPCSE as it defaults to 0 */ - } + rxcsum &= ~E1000_RXCSUM_TUOFL; ew32(RXCSUM, rxcsum); } - /* enable early receives on 82573, only takes effect if using > 2048 - * byte total frame size. for example only for jumbo frames */ -#define E1000_ERT_2048 0x100 - if (hw->mac_type == e1000_82573) - ew32(ERT, E1000_ERT_2048); - /* Enable Receives */ ew32(RCTL, rctl); } @@ -2256,10 +2152,6 @@ static void e1000_free_rx_resources(struct e1000_adapter *adapter, vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; - kfree(rx_ring->ps_page); - rx_ring->ps_page = NULL; - kfree(rx_ring->ps_page_dma); - rx_ring->ps_page_dma = NULL; pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); @@ -2292,11 +2184,9 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, { struct e1000_hw *hw = &adapter->hw; struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct e1000_ps_page_dma *ps_page_dma; struct pci_dev *pdev = adapter->pdev; unsigned long size; - unsigned int i, j; + unsigned int i; /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { @@ -2310,25 +2200,10 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; } - ps_page = &rx_ring->ps_page[i]; - ps_page_dma = &rx_ring->ps_page_dma[i]; - for (j = 0; j < adapter->rx_ps_pages; j++) { - if (!ps_page->ps_page[j]) break; - pci_unmap_page(pdev, - ps_page_dma->ps_page_dma[j], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - ps_page_dma->ps_page_dma[j] = 0; - put_page(ps_page->ps_page[j]); - ps_page->ps_page[j] = NULL; - } } size = sizeof(struct e1000_buffer) * rx_ring->count; memset(rx_ring->buffer_info, 0, size); - size = sizeof(struct e1000_ps_page) * rx_ring->count; - memset(rx_ring->ps_page, 0, size); - size = sizeof(struct e1000_ps_page_dma) * rx_ring->count; - memset(rx_ring->ps_page_dma, 0, size); /* Zero out the descriptor ring */ @@ -4234,181 +4109,6 @@ next_desc: return cleaned; } -/** - * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split - * @adapter: board private structure - **/ - -static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do) -{ - union e1000_rx_desc_packet_split *rx_desc, *next_rxd; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info, *next_buffer; - struct e1000_ps_page *ps_page; - struct e1000_ps_page_dma *ps_page_dma; - struct sk_buff *skb; - unsigned int i, j; - u32 length, staterr; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes=0, total_rx_packets=0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - ps_page = &rx_ring->ps_page[i]; - ps_page_dma = &rx_ring->ps_page_dma[i]; - - if (unlikely(*work_done >= work_to_do)) - break; - (*work_done)++; - - skb = buffer_info->skb; - - /* in the packet split case this is header only */ - prefetch(skb->data - NET_IP_ALIGN); - - if (++i == rx_ring->count) i = 0; - next_rxd = E1000_RX_DESC_PS(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, - PCI_DMA_FROMDEVICE); - - if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) { - E1000_DBG("%s: Packet Split buffers didn't pick up" - " the full packet\n", netdev->name); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { - dev_kfree_skb_irq(skb); - goto next_desc; - } - - length = le16_to_cpu(rx_desc->wb.middle.length0); - - if (unlikely(!length)) { - E1000_DBG("%s: Last part of the packet spanning" - " multiple descriptors\n", netdev->name); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - /* Good Receive */ - skb_put(skb, length); - - { - /* this looks ugly, but it seems compiler issues make it - more efficient than reusing j */ - int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); - - /* page alloc/put takes too long and effects small packet - * throughput, so unsplit small packets and save the alloc/put*/ - if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) { - u8 *vaddr; - /* there is no documentation about how to call - * kmap_atomic, so we can't hold the mapping - * very long */ - pci_dma_sync_single_for_cpu(pdev, - ps_page_dma->ps_page_dma[0], - PAGE_SIZE, - PCI_DMA_FROMDEVICE); - vaddr = kmap_atomic(ps_page->ps_page[0], - KM_SKB_DATA_SOFTIRQ); - memcpy(skb_tail_pointer(skb), vaddr, l1); - kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); - pci_dma_sync_single_for_device(pdev, - ps_page_dma->ps_page_dma[0], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - /* remove the CRC */ - l1 -= 4; - skb_put(skb, l1); - goto copydone; - } /* if */ - } - - for (j = 0; j < adapter->rx_ps_pages; j++) { - length = le16_to_cpu(rx_desc->wb.upper.length[j]); - if (!length) - break; - pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], - PAGE_SIZE, PCI_DMA_FROMDEVICE); - ps_page_dma->ps_page_dma[j] = 0; - skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0, - length); - ps_page->ps_page[j] = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += length; - } - - /* strip the ethernet crc, problem is we're using pages now so - * this whole operation can get a little cpu intensive */ - pskb_trim(skb, skb->len - 4); - -copydone: - total_rx_bytes += skb->len; - total_rx_packets++; - - e1000_rx_checksum(adapter, staterr, - le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); - skb->protocol = eth_type_trans(skb, netdev); - - if (likely(rx_desc->wb.upper.header_status & - cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) - adapter->rx_hdr_split++; - - if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.middle.vlan)); - } else { - netif_receive_skb(skb); - } - - netdev->last_rx = jiffies; - -next_desc: - rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); - buffer_info->skb = NULL; - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = E1000_DESC_UNUSED(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - adapter->net_stats.rx_bytes += total_rx_bytes; - adapter->net_stats.rx_packets += total_rx_packets; - return cleaned; -} - /** * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended * @adapter: address of board private structure @@ -4520,104 +4220,6 @@ map_skb: } } -/** - * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split - * @adapter: address of board private structure - **/ - -static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_packet_split *rx_desc; - struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct e1000_ps_page_dma *ps_page_dma; - struct sk_buff *skb; - unsigned int i, j; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - ps_page = &rx_ring->ps_page[i]; - ps_page_dma = &rx_ring->ps_page_dma[i]; - - while (cleaned_count--) { - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - if (j < adapter->rx_ps_pages) { - if (likely(!ps_page->ps_page[j])) { - ps_page->ps_page[j] = - alloc_page(GFP_ATOMIC); - if (unlikely(!ps_page->ps_page[j])) { - adapter->alloc_rx_buff_failed++; - goto no_buffers; - } - ps_page_dma->ps_page_dma[j] = - pci_map_page(pdev, - ps_page->ps_page[j], - 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - } - /* Refresh the desc even if buffer_addrs didn't - * change because each write-back erases - * this info. - */ - rx_desc->read.buffer_addr[j+1] = - cpu_to_le64(ps_page_dma->ps_page_dma[j]); - } else - rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); - } - - skb = netdev_alloc_skb(netdev, - adapter->rx_ps_bsize0 + NET_IP_ALIGN); - - if (unlikely(!skb)) { - adapter->alloc_rx_buff_failed++; - break; - } - - /* Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, NET_IP_ALIGN); - - buffer_info->skb = skb; - buffer_info->length = adapter->rx_ps_bsize0; - buffer_info->dma = pci_map_single(pdev, skb->data, - adapter->rx_ps_bsize0, - PCI_DMA_FROMDEVICE); - - rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) i = 0; - buffer_info = &rx_ring->buffer_info[i]; - ps_page = &rx_ring->ps_page[i]; - ps_page_dma = &rx_ring->ps_page_dma[i]; - } - -no_buffers: - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - /* Hardware increments by 16 bytes, but packet split - * descriptors are 32 bytes...so we increment tail - * twice as much. - */ - writel(i<<1, hw->hw_addr + rx_ring->rdt); - } -} - /** * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. * @adapter: -- cgit v1.2.3 From 399ccdc1cd4e92e541d4dacbbf18c52bd693418b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 25 Sep 2008 14:51:03 +0200 Subject: ALSA: fix locking in snd_pcm_open*() and snd_rawmidi_open*() The PCM and rawmidi open callbacks have a lock against card->controls_list but it takes a wrong one, card->controls_rwsem, instead of a right one card->ctl_files_rwlock. This patch fixes them. This change also fixes automatically the potential deadlocks due to mm->mmap_sem in munmap and copy_from/to_user, reported by Sitsofe Wheeler: A: snd_ctl_elem_user_tlv(): card->controls_rwsem => mm->mmap_sem B: snd_pcm_open(): card->open_mutex => card->controls_rwsem C: munmap: mm->mmap_sem => snd_pcm_release(): card->open_mutex The patch breaks the chain. Signed-off-by: Takashi Iwai --- sound/core/pcm.c | 4 ++-- sound/core/rawmidi.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 9dd9bc73fe1..ece25c718e9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -781,7 +781,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return -ENODEV; card = pcm->card; - down_read(&card->controls_rwsem); + read_lock(&card->ctl_files_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { if (kctl->pid == current->pid) { prefer_subdevice = kctl->prefer_pcm_subdevice; @@ -789,7 +789,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, break; } } - up_read(&card->controls_rwsem); + read_unlock(&card->ctl_files_rwlock); switch (stream) { case SNDRV_PCM_STREAM_PLAYBACK: diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index f7ea7287c59..b917a9f981c 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -418,7 +418,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_lock(&rmidi->open_mutex); while (1) { subdevice = -1; - down_read(&card->controls_rwsem); + read_lock(&card->ctl_files_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { if (kctl->pid == current->pid) { subdevice = kctl->prefer_rawmidi_subdevice; @@ -426,7 +426,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) break; } } - up_read(&card->controls_rwsem); + read_unlock(&card->ctl_files_rwlock); err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device, subdevice, fflags, rawmidi_file); if (err >= 0) -- cgit v1.2.3 From 24e8fc498e9618338854bfbcf8d1d737e0bf1775 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 25 Sep 2008 17:51:11 +0200 Subject: ALSA: remove unneeded power_mutex lock in snd_pcm_drop The power_mutex lock in snd_pcm_drop may cause a possible deadlock chain, and above all, it's unneeded. Let's get rid of it. Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c49b9d9e303..c487025d345 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1546,16 +1546,10 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) card = substream->pcm->card; if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || + runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) return -EBADFD; - snd_power_lock(card); - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto _unlock; - } - snd_pcm_stream_lock_irq(substream); /* resume pause */ if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) @@ -1564,8 +1558,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); /* runtime->control->appl_ptr = runtime->status->hw_ptr; */ snd_pcm_stream_unlock_irq(substream); - _unlock: - snd_power_unlock(card); + return result; } -- cgit v1.2.3 From ef40a685311bef053dedd833a72dffaf25669dda Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 25 Sep 2008 13:06:59 -0700 Subject: Revert "ehea: fix mutex and spinlock use" This reverts commit 2eefbd63d0c85daa1317636474c226e236beba81. On request by driver author and Jeff Garzik. Signed-off-by: David S. Miller --- drivers/net/ehea/ehea_main.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index c765ec60946..b70c5314f53 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -219,11 +219,9 @@ static void ehea_update_firmware_handles(void) } out_update: - mutex_lock(&ehea_fw_handles.lock); kfree(ehea_fw_handles.arr); ehea_fw_handles.arr = arr; ehea_fw_handles.num_entries = i; - mutex_unlock(&ehea_fw_handles.lock); } static void ehea_update_bcmc_registrations(void) @@ -295,11 +293,9 @@ static void ehea_update_bcmc_registrations(void) } out_update: - spin_lock(&ehea_bcmc_regs.lock); kfree(ehea_bcmc_regs.arr); ehea_bcmc_regs.arr = arr; ehea_bcmc_regs.num_entries = i; - spin_unlock(&ehea_bcmc_regs.lock); } static struct net_device_stats *ehea_get_stats(struct net_device *dev) @@ -1774,6 +1770,8 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); + spin_lock(&ehea_bcmc_regs.lock); + /* Deregister old MAC in pHYP */ if (port->state == EHEA_PORT_UP) { ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -1794,6 +1792,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) out_upregs: ehea_update_bcmc_registrations(); + spin_unlock(&ehea_bcmc_regs.lock); out_free: kfree(cb0); out: @@ -1955,6 +1954,8 @@ static void ehea_set_multicast_list(struct net_device *dev) } ehea_promiscuous(dev, 0); + spin_lock(&ehea_bcmc_regs.lock); + if (dev->flags & IFF_ALLMULTI) { ehea_allmulti(dev, 1); goto out; @@ -1984,6 +1985,7 @@ static void ehea_set_multicast_list(struct net_device *dev) } out: ehea_update_bcmc_registrations(); + spin_unlock(&ehea_bcmc_regs.lock); return; } @@ -2464,6 +2466,8 @@ static int ehea_up(struct net_device *dev) if (port->state == EHEA_PORT_UP) return 0; + mutex_lock(&ehea_fw_handles.lock); + ret = ehea_port_res_setup(port, port->num_def_qps, port->num_add_tx_qps); if (ret) { @@ -2500,6 +2504,8 @@ static int ehea_up(struct net_device *dev) } } + spin_lock(&ehea_bcmc_regs.lock); + ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); if (ret) { ret = -EIO; @@ -2521,8 +2527,10 @@ out: ehea_info("Failed starting %s. ret=%i", dev->name, ret); ehea_update_bcmc_registrations(); + spin_unlock(&ehea_bcmc_regs.lock); ehea_update_firmware_handles(); + mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -2572,6 +2580,9 @@ static int ehea_down(struct net_device *dev) if (port->state == EHEA_PORT_DOWN) return 0; + mutex_lock(&ehea_fw_handles.lock); + + spin_lock(&ehea_bcmc_regs.lock); ehea_drop_multicast_list(dev); ehea_broadcast_reg_helper(port, H_DEREG_BCMC); @@ -2580,6 +2591,7 @@ static int ehea_down(struct net_device *dev) port->state = EHEA_PORT_DOWN; ehea_update_bcmc_registrations(); + spin_unlock(&ehea_bcmc_regs.lock); ret = ehea_clean_all_portres(port); if (ret) @@ -2587,6 +2599,7 @@ static int ehea_down(struct net_device *dev) dev->name, ret); ehea_update_firmware_handles(); + mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -3365,6 +3378,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, ehea_error("Invalid ibmebus device probed"); return -EINVAL; } + mutex_lock(&ehea_fw_handles.lock); adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { @@ -3448,6 +3462,7 @@ out_free_ad: out: ehea_update_firmware_handles(); + mutex_unlock(&ehea_fw_handles.lock); return ret; } @@ -3466,6 +3481,8 @@ static int __devexit ehea_remove(struct of_device *dev) flush_scheduled_work(); + mutex_lock(&ehea_fw_handles.lock); + ibmebus_free_irq(adapter->neq->attr.ist1, adapter); tasklet_kill(&adapter->neq_tasklet); @@ -3475,6 +3492,7 @@ static int __devexit ehea_remove(struct of_device *dev) kfree(adapter); ehea_update_firmware_handles(); + mutex_unlock(&ehea_fw_handles.lock); return 0; } -- cgit v1.2.3 From 6ef190cc92e33565accff6a320f0e7d90480bfe7 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 25 Sep 2008 15:28:08 -0700 Subject: IPoIB: Fix crash when path record fails after path flush Commit ee1e2c82 ("IPoIB: Refresh paths instead of flushing them on SM change events") changed how paths are flushed on an SM event. This change introduces a problem if the path record query triggered by fails, causing path->ah to become NULL. A later successful path query will then trigger WARN_ON() in path_rec_completion(), and crash because path->ah has already been freed, so the ipoib_put_ah() inside the lock in path_rec_completion() may actually drop the last reference (contrary to the comment that claims this is safe). Fix this by updating path->ah and freeing old_ah only when the path record query is successful. This prevents the neighbour AH and that path AH from getting out of sync. This fixes Reported-by: Rabah Salem Debugged-by: Eli Cohen Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1b1df5cc411..e9ca3cb57d5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -404,7 +404,7 @@ static void path_rec_completion(int status, struct net_device *dev = path->dev; struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_ah *ah = NULL; - struct ipoib_ah *old_ah; + struct ipoib_ah *old_ah = NULL; struct ipoib_neigh *neigh, *tn; struct sk_buff_head skqueue; struct sk_buff *skb; @@ -428,12 +428,12 @@ static void path_rec_completion(int status, spin_lock_irqsave(&priv->lock, flags); - old_ah = path->ah; - path->ah = ah; - if (ah) { path->pathrec = *pathrec; + old_ah = path->ah; + path->ah = ah; + ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", ah, be16_to_cpu(pathrec->dlid), pathrec->sl); -- cgit v1.2.3 From f1ccd2955157e1aff992f6aaaba0944209076220 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Fri, 26 Sep 2008 12:16:46 +1000 Subject: [XFS] Fix extent list corruption in xfs_iext_irec_compact_full(). If we don't move all the records from the next buffer into the current buffer then we need to update the er_extoff field of the next buffer as we shift the remaining records to the start of the buffer. SGI-PV: 987159 SGI-Modid: xfs-linux-melb:xfs-kern:32165a Signed-off-by: Lachlan McIlroy Signed-off-by: Eric Sandeen Signed-off-by: Russell Cattelan --- fs/xfs/xfs_inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 00e80df9dd9..419cfc2eacb 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -4584,6 +4584,7 @@ xfs_iext_irec_compact_full( (XFS_LINEAR_EXTS - erp_next->er_extcount) * sizeof(xfs_bmbt_rec_t)); + erp_next->er_extoff += ext_diff; } } -- cgit v1.2.3 From 71a8c87fb300b601eacf7a86cc6c6322fe827bfd Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Fri, 26 Sep 2008 12:17:57 +1000 Subject: [XFS] Remove xfs_iext_irec_compact_full() Yet another bug was found in xfs_iext_irec_compact_full() and while the source of the bug was found it wasn't an easy task to track it down because the conditions are very difficult to reproduce. A HUGE thank-you goes to Russell Cattelan and Eric Sandeen for their significant effort in tracking down the source of this corruption. xfs_iext_irec_compact_full() and xfs_iext_irec_compact_pages() are almost identical - they both compact indirect extent lists by moving extents from subsequent buffers into earlier ones. xfs_iext_irec_compact_pages() only moves extents if all of the extents in the next buffer will fit into the empty space in the buffer before it. xfs_iext_irec_compact_full() will go a step further and move part of the next buffer if all the extents wont fit. It will then shift the remaining extents in the next buffer up to the start of the buffer. The bug here was that we did not update er_extoff and this caused extent list corruption. It does not appear that this extra functionality gains us much. Calling xfs_iext_irec_compact_pages() instead will do a good enough job at compacting the indirect list and will be quicker too. For the case in xfs_iext_indirect_to_direct() the total number of extents in the indirect list will fit into one buffer so we will never need the extra functionality of xfs_iext_irec_compact_full() there. Also xfs_iext_irec_compact_pages() doesn't need to do a memmove() (the buffers will never overlap) so we don't want the performance hit that can incur. SGI-PV: 987159 SGI-Modid: xfs-linux-melb:xfs-kern:32166a Signed-off-by: Lachlan McIlroy Signed-off-by: Eric Sandeen --- fs/xfs/xfs_inode.c | 95 ++---------------------------------------------------- 1 file changed, 3 insertions(+), 92 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 419cfc2eacb..dbd9cef852e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -4118,7 +4118,7 @@ xfs_iext_indirect_to_direct( ASSERT(nextents <= XFS_LINEAR_EXTS); size = nextents * sizeof(xfs_bmbt_rec_t); - xfs_iext_irec_compact_full(ifp); + xfs_iext_irec_compact_pages(ifp); ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); ep = ifp->if_u1.if_ext_irec->er_extbuf; @@ -4449,8 +4449,7 @@ xfs_iext_irec_remove( * compaction policy is as follows: * * Full Compaction: Extents fit into a single page (or inline buffer) - * Full Compaction: Extents occupy less than 10% of allocated space - * Partial Compaction: Extents occupy > 10% and < 50% of allocated space + * Partial Compaction: Extents occupy less than 50% of allocated space * No Compaction: Extents occupy at least 50% of allocated space */ void @@ -4471,8 +4470,6 @@ xfs_iext_irec_compact( xfs_iext_direct_to_inline(ifp, nextents); } else if (nextents <= XFS_LINEAR_EXTS) { xfs_iext_indirect_to_direct(ifp); - } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) { - xfs_iext_irec_compact_full(ifp); } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { xfs_iext_irec_compact_pages(ifp); } @@ -4496,7 +4493,7 @@ xfs_iext_irec_compact_pages( erp_next = erp + 1; if (erp_next->er_extcount <= (XFS_LINEAR_EXTS - erp->er_extcount)) { - memmove(&erp->er_extbuf[erp->er_extcount], + memcpy(&erp->er_extbuf[erp->er_extcount], erp_next->er_extbuf, erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); erp->er_extcount += erp_next->er_extcount; @@ -4515,92 +4512,6 @@ xfs_iext_irec_compact_pages( } } -/* - * Fully compact the extent records managed by the indirection array. - */ -void -xfs_iext_irec_compact_full( - xfs_ifork_t *ifp) /* inode fork pointer */ -{ - xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */ - xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */ - int erp_idx = 0; /* extent irec index */ - int ext_avail; /* empty entries in ex list */ - int ext_diff; /* number of exts to add */ - int nlists; /* number of irec's (ex lists) */ - - ASSERT(ifp->if_flags & XFS_IFEXTIREC); - - nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; - erp = ifp->if_u1.if_ext_irec; - ep = &erp->er_extbuf[erp->er_extcount]; - erp_next = erp + 1; - ep_next = erp_next->er_extbuf; - - while (erp_idx < nlists - 1) { - /* - * Check how many extent records are available in this irec. - * If there is none skip the whole exercise. - */ - ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; - if (ext_avail) { - - /* - * Copy over as many as possible extent records into - * the previous page. - */ - ext_diff = MIN(ext_avail, erp_next->er_extcount); - memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); - erp->er_extcount += ext_diff; - erp_next->er_extcount -= ext_diff; - - /* - * If the next irec is empty now we can simply - * remove it. - */ - if (erp_next->er_extcount == 0) { - /* - * Free page before removing extent record - * so er_extoffs don't get modified in - * xfs_iext_irec_remove. - */ - kmem_free(erp_next->er_extbuf); - erp_next->er_extbuf = NULL; - xfs_iext_irec_remove(ifp, erp_idx + 1); - erp = &ifp->if_u1.if_ext_irec[erp_idx]; - nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; - - /* - * If the next irec is not empty move up the content - * that has not been copied to the previous page to - * the beggining of this one. - */ - } else { - memmove(erp_next->er_extbuf, &ep_next[ext_diff], - erp_next->er_extcount * - sizeof(xfs_bmbt_rec_t)); - ep_next = erp_next->er_extbuf; - memset(&ep_next[erp_next->er_extcount], 0, - (XFS_LINEAR_EXTS - - erp_next->er_extcount) * - sizeof(xfs_bmbt_rec_t)); - erp_next->er_extoff += ext_diff; - } - } - - if (erp->er_extcount == XFS_LINEAR_EXTS) { - erp_idx++; - if (erp_idx < nlists) - erp = &ifp->if_u1.if_ext_irec[erp_idx]; - else - break; - } - ep = &erp->er_extbuf[erp->er_extcount]; - erp_next = erp + 1; - ep_next = erp_next->er_extbuf; - } -} - /* * This is called to update the er_extoff field in the indirection * array when extents have been added or removed from one of the -- cgit v1.2.3 From 18d6522b86d21a04c8ac1ea79747e2e434a956d9 Mon Sep 17 00:00:00 2001 From: Atsuo Igarashi Date: Fri, 26 Sep 2008 10:36:41 -0500 Subject: kgdb: could not write to the last of valid memory with kgdb On the ARM architecture, kgdb will crash the kernel if the last byte of valid memory is written due to a flush_icache_range flushing beyond the memory boundary. Signed-off-by: Atsuo Igarashi Signed-off-by: Jason Wessel --- kernel/kgdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kgdb.c b/kernel/kgdb.c index eaa21fc9ad1..949806ab67d 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -488,7 +488,7 @@ static int write_mem_msg(int binary) if (err) return err; if (CACHE_FLUSH_IS_SAFE) - flush_icache_range(addr, addr + length + 1); + flush_icache_range(addr, addr + length); return 0; } -- cgit v1.2.3 From d7161a65341556bacb5e6654e133803f46f51063 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 26 Sep 2008 10:36:41 -0500 Subject: kgdb, x86, arm, mips, powerpc: ignore user space single stepping On the x86 arch, user space single step exceptions should be ignored if they occur in the kernel space, such as ptrace stepping through a system call. First check if it is kgdb that is executing a single step, then ensure it is not an accidental traversal into the user space, while in kgdb, any other time the TIF_SINGLESTEP is set, kgdb should ignore the exception. On x86, arm, mips and powerpc, the kgdb_contthread usage was inconsistent with the way single stepping is implemented in the kgdb core. The arch specific stub should always set the kgdb_cpu_doing_single_step correctly if it is single stepping. This allows kgdb to correctly process an instruction steps if ptrace happens to be requesting an instruction step over a system call. Signed-off-by: Jason Wessel --- arch/arm/kernel/kgdb.c | 2 -- arch/mips/kernel/kgdb.c | 3 +-- arch/powerpc/kernel/kgdb.c | 5 ++--- arch/x86/kernel/kgdb.c | 18 +++++++++++------- kernel/kgdb.c | 8 ++++---- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index aaffaecffcd..ba8ccfede96 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c @@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, case 'D': case 'k': case 'c': - kgdb_contthread = NULL; - /* * Try to read optional parameter, pc unchanged if no parm. * If this was a compiled breakpoint, we need to move diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 8f6d58ede33..6e152c80cd4 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, atomic_set(&kgdb_cpu_doing_single_step, -1); if (remcom_in_buffer[0] == 's') - if (kgdb_contthread) - atomic_set(&kgdb_cpu_doing_single_step, cpu); + atomic_set(&kgdb_cpu_doing_single_step, cpu); return 0; } diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index b4fdf2f2743..fe8f71dd0b3 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, linux_regs->msr |= MSR_SE; #endif kgdb_single_step = 1; - if (kgdb_contthread) - atomic_set(&kgdb_cpu_doing_single_step, - raw_smp_processor_id()); + atomic_set(&kgdb_cpu_doing_single_step, + raw_smp_processor_id()); } return 0; } diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index f47f0eb886b..00f7896c9a1 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -378,10 +378,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, if (remcomInBuffer[0] == 's') { linux_regs->flags |= X86_EFLAGS_TF; kgdb_single_step = 1; - if (kgdb_contthread) { - atomic_set(&kgdb_cpu_doing_single_step, - raw_smp_processor_id()); - } + atomic_set(&kgdb_cpu_doing_single_step, + raw_smp_processor_id()); } get_debugreg(dr6, 6); @@ -466,9 +464,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) case DIE_DEBUG: if (atomic_read(&kgdb_cpu_doing_single_step) == - raw_smp_processor_id() && - user_mode(regs)) - return single_step_cont(regs, args); + raw_smp_processor_id()) { + if (user_mode(regs)) + return single_step_cont(regs, args); + break; + } else if (test_thread_flag(TIF_SINGLESTEP)) + /* This means a user thread is single stepping + * a system call which should be ignored + */ + return NOTIFY_DONE; /* fall through */ default: if (user_mode(regs)) diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 949806ab67d..25d955dbb98 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -1462,7 +1462,7 @@ acquirelock: * Get the passive CPU lock which will hold all the non-primary * CPU in a spin state while the debugger is active */ - if (!kgdb_single_step || !kgdb_contthread) { + if (!kgdb_single_step) { for (i = 0; i < NR_CPUS; i++) atomic_set(&passive_cpu_wait[i], 1); } @@ -1475,7 +1475,7 @@ acquirelock: #ifdef CONFIG_SMP /* Signal the other CPUs to enter kgdb_wait() */ - if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup) + if ((!kgdb_single_step) && kgdb_do_roundup) kgdb_roundup_cpus(flags); #endif @@ -1494,7 +1494,7 @@ acquirelock: kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); kgdb_deactivate_sw_breakpoints(); kgdb_single_step = 0; - kgdb_contthread = NULL; + kgdb_contthread = current; exception_level = 0; /* Talk to debugger with gdbserial protocol */ @@ -1508,7 +1508,7 @@ acquirelock: kgdb_info[ks->cpu].task = NULL; atomic_set(&cpu_in_kgdb[ks->cpu], 0); - if (!kgdb_single_step || !kgdb_contthread) { + if (!kgdb_single_step) { for (i = NR_CPUS-1; i >= 0; i--) atomic_set(&passive_cpu_wait[i], 0); /* -- cgit v1.2.3 From 95dbf1dbe39ed336a3e72116c95cfa98dd3457e6 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 26 Sep 2008 10:36:42 -0500 Subject: kgdb, x86_64: gdb serial has BX and DX reversed The BX and DX registers in the gdb serial register packet need to be flipped for gdb to receive the correct data. Signed-off-by: Jason Wessel --- include/asm-x86/kgdb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h index 484c47554f3..e86b3060bdc 100644 --- a/include/asm-x86/kgdb.h +++ b/include/asm-x86/kgdb.h @@ -42,9 +42,9 @@ enum regnames { #else /* ! CONFIG_X86_32 */ enum regnames { GDB_AX, /* 0 */ - GDB_DX, /* 1 */ + GDB_BX, /* 1 */ GDB_CX, /* 2 */ - GDB_BX, /* 3 */ + GDB_DX, /* 3 */ GDB_SI, /* 4 */ GDB_DI, /* 5 */ GDB_BP, /* 6 */ -- cgit v1.2.3 From 703a1edcd1534468fc18f733c03bd91a65c8c6f0 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 26 Sep 2008 10:36:42 -0500 Subject: kgdb, x86_64: fix PS CS SS registers in gdb serial On x86_64 the gdb serial register structure defines the PS (also known as eflags), CS and SS registers as 4 bytes entities. This patch splits the x86_64 regnames enum into a 32 and 64 version to account for the 32 bit entities in the gdb serial packets. Also the program counter is properly filled in for the sleeping threads. Signed-off-by: Jason Wessel --- arch/x86/kernel/kgdb.c | 25 +++++++++++++++++++++---- include/asm-x86/kgdb.h | 20 +++++++++----------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 00f7896c9a1..8282a213968 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -69,6 +69,9 @@ static int gdb_x86vector = -1; */ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { +#ifndef CONFIG_X86_32 + u32 *gdb_regs32 = (u32 *)gdb_regs; +#endif gdb_regs[GDB_AX] = regs->ax; gdb_regs[GDB_BX] = regs->bx; gdb_regs[GDB_CX] = regs->cx; @@ -76,9 +79,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) gdb_regs[GDB_SI] = regs->si; gdb_regs[GDB_DI] = regs->di; gdb_regs[GDB_BP] = regs->bp; - gdb_regs[GDB_PS] = regs->flags; gdb_regs[GDB_PC] = regs->ip; #ifdef CONFIG_X86_32 + gdb_regs[GDB_PS] = regs->flags; gdb_regs[GDB_DS] = regs->ds; gdb_regs[GDB_ES] = regs->es; gdb_regs[GDB_CS] = regs->cs; @@ -94,6 +97,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) gdb_regs[GDB_R13] = regs->r13; gdb_regs[GDB_R14] = regs->r14; gdb_regs[GDB_R15] = regs->r15; + gdb_regs32[GDB_PS] = regs->flags; + gdb_regs32[GDB_CS] = regs->cs; + gdb_regs32[GDB_SS] = regs->ss; #endif gdb_regs[GDB_SP] = regs->sp; } @@ -112,6 +118,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) */ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) { +#ifndef CONFIG_X86_32 + u32 *gdb_regs32 = (u32 *)gdb_regs; +#endif gdb_regs[GDB_AX] = 0; gdb_regs[GDB_BX] = 0; gdb_regs[GDB_CX] = 0; @@ -129,8 +138,10 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) gdb_regs[GDB_FS] = 0xFFFF; gdb_regs[GDB_GS] = 0xFFFF; #else - gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); - gdb_regs[GDB_PC] = 0; + gdb_regs32[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); + gdb_regs32[GDB_CS] = __KERNEL_CS; + gdb_regs32[GDB_SS] = __KERNEL_DS; + gdb_regs[GDB_PC] = p->thread.ip; gdb_regs[GDB_R8] = 0; gdb_regs[GDB_R9] = 0; gdb_regs[GDB_R10] = 0; @@ -153,6 +164,9 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) */ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) { +#ifndef CONFIG_X86_32 + u32 *gdb_regs32 = (u32 *)gdb_regs; +#endif regs->ax = gdb_regs[GDB_AX]; regs->bx = gdb_regs[GDB_BX]; regs->cx = gdb_regs[GDB_CX]; @@ -160,9 +174,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) regs->si = gdb_regs[GDB_SI]; regs->di = gdb_regs[GDB_DI]; regs->bp = gdb_regs[GDB_BP]; - regs->flags = gdb_regs[GDB_PS]; regs->ip = gdb_regs[GDB_PC]; #ifdef CONFIG_X86_32 + regs->flags = gdb_regs[GDB_PS]; regs->ds = gdb_regs[GDB_DS]; regs->es = gdb_regs[GDB_ES]; regs->cs = gdb_regs[GDB_CS]; @@ -175,6 +189,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) regs->r13 = gdb_regs[GDB_R13]; regs->r14 = gdb_regs[GDB_R14]; regs->r15 = gdb_regs[GDB_R15]; + regs->flags = gdb_regs32[GDB_PS]; + regs->cs = gdb_regs32[GDB_CS]; + regs->ss = gdb_regs32[GDB_SS]; #endif } diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h index e86b3060bdc..94d63db1036 100644 --- a/include/asm-x86/kgdb.h +++ b/include/asm-x86/kgdb.h @@ -39,8 +39,9 @@ enum regnames { GDB_FS, /* 14 */ GDB_GS, /* 15 */ }; +#define NUMREGBYTES ((GDB_GS+1)*4) #else /* ! CONFIG_X86_32 */ -enum regnames { +enum regnames64 { GDB_AX, /* 0 */ GDB_BX, /* 1 */ GDB_CX, /* 2 */ @@ -58,18 +59,15 @@ enum regnames { GDB_R14, /* 14 */ GDB_R15, /* 15 */ GDB_PC, /* 16 */ - GDB_PS, /* 17 */ }; -#endif /* CONFIG_X86_32 */ -/* - * Number of bytes of registers: - */ -#ifdef CONFIG_X86_32 -# define NUMREGBYTES 64 -#else -# define NUMREGBYTES ((GDB_PS+1)*8) -#endif +enum regnames32 { + GDB_PS = 34, + GDB_CS, + GDB_SS, +}; +#define NUMREGBYTES ((GDB_SS+1)*4) +#endif /* CONFIG_X86_32 */ static inline void arch_kgdb_breakpoint(void) { -- cgit v1.2.3 From 0dca0fd2bfeb99738708d6c9117994ebf398e72c Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 26 Sep 2008 10:36:42 -0500 Subject: kgdboc,tty: Fix tty polling search to use name correctly The tty_find_polling_driver() routine did not correctly check the base part of the tty name. This can lead to kgdboc selecting an incorrect driver, as well as accepting a completely invalid tty such as "echo ffff0 > /sys/module/kgdboc/parameters/kgdboc". Signed-off-by: Jason Wessel --- drivers/char/tty_io.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index daeb8f76697..e4dce870954 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -695,13 +695,23 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) { struct tty_driver *p, *res = NULL; int tty_line = 0; + int len; char *str; + for (str = name; *str; str++) + if ((*str >= '0' && *str <= '9') || *str == ',') + break; + if (!*str) + return NULL; + + len = str - name; + tty_line = simple_strtoul(str, &str, 10); + mutex_lock(&tty_mutex); /* Search through the tty devices to look for a match */ list_for_each_entry(p, &tty_drivers, tty_drivers) { - str = name + strlen(p->name); - tty_line = simple_strtoul(str, &str, 10); + if (strncmp(name, p->name, len) != 0) + continue; if (*str == ',') str++; if (*str == '\0') -- cgit v1.2.3 From bc173c5789e1fc6065fd378edc815914b40ee86b Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 26 Sep 2008 16:22:58 +0100 Subject: ARM: Delete ARM's own cnt32_to_63.h Delete ARM's own cnt32_to_63.h as the copy in include/linux/ should now be used instead. Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- arch/arm/include/asm/cnt32_to_63.h | 78 -------------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 arch/arm/include/asm/cnt32_to_63.h diff --git a/arch/arm/include/asm/cnt32_to_63.h b/arch/arm/include/asm/cnt32_to_63.h deleted file mode 100644 index 480c873fa74..00000000000 --- a/arch/arm/include/asm/cnt32_to_63.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits - * - * Author: Nicolas Pitre - * Created: December 3, 2006 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#ifndef __INCLUDE_CNT32_TO_63_H__ -#define __INCLUDE_CNT32_TO_63_H__ - -#include -#include -#include - -/* - * Prototype: u64 cnt32_to_63(u32 cnt) - * Many hardware clock counters are only 32 bits wide and therefore have - * a relatively short period making wrap-arounds rather frequent. This - * is a problem when implementing sched_clock() for example, where a 64-bit - * non-wrapping monotonic value is expected to be returned. - * - * To overcome that limitation, let's extend a 32-bit counter to 63 bits - * in a completely lock free fashion. Bits 0 to 31 of the clock are provided - * by the hardware while bits 32 to 62 are stored in memory. The top bit in - * memory is used to synchronize with the hardware clock half-period. When - * the top bit of both counters (hardware and in memory) differ then the - * memory is updated with a new value, incrementing it when the hardware - * counter wraps around. - * - * Because a word store in memory is atomic then the incremented value will - * always be in synch with the top bit indicating to any potential concurrent - * reader if the value in memory is up to date or not with regards to the - * needed increment. And any race in updating the value in memory is harmless - * as the same value would simply be stored more than once. - * - * The only restriction for the algorithm to work properly is that this - * code must be executed at least once per each half period of the 32-bit - * counter to properly update the state bit in memory. This is usually not a - * problem in practice, but if it is then a kernel timer could be scheduled - * to manage for this code to be executed often enough. - * - * Note that the top bit (bit 63) in the returned value should be considered - * as garbage. It is not cleared here because callers are likely to use a - * multiplier on the returned value which can get rid of the top bit - * implicitly by making the multiplier even, therefore saving on a runtime - * clear-bit instruction. Otherwise caller must remember to clear the top - * bit explicitly. - */ - -/* this is used only to give gcc a clue about good code generation */ -typedef union { - struct { -#if defined(__LITTLE_ENDIAN) - u32 lo, hi; -#elif defined(__BIG_ENDIAN) - u32 hi, lo; -#endif - }; - u64 val; -} cnt32_to_63_t; - -#define cnt32_to_63(cnt_lo) \ -({ \ - static volatile u32 __m_cnt_hi = 0; \ - cnt32_to_63_t __x; \ - __x.hi = __m_cnt_hi; \ - __x.lo = (cnt_lo); \ - if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ - __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ - __x.val; \ -}) - -#endif -- cgit v1.2.3 From 1575da9ee4804ca889f32f8567dd7965e6fe4abc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Sep 2008 14:57:11 +0900 Subject: m32r: remove the unused NOHIGHMEM option Remove the unused NOHIGHMEM option. Reviewed-by: Robert P. J. Day Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Hirokazu Takata --- arch/m32r/Kconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index a5f864c445b..0266519491a 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -216,10 +216,6 @@ config MEMORY_SIZE default "01000000" if PLAT_M32104UT default "00800000" if PLAT_OAKS32R -config NOHIGHMEM - bool - default y - config ARCH_DISCONTIGMEM_ENABLE bool "Internal RAM Support" depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104 -- cgit v1.2.3 From 1b20b093e7f81ff8cb322773684b260d1487b610 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Sep 2008 14:58:54 +0900 Subject: m32r: don't offer CONFIG_ISA As far as I know no M32R hardware actually has ISA slots. And ISA drivers don't compile on M32R. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Hirokazu Takata --- arch/m32r/Kconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 0266519491a..f57113f1f89 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -406,11 +406,7 @@ config PCI_DIRECT source "drivers/pci/Kconfig" config ISA - bool "ISA support" - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. If you have ISA, say Y, otherwise N. + bool source "drivers/pcmcia/Kconfig" -- cgit v1.2.3 From affa6b120fa895e2bed0e131282fe89c05da1008 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Sep 2008 14:59:57 +0900 Subject: m32r: export empty_zero_page ERROR: "empty_zero_page" [fs/ext4/ext4dev.ko] undefined! Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Hirokazu Takata --- arch/m32r/kernel/m32r_ksyms.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index 16bcb189a38..22624b51d4d 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c @@ -14,6 +14,7 @@ #include #include #include +#include /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); @@ -65,6 +66,7 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(_inb); EXPORT_SYMBOL(_inw); -- cgit v1.2.3 From 4b65fd41807dec1484003a7618c492477511509e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Sep 2008 15:01:15 +0900 Subject: m32r: export __ndelay ERROR: "__ndelay" [drivers/spi/spi_bitbang.ko] undefined! Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Hirokazu Takata --- arch/m32r/lib/delay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c index 59bfc34e0d9..ced549be80f 100644 --- a/arch/m32r/lib/delay.c +++ b/arch/m32r/lib/delay.c @@ -6,6 +6,7 @@ */ #include +#include #ifdef CONFIG_SMP #include #include @@ -121,3 +122,4 @@ void __ndelay(unsigned long nsecs) { __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ } +EXPORT_SYMBOL(__ndelay); -- cgit v1.2.3 From 81e4807303c416a0defdce8b23a6204416d33280 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 24 Sep 2008 15:01:47 +0900 Subject: m32r/kernel/: cleanups This patch contains the following cleanups: - make the following needlessly global code static: - entry.S: resume_userspace - process.c: pm_idle - process.c: default_idle() - smp.c: send_IPI_allbutself() - time.c: timer_interrupt() - time.c: struct irq0 - traps.c: set_eit_vector_entries() - traps.c: kstack_depth_to_print - traps.c: show_trace() - traps.c: die_lock - remove the following unused code: - head.S: startup_32 - process.c: hlt_counter - process.c: disable_hlt() - process.c: enable_hlt() - process.c: dump_task_regs() - remove the following variables and their usages since they were always 0: - irq.c: irq_err_count - irq.c: irq_mis_count Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Hirokazu Takata --- arch/m32r/kernel/entry.S | 2 +- arch/m32r/kernel/head.S | 1 - arch/m32r/kernel/irq.c | 6 ------ arch/m32r/kernel/process.c | 30 ++---------------------------- arch/m32r/kernel/smp.c | 4 ++-- arch/m32r/kernel/time.c | 5 ++--- arch/m32r/kernel/traps.c | 8 ++++---- 7 files changed, 11 insertions(+), 45 deletions(-) diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index d4eaa2fd181..612d35b082a 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -143,7 +143,7 @@ ret_from_intr: and3 r4, r4, #0x8000 ; check BSM bit #endif beqz r4, resume_kernel -ENTRY(resume_userspace) +resume_userspace: DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt ; setting need_resched or sigpending ; between sampling and the iret diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S index dab7436d7bb..40180778a5c 100644 --- a/arch/m32r/kernel/head.S +++ b/arch/m32r/kernel/head.S @@ -29,7 +29,6 @@ __INITDATA .global _end ENTRY(stext) ENTRY(_stext) -ENTRY(startup_32) /* Setup up the stack pointer */ LDIMM (r0, spi_stack_top) LDIMM (r1, spu_stack_top) diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index d0c5b0b7da2..2aeae467009 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -22,9 +22,6 @@ #include #include -atomic_t irq_err_count; -atomic_t irq_mis_count; - /* * Generic, controller-independent functions: */ @@ -63,9 +60,6 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) { - seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); - seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); } return 0; } diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index a689e2978b6..5be4faaf5b1 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -35,8 +35,6 @@ #include -static int hlt_counter=0; - /* * Return saved PC of a blocked thread. */ @@ -48,31 +46,16 @@ unsigned long thread_saved_pc(struct task_struct *tsk) /* * Powermanagement idle function, if any.. */ -void (*pm_idle)(void) = NULL; -EXPORT_SYMBOL(pm_idle); +static void (*pm_idle)(void) = NULL; void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); -void disable_hlt(void) -{ - hlt_counter++; -} - -EXPORT_SYMBOL(disable_hlt); - -void enable_hlt(void) -{ - hlt_counter--; -} - -EXPORT_SYMBOL(enable_hlt); - /* * We use this is we don't have any better * idle routine.. */ -void default_idle(void) +static void default_idle(void) { /* M32R_FIXME: Please use "cpu_sleep" mode. */ cpu_relax(); @@ -260,15 +243,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long spu, return 0; } -/* - * Capture the user space registers if the task is not running (in user space) - */ -int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) -{ - /* M32R_FIXME */ - return 1; -} - asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, struct pt_regs regs) diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c index 7577f971ea4..929e5c9d3ad 100644 --- a/arch/m32r/kernel/smp.c +++ b/arch/m32r/kernel/smp.c @@ -84,7 +84,7 @@ void smp_send_timer(void); void smp_ipi_timer_interrupt(struct pt_regs *); void smp_local_timer_interrupt(void); -void send_IPI_allbutself(int, int); +static void send_IPI_allbutself(int, int); static void send_IPI_mask(cpumask_t, int, int); unsigned long send_IPI_mask_phys(cpumask_t, int, int); @@ -722,7 +722,7 @@ void smp_local_timer_interrupt(void) * ---------- --- -------------------------------------------------------- * *==========================================================================*/ -void send_IPI_allbutself(int ipi_num, int try) +static void send_IPI_allbutself(int ipi_num, int try) { cpumask_t cpumask; diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 994cc155635..6ea017727cc 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -34,7 +34,6 @@ #include #ifdef CONFIG_SMP -extern void send_IPI_allbutself(int, int); extern void smp_local_timer_interrupt(void); #endif @@ -188,7 +187,7 @@ static long last_rtc_update = 0; * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -irqreturn_t timer_interrupt(int irq, void *dev_id) +static irqreturn_t timer_interrupt(int irq, void *dev_id) { #ifndef CONFIG_SMP profile_tick(CPU_PROFILING); @@ -228,7 +227,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -struct irqaction irq0 = { +static struct irqaction irq0 = { .handler = timer_interrupt, .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c index 46159a4e644..03b14e55cd8 100644 --- a/arch/m32r/kernel/traps.c +++ b/arch/m32r/kernel/traps.c @@ -61,7 +61,7 @@ extern unsigned long eit_vector[]; ((unsigned long)func - (unsigned long)eit_vector - entry*4)/4 \ + 0xff000000UL -void set_eit_vector_entries(void) +static void set_eit_vector_entries(void) { extern void default_eit_handler(void); extern void system_call(void); @@ -121,9 +121,9 @@ void __init trap_init(void) cpu_init(); } -int kstack_depth_to_print = 24; +static int kstack_depth_to_print = 24; -void show_trace(struct task_struct *task, unsigned long *stack) +static void show_trace(struct task_struct *task, unsigned long *stack) { unsigned long addr; @@ -224,7 +224,7 @@ bad: printk("\n"); } -DEFINE_SPINLOCK(die_lock); +static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) { -- cgit v1.2.3 From 19506fc51852e859bb08ab5abbdb8fd02b7392f2 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Thu, 25 Sep 2008 16:45:10 +0200 Subject: [MIPS] au1000: Make sure GPIO value is zero or one David Brownell wrote: > The problem is that "value" is zero-or-nonzero. > This code wrongly assumes it's zero-or-one. > Possible fix: "((!!value) << gpio)". Signed-off-by: Bruno Randolf Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c index 1f058434b72..e660ddd611c 100644 --- a/arch/mips/au1000/common/gpio.c +++ b/arch/mips/au1000/common/gpio.c @@ -48,7 +48,7 @@ static void au1xxx_gpio2_write(unsigned gpio, int value) { gpio -= AU1XXX_GPIO_BASE; - gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio); + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); } static int au1xxx_gpio2_direction_input(unsigned gpio) @@ -62,7 +62,7 @@ static int au1xxx_gpio2_direction_output(unsigned gpio, int value) { gpio -= AU1XXX_GPIO_BASE; gpio2->dir |= 0x01 << gpio; - gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio); + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); return 0; } -- cgit v1.2.3 From f4d15f1c877644a604f8c8c3d094c13f9f8bdcf2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 27 Sep 2008 15:05:06 +0100 Subject: [MIPS] IP27: Switch to dynamic interrupt routing avoding panic on error. pcibios_map_irq is no way of returning an error but on IP27 an interrupt is possibly not routable when running out of resources. So do the interrupt routing at pcibios_enable_device time. Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ip27.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index bd78368c82b..f97ab146101 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -142,26 +142,48 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) * on any one of the hubs connected to its xbow. */ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return 0; +} + +/* Most MIPS systems have straight-forward swizzling needs. */ +static inline u8 bridge_swizzle(u8 pin, u8 slot) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev) +{ + while (dev->bus->parent) { + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } + + return dev; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - int irq = bc->pci_int[slot]; + struct pci_dev *rdev = bridge_root_dev(dev); + int slot = PCI_SLOT(rdev->devfn); + int irq; + irq = bc->pci_int[slot]; if (irq == -1) { - irq = bc->pci_int[slot] = request_bridge_irq(bc); + irq = request_bridge_irq(bc); if (irq < 0) - panic("Can't allocate interrupt for PCI device %s\n", - pci_name(dev)); + return irq; + + bc->pci_int[slot] = irq; } irq_to_bridge[irq] = bc; irq_to_slot[irq] = slot; - return irq; -} + dev->irq = irq; -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ return 0; } -- cgit v1.2.3 From 2dc42b47a7886bdc87514990c68ecdf8de61e653 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 27 Sep 2008 16:06:16 +0200 Subject: [MIPS] BCM47xx: Fix build error due to missing PCI functions This patch defines pcibios_map_irq() and pcibios_plat_dev_init() for the BCM47xx platform. It fixes the regression introduced by commit aab547ce0d1493d400b6468c521a0137cd8c1edf. Signed-off-by: Aurelien Jarno Signed-off-by: Ralf Baechle --- arch/mips/pci/Makefile | 1 + arch/mips/pci/pci-bcm47xx.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 arch/mips/pci/pci-bcm47xx.c diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 15e01aec37f..c8c32f417b6 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SOC_TX3927) += ops-tx3927.o obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o obj-$(CONFIG_PCI_TX4927) += ops-tx4927.o +obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o # # These are still pretty much in the old state, watch, go blind. diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c new file mode 100644 index 00000000000..bea9b6cdfdb --- /dev/null +++ b/arch/mips/pci/pci-bcm47xx.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Aurelien Jarno + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return 0; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + int res; + u8 slot, pin; + + res = ssb_pcibios_plat_dev_init(dev); + if (res < 0) { + printk(KERN_ALERT "PCI: Failed to init device %s\n", + pci_name(dev)); + return res; + } + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + slot = PCI_SLOT(dev->devfn); + res = ssb_pcibios_map_irq(dev, slot, pin); + + /* IRQ-0 and IRQ-1 are software interrupts. */ + if (res < 2) { + printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n", + pci_name(dev)); + return res; + } + + dev->irq = res; + return 0; +} + -- cgit v1.2.3 From ac82da3381fc663dbda31612a0bff60bc41676a3 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 26 Sep 2008 22:27:11 +0200 Subject: [SSB] Initialise dma_mask for SSB_BUSTYPE_SSB devices For SSB_BUSTYPE_SSB type devices, we need to initialize dma_mask using coherent_dma_mask so that calls to dma_set_mask() succeed. It fixes the regression on the b44 driver introduced by commit f225763a7d6c92c4932dbd528437997078496fcc Signed-off-by: Aurelien Jarno Signed-off-by: Ralf Baechle --- drivers/ssb/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 87ab2443e66..0ffabf5c0b6 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -471,6 +471,7 @@ static int ssb_devices_register(struct ssb_bus *bus) #endif break; case SSB_BUSTYPE_SSB: + dev->dma_mask = &dev->coherent_dma_mask; break; } -- cgit v1.2.3 From 3d977760b9478538821a75dd5eb74d0f2a2b01e3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 27 Sep 2008 19:32:16 +0200 Subject: Swarm: Fix crash due to missing initialization If things are just right this will result in the hws[0]->parent being passed to ide_host_add() being non-zero and an ooops a little later. Signed-off-by: Ralf Baechle Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/mips/swarm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index badf79fc9e3..39c9ee99585 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -107,6 +107,7 @@ static int __devinit swarm_ide_probe(struct device *dev) base = ioremap(offset, size); + memset(&hw, 0, sizeof(hw)); for (i = 0; i <= 7; i++) hw.io_ports_array[i] = (unsigned long)(base + ((0x1f0 + i) << 5)); -- cgit v1.2.3 From 801bd32e205ca6ef78dcaf80121f1eccb89b8c1e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 27 Sep 2008 19:32:17 +0200 Subject: ide-tape: fix vendor strings Remove superfluous two bytes from each string buffer and add proper length format specifiers. Signed-off-by: Borislav Petkov Tested-by: Mark de Wever Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-tape.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 1bce84b5663..3833189144e 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2338,7 +2338,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; struct ide_atapi_pc pc; - char fw_rev[6], vendor_id[10], product_id[18]; + char fw_rev[4], vendor_id[8], product_id[16]; idetape_create_inquiry_cmd(&pc); if (idetape_queue_pc_tail(drive, &pc)) { @@ -2350,11 +2350,11 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) memcpy(product_id, &pc.buf[16], 16); memcpy(fw_rev, &pc.buf[32], 4); - ide_fixstring(vendor_id, 10, 0); - ide_fixstring(product_id, 18, 0); - ide_fixstring(fw_rev, 6, 0); + ide_fixstring(vendor_id, 8, 0); + ide_fixstring(product_id, 16, 0); + ide_fixstring(fw_rev, 4, 0); - printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", + printk(KERN_INFO "ide-tape: %s <-> %s: %.8s %.16s rev %.4s\n", drive->name, tape->name, vendor_id, product_id, fw_rev); } -- cgit v1.2.3 From 278ecfb8f4100c0edc2bc77695b591ea16388829 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 27 Sep 2008 19:32:17 +0200 Subject: ide: note that IDE generic may prevent other drivers from attaching Enabling IDE generic may prevent ATA controllers located on legacy ports from being attached to more proper driver or can prevent other controllers which share the IRQ from working. Note it in the help message. Signed-off-by: Tejun Heo Cc: xerces8 Cc: Jeff Garzik Cc: stein@hermes.si [bart: s/will grab/may grab/ since Borislav has fixed PCI-case for .28] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index fc735ab08ff..8e93a797c93 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -292,6 +292,20 @@ config IDE_GENERIC tristate "generic/default IDE chipset support" depends on ALPHA || X86 || IA64 || M32R || MIPS help + This is the generic IDE driver. This driver attaches to the + fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and + so on). Please note that if this driver is built into the + kernel or loaded before other ATA (IDE or libata) drivers + and the controller is located at legacy ports, this driver + may grab those ports and thus can prevent the controller + specific driver from attaching. + + Also, currently, IDE generic doesn't allow IRQ sharing + meaning that the IRQs it grabs won't be available to other + controllers sharing those IRQs which usually makes drivers + for those controllers fail. Generally, it's not a good idea + to load IDE generic driver on modern systems. + If unsure, say N. config BLK_DEV_PLATFORM -- cgit v1.2.3 From d0eb40628e29c2bb3b5f8242b1d2f50b1a88d9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 27 Sep 2008 19:32:17 +0200 Subject: cdrom: update ioctl documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct copy-paste problem: CDROMCLOSETRAY is about closing the tray, not opening it. Signed-off-by: Márton Németh Signed-off-by: Andrew Morton Cc: Jens Axboe Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ioctl/cdrom.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/ioctl/cdrom.txt b/Documentation/ioctl/cdrom.txt index 62d4af44ec4..59df81c8da2 100644 --- a/Documentation/ioctl/cdrom.txt +++ b/Documentation/ioctl/cdrom.txt @@ -271,14 +271,14 @@ CDROMCLOSETRAY pendant of CDROMEJECT usage: - ioctl(fd, CDROMEJECT, 0); + ioctl(fd, CDROMCLOSETRAY, 0); inputs: none outputs: none error returns: - ENOSYS cd drive not capable of ejecting + ENOSYS cd drive not capable of closing the tray EBUSY other processes are accessing drive, or door is locked notes: -- cgit v1.2.3 From c9eeb248f3b44939532a9716bc06413383aa5d63 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 24 Sep 2008 12:00:22 +0300 Subject: [SCSI] qlogicpti: fix sg list traversal error in continuation entries The current sg list traversal logic for the continuation entries doesn't advance the list pointer once all seven slots are used, so the next continuation entry (if there is one) wrongly begins again at the start of the sg list. Fix by advancing the sg pointer after the for_each_sg(). Reported-by: Meelis Roos Cc: David Miller Signed-off-by: James Bottomley --- drivers/scsi/qlogicpti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 4a1cf6377f6..90535089672 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -914,6 +914,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, ds[i].d_count = sg_dma_len(s); } sg_count -= n; + sg = s; } } else { cmd->dataseg[0].d_base = 0; -- cgit v1.2.3 From 4c1eb90a0908c0c60db2169dce08fb672e7582f1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 28 Sep 2008 07:39:01 +0900 Subject: sata_nv: reinstate nv_hardreset() for non generic controllers Commit 2fd673ecf0378ddeeeb87b3605e50212e0c0ddc6 which tried to remove hardreset for generic accidentally removed it for all flavors as all others were inheriting from nv_generic_ops. This patch reinstates nv_hardreset() and puts it into nv_common_ops which all flavors inherit from. nv_generic_ops now inherits from nv_common_ops and overrides .hardreset to ATA_OP_NULL. While at it, explain why nv_hardreset and ATA_OP_NULL override are necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 1e1f3f3757a..14601dc05e4 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -309,6 +309,8 @@ static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); +static int nv_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -403,28 +405,45 @@ static struct scsi_host_template nv_swncq_sht = { .slave_configure = nv_swncq_slave_config, }; -static struct ata_port_operations nv_generic_ops = { +/* OSDL bz3352 reports that some nv controllers can't determine device + * signature reliably and nv_hardreset is implemented to work around + * the problem. This was reported on nf3 and it's unclear whether any + * other controllers are affected. However, the workaround has been + * applied to all variants and there isn't much to gain by trying to + * find out exactly which ones are affected at this point especially + * because NV has moved over to ahci for newer controllers. + */ +static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = ATA_OP_NULL, + .hardreset = nv_hardreset, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; +/* OSDL bz11195 reports that link doesn't come online after hardreset + * on generic nv's and there have been several other similar reports + * on linux-ide. Disable hardreset for generic nv's. + */ +static struct ata_port_operations nv_generic_ops = { + .inherits = &nv_common_ops, + .hardreset = ATA_OP_NULL, +}; + static struct ata_port_operations nv_nf2_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, }; static struct ata_port_operations nv_ck804_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, .host_stop = nv_ck804_host_stop, }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -448,7 +467,7 @@ static struct ata_port_operations nv_adma_ops = { }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_generic_ops, + .inherits = &nv_common_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1586,6 +1605,21 @@ static void nv_mcp55_thaw(struct ata_port *ap) ata_sff_thaw(ap); } +static int nv_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + int rc; + + /* SATA hardreset fails to retrieve proper device signature on + * some controllers. Request follow up SRST. For more info, + * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 + */ + rc = sata_sff_hardreset(link, class, deadline); + if (rc) + return rc; + return -EAGAIN; +} + static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; -- cgit v1.2.3 From 7e6cfb54b1ff4b64d74aa8cd191204c9598c073d Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 29 Sep 2008 09:38:55 +0200 Subject: scsi: fix fall out of sg-chaining patch in qlogicpti Boaz writes: "I've reviewed all patches since Matthew's, and I find one small problem. In the load_cmd() there is a compound loop where the first 4 sg's are set then the rest are set into a memory structure in group of 7 sg's. Well the second 7-group and on is a bug because sg pointer does not advance. This is a fall out from Jens's patch." The reporter, Meelis Roos , verified that this patch does indeed fix his problem with qlogicpti. Signed-off-by: Jens Axboe --- drivers/scsi/qlogicpti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 4a1cf6377f6..90535089672 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -914,6 +914,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, ds[i].d_count = sg_dma_len(s); } sg_count -= n; + sg = s; } } else { cmd->dataseg[0].d_base = 0; -- cgit v1.2.3 From ec2cd95f340fb07b905839ee219b3846ecf58396 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 29 Jul 2008 16:35:52 -0500 Subject: ALSA: make the CS4270 driver a new-style I2C driver Update the CS4270 ALSA device driver to use the new-style I2C interface. Starting with the 2.6.27 PowerPC kernel, I2C devices that have entries in the device trees can no longer be probed by old-style I2C drivers. The device tree for Freescale MPC8610 HPCD has included an entry for the CS4270 since 2.6.25, but that entry was previously ignored by the PowerPC I2C subsystem. Since that's no longer the case, the best solution is to update the CS4270 driver to a new-style interface, rather than try to revert the behavior of new PowerPC I2C subsystem. Signed-off-by: Timur Tabi Signed-off-by: Takashi Iwai --- sound/soc/codecs/cs4270.c | 71 ++++++++++------------------------------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 9deb8c74fdf..82d94f00aa4 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -490,34 +490,7 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) #endif -static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind); - -/* - * Notify the driver that a new I2C bus has been found. - * - * This function is called for each I2C bus in the system. The function - * then asks the I2C subsystem to probe that bus at the addresses on which - * our device (the CS4270) could exist. If a device is found at one of - * those addresses, then our probe function (cs4270_i2c_probe) is called. - */ -static int cs4270_i2c_attach(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, cs4270_i2c_probe); -} - -static int cs4270_i2c_detach(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - - i2c_detach_client(client); - codec->control_data = NULL; - - kfree(codec->reg_cache); - codec->reg_cache = NULL; - - kfree(client); - return 0; -} +static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *); /* A list of non-DAPM controls that the CS4270 supports */ static const struct snd_kcontrol_new cs4270_snd_controls[] = { @@ -525,14 +498,19 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) }; +static const struct i2c_device_id cs4270_id[] = { + {"cs4270", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs4270_id); + static struct i2c_driver cs4270_i2c_driver = { .driver = { .name = "CS4270 I2C", .owner = THIS_MODULE, }, - .id = I2C_DRIVERID_CS4270, - .attach_adapter = cs4270_i2c_attach, - .detach_client = cs4270_i2c_detach, + .id_table = cs4270_id, + .probe = cs4270_i2c_probe, }; /* @@ -561,11 +539,11 @@ static struct snd_soc_device *cs4270_socdev; * Note: snd_soc_new_pcms() must be called before this function can be called, * because of snd_ctl_add(). */ -static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) +static int cs4270_i2c_probe(struct i2c_client *i2c_client, + const struct i2c_device_id *id) { struct snd_soc_device *socdev = cs4270_socdev; struct snd_soc_codec *codec = socdev->codec; - struct i2c_client *i2c_client = NULL; int i; int ret = 0; @@ -578,12 +556,6 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) /* Note: codec_dai->codec is NULL here */ - i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!i2c_client) { - printk(KERN_ERR "cs4270: could not allocate I2C client\n"); - return -ENOMEM; - } - codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); if (!codec->reg_cache) { printk(KERN_ERR "cs4270: could not allocate register cache\n"); @@ -591,13 +563,6 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) goto error; } - i2c_set_clientdata(i2c_client, codec); - strcpy(i2c_client->name, "CS4270"); - - i2c_client->driver = &cs4270_i2c_driver; - i2c_client->adapter = adapter; - i2c_client->addr = addr; - /* Verify that we have a CS4270 */ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); @@ -612,18 +577,10 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) goto error; } - printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr); + printk(KERN_INFO "cs4270: found device at I2C address %X\n", + i2c_client->addr); printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); - /* Tell the I2C layer a new client has arrived */ - - ret = i2c_attach_client(i2c_client); - if (ret) { - printk(KERN_ERR "cs4270: could not attach codec, " - "I2C address %x, error code %i\n", addr, ret); - goto error; - } - codec->control_data = i2c_client; codec->read = cs4270_read_reg_cache; codec->write = cs4270_i2c_write; @@ -648,6 +605,8 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) goto error; } + i2c_set_clientdata(i2c_client, codec); + return 0; error: -- cgit v1.2.3 From 9778e9a0eafe796c2affcd1fa1fa8a3765e026e6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 27 Sep 2008 20:30:52 +0200 Subject: ALSA: ASoC: Fix another cs4270 error path Conversion to new-style i2c driver missed the error path of the probe function. Fix it. Signed-off-by: Jean Delvare Cc: Timur Tabi Signed-off-by: Takashi Iwai --- sound/soc/codecs/cs4270.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 82d94f00aa4..d68650de39b 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -610,17 +610,12 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, return 0; error: - if (codec->control_data) { - i2c_detach_client(i2c_client); - codec->control_data = NULL; - } + codec->control_data = NULL; kfree(codec->reg_cache); codec->reg_cache = NULL; codec->reg_cache_size = 0; - kfree(i2c_client); - return ret; } -- cgit v1.2.3 From d0185c0882d76b8126d4a099c7ac82b3b216d103 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 Sep 2008 07:42:57 -0700 Subject: Fix NULL pointer dereference in proc_sys_compare The VFS interface for the 'd_compare()' is a bit special (read: 'odd'), because it really just essentially replaces a memcmp(). The filesystem is supposed to just compare the two names with whatever case-independent or other function. And when I say 'is supposed to', I obviously mean that 'procfs does odd things, and actually looks at the dentry that we don't even pass down, rather than just the name'. Which results in problems, because we actually call d_compare before we have even verified that the dentry is still hashed at all. And that causes a problm since the inode that procfs looks at may have been free'd and the d_inode pointer is NULL. procfs just assumes that all dentries are positive, since procfs itself never generates a negative one. But memory pressure will still result in the dentry getting torn down, and as it is removed by RCU, it still remains visible on some lists - and to d_compare. If the filesystem just did a name comparison, we wouldn't care. And we could just fix procfs to know about negative dentries too. But rather than have the low-level filesystems know about internal VFS details, just move the check for a unhashed dentry up a bit, so that we will only call d_compare on dentries that are still active. The actual oops this caused didn't look like a NULL pointer dereference because procfs did a 'container_of(inode, struct proc_inode, vfs_inode)' to get at its internal proc_inode information from the inode pointer, and accessed a field below the inode. So the oops would look something like BUG: unable to handle kernel paging request at fffffffffffffff0 IP: [] proc_sys_compare+0x36/0x50 and was seen on both x86-64 (Alexey Dobriyan and Hugh Dickins) and ppc64 (Hugh Dickins). Reported-by: Alexey Dobriyan Acked-by: Hugh Dickins Cc: Al Viro Reviewed-by: "Eric W. Biederman" Signed-of-by: Linus Torvalds --- fs/dcache.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 80e93956ace..e7a1a99b746 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1395,6 +1395,10 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) if (dentry->d_parent != parent) goto next; + /* non-existing due to RCU? */ + if (d_unhashed(dentry)) + goto next; + /* * It is safe to compare names since d_move() cannot * change the qstr (protected by d_lock). @@ -1410,10 +1414,8 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) goto next; } - if (!d_unhashed(dentry)) { - atomic_inc(&dentry->d_count); - found = dentry; - } + atomic_inc(&dentry->d_count); + found = dentry; spin_unlock(&dentry->d_lock); break; next: -- cgit v1.2.3 From 204c96f609045a8ce84d1dca3e758ee9b0b2a95c Mon Sep 17 00:00:00 2001 From: "zippel@linux-m68k.org" Date: Mon, 29 Sep 2008 05:27:10 +0200 Subject: kconfig: fix silentoldconfig Recent changes to oldconfig have mixed up the silentoldconfig handling, so this fixes that by clearly separating that special mode, e.g. KCONFIG_NOSILENTUPDATE is only relevant here, the .config is written as needed. This will also properly close Bug 11230. Signed-off-by: Roman Zippel Signed-off-by: Linus Torvalds --- scripts/kconfig/conf.c | 123 +++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 66 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 36b5eedcdc7..3e1057f885c 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -32,6 +32,7 @@ char *defconfig_file; static int indent = 1; static int valid_stdin = 1; +static int sync_kconfig; static int conf_cnt; static char line[128]; static struct menu *rootEntry; @@ -65,7 +66,7 @@ static void strip(char *str) static void check_stdin(void) { - if (!valid_stdin && input_mode == ask_silent) { + if (!valid_stdin) { printf(_("aborted!\n\n")); printf(_("Console input/output is redirected. ")); printf(_("Run 'make oldconfig' to update configuration.\n\n")); @@ -427,43 +428,6 @@ static void check_conf(struct menu *menu) check_conf(child); } -static void conf_do_update(void) -{ - /* Update until a loop caused no more changes */ - do { - conf_cnt = 0; - check_conf(&rootmenu); - } while (conf_cnt); -} - -static int conf_silent_update(void) -{ - const char *name; - - if (conf_get_changed()) { - name = getenv("KCONFIG_NOSILENTUPDATE"); - if (name && *name) { - fprintf(stderr, - _("\n*** Kernel configuration requires explicit update.\n\n")); - return 1; - } - conf_do_update(); - } - return 0; -} - -static int conf_update(void) -{ - rootEntry = &rootmenu; - conf(&rootmenu); - if (input_mode == ask_all) { - input_mode = ask_silent; - valid_stdin = 1; - } - conf_do_update(); - return 0; -} - int main(int ac, char **av) { int opt; @@ -477,11 +441,11 @@ int main(int ac, char **av) while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { switch (opt) { case 'o': - input_mode = ask_new; + input_mode = ask_silent; break; case 's': input_mode = ask_silent; - valid_stdin = isatty(0) && isatty(1) && isatty(2); + sync_kconfig = 1; break; case 'd': input_mode = set_default; @@ -519,6 +483,19 @@ int main(int ac, char **av) name = av[optind]; conf_parse(name); //zconfdump(stdout); + if (sync_kconfig) { + if (stat(".config", &tmpstat)) { + fprintf(stderr, _("***\n" + "*** You have not yet configured your kernel!\n" + "*** (missing kernel .config file)\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n")); + exit(1); + } + } + switch (input_mode) { case set_default: if (!defconfig_file) @@ -531,16 +508,6 @@ int main(int ac, char **av) } break; case ask_silent: - if (stat(".config", &tmpstat)) { - printf(_("***\n" - "*** You have not yet configured your kernel!\n" - "*** (missing kernel .config file)\n" - "***\n" - "*** Please run some configurator (e.g. \"make oldconfig\" or\n" - "*** \"make menuconfig\" or \"make xconfig\").\n" - "***\n")); - exit(1); - } case ask_all: case ask_new: conf_read(NULL); @@ -569,6 +536,19 @@ int main(int ac, char **av) default: break; } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** Kernel configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = isatty(0) && isatty(1) && isatty(2); + } + switch (input_mode) { case set_no: conf_set_all_new_symbols(def_no); @@ -585,27 +565,38 @@ int main(int ac, char **av) case set_default: conf_set_all_new_symbols(def_default); break; - case ask_silent: case ask_new: - if (conf_silent_update()) - exit(1); - break; case ask_all: - if (conf_update()) - exit(1); + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = ask_silent; + /* fall through */ + case ask_silent: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt); break; } - if (conf_write(NULL)) { - fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); - exit(1); - } - /* ask_silent is used during the build so we shall update autoconf. - * All other commands are only used to generate a config. - */ - if (input_mode == ask_silent && conf_write_autoconf()) { - fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); - return 1; + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n")); + return 1; + } + } else { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); + exit(1); + } } return 0; } -- cgit v1.2.3 From 661b0680f736e628a6da1cc030c201646587d658 Mon Sep 17 00:00:00 2001 From: "zippel@linux-m68k.org" Date: Mon, 29 Sep 2008 05:27:11 +0200 Subject: kconfig: readd lost change count Commit f072181e6403b0fe2e2aa800a005497b748fd284 ("kconfig: drop the ""trying to assign nonexistent symbol" warning") simply dropped the warnings, but it does a little more than that, it also marks the current .config as needed saving, so add this back. Signed-off-by: Roman Zippel Signed-off-by: Linus Torvalds --- scripts/kconfig/confdata.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index df6a188b993..b91cf241a53 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -222,8 +222,10 @@ load: continue; if (def == S_DEF_USER) { sym = sym_find(line + 9); - if (!sym) + if (!sym) { + sym_add_change_count(1); break; + } } else { sym = sym_lookup(line + 9, 0); if (sym->type == S_UNKNOWN) @@ -259,8 +261,10 @@ load: } if (def == S_DEF_USER) { sym = sym_find(line + 7); - if (!sym) + if (!sym) { + sym_add_change_count(1); break; + } } else { sym = sym_lookup(line + 7, 0); if (sym->type == S_UNKNOWN) -- cgit v1.2.3 From 31a78f23bac0069004e69f98808b6988baccb6b6 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Sun, 28 Sep 2008 23:09:31 +0100 Subject: mm owner: fix race between swapoff and exit There's a race between mm->owner assignment and swapoff, more easily seen when task slab poisoning is turned on. The condition occurs when try_to_unuse() runs in parallel with an exiting task. A similar race can occur with callers of get_task_mm(), such as /proc// or ptrace or page migration. CPU0 CPU1 try_to_unuse looks at mm = task0->mm increments mm->mm_users task 0 exits mm->owner needs to be updated, but no new owner is found (mm_users > 1, but no other task has task->mm = task0->mm) mm_update_next_owner() leaves mmput(mm) decrements mm->mm_users task0 freed dereferencing mm->owner fails The fix is to notify the subsystem via mm_owner_changed callback(), if no new owner is found, by specifying the new task as NULL. Jiri Slaby: mm->owner was set to NULL prior to calling cgroup_mm_owner_callbacks(), but must be set after that, so as not to pass NULL as old owner causing oops. Daisuke Nishimura: mm_update_next_owner() may set mm->owner to NULL, but mem_cgroup_from_task() and its callers need to take account of this situation to avoid oops. Hugh Dickins: Lockdep warning and hang below exec_mmap() when testing these patches. exit_mm() up_reads mmap_sem before calling mm_update_next_owner(), so exec_mmap() now needs to do the same. And with that repositioning, there's now no point in mm_need_new_owner() allowing for NULL mm. Reported-by: Hugh Dickins Signed-off-by: Balbir Singh Signed-off-by: Jiri Slaby Signed-off-by: Daisuke Nishimura Signed-off-by: Hugh Dickins Cc: KAMEZAWA Hiroyuki Cc: Paul Menage Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- kernel/cgroup.c | 5 +++-- kernel/exit.c | 12 ++++++++++-- mm/memcontrol.c | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 32993beecbe..cecee501ce7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -752,11 +752,11 @@ static int exec_mmap(struct mm_struct *mm) tsk->active_mm = mm; activate_mm(active_mm, mm); task_unlock(tsk); - mm_update_next_owner(old_mm); arch_pick_mmap_layout(mm); if (old_mm) { up_read(&old_mm->mmap_sem); BUG_ON(active_mm != old_mm); + mm_update_next_owner(old_mm); mmput(old_mm); return 0; } diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 13932abde15..a0123d75ec9 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2738,14 +2738,15 @@ void cgroup_fork_callbacks(struct task_struct *child) */ void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new) { - struct cgroup *oldcgrp, *newcgrp; + struct cgroup *oldcgrp, *newcgrp = NULL; if (need_mm_owner_callback) { int i; for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { struct cgroup_subsys *ss = subsys[i]; oldcgrp = task_cgroup(old, ss->subsys_id); - newcgrp = task_cgroup(new, ss->subsys_id); + if (new) + newcgrp = task_cgroup(new, ss->subsys_id); if (oldcgrp == newcgrp) continue; if (ss->mm_owner_changed) diff --git a/kernel/exit.c b/kernel/exit.c index 16395644a98..85a83c83185 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -583,8 +583,6 @@ mm_need_new_owner(struct mm_struct *mm, struct task_struct *p) * If there are other users of the mm and the owner (us) is exiting * we need to find a new owner to take on the responsibility. */ - if (!mm) - return 0; if (atomic_read(&mm->mm_users) <= 1) return 0; if (mm->owner != p) @@ -627,6 +625,16 @@ retry: } while_each_thread(g, c); read_unlock(&tasklist_lock); + /* + * We found no owner yet mm_users > 1: this implies that we are + * most likely racing with swapoff (try_to_unuse()) or /proc or + * ptrace or page migration (get_task_mm()). Mark owner as NULL, + * so that subsystems can understand the callback and take action. + */ + down_write(&mm->mmap_sem); + cgroup_mm_owner_callbacks(mm->owner, NULL); + mm->owner = NULL; + up_write(&mm->mmap_sem); return; assign_new_owner: diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c0500e4d3a2..36896f3eb7f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -250,6 +250,14 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) { + /* + * mm_update_next_owner() may clear mm->owner to NULL + * if it races with swapoff, page migration, etc. + * So this can be called with p == NULL. + */ + if (unlikely(!p)) + return NULL; + return container_of(task_subsys_state(p, mem_cgroup_subsys_id), struct mem_cgroup, css); } @@ -549,6 +557,11 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, if (likely(!memcg)) { rcu_read_lock(); mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); + if (unlikely(!mem)) { + rcu_read_unlock(); + kmem_cache_free(page_cgroup_cache, pc); + return 0; + } /* * For every charge from the cgroup, increment reference count */ @@ -801,6 +814,10 @@ int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask) rcu_read_lock(); mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); + if (unlikely(!mem)) { + rcu_read_unlock(); + return 0; + } css_get(&mem->css); rcu_read_unlock(); -- cgit v1.2.3 From 94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 Sep 2008 15:24:02 -0700 Subject: Linux 2.6.27-rc8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cab896a9729..1d03c1644dd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc8 NAME = Rotary Wombat # *DOCUMENTATION* -- cgit v1.2.3 From d01dbeb6af7a0848063033f73c3d146fec7451f3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 30 Sep 2008 02:03:19 -0700 Subject: ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space We're never supposed to shrink the headroom or tailroom. In fact, shrinking the headroom is a fatal action. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/xfrm/xfrm_output.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e98..dc50f1e71f7 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) - skb_headroom(skb); int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); - if (nhead > 0 || ntail > 0) - return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); - - return 0; + if (nhead <= 0) { + if (ntail <= 0) + return 0; + nhead = 0; + } else if (ntail < 0) + ntail = 0; + + return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); } static int xfrm_output_one(struct sk_buff *skb, int err) -- cgit v1.2.3 From cf04a4c764cd3e651a64b3e667bb6a673ead99e1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 30 Sep 2008 02:22:14 -0700 Subject: netdev: use const for some name functions dev_change_name and netdev_drivername should use const char on parameters that are read-only input values. The strcpy to newname is not needed since newname is not used later in function. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++-- net/core/dev.c | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d675df08b94..9cfd20be8b7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1225,7 +1225,7 @@ extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); extern int dev_ethtool(struct net *net, struct ifreq *); extern unsigned dev_get_flags(const struct net_device *); extern int dev_change_flags(struct net_device *, unsigned); -extern int dev_change_name(struct net_device *, char *); +extern int dev_change_name(struct net_device *, const char *); extern int dev_set_alias(struct net_device *, const char *, size_t); extern int dev_change_net_namespace(struct net_device *, struct net *, const char *); @@ -1670,7 +1670,7 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern int netdev_class_create_file(struct class_attribute *class_attr); extern void netdev_class_remove_file(struct class_attribute *class_attr); -extern char *netdev_drivername(struct net_device *dev, char *buffer, int len); +extern char *netdev_drivername(const struct net_device *dev, char *buffer, int len); extern void linkwatch_run_queue(void); diff --git a/net/core/dev.c b/net/core/dev.c index a90737fe247..64f0d5b7cdf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -890,7 +890,7 @@ int dev_alloc_name(struct net_device *dev, const char *name) * Change name of a device, can pass format strings "eth%d". * for wildcarding. */ -int dev_change_name(struct net_device *dev, char *newname) +int dev_change_name(struct net_device *dev, const char *newname) { char oldname[IFNAMSIZ]; int err = 0; @@ -916,7 +916,6 @@ int dev_change_name(struct net_device *dev, char *newname) err = dev_alloc_name(dev, newname); if (err < 0) return err; - strcpy(newname, dev->name); } else if (__dev_get_by_name(net, newname)) return -EEXIST; @@ -4754,10 +4753,10 @@ err_name: return -ENOMEM; } -char *netdev_drivername(struct net_device *dev, char *buffer, int len) +char *netdev_drivername(const struct net_device *dev, char *buffer, int len) { - struct device_driver *driver; - struct device *parent; + const struct device_driver *driver; + const struct device *parent; if (len <= 0 || !buffer) return buffer; -- cgit v1.2.3 From f0db275a81ef184293ca7ef3646fe065b336efb7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 30 Sep 2008 02:23:58 -0700 Subject: netdev: docbook comment update (revised) Add more docbook comments to network device functions and cleanup the comments. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/dev.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 64f0d5b7cdf..2cc258b7acc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -956,6 +956,7 @@ rollback: * dev_set_alias - change ifalias of a device * @dev: device * @alias: name up to IFALIASZ + * @len: limit of bytes to copy from info * * Set ifalias for a device, */ @@ -3330,6 +3331,12 @@ static void dev_addr_discard(struct net_device *dev) netif_addr_unlock_bh(dev); } +/** + * dev_get_flags - get flags reported to userspace + * @dev: device + * + * Get the combination of flag bits exported through APIs to userspace. + */ unsigned dev_get_flags(const struct net_device *dev) { unsigned flags; @@ -3354,6 +3361,14 @@ unsigned dev_get_flags(const struct net_device *dev) return flags; } +/** + * dev_change_flags - change device settings + * @dev: device + * @flags: device state flags + * + * Change settings on device based state flags. The flags are + * in the userspace exported format. + */ int dev_change_flags(struct net_device *dev, unsigned flags) { int ret, changes; @@ -3423,6 +3438,13 @@ int dev_change_flags(struct net_device *dev, unsigned flags) return ret; } +/** + * dev_set_mtu - Change maximum transfer unit + * @dev: device + * @new_mtu: new transfer unit + * + * Change the maximum transfer size of the network device. + */ int dev_set_mtu(struct net_device *dev, int new_mtu) { int err; @@ -3447,6 +3469,13 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) return err; } +/** + * dev_set_mac_address - Change Media Access Control Address + * @dev: device + * @sa: new address + * + * Change the hardware (MAC) address of the device + */ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) { int err; @@ -4350,7 +4379,12 @@ void free_netdev(struct net_device *dev) put_device(&dev->dev); } -/* Synchronize with packet receive processing. */ +/** + * synchronize_net - Synchronize with packet receive processing + * + * Wait for packets currently being received to be done. + * Does not block later packets from starting. + */ void synchronize_net(void) { might_sleep(); @@ -4652,7 +4686,7 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan, } /** - * netdev_dma_regiser - register the networking subsystem as a DMA client + * netdev_dma_register - register the networking subsystem as a DMA client */ static int __init netdev_dma_register(void) { @@ -4753,6 +4787,14 @@ err_name: return -ENOMEM; } +/** + * netdev_drivername - network driver for the device + * @dev: network device + * @buffer: buffer for resulting name + * @len: size of buffer + * + * Determine network driver for device. + */ char *netdev_drivername(const struct net_device *dev, char *buffer, int len) { const struct device_driver *driver; -- cgit v1.2.3 From 8980713b97393b21a50d11408a22d2caa87d016a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 30 Sep 2008 02:51:18 -0700 Subject: Phonet: Netlink factorization and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pn_netlink.c | 91 +++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index b1ea19a230d..b1770d66bc8 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -54,11 +54,16 @@ errout: rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); } -static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) +static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = { + [IFA_LOCAL] = { .type = NLA_U8 }, +}; + +static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr) { - struct rtattr **rta = attr; - struct ifaddrmsg *ifm = NLMSG_DATA(nlm); + struct net *net = sock_net(skb->sk); + struct nlattr *tb[IFA_MAX+1]; struct net_device *dev; + struct ifaddrmsg *ifm; int err; u8 pnaddr; @@ -67,52 +72,28 @@ static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) ASSERT_RTNL(); - if (rta[IFA_LOCAL - 1] == NULL) - return -EINVAL; - - dev = __dev_get_by_index(&init_net, ifm->ifa_index); - if (dev == NULL) - return -ENODEV; + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_phonet_policy); + if (err < 0) + return err; - if (ifm->ifa_prefixlen > 0) + ifm = nlmsg_data(nlh); + if (tb[IFA_LOCAL] == NULL) return -EINVAL; - - memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); - - err = phonet_address_add(dev, pnaddr); - if (!err) - rtmsg_notify(RTM_NEWADDR, dev, pnaddr); - return err; -} - -static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) -{ - struct rtattr **rta = attr; - struct ifaddrmsg *ifm = NLMSG_DATA(nlm); - struct net_device *dev; - int err; - u8 pnaddr; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - ASSERT_RTNL(); - - if (rta[IFA_LOCAL - 1] == NULL) + pnaddr = nla_get_u8(tb[IFA_LOCAL]); + if (pnaddr & 3) + /* Phonet addresses only have 6 high-order bits */ return -EINVAL; - dev = __dev_get_by_index(&init_net, ifm->ifa_index); + dev = __dev_get_by_index(net, ifm->ifa_index); if (dev == NULL) return -ENODEV; - if (ifm->ifa_prefixlen > 0) - return -EADDRNOTAVAIL; - - memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); - - err = phonet_address_del(dev, pnaddr); + if (nlh->nlmsg_type == RTM_NEWADDR) + err = phonet_address_add(dev, pnaddr); + else + err = phonet_address_del(dev, pnaddr); if (!err) - rtmsg_notify(RTM_DELADDR, dev, pnaddr); + rtmsg_notify(nlh->nlmsg_type, dev, pnaddr); return err; } @@ -121,25 +102,23 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, { struct ifaddrmsg *ifm; struct nlmsghdr *nlh; - unsigned int orig_len = skb->len; - nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg)); - ifm = NLMSG_DATA(nlh); + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), 0); + if (nlh == NULL) + return -EMSGSIZE; + + ifm = nlmsg_data(nlh); ifm->ifa_family = AF_PHONET; ifm->ifa_prefixlen = 0; ifm->ifa_flags = IFA_F_PERMANENT; - ifm->ifa_scope = RT_SCOPE_HOST; + ifm->ifa_scope = RT_SCOPE_LINK; ifm->ifa_index = dev->ifindex; - RTA_PUT(skb, IFA_LOCAL, 1, &addr); - nlh->nlmsg_len = skb->len - orig_len; - - return 0; - -nlmsg_failure: -rtattr_failure: - skb_trim(skb, orig_len); + NLA_PUT_U8(skb, IFA_LOCAL, addr); + return nlmsg_end(skb, nlh); - return -1; +nla_put_failure: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; } static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) @@ -180,7 +159,7 @@ out: void __init phonet_netlink_register(void) { - rtnl_register(PF_PHONET, RTM_NEWADDR, newaddr_doit, NULL); - rtnl_register(PF_PHONET, RTM_DELADDR, deladdr_doit, NULL); + rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); + rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); } -- cgit v1.2.3 From ac2dc8ca14fb9028b160d89fdef04ecc66add3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 30 Sep 2008 02:52:01 -0700 Subject: Phonet: improve documentation Fix grammar errors spotted by Randy Dunlap, and adds some more details. Signed-off-by: Remi Denis-Courmont Signed-off-by: David S. Miller --- Documentation/networking/phonet.txt | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt index f3c72e0ca8d..57d3e59edb1 100644 --- a/Documentation/networking/phonet.txt +++ b/Documentation/networking/phonet.txt @@ -21,7 +21,7 @@ depending on the device, such as: Packets format -------------- -Phonet packet have a common header as follow: +Phonet packets have a common header as follows: struct phonethdr { uint8_t pn_media; /* Media type (link-layer identifier) */ @@ -33,14 +33,17 @@ Phonet packet have a common header as follow: uint8_t pn_sobj; /* Sender object ID */ }; -The device ID is split: the 6 higher order bits consitutes the device -address, while the 2 lower order bits are used for multiplexing, as are -the 8-bits object identifiers. As such, Phonet can be considered as a +On Linux, the link-layer header includes the pn_media byte (see below). +The next 7 bytes are part of the network-layer header. + +The device ID is split: the 6 higher-order bits consitute the device +address, while the 2 lower-order bits are used for multiplexing, as are +the 8-bit object identifiers. As such, Phonet can be considered as a network layer with 6 bits of address space and 10 bits for transport protocol (much like port numbers in IP world). -The modem always has address number zero. Each other device has a its -own 6-bits address. +The modem always has address number zero. All other device have a their +own 6-bit address. Link layer @@ -49,11 +52,18 @@ Link layer Phonet links are always point-to-point links. The link layer header consists of a single Phonet media type byte. It uniquely identifies the link through which the packet is transmitted, from the modem's -perspective. - -Linux Phonet network interfaces use a dedicated link layer type -(ETH_P_PHONET) which is out of the Ethernet type range. They can only -send and receive Phonet packets. +perspective. Each Phonet network device shall prepend and set the media +type byte as appropriate. For convenience, a common phonet_header_ops +link-layer header operations structure is provided. It sets the +media type according to the network device hardware address. + +Linux Phonet network interfaces support a dedicated link layer packets +type (ETH_P_PHONET) which is out of the Ethernet type range. They can +only send and receive Phonet packets. + +The virtual TUN tunnel device driver can also be used for Phonet. This +requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case, +there is no link-layer header, so there is no Phonet media type byte. Note that Phonet interfaces are not allowed to re-order packets, so only the (default) Linux FIFO qdisc should be used with them. -- cgit v1.2.3 From a57334e95e4fb132acca05bdc0efa2f9dda194af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 30 Sep 2008 02:53:18 -0700 Subject: Phonet: declare headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/Kbuild | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b68ec09399b..f431e40725d 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -126,6 +126,7 @@ header-y += pci_regs.h header-y += pfkeyv2.h header-y += pg.h header-y += phantom.h +header-y += phonet.h header-y += pkt_cls.h header-y += pkt_sched.h header-y += posix_types.h @@ -232,6 +233,7 @@ unifdef-y += if_fddi.h unifdef-y += if_frad.h unifdef-y += if_ltalk.h unifdef-y += if_link.h +unifdef-y += if_phonet.h unifdef-y += if_pppol2tp.h unifdef-y += if_pppox.h unifdef-y += if_tr.h -- cgit v1.2.3 From 8b122efd13a227d35d5ca242561770db1b5e3658 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 30 Sep 2008 03:03:35 -0700 Subject: iucv: Fix mismerge again. fb65a7c091529bfffb1262515252c0d0f6241c5c ("iucv: Fix bad merging.") fixed a merge error, but in a wrong way. We now end up with the bug below. This patch corrects the mismerge like it was intended. BUG: scheduling while atomic: swapper/1/0x00000000 Modules linked in: CPU: 1 Not tainted 2.6.27-rc7-00094-gc0f4d6d #9 Process swapper (pid: 1, task: 000000003fe7d988, ksp: 000000003fe838c0) 0000000000000000 000000003fe839b8 0000000000000002 0000000000000000 000000003fe83a58 000000003fe839d0 000000003fe839d0 0000000000390de6 000000000058acd8 00000000000000d0 000000003fe7dcd8 0000000000000000 000000000000000c 000000000000000d 0000000000000000 000000003fe83a28 000000000039c5b8 0000000000015e5e 000000003fe839b8 000000003fe83a00 Call Trace: ([<0000000000015d6a>] show_trace+0xe6/0x134) [<0000000000039656>] __schedule_bug+0xa2/0xa8 [<0000000000391744>] schedule+0x49c/0x910 [<0000000000391f64>] schedule_timeout+0xc4/0x114 [<00000000003910d4>] wait_for_common+0xe8/0x1b4 [<00000000000549ae>] call_usermodehelper_exec+0xa6/0xec [<00000000001af7b8>] kobject_uevent_env+0x418/0x438 [<00000000001d08fc>] bus_add_driver+0x1e4/0x298 [<00000000001d1ee4>] driver_register+0x90/0x18c [<0000000000566848>] netiucv_init+0x168/0x2c8 [<00000000000120be>] do_one_initcall+0x3e/0x17c [<000000000054a31a>] kernel_init+0x1ce/0x248 [<000000000001a97a>] kernel_thread_starter+0x6/0xc [<000000000001a974>] kernel_thread_starter+0x0/0xc iucv: NETIUCV driver initialized initcall netiucv_init+0x0/0x2c8 returned with preemption imbalance Signed-off-by: Heiko Carstens Signed-off-by: David S. Miller --- net/iucv/iucv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 705959b31e2..d7b54b5bfa6 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -524,7 +524,6 @@ static int iucv_enable(void) get_online_cpus(); for_each_online_cpu(cpu) smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); - preempt_enable(); if (cpus_empty(iucv_buffer_cpumask)) /* No cpu could declare an iucv buffer. */ goto out_path; @@ -547,7 +546,9 @@ out: */ static void iucv_disable(void) { + get_online_cpus(); on_each_cpu(iucv_retrieve_cpu, NULL, 1); + put_online_cpus(); kfree(iucv_path_table); } -- cgit v1.2.3 From ba0166708ef4da7eeb61dd92bbba4d5a749d6561 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 30 Sep 2008 05:32:24 -0700 Subject: sctp: Fix kernel panic while process protocol violation parameter Since call to function sctp_sf_abort_violation() need paramter 'arg' with 'struct sctp_chunk' type, it will read the chunk type and chunk length from the chunk_hdr member of chunk. But call to sctp_sf_violation_paramlen() always with 'struct sctp_paramhdr' type's parameter, it will be passed to sctp_sf_abort_violation(). This may cause kernel panic. sctp_sf_violation_paramlen() |-- sctp_sf_abort_violation() |-- sctp_make_abort_violation() This patch fixed this problem. This patch also fix two place which called sctp_sf_violation_paramlen() with wrong paramter type. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sm.h | 3 +++ net/sctp/sm_make_chunk.c | 37 ++++++++++++++++++++++++------------- net/sctp/sm_statefuns.c | 48 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 24811732bdb..029a54a0239 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -227,6 +227,9 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *, const struct sctp_chunk *, const __u8 *, const size_t ); +struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *, + const struct sctp_chunk *, + struct sctp_paramhdr *); struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, const struct sctp_transport *, const void *payload, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b599cbba4fb..d68869f966c 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1012,6 +1012,29 @@ end: return retval; } +struct sctp_chunk *sctp_make_violation_paramlen( + const struct sctp_association *asoc, + const struct sctp_chunk *chunk, + struct sctp_paramhdr *param) +{ + struct sctp_chunk *retval; + static const char error[] = "The following parameter had invalid length:"; + size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + + sizeof(sctp_paramhdr_t); + + retval = sctp_make_abort(asoc, chunk, payload_len); + if (!retval) + goto nodata; + + sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, + sizeof(error) + sizeof(sctp_paramhdr_t)); + sctp_addto_chunk(retval, sizeof(error), error); + sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); + +nodata: + return retval; +} + /* Make a HEARTBEAT chunk. */ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, const struct sctp_transport *transport, @@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, const struct sctp_chunk *chunk, struct sctp_chunk **errp) { - static const char error[] = "The following parameter had invalid length:"; - size_t payload_len = WORD_ROUND(sizeof(error)) + - sizeof(sctp_paramhdr_t); - - /* This is a fatal error. Any accumulated non-fatal errors are * not reported. */ @@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, sctp_chunk_free(*errp); /* Create an error chunk and fill it in with our payload. */ - *errp = sctp_make_op_error_space(asoc, chunk, payload_len); - - if (*errp) { - sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, - sizeof(error) + sizeof(sctp_paramhdr_t)); - sctp_addto_chunk(*errp, sizeof(error), error); - sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); - } + *errp = sctp_make_violation_paramlen(asoc, chunk, param); return 0; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2..7c622af2ce5 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( const struct sctp_endpoint *ep, const struct sctp_association *asoc, const sctp_subtype_t type, - void *arg, + void *arg, void *ext, sctp_cmd_seq_t *commands); static sctp_disposition_t sctp_sf_violation_ctsn( @@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, addr_param = (union sctp_addr_param *)hdr->params; length = ntohs(addr_param->p.length); if (length < sizeof(sctp_paramhdr_t)) - return sctp_sf_violation_paramlen(ep, asoc, type, + return sctp_sf_violation_paramlen(ep, asoc, type, arg, (void *)addr_param, commands); /* Verify the ASCONF chunk before processing it. */ @@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, (sctp_paramhdr_t *)((void *)addr_param + length), (void *)chunk->chunk_end, &err_param)) - return sctp_sf_violation_paramlen(ep, asoc, type, - (void *)&err_param, commands); + return sctp_sf_violation_paramlen(ep, asoc, type, arg, + (void *)err_param, commands); /* ADDIP 5.2 E1) Compare the value of the serial number to the value * the endpoint stored in a new association variable @@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, (sctp_paramhdr_t *)addip_hdr->params, (void *)asconf_ack->chunk_end, &err_param)) - return sctp_sf_violation_paramlen(ep, asoc, type, - (void *)&err_param, commands); + return sctp_sf_violation_paramlen(ep, asoc, type, arg, + (void *)err_param, commands); if (last_asconf) { addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; @@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen( const struct sctp_endpoint *ep, const struct sctp_association *asoc, const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) { - static const char err_str[] = "The following parameter had invalid length:"; + void *arg, void *ext, + sctp_cmd_seq_t *commands) +{ + struct sctp_chunk *chunk = arg; + struct sctp_paramhdr *param = ext; + struct sctp_chunk *abort = NULL; - return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, - sizeof(err_str)); + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) + goto discard; + + /* Make the abort chunk. */ + abort = sctp_make_violation_paramlen(asoc, chunk, param); + if (!abort) + goto nomem; + + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); + + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); + SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); + +discard: + sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); + + SCTP_INC_STATS(SCTP_MIB_ABORTEDS); + + return SCTP_DISPOSITION_ABORT; +nomem: + return SCTP_DISPOSITION_NOMEM; } /* Handle a protocol violation when the peer trying to advance the -- cgit v1.2.3 From 3bb91bff8165223aa14f015a6c9150a536b40d9b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 19 Sep 2008 14:47:38 -0500 Subject: b43: Fix Bluetooth coexistence SPROM coding error for Motorola 7010 variant of BCM4306 An additional BCM4306 has been found with the Bluetooth coexistence SPROM coding error. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 0f628a29d83..2968919a827 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4545,7 +4545,8 @@ static void b43_sprom_fixup(struct ssb_bus *bus) IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || - IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) || + IS_PDEV(pdev, BROADCOM, 0x4320, MOTOROLA, 0x7010)) bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; } } -- cgit v1.2.3 From 1f1c0e33a0ab1379272da68fe58abf586c8e96e5 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 25 Sep 2008 14:54:28 -0500 Subject: p54: Fix sparse warnings The command make C=2 CF="-D__CHECK_ENDIAN__" drivers/net/wireless/p54/ generates the following warnings: .../p54common.c:152:38: warning: incorrect type in argument 1 (different base types) .../p54common.c:152:38: expected restricted __be32 const [usertype] *p .../p54common.c:152:38: got unsigned int * .../p54common.c:184:15: warning: restricted __le32 degrades to integer .../p54common.c:185:29: warning: cast to restricted __le16 .../p54common.c:309:11: warning: symbol 'p54_rf_chips' was not declared. Should it be static? .../p54common.c:313:5: warning: symbol 'p54_parse_eeprom' was not declared. Should it be static? .../p54common.c:620:43: warning: incorrect type in argument 3 (different base types) .../p54common.c:620:43: expected unsigned long [unsigned] [usertype] len .../p54common.c:620:43: got restricted __le16 [usertype] len .../p54common.c:780:41: warning: restricted __le16 degrades to integer .../p54common.c:781:32: warning: restricted __le16 degrades to integer .../p54common.c:1250:28: warning: incorrect type in argument 2 (different base types) .../p54common.c:1250:28: expected unsigned short [unsigned] [usertype] filter_type .../p54common.c:1250:28: got restricted __le16 [usertype] filter_type .../p54common.c:1252:28: warning: incorrect type in argument 2 (different base types) .../p54common.c:1252:28: expected unsigned short [unsigned] [usertype] filter_type .../p54common.c:1252:28: got restricted __le16 [usertype] filter_type .../p54common.c:1257:42: warning: incorrect type in argument 2 (different base types) .../p54common.c:1257:42: expected unsigned short [unsigned] [usertype] filter_type .../p54common.c:1257:42: got restricted __le16 .../p54common.c:1260:42: warning: incorrect type in argument 2 (different base types) .../p54common.c:1260:42: expected unsigned short [unsigned] [usertype] filter_type .../p54common.c:1260:42: got restricted __le16 .../p54usb.c:228:10: warning: restricted __le32 degrades to integer .../p54usb.c:228:23: warning: restricted __le32 degrades to integer .../p54usb.c:228:7: warning: incorrect type in assignment (different base types) .../p54usb.c:228:7: expected restricted __le32 [assigned] [usertype] chk .../p54usb.c:228:7: got unsigned int .../p54usb.c:221:8: warning: symbol 'p54u_lm87_chksum' was not declared. Should it be static? All of the above have been fixed. One question, however, remains: In struct bootrec, the array "data" is treated in many places as native CPU order, but it may be little-endian everywhere. As far as I can tell, this driver has only been used with little-endian hardware. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 33 ++++++++++++++++++--------------- drivers/net/wireless/p54/p54common.h | 3 ++- drivers/net/wireless/p54/p54usb.c | 8 ++++---- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index bac58ed03e5..de5e8f44b20 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -149,7 +149,8 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) u32 code = le32_to_cpu(bootrec->code); switch (code) { case BR_CODE_COMPONENT_ID: - priv->fw_interface = be32_to_cpup(bootrec->data); + priv->fw_interface = be32_to_cpup((__be32 *) + bootrec->data); switch (priv->fw_interface) { case FW_FMAC: printk(KERN_INFO "p54: FreeMAC firmware\n"); @@ -181,9 +182,8 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500; priv->headroom = desc->headroom; priv->tailroom = desc->tailroom; - if (bootrec->len == 11) - priv->rx_mtu = (size_t) le16_to_cpu( - (__le16)bootrec->data[10]); + if (le32_to_cpu(bootrec->len) == 11) + priv->rx_mtu = le16_to_cpu(bootrec->rx_mtu); else priv->rx_mtu = (size_t) 0x620 - priv->tx_hdr_len; @@ -306,11 +306,11 @@ static int p54_convert_rev1(struct ieee80211_hw *dev, return 0; } -const char* p54_rf_chips[] = { "NULL", "Indigo?", "Duette", +static const char *p54_rf_chips[] = { "NULL", "Indigo?", "Duette", "Frisbee", "Xbow", "Longbow" }; static int p54_init_xbow_synth(struct ieee80211_hw *dev); -int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) +static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; struct eeprom_pda_wrap *wrap = NULL; @@ -617,7 +617,7 @@ static void p54_rx_eeprom_readback(struct ieee80211_hw *dev, if (!priv->eeprom) return ; - memcpy(priv->eeprom, eeprom->data, eeprom->len); + memcpy(priv->eeprom, eeprom->data, le16_to_cpu(eeprom->len)); complete(&priv->eeprom_comp); } @@ -777,8 +777,9 @@ int p54_read_eeprom(struct ieee80211_hw *dev) hdr->len = cpu_to_le16(blocksize + sizeof(*eeprom_hdr)); eeprom_hdr->offset = cpu_to_le16(offset); eeprom_hdr->len = cpu_to_le16(blocksize); - p54_assign_address(dev, NULL, hdr, hdr->len + sizeof(*hdr)); - priv->tx(dev, hdr, hdr->len + sizeof(*hdr), 0); + p54_assign_address(dev, NULL, hdr, le16_to_cpu(hdr->len) + + sizeof(*hdr)); + priv->tx(dev, hdr, le16_to_cpu(hdr->len) + sizeof(*hdr), 0); if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) { printk(KERN_ERR "%s: device does not respond!\n", @@ -1247,18 +1248,20 @@ static void p54_configure_filter(struct ieee80211_hw *dev, if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - p54_set_filter(dev, priv->filter_type, NULL); + p54_set_filter(dev, le16_to_cpu(priv->filter_type), + NULL); else - p54_set_filter(dev, priv->filter_type, priv->bssid); + p54_set_filter(dev, le16_to_cpu(priv->filter_type), + priv->bssid); } if (changed_flags & FIF_PROMISC_IN_BSS) { if (*total_flags & FIF_PROMISC_IN_BSS) - p54_set_filter(dev, priv->filter_type | - cpu_to_le16(0x8), NULL); + p54_set_filter(dev, le16_to_cpu(priv->filter_type) | + 0x8, NULL); else - p54_set_filter(dev, priv->filter_type & - ~cpu_to_le16(0x8), priv->bssid); + p54_set_filter(dev, le16_to_cpu(priv->filter_type) & + ~0x8, priv->bssid); } } diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 4da736c789a..2fa994cfcfe 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -18,7 +18,8 @@ struct bootrec { __le32 code; __le32 len; - u32 data[0]; + u32 data[10]; + __le16 rx_mtu; } __attribute__((packed)); struct bootrec_exp_if { diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 7444f372977..1912f5e9a0a 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -218,17 +218,17 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, usb_submit_urb(data_urb, GFP_ATOMIC); } -__le32 p54u_lm87_chksum(const u32 *data, size_t length) +static __le32 p54u_lm87_chksum(const u32 *data, size_t length) { - __le32 chk = 0; + u32 chk = 0; length >>= 2; while (length--) { - chk ^= cpu_to_le32(*data++); + chk ^= *data++; chk = (chk >> 5) ^ (chk << 3); } - return chk; + return cpu_to_le32(chk); } static void p54u_tx_lm87(struct ieee80211_hw *dev, -- cgit v1.2.3 From 8cd519e89616057c8a433a54a3e60883e4893017 Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 26 Sep 2008 15:09:32 +0800 Subject: iwlwifi: refactor rx register initialization The patch adds HW bug W/A FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY so that we can enable again interrupt coalescing. It also uses named constants for open code. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-csr.h | 2 +- drivers/net/wireless/iwlwifi/iwl-fh.h | 9 +++++---- drivers/net/wireless/iwlwifi/iwl-rx.c | 30 +++++++++++++++++++----------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 52629fbd835..662edf4f8d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -64,7 +64,7 @@ #define CSR_BASE (0x000) #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ -#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ +#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index cd11c0ca299..a72efdf6d1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -247,8 +247,8 @@ #define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */ #define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/ -#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20) -#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_BITSHIFT (4) +#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20) +#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4) #define RX_RB_TIMEOUT (0x10) #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) @@ -260,8 +260,9 @@ #define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000) #define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) +#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004) +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) +#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) /** diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 38b2946b1d8..7cde9d76ff5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -376,7 +376,9 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { int ret; unsigned long flags; - unsigned int rb_size; + u32 rb_size; + const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ + const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */ spin_lock_irqsave(&priv->lock, flags); ret = iwl_grab_nic_access(priv); @@ -398,26 +400,32 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) /* Tell device where to find RBD circular buffer in DRAM */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - rxq->dma_addr >> 8); + (u32)(rxq->dma_addr >> 8)); /* Tell device where in DRAM to update its Rx status */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, (priv->shared_phys + priv->rb_closed_offset) >> 4); - /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ + /* Enable Rx DMA + * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set becuase of HW bug in + * the credit mechanism in 5000 HW RX FIFO + * Direct rx interrupts to hosts + * Rx buffer size 4 or 8k + * RB timeout 0x10 + * 256 RBDs + */ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size | - /* 0x10 << 4 | */ - (RX_QUEUE_SIZE_LOG << - FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); - - /* - * iwl_write32(priv,CSR_INT_COAL_REG,0); - */ + rb_size| + (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); iwl_release_nic_access(priv); + + iwl_write32(priv, CSR_INT_COALESCING, 0x40); + spin_unlock_irqrestore(&priv->lock, flags); return 0; -- cgit v1.2.3 From e602cb180e97c46dfb01a4644781ec68ee0cda22 Mon Sep 17 00:00:00 2001 From: Ester Kummer Date: Fri, 26 Sep 2008 15:09:33 +0800 Subject: iwlwifi: enable power save setting upon config This patch enables power save setting from config (iwconfig power) The sysfs power_level interface is still preserved as it has mac80211 power implementation is not yet rich enough. Signed-off-by: Ester Kummer Reviewed-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7330890fd05..a589f7ea57f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2875,6 +2875,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } + if (conf->flags & IEEE80211_CONF_PS) + ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); + else + ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); + if (ret) + IWL_DEBUG_MAC80211("Error setting power level\n"); + IWL_DEBUG_MAC80211("TX Power old=%d new=%d\n", priv->tx_power_user_lmt, conf->power_level); -- cgit v1.2.3 From 093d874c02e8d3091aa38596faf0ff2bfd4f0ceb Mon Sep 17 00:00:00 2001 From: "Winkler, Tomas" Date: Fri, 26 Sep 2008 15:09:34 +0800 Subject: iwlwifi: use correct DMA_MASK Use correct DMA_MASK: 4964 and 5000 support 36 bit addresses for pci express memory access. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a589f7ea57f..204abab7644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4243,13 +4243,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_set_master(pdev); - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); if (err) { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ if (err) { printk(KERN_WARNING "%s: No suitable DMA available.\n", -- cgit v1.2.3 From b4a4bf5d77c7d32098a7080f34a8857dd7fa466d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Sep 2008 13:34:54 +0200 Subject: mac80211: fixups for "make master iface not wireless" In "mac80211: make master iface not wireless" I accidentally forgot to include these changes ... leading to the expected BUG_ON errors. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 9 ++++----- net/mac80211/wme.c | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b5cd91e8971..8336fee68d3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -58,8 +58,9 @@ static inline int identical_mac_addr_allowed(int type1, int type2) static int ieee80211_open(struct net_device *dev) { - struct ieee80211_sub_if_data *sdata, *nsdata; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *nsdata; + struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_if_init_conf conf; u32 changed = 0; @@ -67,8 +68,6 @@ static int ieee80211_open(struct net_device *dev) bool need_hw_reconfig = 0; u8 null_addr[ETH_ALEN] = {0}; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* fail early if user set an invalid address */ if (compare_ether_addr(dev->dev_addr, null_addr) && !is_valid_ether_addr(dev->dev_addr)) @@ -512,8 +511,8 @@ static int ieee80211_stop(struct net_device *dev) static void ieee80211_set_multicast_list(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int allmulti, promisc, sdata_allmulti, sdata_promisc; allmulti = !!(dev->flags & IFF_ALLMULTI); diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index c703f8b44e9..139b5f267b3 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -73,9 +73,8 @@ static int wme_downgrade_ac(struct sk_buff *skb) /* Indicate which queue to use. */ -static u16 classify80211(struct sk_buff *skb, struct net_device *dev) +static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; if (!ieee80211_is_data(hdr->frame_control)) { @@ -113,14 +112,15 @@ static u16 classify80211(struct sk_buff *skb, struct net_device *dev) u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) { + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct sta_info *sta; u16 queue; u8 tid; - queue = classify80211(skb, dev); + queue = classify80211(local, skb); if (unlikely(queue >= local->hw.queues)) queue = local->hw.queues - 1; -- cgit v1.2.3 From 570bdfb17dfc92061f7e26f6320b309c1df00997 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 26 Sep 2008 08:23:00 -0500 Subject: b43: Fix Bluetooth Coexistence SPROM programming error for HP 12f8 version of BCM4306 Yet another BCM4306 card with the Bluetooth Coexistence SPROM programming error has been found. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 2968919a827..e5e71220e7d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4543,6 +4543,7 @@ static void b43_sprom_fixup(struct ssb_bus *bus) pdev = bus->host_pci; if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || + IS_PDEV(pdev, BROADCOM, 0x4320, HP, 0x12f8) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) || -- cgit v1.2.3 From d88410a0b657c5ccebd1c120af1f14c5ca6a3d95 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Thu, 25 Sep 2008 20:45:01 +0300 Subject: mac80211: remove wme_tx_queue and wme_rx_queue from net/mac80211/sta_info.h This patch removes wme_tx_queue and wme_rx_queue from struct sta_info and from the debugfs sub-structure of struct sta_info in net/mac80211/sta_info.h, as they are useless and not used. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/sta_info.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c3f43696462..a6b51862a89 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -189,7 +189,6 @@ struct sta_ampdu_mlme { * @last_qual: qual of last received frame from this STA * @last_noise: noise of last received frame from this STA * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) - * @wme_rx_queue: TBD * @tx_filtered_count: TBD * @tx_retry_failed: TBD * @tx_retry_count: TBD @@ -199,7 +198,6 @@ struct sta_ampdu_mlme { * @tx_fragments: number of transmitted MPDUs * @last_txrate_idx: Index of the last used transmit rate * @tid_seq: TBD - * @wme_tx_queue: TBD * @ampdu_mlme: TBD * @timer_to_tid: identity mapping to ID timers * @tid_to_tx_q: map tid to tx queue @@ -258,9 +256,6 @@ struct sta_info { int last_qual; int last_noise; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; -#endif /* Updated from TX status path only, no locking requirements */ unsigned long tx_filtered_count; @@ -274,9 +269,6 @@ struct sta_info { unsigned long tx_fragments; unsigned int last_txrate_idx; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; -#endif /* * Aggregation information, locked with lock. @@ -307,10 +299,6 @@ struct sta_info { struct dentry *num_ps_buf_frames; struct dentry *inactive_ms; struct dentry *last_seq_ctrl; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - struct dentry *wme_rx_queue; - struct dentry *wme_tx_queue; -#endif struct dentry *agg_status; } debugfs; #endif -- cgit v1.2.3 From 3ed6e0803b4fe95107f6cb5a432587d03cd4d17a Mon Sep 17 00:00:00 2001 From: Anna Neal Date: Fri, 26 Sep 2008 11:34:35 -0400 Subject: libertas: Improvements on automatic tx power control via SIOCSIWTXPOW (fixups) This patch addresses comments from Dan Williams about the patch committed as "libertas: Improvements on automatic tx power control via SIOCSIWTXPOW." Signed-off-by: Anna Neal Signed-off-by: Javier Cardona Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 2 +- drivers/net/wireless/libertas/cmd.h | 6 ++++++ drivers/net/wireless/libertas/defs.h | 1 - drivers/net/wireless/libertas/wext.c | 12 ++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index aee19fa844e..a912fb68c09 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1949,7 +1949,7 @@ int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_ACT_SET); cmd.enable = !!enable; - cmd.usesnr = !!enable; + cmd.usesnr = !!usesnr; cmd.P0 = p0; cmd.P1 = p1; cmd.P2 = p2; diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index d002160f597..36be4c9703e 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -32,6 +32,12 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, int8_t p2, int usesnr); +int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, + int8_t p1, int8_t p2); + +int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, + int8_t p2, int usesnr); + int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, struct cmd_header *resp); diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 58d11a35e61..076a636e8f6 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -189,7 +189,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MRVDRV_CMD_UPLD_RDY 0x0008 #define MRVDRV_CARDEVENT 0x0010 - /* Automatic TX control default levels */ #define POW_ADAPT_DEFAULT_P0 13 #define POW_ADAPT_DEFAULT_P1 15 diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 6ebdd7f161f..82c3e5a50ea 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1025,6 +1025,18 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, new_rate); goto out; } + if (priv->fwrelease < 0x09000000) { + ret = lbs_set_power_adapt_cfg(priv, 0, + POW_ADAPT_DEFAULT_P0, + POW_ADAPT_DEFAULT_P1, + POW_ADAPT_DEFAULT_P2); + if (ret) + goto out; + } + ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, + TPC_DEFAULT_P2, 1); + if (ret) + goto out; } /* Try the newer command first (Firmware Spec 5.1 and above) */ -- cgit v1.2.3 From 55ad175fb65a4a3a7e4d1aa13c460de281b4e8ac Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 29 Sep 2008 16:28:21 -0400 Subject: ieee80211.h: remove superfluous ETH_P_PAE definition Signed-off-by: John W. Linville --- include/net/ieee80211.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index b31399e1fd8..6048579d0b2 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -190,10 +190,6 @@ const char *escape_essid(const char *essid, u8 essid_len); #endif #include /* new driver API */ -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ #ifndef ETH_P_80211_RAW -- cgit v1.2.3 From 4c99f3e4cfc3190e01c55e72d15a837d9dc41426 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 28 Sep 2008 15:11:38 +0200 Subject: rt2x00: Fix build errors due to modularized rfkill or leds and built-in rt2x00. Fix by disabling rt2x00 rfkill support when rt2x00 is built-in and rfkill has been modularized, and a similar scheme for the relationship between leds_class and rt2x00.. Also, give a warning to the end-user when rfkill-/leds-support is disabled this way, so that the end-user has at least some clues on what is going on. Proper fixing required some general updates of the Kconfig-structure for the rt2x00 driver, whereby internal configuration symbols had to be moved to after the user-visible configuration symbols. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 69 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index b686dc45483..f839ce044af 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -1,5 +1,5 @@ -config RT2X00 - tristate "Ralink driver support" +menuconfig RT2X00 + bool "Ralink driver support" depends on MAC80211 && WLAN_80211 && EXPERIMENTAL ---help--- This will enable the experimental support for the Ralink drivers, @@ -17,39 +17,6 @@ config RT2X00 if RT2X00 -config RT2X00_LIB - tristate - -config RT2X00_LIB_PCI - tristate - select RT2X00_LIB - -config RT2X00_LIB_USB - tristate - select RT2X00_LIB - -config RT2X00_LIB_FIRMWARE - boolean - depends on RT2X00_LIB - select FW_LOADER - -config RT2X00_LIB_CRYPTO - boolean - depends on RT2X00_LIB - -config RT2X00_LIB_RFKILL - boolean - depends on RT2X00_LIB - depends on RFKILL - default y - -config RT2X00_LIB_LEDS - boolean - depends on RT2X00_LIB - depends on NEW_LEDS - depends on LEDS_CLASS - default y - config RT2400PCI tristate "Ralink rt2400 (PCI/PCMCIA) support" depends on PCI @@ -109,6 +76,38 @@ config RT73USB When compiled as a module, this driver will be called "rt73usb.ko". +config RT2X00_LIB_PCI + tristate + select RT2X00_LIB + +config RT2X00_LIB_USB + tristate + select RT2X00_LIB + +config RT2X00_LIB + tristate + +config RT2X00_LIB_FIRMWARE + boolean + select FW_LOADER + +config RT2X00_LIB_CRYPTO + boolean + +config RT2X00_LIB_RFKILL + boolean + default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n) + +comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00" + depends on RT2X00_LIB=y && RFKILL=m + +config RT2X00_LIB_LEDS + boolean + default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) + +comment "rt2x00 leds support disabled due to modularized LEDS_CLASS and built-in rt2x00" + depends on RT2X00_LIB=y && LEDS_CLASS=m + config RT2X00_LIB_DEBUGFS bool "Ralink debugfs support" depends on RT2X00_LIB && MAC80211_DEBUGFS -- cgit v1.2.3 From b0dee5784dff3e2984510a7fe7a7e48109001f94 Mon Sep 17 00:00:00 2001 From: Davide Pesavento Date: Sat, 27 Sep 2008 17:29:12 +0200 Subject: Fix modpost failure when rx handlers are not inlined. When CONFIG_MAC80211_MESH=n and CONFIG_MAC80211_NOINLINE=y, gcc doesn't optimize out a call to ieee80211_rx_h_mesh_fwding, even if the previous comparison is always false in this case. This leads to the following errors during modpost: ERROR: "mpp_path_lookup" [net/mac80211/mac80211.ko] undefined! ERROR: "mpp_path_add" [net/mac80211/mac80211.ko] undefined! Fix by removing the possibility of uninlining ieee80211_rx_h_mesh_fwding rx handler. Signed-off-by: Davide Pesavento Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c489865761b..77e7b014872 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1379,7 +1379,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) return RX_QUEUED; } -static ieee80211_rx_result debug_noinline +static ieee80211_rx_result ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr; -- cgit v1.2.3 From 14be9947ef9843102b67d315c7483de112b5b2d7 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 28 Sep 2008 12:09:43 -0400 Subject: ath5k: write beacon control register twice when resetting tsf According to the newly-released Atheros HAL code, asserting the TSF reset bit will toggle a hardware internal state, resulting in a spurious reset on the next chip reset. Whenever we force a TSF bit, write the bit twice to clear the internal signal. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/pcu.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index c77cee2a558..a47df9a24aa 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -633,8 +633,20 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) */ void ath5k_hw_reset_tsf(struct ath5k_hw *ah) { + u32 val; + ATH5K_TRACE(ah->ah_sc); - AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF); + + val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; + + /* + * Each write to the RESET_TSF bit toggles a hardware internal + * signal to reset TSF, but if left high it will cause a TSF reset + * on the next chip reset as well. Thus we always write the value + * twice to clear the signal. + */ + ath5k_hw_reg_write(ah, val, AR5K_BEACON); + ath5k_hw_reg_write(ah, val, AR5K_BEACON); } /* -- cgit v1.2.3 From 1bef016a5a2c52de45b332c8fa797958becde9bf Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 29 Sep 2008 02:09:09 +0300 Subject: ath5k: Update registers and SREV ids v2 * Update registers * Update SREV values and add some PHY srevs * Prepare ath5k.h for newer radios etc Thanks to Atheros 's HAL source we now know for sure how many parts we have and what their SREV values are. We also have some updates on registers. Prepare ath5k for some major updates ;-) My previous mail had 2 more patches following (git log misusage), sorry for double posting ;-( Changes-Licensed-under: ISC Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 59 ++-- drivers/net/wireless/ath5k/attach.c | 26 +- drivers/net/wireless/ath5k/base.c | 50 ++-- drivers/net/wireless/ath5k/qcu.c | 8 +- drivers/net/wireless/ath5k/reg.h | 577 +++++++++++++++++++++++++----------- drivers/net/wireless/ath5k/reset.c | 8 +- 6 files changed, 490 insertions(+), 238 deletions(-) diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 20018869051..7134c40d6a6 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -281,7 +281,9 @@ enum ath5k_radio { AR5K_RF5112 = 2, AR5K_RF2413 = 3, AR5K_RF5413 = 4, - AR5K_RF2425 = 5, + AR5K_RF2316 = 5, + AR5K_RF2317 = 6, + AR5K_RF2425 = 7, }; /* @@ -289,7 +291,7 @@ enum ath5k_radio { */ enum ath5k_srev_type { - AR5K_VERSION_VER, + AR5K_VERSION_MAC, AR5K_VERSION_RAD, }; @@ -301,23 +303,24 @@ struct ath5k_srev_name { #define AR5K_SREV_UNKNOWN 0xffff -#define AR5K_SREV_VER_AR5210 0x00 -#define AR5K_SREV_VER_AR5311 0x10 -#define AR5K_SREV_VER_AR5311A 0x20 -#define AR5K_SREV_VER_AR5311B 0x30 -#define AR5K_SREV_VER_AR5211 0x40 -#define AR5K_SREV_VER_AR5212 0x50 -#define AR5K_SREV_VER_AR5213 0x55 -#define AR5K_SREV_VER_AR5213A 0x59 -#define AR5K_SREV_VER_AR2413 0x78 -#define AR5K_SREV_VER_AR2414 0x79 -#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */ -#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */ -#define AR5K_SREV_VER_AR5413 0xa4 -#define AR5K_SREV_VER_AR5414 0xa5 -#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */ -#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */ -#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */ +#define AR5K_SREV_AR5210 0x00 /* Crete */ +#define AR5K_SREV_AR5311 0x10 /* Maui 1 */ +#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */ +#define AR5K_SREV_AR5311B 0x30 /* Spirit */ +#define AR5K_SREV_AR5211 0x40 /* Oahu */ +#define AR5K_SREV_AR5212 0x50 /* Venice */ +#define AR5K_SREV_AR5213 0x55 /* ??? */ +#define AR5K_SREV_AR5213A 0x59 /* Hainan */ +#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ +#define AR5K_SREV_AR2414 0x70 /* Griffin */ +#define AR5K_SREV_AR5424 0x90 /* Condor */ +#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ +#define AR5K_SREV_AR5414 0xa0 /* Eagle */ +#define AR5K_SREV_AR2415 0xb0 /* Cobra */ +#define AR5K_SREV_AR5416 0xc0 /* PCI-E */ +#define AR5K_SREV_AR5418 0xca /* PCI-E */ +#define AR5K_SREV_AR2425 0xe0 /* Swan */ +#define AR5K_SREV_AR2417 0xf0 /* Nala */ #define AR5K_SREV_RAD_5110 0x00 #define AR5K_SREV_RAD_5111 0x10 @@ -329,10 +332,20 @@ struct ath5k_srev_name { #define AR5K_SREV_RAD_2112 0x40 #define AR5K_SREV_RAD_2112A 0x45 #define AR5K_SREV_RAD_2112B 0x46 -#define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */ -#define AR5K_SREV_RAD_SC1 0x60 /* Found on 5413/5414 */ -#define AR5K_SREV_RAD_SC2 0xa0 /* Found on 2424-5/5424 */ -#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ +#define AR5K_SREV_RAD_2413 0x50 +#define AR5K_SREV_RAD_5413 0x60 +#define AR5K_SREV_RAD_2316 0x70 +#define AR5K_SREV_RAD_2317 0x80 +#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */ +#define AR5K_SREV_RAD_2425 0xa2 +#define AR5K_SREV_RAD_5133 0xc0 + +#define AR5K_SREV_PHY_5211 0x30 +#define AR5K_SREV_PHY_5212 0x41 +#define AR5K_SREV_PHY_2112B 0x43 +#define AR5K_SREV_PHY_2413 0x45 +#define AR5K_SREV_PHY_5413 0x61 +#define AR5K_SREV_PHY_2425 0x70 /* IEEE defs */ #define IEEE80211_MAX_LEN 2500 diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 153c4111fab..d92b4a12567 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c @@ -168,19 +168,19 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) CHANNEL_2GHZ); /* Return on unsuported chips (unsupported eeprom etc) */ - if ((srev >= AR5K_SREV_VER_AR5416) && - (srev < AR5K_SREV_VER_AR2425)) { + if ((srev >= AR5K_SREV_AR5416) && + (srev < AR5K_SREV_AR2425)) { ATH5K_ERR(sc, "Device not yet supported.\n"); ret = -ENODEV; goto err_free; - } else if (srev == AR5K_SREV_VER_AR2425) { + } else if (srev == AR5K_SREV_AR2425) { ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); } /* Identify single chip solutions */ - if (((srev <= AR5K_SREV_VER_AR5414) && - (srev >= AR5K_SREV_VER_AR2413)) || - (srev == AR5K_SREV_VER_AR2425)) { + if (((srev <= AR5K_SREV_AR5414) && + (srev >= AR5K_SREV_AR2413)) || + (srev == AR5K_SREV_AR2425)) { ah->ah_single_chip = true; } else { ah->ah_single_chip = false; @@ -199,24 +199,24 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) * correctly. For now we are based on mac's srev to * identify RF2425 radio. */ - } else if (srev == AR5K_SREV_VER_AR2425) { + } else if (srev == AR5K_SREV_AR2425) { ah->ah_radio = AR5K_RF2425; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { ah->ah_radio = AR5K_RF5111; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_2413) { ah->ah_radio = AR5K_RF5112; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5413) { ah->ah_radio = AR5K_RF2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_2316) { ah->ah_radio = AR5K_RF5413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { /* AR5424 */ - if (srev >= AR5K_SREV_VER_AR5424) { + if (srev >= AR5K_SREV_AR5424) { ah->ah_radio = AR5K_RF5413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; /* AR2424 */ @@ -252,8 +252,8 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Write AR5K_PCICFG_UNK on 2112B and later chips */ if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || - srev > AR5K_SREV_VER_AR2413) { - ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG); + srev > AR5K_SREV_AR2413) { + ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); } /* diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index e09ed2ce675..c8bb9bfb51f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -100,34 +100,40 @@ MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); /* Known SREVs */ static struct ath5k_srev_name srev_names[] = { - { "5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210 }, - { "5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311 }, - { "5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A }, - { "5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B }, - { "5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211 }, - { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 }, - { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 }, - { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A }, - { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 }, - { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 }, - { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 }, - { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 }, - { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 }, - { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, - { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, - { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, - { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 }, - { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, + { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, + { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, + { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, + { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, + { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, + { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, + { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, + { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, + { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, + { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, + { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, + { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, + { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, + { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, + { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, + { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, + { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, + { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, + { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, + { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, + { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, - { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 }, - { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 }, - { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 }, + { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, + { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, + { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, + { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, }; @@ -536,7 +542,7 @@ ath5k_pci_probe(struct pci_dev *pdev, goto err_ah; ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_VER,sc->ah->ah_mac_srev), + ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), sc->ah->ah_mac_srev, sc->ah->ah_phy_revision); diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c index 2e20f7816ca..01bf09176d2 100644 --- a/drivers/net/wireless/ath5k/qcu.c +++ b/drivers/net/wireless/ath5k/qcu.c @@ -375,7 +375,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) case AR5K_TX_QUEUE_BEACON: AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_BCN | + AR5K_QCU_MISC_CBREXP_BCN_DIS | AR5K_QCU_MISC_BCN_ENABLE); AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), @@ -395,8 +395,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) case AR5K_TX_QUEUE_CAB: AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP | - AR5K_QCU_MISC_CBREXP_BCN); + AR5K_QCU_MISC_CBREXP_DIS | + AR5K_QCU_MISC_CBREXP_BCN_DIS); AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << @@ -405,7 +405,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) case AR5K_TX_QUEUE_UAPSD: AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBREXP); + AR5K_QCU_MISC_CBREXP_DIS); break; case AR5K_TX_QUEUE_DATA: diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 410f99a6d61..55054b575e8 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -29,6 +29,10 @@ * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf * * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf + * + * This file also contains register values found on a memory dump of + * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal + * released by Atheros and on various debug messages found on the net. */ @@ -295,7 +299,7 @@ #define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ #define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */ #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ -#define AR5K_ISR_BRSSI 0x00020000 +#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ #define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ @@ -303,46 +307,56 @@ #define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ #define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ #define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ -#define AR5K_ISR_TIM 0x00800000 /* [5210] */ -#define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */ -#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/ -#define AR5K_ISR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */ -#define AR5K_ISR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */ -#define AR5K_ISR_QTRIG 0x08000000 /* [5211+] */ +#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ +#define AR5K_ISR_TIM 0x00800000 /* [5211+] */ +#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, + CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ +#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ +#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ +#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ +#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ /* * Secondary status registers [5211+] (0 - 4) * - * I guess from the names that these give the status for each - * queue, that's why only masks are defined here, haven't got - * any info about them (couldn't find them anywhere in ar5k code). + * These give the status for each QCU, only QCUs 0-9 are + * represented. */ #define AR5K_SISR0 0x0084 /* Register Address [5211+] */ #define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ +#define AR5K_SISR0_QCU_TXOK_S 0 #define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ +#define AR5K_SISR0_QCU_TXDESC_S 16 #define AR5K_SISR1 0x0088 /* Register Address [5211+] */ #define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ +#define AR5K_SISR1_QCU_TXERR_S 0 #define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ +#define AR5K_SISR1_QCU_TXEOL_S 16 #define AR5K_SISR2 0x008c /* Register Address [5211+] */ #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ +#define AR5K_SISR2_QCU_TXURN_S 0 #define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ #define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SISR2_DPERR 0x00400000 /* Det par Error (?) */ +#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ #define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ #define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ +#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ #define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ +#define AR5K_SISR3_QCBORN_S 0 #define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ +#define AR5K_SISR3_QCBRURN_S 16 #define AR5K_SISR4 0x0094 /* Register Address [5211+] */ #define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */ +#define AR5K_SISR4_QTRIG_S 0 /* * Shadow read-and-clear interrupt status registers [5211+] @@ -379,7 +393,7 @@ #define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ #define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */ #define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ -#define AR5K_IMR_BRSSI 0x00020000 +#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ #define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ #define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ #define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ @@ -387,12 +401,14 @@ #define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/ #define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */ #define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */ +#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ #define AR5K_IMR_TIM 0x00800000 /* [5211+] */ -#define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */ +#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, + CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ #define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ -#define AR5K_IMR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */ -#define AR5K_IMR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */ -#define AR5K_IMR_QTRIG 0x08000000 /* [5211+] */ +#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */ +#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */ +#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ /* * Secondary interrupt mask registers [5211+] (0 - 4) @@ -414,13 +430,14 @@ #define AR5K_SIMR2_QCU_TXURN_S 0 #define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ #define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SIMR2_DPERR 0x00400000 /* Det par Error (?) */ +#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ #define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ #define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ #define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ +#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */ #define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ #define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ @@ -586,15 +603,15 @@ #define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ #define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ #define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ -#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */ -#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */ -#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */ +#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */ +#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */ +#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */ #define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ -#define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */ -#define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */ +#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */ +#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */ #define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */ -#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled */ -#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME enalbed */ +#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */ +#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */ #define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */ #define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */ #define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */ @@ -663,6 +680,7 @@ #define AR5K_DCU_LCL_IFS_CW_MAX_S 10 #define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */ #define AR5K_DCU_LCL_IFS_AIFS_S 20 +#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */ #define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q) /* @@ -691,11 +709,7 @@ /* * DCU misc registers [5211+] * - * For some of the registers i couldn't find in the code - * (only backoff stuff is there realy) i tried to match the - * names with 802.11e parameters etc, so i guess VIRTCOL here - * means Virtual Collision and HCFPOLL means Hybrid Coordination - * factor Poll (CF- Poll). Arbiter lockout control controls the + * Note: Arbiter lockout control controls the * behaviour on low priority queues when we have multiple queues * with pending frames. Intra-frame lockout means we wait until * the queue's current frame transmits (with post frame backoff and bursting) @@ -705,15 +719,20 @@ * No lockout means there is no special handling. */ #define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ -#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff threshold */ +#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */ +#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series + station RTS/data failure count + reset policy (?) */ +#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series + CW reset policy */ +#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */ #define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ #define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */ #define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */ #define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */ #define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ -#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 -#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1 -#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2 +#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 +#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1 #define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */ #define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ #define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 @@ -768,8 +787,9 @@ #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFC cnt reset policy (?) */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */ #define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */ #define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */ @@ -831,9 +851,11 @@ #define AR5K_SLEEP_CTL_SLE_S 16 #define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */ #define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ -#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 +#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */ #define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ -/* more bits */ +#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */ +#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */ +#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */ /* * Interrupt pending register @@ -849,27 +871,28 @@ /* * PCI configuration register + * TODO: Fix LED stuff */ #define AR5K_PCICFG 0x4010 /* Register Address */ #define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ -#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock (?) */ +#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */ #define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ #define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ #define AR5K_PCICFG_EESIZE_S 3 #define AR5K_PCICFG_EESIZE_4K 0 /* 4K */ #define AR5K_PCICFG_EESIZE_8K 1 /* 8K */ #define AR5K_PCICFG_EESIZE_16K 2 /* 16K */ -#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */ +#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */ #define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */ #define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */ #define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */ #define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */ #define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */ -#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */ -#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */ +#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */ +#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ -#define AR5K_PCICFG_UNK 0x00001000 /* Passed on some parts durring attach (?) */ -#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts (?) */ +#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ +#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ @@ -882,7 +905,8 @@ #define AR5K_PCICFG_LEDSTATE \ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) -#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate (field) */ +#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */ +#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24 /* * "General Purpose Input/Output" (GPIO) control register @@ -904,8 +928,8 @@ #define AR5K_GPIOCR 0x4014 /* Register Address */ #define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ -#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is off (?) */ -#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is on */ +#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */ +#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */ #define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */ #define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */ #define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */ @@ -923,7 +947,6 @@ #define AR5K_GPIODI 0x401c #define AR5K_GPIODI_M 0x0000002f - /* * Silicon revision register */ @@ -933,7 +956,59 @@ #define AR5K_SREV_VER 0x000000ff /* Mask for version */ #define AR5K_SREV_VER_S 4 +/* + * TXE write posting register + */ +#define AR5K_TXEPOST 0x4028 + +/* + * QCU sleep mask + */ +#define AR5K_QCU_SLEEP_MASK 0x402c + +/* 0x4068 is compression buffer configuration + * register on 5414 and pm configuration register + * on 5424 and newer pci-e chips. */ + +/* + * Compression buffer configuration + * register (enable/disable) [5414] + */ +#define AR5K_5414_CBCFG 0x4068 +#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */ + +/* + * PCI-E Power managment configuration + * and status register [5424+] + */ +#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */ +/* Only 5424 */ +#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1 + when d2_sleep_en is asserted */ +#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */ +#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */ +#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes + down */ +/* Wake On Wireless */ +#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */ +#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */ +#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */ +#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080 +#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100 +#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200 +#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400 + +/* + * PCI-E Workaround enable register + */ +#define AR5K_PCIE_WAEN 0x407c +/* + * PCI-E Serializer/Desirializer + * registers + */ +#define AR5K_PCIE_SERDES 0x4080 +#define AR5K_PCIE_SERDES_RESET 0x4084 /*====EEPROM REGISTERS====*/ @@ -1006,13 +1081,27 @@ * EEPROM config register */ #define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ -#define AR5K_EEPROM_CFG_SIZE_OVR 0x00000001 +#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ +#define AR5K_EEPROM_CFG_SIZE_AUTO 0 +#define AR5K_EEPROM_CFG_SIZE_4KBIT 1 +#define AR5K_EEPROM_CFG_SIZE_8KBIT 2 +#define AR5K_EEPROM_CFG_SIZE_16KBIT 3 #define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */ #define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */ -#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protectio key */ +#define AR5K_EEPROM_CFG_CLK_RATE_S 3 +#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0 +#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1 +#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2 +#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */ +#define AR5K_EEPROM_CFG_PROT_KEY_S 8 #define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */ +/* + * TODO: Wake On Wireless registers + * Range 0x7000 - 0x7ce0 + */ + /* * Protocol Control Unit (PCU) registers */ @@ -1045,11 +1134,13 @@ #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ #define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ #define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ -#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */ -#define AR5K_STA_ID1_SELF_GEN_SECTORE 0x04000000 /* Self generate sectore (?) */ +#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ +#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ #define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ -#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Keysearch mode (?) */ +#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ #define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */ +#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ +#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ /* * First BSSID register (MAC address, lower 32bits) @@ -1308,16 +1399,16 @@ #define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) -#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 +#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ #define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) -#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 +#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Enable scrambler seed */ -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 +#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */ +#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 #define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) #define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ @@ -1326,12 +1417,15 @@ #define AR5K_DIAG_SW_SCRAM_SEED_S 10 #define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 -#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 +#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) -#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 +#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ #define AR5K_DIAG_SW_OBSPT_S 18 -/* more bits */ +#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ +#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ +#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high (?) */ +#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ /* * TSF (clock) register (lower 32 bits) @@ -1542,16 +1636,16 @@ * * XXX: PCDAC steps (0.5dbm) or DBM ? * - * XXX: Mask changes for newer chips to 7f - * like tx power table ? */ #define AR5K_TXPC 0x80e8 /* Register Address */ -#define AR5K_TXPC_ACK_M 0x0000003f /* Mask for ACK tx power */ +#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */ #define AR5K_TXPC_ACK_S 0 -#define AR5K_TXPC_CTS_M 0x00003f00 /* Mask for CTS tx power */ +#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */ #define AR5K_TXPC_CTS_S 8 -#define AR5K_TXPC_CHIRP_M 0x003f0000 /* Mask for CHIRP tx power */ -#define AR5K_TXPC_CHIRP_S 22 +#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */ +#define AR5K_TXPC_CHIRP_S 16 +#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */ +#define AR5K_TXPC_DOPPLER_S 24 /* * Profile count registers @@ -1562,14 +1656,19 @@ #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ /* - * Quiet (period) control registers (?) + * Quiet period control registers */ #define AR5K_QUIET_CTL1 0x80fc /* Register Address */ -#define AR5K_QUIET_CTL1_NEXT_QT 0x0000ffff /* Mask for next quiet (period?) (?) */ -#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet (period?) */ +#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ +#define AR5K_QUIET_CTL1_NEXT_QT_TSF_0 +#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ +#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ + #define AR5K_QUIET_CTL2 0x8100 /* Register Address */ -#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period (?) */ -#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet duration (?) */ +#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */ +#define AR5K_QUIET_CTL2_QT_PER_S 0 +#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */ +#define AR5K_QUIET_CTL2_QT_DUR_S 16 /* * TSF parameter register @@ -1579,12 +1678,15 @@ #define AR5K_TSF_PARM_INC_S 0 /* - * QoS register (?) + * QoS NOACK policy */ -#define AR5K_QOS 0x8108 /* Register Address */ -#define AR5K_QOS_NOACK_2BIT_VALUES 0x00000000 /* (field) */ -#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000020 /* (field) */ -#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000080 /* (field) */ +#define AR5K_QOS_NOACK 0x8108 /* Register Address */ +#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */ +#define AR5K_QOS_NOACK_2BIT_VALUES_S 0 +#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */ +#define AR5K_QOS_NOACK_BIT_OFFSET_S 4 +#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */ +#define AR5K_QOS_NOACK_BYTE_OFFSET_S 8 /* * PHY error filter register @@ -1608,29 +1710,15 @@ /* * MIC QoS control register (?) */ -#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ -#define AR5K_MIC_QOS_CTL_0 0x00000001 /* MIC QoS control 0 (?) */ -#define AR5K_MIC_QOS_CTL_1 0x00000004 /* MIC QoS control 1 (?) */ -#define AR5K_MIC_QOS_CTL_2 0x00000010 /* MIC QoS control 2 (?) */ -#define AR5K_MIC_QOS_CTL_3 0x00000040 /* MIC QoS control 3 (?) */ -#define AR5K_MIC_QOS_CTL_4 0x00000100 /* MIC QoS control 4 (?) */ -#define AR5K_MIC_QOS_CTL_5 0x00000400 /* MIC QoS control 5 (?) */ -#define AR5K_MIC_QOS_CTL_6 0x00001000 /* MIC QoS control 6 (?) */ -#define AR5K_MIC_QOS_CTL_7 0x00004000 /* MIC QoS control 7 (?) */ -#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ +#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ +#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2)) +#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ /* * MIC QoS select register (?) */ -#define AR5K_MIC_QOS_SEL 0x811c -#define AR5K_MIC_QOS_SEL_0 0x00000001 -#define AR5K_MIC_QOS_SEL_1 0x00000010 -#define AR5K_MIC_QOS_SEL_2 0x00000100 -#define AR5K_MIC_QOS_SEL_3 0x00001000 -#define AR5K_MIC_QOS_SEL_4 0x00010000 -#define AR5K_MIC_QOS_SEL_5 0x00100000 -#define AR5K_MIC_QOS_SEL_6 0x01000000 -#define AR5K_MIC_QOS_SEL_7 0x10000000 +#define AR5K_MIC_QOS_SEL 0x811c +#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4)) /* * Misc mode control register (?) @@ -1664,6 +1752,11 @@ */ #define AR5K_TSF_THRES 0x813c +/* + * TODO: Wake On Wireless registers + * Range: 0x8147 - 0x818c + */ + /* * Rate -> ACK SIFS mapping table (32 entries) */ @@ -1779,7 +1872,8 @@ */ #define AR5K_PHY_TURBO 0x9804 /* Register Address */ #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ -#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Short mode (20Mhz channels) (?) */ +#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ +#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ /* * PHY agility command register @@ -1789,6 +1883,11 @@ #define AR5K_PHY_TST1 0x9808 #define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/ #define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */ +#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */ +#define AR5K_PHY_TST1_TXSRC_SRC_S 1 +#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */ +#define AR5K_PHY_TST1_TXSRC_ALT_S 7 + /* * PHY timing register 3 [5112+] @@ -1813,15 +1912,23 @@ /* * PHY RF control registers - * (i think these are delay times, - * these calibration values exist - * in EEPROM) */ #define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */ -#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* Mask for TX frame to TX d(esc?) start */ +#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */ +#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0 #define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ -#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* Mask for TX end to XLNA on */ +#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* TX end to XLNA on */ +#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 0 + +#define AR5K_PHY_ADC_CTL 0x982c +#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0 +#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000 +#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000 +#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16 #define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */ #define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */ @@ -1843,14 +1950,19 @@ * PHY settling register */ #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ -#define AR5K_PHY_SETTLING_AGC 0x0000007f /* Mask for AGC settling time */ -#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Mask for Switch settlig time */ +#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ +#define AR5K_PHY_SETTLING_AGC_S 0 +#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ +#define AR5K_PHY_SETTLINK_SWITCH_S 7 /* * PHY Gain registers */ #define AR5K_PHY_GAIN 0x9848 /* Register Address */ -#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* Mask for TX-RX Attenuation */ +#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */ +#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12 +#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000 +#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18 #define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */ #define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ @@ -1860,18 +1972,21 @@ * (for more infos read ANI patent) */ #define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ -#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* Mask for ADC desired size */ -#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* Mask for PGA desired size */ -#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Mask for Total desired size */ +#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */ +#define AR5K_PHY_DESIRED_SIZE_ADC_S 0 +#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */ +#define AR5K_PHY_DESIRED_SIZE_PGA_S 8 +#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */ +#define AR5K_PHY_DESIRED_SIZE_TOT_S 20 /* * PHY signal register * (for more infos read ANI patent) */ #define AR5K_PHY_SIG 0x9858 /* Register Address */ -#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* Mask for FIRSTEP */ +#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */ #define AR5K_PHY_SIG_FIRSTEP_S 12 -#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* Mask for FIPWR */ +#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */ #define AR5K_PHY_SIG_FIRPWR_S 18 /* @@ -1879,9 +1994,9 @@ * (for more infos read ANI patent) */ #define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */ -#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* Mask for AGC Coarse low */ +#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */ #define AR5K_PHY_AGCCOARSE_LO_S 7 -#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* Mask for AGC Coarse high */ +#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */ #define AR5K_PHY_AGCCOARSE_HI_S 15 /* @@ -1890,6 +2005,8 @@ #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ +#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ +#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ /* * PHY noise floor status register @@ -1900,7 +2017,10 @@ #define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) #define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) -#define AR5K_PHY_NF_THRESH62 0x00001000 /* Thresh62 -check ANI patent- (field) */ +#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ +#define AR5K_PHY_NF_THRESH62_S 12 +#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ +#define AR5K_PHY_NF_MINCCA_PWR_S 19 /* * PHY ADC saturation register [5110] @@ -1940,24 +2060,31 @@ */ #define AR5K_PHY_SCR 0x9870 #define AR5K_PHY_SCR_32MHZ 0x0000001f + #define AR5K_PHY_SLMT 0x9874 #define AR5K_PHY_SLMT_32MHZ 0x0000007f + #define AR5K_PHY_SCAL 0x9878 #define AR5K_PHY_SCAL_32MHZ 0x0000000e + /* * PHY PLL (Phase Locked Loop) control register */ #define AR5K_PHY_PLL 0x987c -#define AR5K_PHY_PLL_20MHZ 0x13 /* For half rate (?) [5111+] */ -#define AR5K_PHY_PLL_40MHZ_5211 0x18 /* For 802.11a */ +#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */ +/* 40MHz -> 5GHz band */ +#define AR5K_PHY_PLL_40MHZ_5211 0x00000018 #define AR5K_PHY_PLL_40MHZ_5212 0x000000aa +#define AR5K_PHY_PLL_40MHZ_5413 0x00000004 #define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \ AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212) -#define AR5K_PHY_PLL_44MHZ_5211 0x19 /* For 802.11b/g */ +/* 44MHz -> 2.4GHz band */ +#define AR5K_PHY_PLL_44MHZ_5211 0x00000019 #define AR5K_PHY_PLL_44MHZ_5212 0x000000ab #define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) + #define AR5K_PHY_PLL_RF5111 0x00000000 #define AR5K_PHY_PLL_RF5112 0x00000040 #define AR5K_PHY_PLL_HALF_RATE 0x00000100 @@ -2023,6 +2150,19 @@ #define AR5K_PHY_RFSTG 0x98d4 #define AR5K_PHY_RFSTG_DISABLE 0x00000021 +/* + * BIN masks (?) + */ +#define AR5K_PHY_BIN_MASK_1 0x9900 +#define AR5K_PHY_BIN_MASK_2 0x9904 +#define AR5K_PHY_BIN_MASK_3 0x9908 + +#define AR5K_PHY_BIN_MASK_CTL 0x990c +#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff +#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0 +#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000 +#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24 + /* * PHY Antenna control register */ @@ -2070,6 +2210,7 @@ #define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ #define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */ #define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 0 #define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */ #define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */ #define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ @@ -2116,7 +2257,6 @@ #define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */ #define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */ - /* * PHY TX rate power registers [5112+] */ @@ -2138,6 +2278,8 @@ #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 #define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ +#define AR5K_PHY_FRAME_CTL_EMU 0x80000000 +#define AR5K_PHY_FRAME_CTL_EMU_S 31 /*---[5110/5111]---*/ #define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */ #define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */ @@ -2156,48 +2298,36 @@ * PHY radar detection register [5111+] */ #define AR5K_PHY_RADAR 0x9954 - -/* Radar enable ........ ........ ........ .......1 */ #define AR5K_PHY_RADAR_ENABLE 0x00000001 -#define AR5K_PHY_RADAR_DISABLE 0x00000000 -#define AR5K_PHY_RADAR_ENABLE_S 0 - -/* This is the value found on the card .1.111.1 .1.1.... 111....1 1...1... -at power on. */ -#define AR5K_PHY_RADAR_PWONDEF_AR5213 0x5d50e188 - -/* This is the value found on the card .1.1.111 ..11...1 .1...1.1 1...11.1 -after DFS is enabled */ -#define AR5K_PHY_RADAR_ENABLED_AR5213 0x5731458d - -/* Finite Impulse Response (FIR) filter .1111111 ........ ........ ........ - * power out threshold. - * 7-bits, standard power range {0..127} in 1/2 dBm units. */ -#define AR5K_PHY_RADAR_FIRPWROUTTHR 0x7f000000 -#define AR5K_PHY_RADAR_FIRPWROUTTHR_S 24 - -/* Radar RSSI/SNR threshold. ........ 111111.. ........ ........ - * 6-bits, dBm range {0..63} in dBm units. */ -#define AR5K_PHY_RADAR_RADARRSSITHR 0x00fc0000 -#define AR5K_PHY_RADAR_RADARRSSITHR_S 18 - -/* Pulse height threshold ........ ......11 1111.... ........ - * 6-bits, dBm range {0..63} in dBm units. */ -#define AR5K_PHY_RADAR_PULSEHEIGHTTHR 0x0003f000 -#define AR5K_PHY_RADAR_PULSEHEIGHTTHR_S 12 - -/* Pulse RSSI/SNR threshold ........ ........ ....1111 11...... - * 6-bits, dBm range {0..63} in dBm units. */ -#define AR5K_PHY_RADAR_PULSERSSITHR 0x00000fc0 -#define AR5K_PHY_RADAR_PULSERSSITHR_S 6 - -/* Inband threshold ........ ........ ........ ..11111. - * 5-bits, units unknown {0..31} (? MHz ?) */ -#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e +#define AR5K_PHY_RADAR_DISABLE 0x00000000 +#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold + 5-bits, units unknown {0..31} + (? MHz ?) */ #define AR5K_PHY_RADAR_INBANDTHR_S 1 +#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_PRSSI_THR_S 6 + +#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12 + +#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold. + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_RSSI_THR_S 18 + +#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response + filter power out threshold. + 7-bits, standard power range + {0..127} in 1/2 dBm units. */ +#define AR5K_PHY_RADAR_FIRPWR_THRS 24 + /* - * PHY antenna switch table registers [5110] + * PHY antenna switch table registers */ #define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 #define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 @@ -2208,25 +2338,65 @@ after DFS is enabled */ #define AR5K_PHY_NFTHRES 0x9968 /* - * PHY clock sleep registers [5112+] + * Sigma Delta register (?) [5213] */ -#define AR5K_PHY_SCLOCK 0x99f0 -#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c -#define AR5K_PHY_SDELAY 0x99f4 -#define AR5K_PHY_SDELAY_32MHZ 0x000000ff -#define AR5K_PHY_SPENDING 0x99f8 -#define AR5K_PHY_SPENDING_14 0x00000014 -#define AR5K_PHY_SPENDING_18 0x00000018 -#define AR5K_PHY_SPENDING_RF5111 0x00000018 -#define AR5K_PHY_SPENDING_RF5112 0x00000014 -/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */ -/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */ -#define AR5K_PHY_SPENDING_RF5413 0x00000014 -#define AR5K_PHY_SPENDING_RF2413 0x00000014 -#define AR5K_PHY_SPENDING_RF2425 0x00000018 +#define AR5K_PHY_SIGMA_DELTA 0x996C +#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8 +#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00 +#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ff3000 +#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +/* + * RF restart register [5112+] (?) + */ +#define AR5K_PHY_RESTART 0x9970 /* restart */ +#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */ +#define AR5K_PHY_RESTART_DIV_GC_S 18 + +/* + * RF Bus access request register (for synth-oly channel switching) + */ +#define AR5K_PHY_RFBUS_REQ 0x997C +#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001 /* - * Misc PHY/radio registers [5110 - 5111] + * Spur mitigation masks (?) + */ +#define AR5K_PHY_TIMING_7 0x9980 +#define AR5K_PHY_TIMING_8 0x9984 +#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff +#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0 + +#define AR5K_PHY_BIN_MASK2_1 0x9988 +#define AR5K_PHY_BIN_MASK2_2 0x998c +#define AR5K_PHY_BIN_MASK2_3 0x9990 + +#define AR5K_PHY_BIN_MASK2_4 0x9994 +#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff +#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR_PHY_TIMING_9 0x9998 +#define AR_PHY_TIMING_10 0x999c +#define AR_PHY_TIMING_10_PILOT_MASK_2 0x000fffff +#define AR_PHY_TIMING_10_PILOT_MASK_2_S 0 + +/* + * Spur mitigation control + */ +#define AR_PHY_TIMING_11 0x99a0 /* Register address */ +#define AR_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */ +#define AR_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0 +#define AR_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */ +#define AR_PHY_TIMING_11_SPUR_FREQ_SD_S 20 +#define AR_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */ +#define AR_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */ + +/* + * Gain tables */ #define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ #define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) @@ -2246,9 +2416,10 @@ after DFS is enabled */ #define AR5K_PHY_CURRENT_RSSI 0x9c1c /* - * PHY RF Bus grant register (?) + * PHY RF Bus grant register */ #define AR5K_PHY_RFBUS_GRANT 0x9c20 +#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001 /* * PHY ADC test register @@ -2291,6 +2462,31 @@ after DFS is enabled */ #define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004 #define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008 +/* + * Heavy clip enable register + */ +#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0 + +/* + * PHY clock sleep registers [5112+] + */ +#define AR5K_PHY_SCLOCK 0x99f0 +#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c +#define AR5K_PHY_SDELAY 0x99f4 +#define AR5K_PHY_SDELAY_32MHZ 0x000000ff +#define AR5K_PHY_SPENDING 0x99f8 +#define AR5K_PHY_SPENDING_14 0x00000014 +#define AR5K_PHY_SPENDING_18 0x00000018 +#define AR5K_PHY_SPENDING_RF5111 0x00000018 +#define AR5K_PHY_SPENDING_RF5112 0x00000014 +/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */ +/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */ +#define AR5K_PHY_SPENDING_RF5413 0x00000018 +#define AR5K_PHY_SPENDING_RF2413 0x00000018 +#define AR5K_PHY_SPENDING_RF2316 0x00000018 +#define AR5K_PHY_SPENDING_RF2317 0x00000018 +#define AR5K_PHY_SPENDING_RF2425 0x00000014 + /* * PHY PAPD I (power?) table (?) * (92! entries) @@ -2342,10 +2538,47 @@ after DFS is enabled */ #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 +/* Same address is used for antenna diversity activation */ +#define AR5K_PHY_FAST_ANT_DIV 0xa208 +#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000 + /* * PHY 2GHz gain register [5111+] */ -#define AR5K_PHY_GAIN_2GHZ 0xa20c -#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 +#define AR5K_PHY_GAIN_2GHZ 0xa20c +#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 #define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 -#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c +#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c + +#define AR5K_PHY_CCK_RX_CTL_4 0xa21c +#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000 +#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19 + +#define AR5K_PHY_DAG_CCK_CTL 0xa228 +#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200 +#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00 +#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10 + +#define AR5K_PHY_FAST_ADC 0xa24c + +#define AR5K_PHY_BLUETOOTH 0xa254 + +/* + * Transmit Power Control register + * [2413+] + */ +#define AR5K_PHY_TPC_RG1 0xa258 +#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 +#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 + +#define AR5K_PHY_TPC_RG5 0xa26C +#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F +#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22 diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 953ba3b19ff..8f1886834e6 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -543,13 +543,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); if (channel->hw_value == CHANNEL_G) - if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) + if (ah->ah_mac_srev < AR5K_SREV_AR2413) ath5k_hw_reg_write(ah, 0x00f80d80, 0x994c); - else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) + else if (ah->ah_mac_srev < AR5K_SREV_AR5424) ath5k_hw_reg_write(ah, 0x00380140, 0x994c); - else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) + else if (ah->ah_mac_srev < AR5K_SREV_AR2425) ath5k_hw_reg_write(ah, 0x00fc0ec0, 0x994c); else /* 2425 */ @@ -915,7 +915,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_reg_write(ah, 0x000100aa, 0x8118); ath5k_hw_reg_write(ah, 0x00003210, 0x811c); ath5k_hw_reg_write(ah, 0x00000052, 0x8108); - if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413) + if (ah->ah_mac_srev >= AR5K_SREV_AR2413) ath5k_hw_reg_write(ah, 0x00000004, 0x8120); } -- cgit v1.2.3 From 1d280ddcfd6666a45915ccc3a76dee033a6b917b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 29 Sep 2008 14:19:29 -0500 Subject: b43: Increase loop tries in do_dummy_tx One of the spin-on-condition loops in routine do_dummy_tx always exits before the condition is satisfied. The hardware might be left in an inconsistent state that might be the cause of the PHY transmission errors seen by some users. Signed-off-by: Larry Finger Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e5e71220e7d..3bf74e236ab 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -815,7 +815,7 @@ void b43_dummy_transmission(struct b43_wldev *dev) break; udelay(10); } - for (i = 0x00; i < 0x0A; i++) { + for (i = 0x00; i < 0x19; i++) { value = b43_read16(dev, 0x0690); if (!(value & 0x0100)) break; -- cgit v1.2.3 From ee81c5544bbf49ea5b301784a605d865947ac1b0 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 29 Sep 2008 01:18:16 +0300 Subject: ath5k: Use new srevs to properly attach radio chips * Use new SREV values and PHY srevs to identify radio type durring attach Changes-Licensed-under: ISC Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/attach.c | 182 ++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index d92b4a12567..51d569883cd 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c @@ -137,7 +137,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; /* - * Set the mac revision based on the pci id + * Set the mac version based on the pci id */ ah->ah_version = mac_version; @@ -160,87 +160,132 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) 0xffffffff; ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, CHANNEL_5GHZ); + ah->ah_phy = AR5K_PHY(0); - if (ah->ah_version == AR5K_AR5210) - ah->ah_radio_2ghz_revision = 0; - else - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - - /* Return on unsuported chips (unsupported eeprom etc) */ - if ((srev >= AR5K_SREV_AR5416) && - (srev < AR5K_SREV_AR2425)) { - ATH5K_ERR(sc, "Device not yet supported.\n"); - ret = -ENODEV; - goto err_free; - } else if (srev == AR5K_SREV_AR2425) { - ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); - } - - /* Identify single chip solutions */ - if (((srev <= AR5K_SREV_AR5414) && - (srev >= AR5K_SREV_AR2413)) || - (srev == AR5K_SREV_AR2425)) { - ah->ah_single_chip = true; - } else { - ah->ah_single_chip = false; - } - - /* Single chip radio */ - if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision) - ah->ah_radio_2ghz_revision = 0; - - /* Identify the radio chip*/ - if (ah->ah_version == AR5K_AR5210) { - ah->ah_radio = AR5K_RF5110; - /* - * Register returns 0x0/0x04 for radio revision - * so ath5k_hw_radio_revision doesn't parse the value - * correctly. For now we are based on mac's srev to - * identify RF2425 radio. - */ - } else if (srev == AR5K_SREV_AR2425) { - ah->ah_radio = AR5K_RF2425; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { + /* Try to identify radio chip based on it's srev */ + switch (ah->ah_radio_5ghz_revision & 0xf0) { + case AR5K_SREV_RAD_5111: ah->ah_radio = AR5K_RF5111; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_2413) { + break; + case AR5K_SREV_RAD_5112: + case AR5K_SREV_RAD_2112: ah->ah_radio = AR5K_RF5112; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5413) { + break; + case AR5K_SREV_RAD_2413: ah->ah_radio = AR5K_RF2413; + ah->ah_single_chip = true; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_2316) { + break; + case AR5K_SREV_RAD_5413: ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { - /* AR5424 */ - if (srev >= AR5K_SREV_AR5424) { + break; + case AR5K_SREV_RAD_2316: + ah->ah_radio = AR5K_RF2316; + ah->ah_single_chip = true; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316; + break; + case AR5K_SREV_RAD_2317: + ah->ah_radio = AR5K_RF2317; + ah->ah_single_chip = true; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2317; + break; + case AR5K_SREV_RAD_5424: + if (ah->ah_mac_version == AR5K_SREV_AR2425 || + ah->ah_mac_version == AR5K_SREV_AR2417){ + ah->ah_radio = AR5K_RF2425; + ah->ah_single_chip = true; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; + } else { ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; - /* AR2424 */ - } else { - ah->ah_radio = AR5K_RF2413; /* For testing */ + } + break; + default: + /* Identify radio based on mac/phy srev */ + if (ah->ah_version == AR5K_AR5210) { + ah->ah_radio = AR5K_RF5110; + ah->ah_single_chip = false; + } else if (ah->ah_version == AR5K_AR5211) { + ah->ah_radio = AR5K_RF5111; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); + } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || + ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_2425) { + ah->ah_radio = AR5K_RF2425; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; + } else if (srev == AR5K_SREV_AR5213A && + ah->ah_phy_revision == AR5K_SREV_PHY_2112B) { + ah->ah_radio = AR5K_RF5112; + ah->ah_single_chip = false; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2112B; + } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) { + ah->ah_radio = AR5K_RF2316; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2316; + } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_5413) { + ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; + } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_2413) { + ah->ah_radio = AR5K_RF2413; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; + } else { + ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); + ret = -ENODEV; + goto err_free; } } - ah->ah_phy = AR5K_PHY(0); + + + /* Return on unsuported chips (unsupported eeprom etc) */ + if ((srev >= AR5K_SREV_AR5416) && + (srev < AR5K_SREV_AR2425)) { + ATH5K_ERR(sc, "Device not yet supported.\n"); + ret = -ENODEV; + goto err_free; + } /* * Write PCI-E power save settings */ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { - ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); - ath5k_hw_reg_write(ah, 0x24924924, 0x4080); - ath5k_hw_reg_write(ah, 0x28000039, 0x4080); - ath5k_hw_reg_write(ah, 0x53160824, 0x4080); - ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); - ath5k_hw_reg_write(ah, 0x001defff, 0x4080); - ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); - ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); - ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); - ath5k_hw_reg_write(ah, 0x00000000, 0x4084); + ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); + /* Shut off RX when elecidle is asserted */ + ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); + /* TODO: EEPROM work */ + ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); + /* Shut off PLL and CLKREQ active in L1 */ + ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); + /* Preserce other settings */ + ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); + /* Reset SERDES to load new settings */ + ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); + mdelay(1); } /* @@ -250,14 +295,13 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) if (ret) goto err_free; - /* Write AR5K_PCICFG_UNK on 2112B and later chips */ - if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || - srev > AR5K_SREV_AR2413) { + /* Enable pci core retry fix on Hainan (5213A) and later chips */ + if (srev >= AR5K_SREV_AR5213A) ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); - } /* - * Get card capabilities, values, ... + * Get card capabilities, calibration values etc + * TODO: EEPROM work */ ret = ath5k_eeprom_init(ah); if (ret) { @@ -273,7 +317,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) goto err_free; } - /* Get MAC address */ + /* Set MAC address */ ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", -- cgit v1.2.3 From 509a106e68aa42acc1a0c44ab365d0de6869bd9e Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 29 Sep 2008 01:23:07 +0300 Subject: ath5k: Use QUIET mechanism on tx dma stop * Use QUIET mechanism to drain tx buffer on PCU for newer chips * Make sure that INTPEND is really 1 and not 0xffffffff while checking for pending interrupts Changes-Licensed-under: ISC Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/dma.c | 49 ++++++++++++++++++++++++++++++++++++---- drivers/net/wireless/ath5k/reg.h | 4 ++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c index a28090be960..7adceb2c7fa 100644 --- a/drivers/net/wireless/ath5k/dma.c +++ b/drivers/net/wireless/ath5k/dma.c @@ -68,7 +68,7 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) /* * It may take some time to disable the DMA receive unit */ - for (i = 2000; i > 0 && + for (i = 1000; i > 0 && (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; i--) udelay(10); @@ -182,11 +182,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) * have any pending frames. Returns -EBUSY if we still have pending frames, * -EINVAL if queue number is out of range. * - * TODO: Test queue drain code */ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) { - unsigned int i = 100; + unsigned int i = 40; u32 tx_queue, pending; ATH5K_TRACE(ah->ah_sc); @@ -233,13 +232,53 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) udelay(100); } while (--i && pending); + /* For 2413+ order PCU to drop packets using + * QUIET mechanism */ + if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && + pending){ + /* Set periodicity and duration */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| + AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), + AR5K_QUIET_CTL2); + + /* Enable quiet period for current TSF */ + ath5k_hw_reg_write(ah, + AR5K_QUIET_CTL1_QT_EN | + AR5K_REG_SM(ath5k_hw_reg_read(ah, + AR5K_TSF_L32_5211) >> 10, + AR5K_QUIET_CTL1_NEXT_QT_TSF), + AR5K_QUIET_CTL1); + + /* Force channel idle high */ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, + AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + + /* Wait a while and disable mechanism */ + udelay(200); + AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, + AR5K_QUIET_CTL1_QT_EN); + + /* Re-check for pending frames */ + i = 40; + do { + pending = ath5k_hw_reg_read(ah, + AR5K_QUEUE_STATUS(queue)) & + AR5K_QCU_STS_FRMPENDCNT; + udelay(100); + } while (--i && pending); + + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, + AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + } + /* Clear register */ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); if (pending) return -EBUSY; } - /* TODO: Check for success else return error */ + /* TODO: Check for success on 5210 else return error */ return 0; } @@ -415,7 +454,7 @@ done: bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_INTPEND); + return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; } /** diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 55054b575e8..e557fe178bb 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -1424,7 +1424,7 @@ #define AR5K_DIAG_SW_OBSPT_S 18 #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ -#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high (?) */ +#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ #define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ /* @@ -1660,7 +1660,7 @@ */ #define AR5K_QUIET_CTL1 0x80fc /* Register Address */ #define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ -#define AR5K_QUIET_CTL1_NEXT_QT_TSF_0 +#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0 #define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ #define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ -- cgit v1.2.3 From 75d0edb82269a1bcf83d32b1d77ab94a5e3ed8af Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 29 Sep 2008 01:24:44 +0300 Subject: ath5k: Fix SREV reporting after SREV updates * Fix srev reporting during attach Changes-Licensed-under: ISC Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index c8bb9bfb51f..3b784358a7c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -396,7 +396,11 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) for (i = 0; i < ARRAY_SIZE(srev_names); i++) { if (srev_names[i].sr_type != type) continue; - if ((val & 0xff) < srev_names[i + 1].sr_val) { + + if ((val & 0xf0) == srev_names[i].sr_val) + name = srev_names[i].sr_name; + + if ((val & 0xff) == srev_names[i].sr_val) { name = srev_names[i].sr_name; break; } -- cgit v1.2.3 From 0d5f0316593df606515b17b037a1fd36c4b8bfdf Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 29 Sep 2008 01:27:27 +0300 Subject: ath5k: Add support for AR2417 v2 * Add support for AR2417 (include pci id) since my previous patch doesn't sit on top of base.c/ath5k.h anymore. * Update module version to 0.6.0 Changes-Licensed-under: ISC Signed-Off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 3b784358a7c..c151588aa48 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -72,7 +72,7 @@ MODULE_AUTHOR("Nick Kossifidis"); MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.5.0 (EXPERIMENTAL)"); +MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); /* Known PCI ids */ @@ -93,7 +93,8 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/ + { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */ { 0 } }; MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); -- cgit v1.2.3 From 6e50e8a2136f1a90de251c653226ded447c5c915 Mon Sep 17 00:00:00 2001 From: Remi Denis-Courmont Date: Wed, 1 Oct 2008 01:30:19 -0700 Subject: phonet: Protect if_phonet.h against multiple inclusions. From: Remi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/if_phonet.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h index 7e989216ec1..d70034bcec0 100644 --- a/include/linux/if_phonet.h +++ b/include/linux/if_phonet.h @@ -5,14 +5,15 @@ * * Copyright (C) 2008 Nokia Corporation. All rights reserved. */ +#ifndef LINUX_IF_PHONET_H +#define LINUX_IF_PHONET_H -#define PHONET_HEADER_LEN 8 /* Phonet header length */ - -#define PHONET_MIN_MTU 6 -/* 6 bytes header + 65535 bytes payload */ -#define PHONET_MAX_MTU 65541 +#define PHONET_MIN_MTU 6 /* pn_length = 0 */ +#define PHONET_MAX_MTU 65541 /* pn_length = 0xffff */ #define PHONET_DEV_MTU PHONET_MAX_MTU #ifdef __KERNEL__ extern struct header_ops phonet_header_ops; #endif + +#endif -- cgit v1.2.3 From 4dd7972d1204c3851a4092cecd2207e05eb29b09 Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Wed, 1 Oct 2008 01:51:39 -0700 Subject: tcp: Fix NULL dereference in tcp_4_send_ack() Fix NULL dereference in tcp_4_send_ack(). As skb->dev is reset to NULL in tcp_v4_rcv() thus OOPS occurs: BUG: unable to handle kernel NULL pointer dereference at 00000000000004d0 IP: [] tcp_v4_send_ack+0x203/0x250 Stack: ffff810005dbb000 ffff810015c8acc0 e77b2c6e5f861600 a01610802e90cb6d 0a08010100000000 88afffff88afffff 0000000080762be8 0000000115c872e8 0004122000000000 0000000000000001 ffffffff80762b88 0000000000000020 Call Trace: [] tcp_v4_reqsk_send_ack+0x20/0x22 [] tcp_check_req+0x108/0x14c [] ? rt_intern_hash+0x322/0x33c [] tcp_v4_do_rcv+0x399/0x4ec [] ? skb_checksum+0x4f/0x272 [] ? __inet_lookup_listener+0x14a/0x15c [] tcp_v4_rcv+0x6a1/0x701 [] ip_local_deliver_finish+0x157/0x24a [] ip_local_deliver+0x72/0x7c [] ip_rcv_finish+0x38d/0x3b2 [] ? scsi_io_completion+0x19d/0x39e [] ip_rcv+0x2a2/0x2e5 [] netif_receive_skb+0x293/0x303 [] process_backlog+0x80/0xd0 [] ? __rcu_process_callbacks+0x125/0x1b4 [] net_rx_action+0xb9/0x17f [] __do_softirq+0xa3/0x164 [] call_softirq+0x1c/0x28 [] do_softirq+0x34/0x72 [] local_bh_enable_ip+0x3f/0x50 [] _spin_unlock_bh+0x12/0x14 [] release_sock+0xb8/0xc1 [] inet_stream_connect+0x146/0x25c [] ? autoremove_wake_function+0x0/0x38 [] sys_connect+0x68/0x8e [] ? fd_install+0x5f/0x68 [] ? sock_map_fd+0x55/0x62 [] system_call_after_swapgs+0x7b/0x80 Code: 41 10 11 d0 83 d0 00 4d 85 ed 89 45 c0 c7 45 c4 08 00 00 00 74 07 41 8b 45 04 89 45 c8 48 8b 43 20 8b 4d b8 48 8d 55 b0 48 89 de <48> 8b 80 d0 04 00 00 48 8b b8 60 01 00 00 e8 20 ae fe ff 65 48 RIP [] tcp_v4_send_ack+0x203/0x250 RSP CR2: 00000000000004d0 Signed-off-by: Vitaliy Gusev Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1b4fee20fc9..011478e46c4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -618,7 +618,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, ]; } rep; struct ip_reply_arg arg; - struct net *net = dev_net(skb->dev); + struct net *net = dev_net(skb->dst->dev); memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&arg, 0, sizeof(arg)); -- cgit v1.2.3 From 2a5b82751f73a0bf6f604ce56d34adba6da1b246 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 1 Oct 2008 02:13:16 -0700 Subject: ipv6: NULL pointer dereferrence in tcp_v6_send_ack The following actions are possible: tcp_v6_rcv skb->dev = NULL; tcp_v6_do_rcv tcp_v6_hnd_req tcp_check_req req->rsk_ops->send_ack == tcp_v6_send_ack So, skb->dev can be NULL in tcp_v6_send_ack. We must obtain namespace from dst entry. Thanks to Vitaliy Gusev for initial problem finding in IPv4 code. Signed-off-by: Denis V. Lunev Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b585c850a89..10e22fd4822 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 struct tcphdr *th = tcp_hdr(skb), *t1; struct sk_buff *buff; struct flowi fl; - struct net *net = dev_net(skb->dev); + struct net *net = dev_net(skb->dst->dev); struct sock *ctl_sk = net->ipv6.tcp_sk; unsigned int tot_len = sizeof(struct tcphdr); __be32 *topt; -- cgit v1.2.3 From 04a4bb55bcf35b63d40fd2725e58599ff8310dd7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 1 Oct 2008 02:33:12 -0700 Subject: net: add skb_recycle_check() to enable netdriver skb recycling This patch adds skb_recycle_check(), which can be used by a network driver after transmitting an skb to check whether this skb can be recycled as a receive buffer. skb_recycle_check() checks that the skb is not shared or cloned, and that it is linear and its head portion large enough (as determined by the driver) to be recycled as a receive buffer. If these conditions are met, it does any necessary reference count dropping and cleans up the skbuff as if it just came from __alloc_skb(). Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 ++ net/core/skbuff.c | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a19ea43fea0..720b688c22b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -383,6 +383,8 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, 1, -1); } +extern int skb_recycle_check(struct sk_buff *skb, int skb_size); + extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); extern struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ca1ccdf1ef7..2c218a0808b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -363,8 +363,7 @@ static void kfree_skbmem(struct sk_buff *skb) } } -/* Free everything but the sk_buff shell. */ -static void skb_release_all(struct sk_buff *skb) +static void skb_release_head_state(struct sk_buff *skb) { dst_release(skb->dst); #ifdef CONFIG_XFRM @@ -388,6 +387,12 @@ static void skb_release_all(struct sk_buff *skb) skb->tc_verd = 0; #endif #endif +} + +/* Free everything but the sk_buff shell. */ +static void skb_release_all(struct sk_buff *skb) +{ + skb_release_head_state(skb); skb_release_data(skb); } @@ -424,6 +429,38 @@ void kfree_skb(struct sk_buff *skb) __kfree_skb(skb); } +int skb_recycle_check(struct sk_buff *skb, int skb_size) +{ + struct skb_shared_info *shinfo; + + if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) + return 0; + + skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); + if (skb_end_pointer(skb) - skb->head < skb_size) + return 0; + + if (skb_shared(skb) || skb_cloned(skb)) + return 0; + + skb_release_head_state(skb); + shinfo = skb_shinfo(skb); + atomic_set(&shinfo->dataref, 1); + shinfo->nr_frags = 0; + shinfo->gso_size = 0; + shinfo->gso_segs = 0; + shinfo->gso_type = 0; + shinfo->ip6_frag_id = 0; + shinfo->frag_list = NULL; + + memset(skb, 0, offsetof(struct sk_buff, tail)); + skb_reset_tail_pointer(skb); + skb->data = skb->head + NET_SKB_PAD; + + return 1; +} +EXPORT_SYMBOL(skb_recycle_check); + static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) { new->tstamp = old->tstamp; -- cgit v1.2.3 From 2bcb4b0f111053d0e8fb4366f0708395d997e93a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 1 Oct 2008 02:33:57 -0700 Subject: mv643xx_eth: hook up skb recycling This gives a nice increase in the maximum loss-free packet forwarding rate in routing workloads. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 66 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 55aa8ba7e0f..372811ade9f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -370,6 +370,9 @@ struct mv643xx_eth_private { u8 work_rx_refill; u8 work_rx_oom; + int skb_size; + struct sk_buff_head rx_recycle; + /* * RX state. */ @@ -566,31 +569,19 @@ static int rxq_process(struct rx_queue *rxq, int budget) static int rxq_refill(struct rx_queue *rxq, int budget) { struct mv643xx_eth_private *mp = rxq_to_mp(rxq); - int skb_size; int refilled; - /* - * Reserve 2+14 bytes for an ethernet header (the hardware - * automatically prepends 2 bytes of dummy data to each - * received packet), 16 bytes for up to four VLAN tags, and - * 4 bytes for the trailing FCS -- 36 bytes total. - */ - skb_size = rxq_to_mp(rxq)->dev->mtu + 36; - - /* - * Make sure that the skb size is a multiple of 8 bytes, as - * the lower three bits of the receive descriptor's buffer - * size field are ignored by the hardware. - */ - skb_size = (skb_size + 7) & ~7; - refilled = 0; while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { struct sk_buff *skb; int unaligned; int rx; - skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1); + skb = __skb_dequeue(&mp->rx_recycle); + if (skb == NULL) + skb = dev_alloc_skb(mp->skb_size + + dma_get_cache_alignment() - 1); + if (skb == NULL) { mp->work_rx_oom |= 1 << rxq->index; goto oom; @@ -608,8 +599,8 @@ static int rxq_refill(struct rx_queue *rxq, int budget) rxq->rx_used_desc = 0; rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data, - skb_size, DMA_FROM_DEVICE); - rxq->rx_desc_area[rx].buf_size = skb_size; + mp->skb_size, DMA_FROM_DEVICE); + rxq->rx_desc_area[rx].buf_size = mp->skb_size; rxq->rx_skb[rx] = skb; wmb(); rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA | @@ -904,8 +895,14 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) desc->byte_cnt, DMA_TO_DEVICE); } - if (skb) - dev_kfree_skb(skb); + if (skb != NULL) { + if (skb_queue_len(&mp->rx_recycle) < + mp->default_rx_ring_size && + skb_recycle_check(skb, mp->skb_size)) + __skb_queue_head(&mp->rx_recycle, skb); + else + dev_kfree_skb(skb); + } } __netif_tx_unlock(nq); @@ -2042,6 +2039,26 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay) wrl(mp, TX_FIFO_URGENT_THRESHOLD(mp->port_num), (coal & 0x3fff) << 4); } +static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) +{ + int skb_size; + + /* + * Reserve 2+14 bytes for an ethernet header (the hardware + * automatically prepends 2 bytes of dummy data to each + * received packet), 16 bytes for up to four VLAN tags, and + * 4 bytes for the trailing FCS -- 36 bytes total. + */ + skb_size = mp->dev->mtu + 36; + + /* + * Make sure that the skb size is a multiple of 8 bytes, as + * the lower three bits of the receive descriptor's buffer + * size field are ignored by the hardware. + */ + mp->skb_size = (skb_size + 7) & ~7; +} + static int mv643xx_eth_open(struct net_device *dev) { struct mv643xx_eth_private *mp = netdev_priv(dev); @@ -2061,8 +2078,12 @@ static int mv643xx_eth_open(struct net_device *dev) init_mac_tables(mp); + mv643xx_eth_recalc_skb_size(mp); + napi_enable(&mp->napi); + skb_queue_head_init(&mp->rx_recycle); + for (i = 0; i < mp->rxq_count; i++) { err = rxq_init(mp, i); if (err) { @@ -2158,6 +2179,8 @@ static int mv643xx_eth_stop(struct net_device *dev) mv643xx_eth_get_stats(dev); mib_counters_update(mp); + skb_queue_purge(&mp->rx_recycle); + for (i = 0; i < mp->rxq_count; i++) rxq_deinit(mp->rxq + i); for (i = 0; i < mp->txq_count; i++) @@ -2184,6 +2207,7 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; dev->mtu = new_mtu; + mv643xx_eth_recalc_skb_size(mp); tx_set_rate(mp, 1000000000, 16777216); if (!netif_running(dev)) -- cgit v1.2.3 From 5dc121e9a7a8a3721cefeb07f3559f50fbedc67e Mon Sep 17 00:00:00 2001 From: Arnaud Ebalard Date: Wed, 1 Oct 2008 02:37:56 -0700 Subject: XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep ip6_dst_blackhole_ops.kmem_cachep is not expected to be NULL (i.e. to be initialized) when dst_alloc() is called from ip6_dst_blackhole(). Otherwise, it results in the following (xfrm_larval_drop is now set to 1 by default): [ 78.697642] Unable to handle kernel paging request for data at address 0x0000004c [ 78.703449] Faulting instruction address: 0xc0097f54 [ 78.786896] Oops: Kernel access of bad area, sig: 11 [#1] [ 78.792791] PowerMac [ 78.798383] Modules linked in: btusb usbhid bluetooth b43 mac80211 cfg80211 ehci_hcd ohci_hcd sungem sungem_phy usbcore ssb [ 78.804263] NIP: c0097f54 LR: c0334a28 CTR: c002d430 [ 78.809997] REGS: eef19ad0 TRAP: 0300 Not tainted (2.6.27-rc5) [ 78.815743] MSR: 00001032 CR: 22242482 XER: 20000000 [ 78.821550] DAR: 0000004c, DSISR: 40000000 [ 78.827278] TASK = eef0df40[3035] 'mip6d' THREAD: eef18000 [ 78.827408] GPR00: 00001032 eef19b80 eef0df40 00000000 00008020 eef19c30 00000001 00000000 [ 78.833249] GPR08: eee5101c c05a5c10 ef9ad500 00000000 24242422 1005787c 00000000 1004f960 [ 78.839151] GPR16: 00000000 10024e90 10050040 48030018 0fe44150 00000000 00000000 eef19c30 [ 78.845046] GPR24: eef19e44 00000000 eef19bf8 efb37c14 eef19bf8 00008020 00009032 c0596064 [ 78.856671] NIP [c0097f54] kmem_cache_alloc+0x20/0x94 [ 78.862581] LR [c0334a28] dst_alloc+0x40/0xc4 [ 78.868451] Call Trace: [ 78.874252] [eef19b80] [c03c1810] ip6_dst_lookup_tail+0x1c8/0x1dc (unreliable) [ 78.880222] [eef19ba0] [c0334a28] dst_alloc+0x40/0xc4 [ 78.886164] [eef19bb0] [c03cd698] ip6_dst_blackhole+0x28/0x1cc [ 78.892090] [eef19be0] [c03d9be8] rawv6_sendmsg+0x75c/0xc88 [ 78.897999] [eef19cb0] [c038bca4] inet_sendmsg+0x4c/0x78 [ 78.903907] [eef19cd0] [c03207c8] sock_sendmsg+0xac/0xe4 [ 78.909734] [eef19db0] [c03209e4] sys_sendmsg+0x1e4/0x2a0 [ 78.915540] [eef19f00] [c03220a8] sys_socketcall+0xfc/0x210 [ 78.921406] [eef19f40] [c0014b3c] ret_from_syscall+0x0/0x38 [ 78.927295] --- Exception: c01 at 0xfe2d730 [ 78.927297] LR = 0xfe2d71c [ 78.939019] Instruction dump: [ 78.944835] 91640018 9144001c 900a0000 4bffff44 9421ffe0 7c0802a6 bf810010 7c9d2378 [ 78.950694] 90010024 7fc000a6 57c0045e 7c000124 <83e3004c> 8383005c 2f9f0000 419e0050 [ 78.956464] ---[ end trace 05fa1ed7972487a1 ]--- As commented by Benjamin Thery, the bug was introduced by f2fc6a54585a1be6669613a31fbaba2ecbadcd36, while adding network namespaces support to ipv6 routes. Signed-off-by: Arnaud Ebalard Acked-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/route.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9af6115f0f5..63442a1e741 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2688,6 +2688,8 @@ int __init ip6_route_init(void) if (ret) goto out_kmem_cache; + ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; + /* Registering of the loopback is done before this portion of code, * the loopback reference in rt6_info will not be taken, do it * manually for init_net */ -- cgit v1.2.3 From 93c8b90f01f0dc73891da4e84b26524b61d29d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Wed, 1 Oct 2008 02:48:31 -0700 Subject: ipv6: almost identical frag hashing funcs combined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit $ diff-funcs ip6qhashfn reassembly.c netfilter/nf_conntrack_reasm.c --- reassembly.c:ip6qhashfn() +++ netfilter/nf_conntrack_reasm.c:ip6qhashfn() @@ -1,5 +1,5 @@ -static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, - struct in6_addr *daddr) +static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr, + const struct in6_addr *daddr) { u32 a, b, c; @@ -9,7 +9,7 @@ a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; - c += ip6_frags.rnd; + c += nf_frags.rnd; __jhash_mix(a, b, c); a += (__force u32)saddr->s6_addr32[3]; And codiff xx.o.old xx.o.new: net/ipv6/netfilter/nf_conntrack_reasm.c: ip6qhashfn | -512 nf_hashfn | +6 nf_ct_frag6_gather | +36 3 functions changed, 42 bytes added, 512 bytes removed, diff: -470 net/ipv6/reassembly.c: ip6qhashfn | -512 ip6_hashfn | +7 ipv6_frag_rcv | +89 3 functions changed, 96 bytes added, 512 bytes removed, diff: -416 net/ipv6/reassembly.c: inet6_hash_frag | +510 1 function changed, 510 bytes added, diff: +510 Total: -376 Compile tested. Signed-off-by: Ilpo Järvinen Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/ipv6.h | 2 ++ net/ipv6/netfilter/nf_conntrack_reasm.c | 32 ++------------------------------ net/ipv6/reassembly.c | 11 ++++++----- 3 files changed, 10 insertions(+), 35 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 113028fb8f6..dfa7ae3c560 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -576,6 +576,8 @@ extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, struct group_filter __user *optval, int __user *optlen); +extern unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, + const struct in6_addr *daddr, u32 rnd); #ifdef CONFIG_PROC_FS extern int ac6_proc_init(struct net *net); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 52d06dd4b81..9967ac7a01a 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -103,39 +102,12 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = { }; #endif -static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr, - const struct in6_addr *daddr) -{ - u32 a, b, c; - - a = (__force u32)saddr->s6_addr32[0]; - b = (__force u32)saddr->s6_addr32[1]; - c = (__force u32)saddr->s6_addr32[2]; - - a += JHASH_GOLDEN_RATIO; - b += JHASH_GOLDEN_RATIO; - c += nf_frags.rnd; - __jhash_mix(a, b, c); - - a += (__force u32)saddr->s6_addr32[3]; - b += (__force u32)daddr->s6_addr32[0]; - c += (__force u32)daddr->s6_addr32[1]; - __jhash_mix(a, b, c); - - a += (__force u32)daddr->s6_addr32[2]; - b += (__force u32)daddr->s6_addr32[3]; - c += (__force u32)id; - __jhash_mix(a, b, c); - - return c & (INETFRAGS_HASHSZ - 1); -} - static unsigned int nf_hashfn(struct inet_frag_queue *q) { const struct nf_ct_frag6_queue *nq; nq = container_of(q, struct nf_ct_frag6_queue, q); - return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr); + return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); } static void nf_skb_free(struct sk_buff *skb) @@ -209,7 +181,7 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) arg.dst = dst; read_lock_bh(&nf_frags.lock); - hash = ip6qhashfn(id, src, dst); + hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); local_bh_enable(); diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 89184b576e2..2eeadfa039c 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -99,8 +99,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, * callers should be careful not to use the hash value outside the ipfrag_lock * as doing so could race with ipfrag_hash_rnd being recalculated. */ -static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, - struct in6_addr *daddr) +unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, + const struct in6_addr *daddr, u32 rnd) { u32 a, b, c; @@ -110,7 +110,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; - c += ip6_frags.rnd; + c += rnd; __jhash_mix(a, b, c); a += (__force u32)saddr->s6_addr32[3]; @@ -125,13 +125,14 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, return c & (INETFRAGS_HASHSZ - 1); } +EXPORT_SYMBOL_GPL(inet6_hash_frag); static unsigned int ip6_hashfn(struct inet_frag_queue *q) { struct frag_queue *fq; fq = container_of(q, struct frag_queue, q); - return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr); + return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd); } int ip6_frag_match(struct inet_frag_queue *q, void *a) @@ -247,7 +248,7 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, arg.dst = dst; read_lock(&ip6_frags.lock); - hash = ip6qhashfn(id, src, dst); + hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); if (q == NULL) -- cgit v1.2.3 From 0523820482dcb42784572ffd2296c2f08c275a2b Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Wed, 1 Oct 2008 05:17:54 -0700 Subject: af_key: Free dumping state on socket close Fix a xfrm_{state,policy}_walk leak if pfkey socket is closed while dumping is on-going. Signed-off-by: Timo Teras Signed-off-by: David S. Miller --- net/key/af_key.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index d628df97e02..b7f5a1c353e 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk) return 0; } -static int pfkey_do_dump(struct pfkey_sock *pfk) +static void pfkey_terminate_dump(struct pfkey_sock *pfk) { - int rc; - - rc = pfk->dump.dump(pfk); - if (rc == -ENOBUFS) - return 0; - - pfk->dump.done(pfk); - pfk->dump.dump = NULL; - pfk->dump.done = NULL; - return rc; + if (pfk->dump.dump) { + pfk->dump.done(pfk); + pfk->dump.dump = NULL; + pfk->dump.done = NULL; + } } static void pfkey_sock_destruct(struct sock *sk) { + pfkey_terminate_dump(pfkey_sk(sk)); skb_queue_purge(&sk->sk_receive_queue); if (!sock_flag(sk, SOCK_DEAD)) { @@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, return err; } +static int pfkey_do_dump(struct pfkey_sock *pfk) +{ + int rc; + + rc = pfk->dump.dump(pfk); + if (rc == -ENOBUFS) + return 0; + + pfkey_terminate_dump(pfk); + return rc; +} + static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) { *new = *orig; -- cgit v1.2.3 From 12a169e7d8f4b1c95252d8b04ed0f1033ed7cfe2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 1 Oct 2008 07:03:24 -0700 Subject: ipsec: Put dumpers on the dump list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Herbert Xu came up with the idea and the original patch to make xfrm_state dump list contain also dumpers: As it is we go to extraordinary lengths to ensure that states don't go away while dumpers go to sleep. It's much easier if we just put the dumpers themselves on the list since they can't go away while they're going. I've also changed the order of addition on new states to prevent a never-ending dump. Timo Teräs improved the patch to apply cleanly to latest tree, modified iteration code to be more readable by using a common struct for entries in the list, implemented the same idea for xfrm_policy dumping and moved the af_key specific "last" entry caching to af_key. Signed-off-by: Herbert Xu Signed-off-by: Timo Teras Signed-off-by: David S. Miller --- include/linux/netlink.h | 2 +- include/net/xfrm.h | 70 ++++++++++++------------------ net/key/af_key.c | 38 ++++++++++++++--- net/xfrm/xfrm_policy.c | 111 +++++++++++++++++++++++++----------------------- net/xfrm/xfrm_state.c | 109 ++++++++++++++++------------------------------- net/xfrm/xfrm_user.c | 4 +- 6 files changed, 159 insertions(+), 175 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index cbba7760545..9ff1b54908f 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -220,7 +220,7 @@ struct netlink_callback int (*dump)(struct sk_buff * skb, struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); int family; - long args[7]; + long args[6]; }; struct netlink_notify diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 48630b26659..b98d2056f27 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -117,12 +117,21 @@ extern struct mutex xfrm_cfg_mutex; metrics. Plus, it will be made via sk->sk_dst_cache. Solved. */ +struct xfrm_state_walk { + struct list_head all; + u8 state; + union { + u8 dying; + u8 proto; + }; + u32 seq; +}; + /* Full description of state of transformer. */ struct xfrm_state { - struct list_head all; union { - struct list_head gclist; + struct hlist_node gclist; struct hlist_node bydst; }; struct hlist_node bysrc; @@ -136,12 +145,8 @@ struct xfrm_state u32 genid; - /* Key manger bits */ - struct { - u8 state; - u8 dying; - u32 seq; - } km; + /* Key manager bits */ + struct xfrm_state_walk km; /* Parameters of this state. */ struct { @@ -449,10 +454,20 @@ struct xfrm_tmpl #define XFRM_MAX_DEPTH 6 +struct xfrm_policy_walk_entry { + struct list_head all; + u8 dead; +}; + +struct xfrm_policy_walk { + struct xfrm_policy_walk_entry walk; + u8 type; + u32 seq; +}; + struct xfrm_policy { struct xfrm_policy *next; - struct list_head bytype; struct hlist_node bydst; struct hlist_node byidx; @@ -467,13 +482,12 @@ struct xfrm_policy struct xfrm_lifetime_cfg lft; struct xfrm_lifetime_cur curlft; struct dst_entry *bundles; - u16 family; + struct xfrm_policy_walk_entry walk; u8 type; u8 action; u8 flags; - u8 dead; u8 xfrm_nr; - /* XXX 1 byte hole, try to pack */ + u16 family; struct xfrm_sec_ctx *security; struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; }; @@ -1245,20 +1259,6 @@ struct xfrm6_tunnel { int priority; }; -struct xfrm_state_walk { - struct list_head list; - unsigned long genid; - struct xfrm_state *state; - int count; - u8 proto; -}; - -struct xfrm_policy_walk { - struct xfrm_policy *policy; - int count; - u8 type, cur_type; -}; - extern void xfrm_init(void); extern void xfrm4_init(void); extern void xfrm_state_init(void); @@ -1410,24 +1410,10 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); -static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type) -{ - walk->cur_type = XFRM_POLICY_TYPE_MAIN; - walk->type = type; - walk->policy = NULL; - walk->count = 0; -} - -static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk) -{ - if (walk->policy != NULL) { - xfrm_pol_put(walk->policy); - walk->policy = NULL; - } -} - +extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type); extern int xfrm_policy_walk(struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *); +extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_selector *sel, diff --git a/net/key/af_key.c b/net/key/af_key.c index b7f5a1c353e..7ae641df70b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -58,6 +58,7 @@ struct pfkey_sock { struct xfrm_policy_walk policy; struct xfrm_state_walk state; } u; + struct sk_buff *skb; } dump; }; @@ -76,6 +77,10 @@ static int pfkey_can_dump(struct sock *sk) static void pfkey_terminate_dump(struct pfkey_sock *pfk) { if (pfk->dump.dump) { + if (pfk->dump.skb) { + kfree_skb(pfk->dump.skb); + pfk->dump.skb = NULL; + } pfk->dump.done(pfk); pfk->dump.dump = NULL; pfk->dump.done = NULL; @@ -308,12 +313,25 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, static int pfkey_do_dump(struct pfkey_sock *pfk) { + struct sadb_msg *hdr; int rc; rc = pfk->dump.dump(pfk); if (rc == -ENOBUFS) return 0; + if (pfk->dump.skb) { + if (!pfkey_can_dump(&pfk->sk)) + return 0; + + hdr = (struct sadb_msg *) pfk->dump.skb->data; + hdr->sadb_msg_seq = 0; + hdr->sadb_msg_errno = rc; + pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + &pfk->sk); + pfk->dump.skb = NULL; + } + pfkey_terminate_dump(pfk); return rc; } @@ -1744,9 +1762,14 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr) out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); out_hdr->sadb_msg_errno = 0; out_hdr->sadb_msg_reserved = 0; - out_hdr->sadb_msg_seq = count; + out_hdr->sadb_msg_seq = count + 1; out_hdr->sadb_msg_pid = pfk->dump.msg_pid; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); + + if (pfk->dump.skb) + pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + &pfk->sk); + pfk->dump.skb = out_skb; + return 0; } @@ -2245,7 +2268,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return 0; out: - xp->dead = 1; + xp->walk.dead = 1; xfrm_policy_destroy(xp); return err; } @@ -2583,9 +2606,14 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) out_hdr->sadb_msg_type = SADB_X_SPDDUMP; out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; out_hdr->sadb_msg_errno = 0; - out_hdr->sadb_msg_seq = count; + out_hdr->sadb_msg_seq = count + 1; out_hdr->sadb_msg_pid = pfk->dump.msg_pid; - pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); + + if (pfk->dump.skb) + pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, + &pfk->sk); + pfk->dump.skb = out_skb; + return 0; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ef9ccbc3875..b7ec08025ff 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -46,7 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex); static DEFINE_RWLOCK(xfrm_policy_lock); -static struct list_head xfrm_policy_bytype[XFRM_POLICY_TYPE_MAX]; +static struct list_head xfrm_policy_all; unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; EXPORT_SYMBOL(xfrm_policy_count); @@ -164,7 +164,7 @@ static void xfrm_policy_timer(unsigned long data) read_lock(&xp->lock); - if (xp->dead) + if (xp->walk.dead) goto out; dir = xfrm_policy_id2dir(xp->index); @@ -236,7 +236,7 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) policy = kzalloc(sizeof(struct xfrm_policy), gfp); if (policy) { - INIT_LIST_HEAD(&policy->bytype); + INIT_LIST_HEAD(&policy->walk.all); INIT_HLIST_NODE(&policy->bydst); INIT_HLIST_NODE(&policy->byidx); rwlock_init(&policy->lock); @@ -252,17 +252,13 @@ EXPORT_SYMBOL(xfrm_policy_alloc); void xfrm_policy_destroy(struct xfrm_policy *policy) { - BUG_ON(!policy->dead); + BUG_ON(!policy->walk.dead); BUG_ON(policy->bundles); if (del_timer(&policy->timer)) BUG(); - write_lock_bh(&xfrm_policy_lock); - list_del(&policy->bytype); - write_unlock_bh(&xfrm_policy_lock); - security_xfrm_policy_free(policy->security); kfree(policy); } @@ -310,8 +306,8 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) int dead; write_lock_bh(&policy->lock); - dead = policy->dead; - policy->dead = 1; + dead = policy->walk.dead; + policy->walk.dead = 1; write_unlock_bh(&policy->lock); if (unlikely(dead)) { @@ -609,6 +605,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) if (delpol) { hlist_del(&delpol->bydst); hlist_del(&delpol->byidx); + list_del(&delpol->walk.all); xfrm_policy_count[dir]--; } policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); @@ -617,7 +614,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) policy->curlft.use_time = 0; if (!mod_timer(&policy->timer, jiffies + HZ)) xfrm_pol_hold(policy); - list_add_tail(&policy->bytype, &xfrm_policy_bytype[policy->type]); + list_add(&policy->walk.all, &xfrm_policy_all); write_unlock_bh(&xfrm_policy_lock); if (delpol) @@ -684,6 +681,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, } hlist_del(&pol->bydst); hlist_del(&pol->byidx); + list_del(&pol->walk.all); xfrm_policy_count[dir]--; } ret = pol; @@ -727,6 +725,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, } hlist_del(&pol->bydst); hlist_del(&pol->byidx); + list_del(&pol->walk.all); xfrm_policy_count[dir]--; } ret = pol; @@ -840,6 +839,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) continue; hlist_del(&pol->bydst); hlist_del(&pol->byidx); + list_del(&pol->walk.all); write_unlock_bh(&xfrm_policy_lock); xfrm_audit_policy_delete(pol, 1, @@ -867,60 +867,68 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *data) { - struct xfrm_policy *old, *pol, *last = NULL; + struct xfrm_policy *pol; + struct xfrm_policy_walk_entry *x; int error = 0; if (walk->type >= XFRM_POLICY_TYPE_MAX && walk->type != XFRM_POLICY_TYPE_ANY) return -EINVAL; - if (walk->policy == NULL && walk->count != 0) + if (list_empty(&walk->walk.all) && walk->seq != 0) return 0; - old = pol = walk->policy; - walk->policy = NULL; - read_lock_bh(&xfrm_policy_lock); - - for (; walk->cur_type < XFRM_POLICY_TYPE_MAX; walk->cur_type++) { - if (walk->type != walk->cur_type && - walk->type != XFRM_POLICY_TYPE_ANY) + write_lock_bh(&xfrm_policy_lock); + if (list_empty(&walk->walk.all)) + x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all); + else + x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); + list_for_each_entry_from(x, &xfrm_policy_all, all) { + if (x->dead) continue; - - if (pol == NULL) { - pol = list_first_entry(&xfrm_policy_bytype[walk->cur_type], - struct xfrm_policy, bytype); - } - list_for_each_entry_from(pol, &xfrm_policy_bytype[walk->cur_type], bytype) { - if (pol->dead) - continue; - if (last) { - error = func(last, xfrm_policy_id2dir(last->index), - walk->count, data); - if (error) { - xfrm_pol_hold(last); - walk->policy = last; - goto out; - } - } - last = pol; - walk->count++; + pol = container_of(x, struct xfrm_policy, walk); + if (walk->type != XFRM_POLICY_TYPE_ANY && + walk->type != pol->type) + continue; + error = func(pol, xfrm_policy_id2dir(pol->index), + walk->seq, data); + if (error) { + list_move_tail(&walk->walk.all, &x->all); + goto out; } - pol = NULL; + walk->seq++; } - if (walk->count == 0) { + if (walk->seq == 0) { error = -ENOENT; goto out; } - if (last) - error = func(last, xfrm_policy_id2dir(last->index), 0, data); + list_del_init(&walk->walk.all); out: - read_unlock_bh(&xfrm_policy_lock); - if (old != NULL) - xfrm_pol_put(old); + write_unlock_bh(&xfrm_policy_lock); return error; } EXPORT_SYMBOL(xfrm_policy_walk); +void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type) +{ + INIT_LIST_HEAD(&walk->walk.all); + walk->walk.dead = 1; + walk->type = type; + walk->seq = 0; +} +EXPORT_SYMBOL(xfrm_policy_walk_init); + +void xfrm_policy_walk_done(struct xfrm_policy_walk *walk) +{ + if (list_empty(&walk->walk.all)) + return; + + write_lock_bh(&xfrm_policy_lock); + list_del(&walk->walk.all); + write_unlock_bh(&xfrm_policy_lock); +} +EXPORT_SYMBOL(xfrm_policy_walk_done); + /* * Find policy to apply to this flow. * @@ -1077,7 +1085,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) struct hlist_head *chain = policy_hash_bysel(&pol->selector, pol->family, dir); - list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]); + list_add(&pol->walk.all, &xfrm_policy_all); hlist_add_head(&pol->bydst, chain); hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); xfrm_policy_count[dir]++; @@ -1095,6 +1103,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, hlist_del(&pol->bydst); hlist_del(&pol->byidx); + list_del(&pol->walk.all); xfrm_policy_count[dir]--; return pol; @@ -1720,7 +1729,7 @@ restart: for (pi = 0; pi < npols; pi++) { read_lock_bh(&pols[pi]->lock); - pol_dead |= pols[pi]->dead; + pol_dead |= pols[pi]->walk.dead; read_unlock_bh(&pols[pi]->lock); } @@ -2415,9 +2424,7 @@ static void __init xfrm_policy_init(void) panic("XFRM: failed to allocate bydst hash\n"); } - for (dir = 0; dir < XFRM_POLICY_TYPE_MAX; dir++) - INIT_LIST_HEAD(&xfrm_policy_bytype[dir]); - + INIT_LIST_HEAD(&xfrm_policy_all); INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); register_netdevice_notifier(&xfrm_dev_notifier); } @@ -2601,7 +2608,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, int i, j, n = 0; write_lock_bh(&pol->lock); - if (unlikely(pol->dead)) { + if (unlikely(pol->walk.dead)) { /* target policy has been deleted */ write_unlock_bh(&pol->lock); return -ENOENT; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 053970e8765..747fd8c291a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -59,14 +59,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; static unsigned int xfrm_state_num; static unsigned int xfrm_state_genid; -/* Counter indicating ongoing walk, protected by xfrm_state_lock. */ -static unsigned long xfrm_state_walk_ongoing; -/* Counter indicating walk completion, protected by xfrm_cfg_mutex. */ -static unsigned long xfrm_state_walk_completed; - -/* List of outstanding state walks used to set the completed counter. */ -static LIST_HEAD(xfrm_state_walks); - static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); @@ -199,8 +191,7 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock); static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; static struct work_struct xfrm_state_gc_work; -static LIST_HEAD(xfrm_state_gc_leftovers); -static LIST_HEAD(xfrm_state_gc_list); +static HLIST_HEAD(xfrm_state_gc_list); static DEFINE_SPINLOCK(xfrm_state_gc_lock); int __xfrm_state_delete(struct xfrm_state *x); @@ -412,23 +403,16 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) static void xfrm_state_gc_task(struct work_struct *data) { - struct xfrm_state *x, *tmp; - unsigned long completed; + struct xfrm_state *x; + struct hlist_node *entry, *tmp; + struct hlist_head gc_list; - mutex_lock(&xfrm_cfg_mutex); spin_lock_bh(&xfrm_state_gc_lock); - list_splice_tail_init(&xfrm_state_gc_list, &xfrm_state_gc_leftovers); + hlist_move_list(&xfrm_state_gc_list, &gc_list); spin_unlock_bh(&xfrm_state_gc_lock); - completed = xfrm_state_walk_completed; - mutex_unlock(&xfrm_cfg_mutex); - - list_for_each_entry_safe(x, tmp, &xfrm_state_gc_leftovers, gclist) { - if ((long)(x->lastused - completed) > 0) - break; - list_del(&x->gclist); + hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) xfrm_state_gc_destroy(x); - } wake_up(&km_waitq); } @@ -529,7 +513,7 @@ struct xfrm_state *xfrm_state_alloc(void) if (x) { atomic_set(&x->refcnt, 1); atomic_set(&x->tunnel_users, 0); - INIT_LIST_HEAD(&x->all); + INIT_LIST_HEAD(&x->km.all); INIT_HLIST_NODE(&x->bydst); INIT_HLIST_NODE(&x->bysrc); INIT_HLIST_NODE(&x->byspi); @@ -556,7 +540,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) WARN_ON(x->km.state != XFRM_STATE_DEAD); spin_lock_bh(&xfrm_state_gc_lock); - list_add_tail(&x->gclist, &xfrm_state_gc_list); + hlist_add_head(&x->gclist, &xfrm_state_gc_list); spin_unlock_bh(&xfrm_state_gc_lock); schedule_work(&xfrm_state_gc_work); } @@ -569,8 +553,7 @@ int __xfrm_state_delete(struct xfrm_state *x) if (x->km.state != XFRM_STATE_DEAD) { x->km.state = XFRM_STATE_DEAD; spin_lock(&xfrm_state_lock); - x->lastused = xfrm_state_walk_ongoing; - list_del_rcu(&x->all); + list_del(&x->km.all); hlist_del(&x->bydst); hlist_del(&x->bysrc); if (x->id.spi) @@ -871,7 +854,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, if (km_query(x, tmpl, pol) == 0) { x->km.state = XFRM_STATE_ACQ; - list_add_tail(&x->all, &xfrm_state_all); + list_add(&x->km.all, &xfrm_state_all); hlist_add_head(&x->bydst, xfrm_state_bydst+h); h = xfrm_src_hash(daddr, saddr, family); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); @@ -940,7 +923,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) x->genid = ++xfrm_state_genid; - list_add_tail(&x->all, &xfrm_state_all); + list_add(&x->km.all, &xfrm_state_all); h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, x->props.reqid, x->props.family); @@ -1069,7 +1052,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re xfrm_state_hold(x); x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; add_timer(&x->timer); - list_add_tail(&x->all, &xfrm_state_all); + list_add(&x->km.all, &xfrm_state_all); hlist_add_head(&x->bydst, xfrm_state_bydst+h); h = xfrm_src_hash(daddr, saddr, family); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); @@ -1566,79 +1549,59 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *data) { - struct xfrm_state *old, *x, *last = NULL; + struct xfrm_state *state; + struct xfrm_state_walk *x; int err = 0; - if (walk->state == NULL && walk->count != 0) + if (walk->seq != 0 && list_empty(&walk->all)) return 0; - old = x = walk->state; - walk->state = NULL; spin_lock_bh(&xfrm_state_lock); - if (x == NULL) - x = list_first_entry(&xfrm_state_all, struct xfrm_state, all); + if (list_empty(&walk->all)) + x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all); + else + x = list_entry(&walk->all, struct xfrm_state_walk, all); list_for_each_entry_from(x, &xfrm_state_all, all) { - if (x->km.state == XFRM_STATE_DEAD) + if (x->state == XFRM_STATE_DEAD) continue; - if (!xfrm_id_proto_match(x->id.proto, walk->proto)) + state = container_of(x, struct xfrm_state, km); + if (!xfrm_id_proto_match(state->id.proto, walk->proto)) continue; - if (last) { - err = func(last, walk->count, data); - if (err) { - xfrm_state_hold(last); - walk->state = last; - goto out; - } + err = func(state, walk->seq, data); + if (err) { + list_move_tail(&walk->all, &x->all); + goto out; } - last = x; - walk->count++; + walk->seq++; } - if (walk->count == 0) { + if (walk->seq == 0) { err = -ENOENT; goto out; } - if (last) - err = func(last, 0, data); + list_del_init(&walk->all); out: spin_unlock_bh(&xfrm_state_lock); - if (old != NULL) - xfrm_state_put(old); return err; } EXPORT_SYMBOL(xfrm_state_walk); void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) { + INIT_LIST_HEAD(&walk->all); walk->proto = proto; - walk->state = NULL; - walk->count = 0; - list_add_tail(&walk->list, &xfrm_state_walks); - walk->genid = ++xfrm_state_walk_ongoing; + walk->state = XFRM_STATE_DEAD; + walk->seq = 0; } EXPORT_SYMBOL(xfrm_state_walk_init); void xfrm_state_walk_done(struct xfrm_state_walk *walk) { - struct list_head *prev; - - if (walk->state != NULL) { - xfrm_state_put(walk->state); - walk->state = NULL; - } - - prev = walk->list.prev; - list_del(&walk->list); - - if (prev != &xfrm_state_walks) { - list_entry(prev, struct xfrm_state_walk, list)->genid = - walk->genid; + if (list_empty(&walk->all)) return; - } - - xfrm_state_walk_completed = walk->genid; - if (!list_empty(&xfrm_state_gc_leftovers)) - schedule_work(&xfrm_state_gc_work); + spin_lock_bh(&xfrm_state_lock); + list_del(&walk->all); + spin_lock_bh(&xfrm_state_lock); } EXPORT_SYMBOL(xfrm_state_walk_done); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 04c41504f84..76f75df21e1 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1102,7 +1102,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, return xp; error: *errp = err; - xp->dead = 1; + xp->walk.dead = 1; xfrm_policy_destroy(xp); return NULL; } @@ -1595,7 +1595,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return -ENOENT; read_lock(&xp->lock); - if (xp->dead) { + if (xp->walk.dead) { read_unlock(&xp->lock); goto out; } -- cgit v1.2.3 From 4edd87ad5cad8e159e0db3ce3131b3d97219c9cd Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 1 Oct 2008 07:09:38 -0700 Subject: net: BUG instead of corrupting memory in pskb_expand_head If the caller of pskb_expand_head specifies a negative nhead we'll silently overwrite other people's memory. This patch makes it BUG instead. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/skbuff.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2c218a0808b..8bd248a6487 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -738,6 +738,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, #endif long off; + BUG_ON(nhead < 0); + if (skb_shared(skb)) BUG(); -- cgit v1.2.3 From a210d01ae3ee006b59e54e772a7f212486e0f021 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 1 Oct 2008 07:28:28 -0700 Subject: ipv4: Loosen source address check on IPv4 output ip_route_output() contains a check to make sure that no flows with non-local source IP addresses are routed. This obviously makes using such addresses impossible. This patch introduces a flowi flag which makes omitting this check possible. The new flag provides a way of handling transparent and non-transparent connections differently. Signed-off-by: Julian Anastasov Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/flow.h | 2 ++ net/ipv4/route.c | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/net/flow.h b/include/net/flow.h index 228b2477cee..b45a5e4fcad 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -47,6 +47,8 @@ struct flowi { #define fl4_scope nl_u.ip4_u.scope __u8 proto; + __u8 flags; +#define FLOWI_FLAG_ANYSRC 0x01 union { struct { __be16 sport; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f62187bb6d0..a6d7c584f53 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2361,11 +2361,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, ipv4_is_zeronet(oldflp->fl4_src)) goto out; - /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - dev_out = ip_dev_find(net, oldflp->fl4_src); - if (dev_out == NULL) - goto out; - /* I removed check for oif == dev_out->oif here. It was wrong for two reasons: 1. ip_dev_find(net, saddr) can return wrong iface, if saddr @@ -2377,6 +2372,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, if (oldflp->oif == 0 && (ipv4_is_multicast(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF))) { + /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ + dev_out = ip_dev_find(net, oldflp->fl4_src); + if (dev_out == NULL) + goto out; + /* Special hack: user can direct multicasts and limited broadcast via necessary interface without fiddling with IP_MULTICAST_IF or IP_PKTINFO. @@ -2395,9 +2395,15 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, fl.oif = dev_out->ifindex; goto make_route; } - if (dev_out) + + if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) { + /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ + dev_out = ip_dev_find(net, oldflp->fl4_src); + if (dev_out == NULL) + goto out; dev_put(dev_out); - dev_out = NULL; + dev_out = NULL; + } } -- cgit v1.2.3 From f5715aea4564f233767ea1d944b2637a5fd7cd2e Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:30:02 -0700 Subject: ipv4: Implement IP_TRANSPARENT socket option This patch introduces the IP_TRANSPARENT socket option: enabling that will make the IPv4 routing omit the non-local source address check on output. Setting IP_TRANSPARENT requires NET_ADMIN capability. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/linux/in.h | 1 + include/net/inet_sock.h | 3 ++- include/net/inet_timewait_sock.h | 3 ++- net/ipv4/inet_timewait_sock.c | 1 + net/ipv4/ip_sockglue.c | 15 ++++++++++++++- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/linux/in.h b/include/linux/in.h index 4065313cd7e..db458beef19 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -75,6 +75,7 @@ struct in_addr { #define IP_IPSEC_POLICY 16 #define IP_XFRM_POLICY 17 #define IP_PASSSEC 18 +#define IP_TRANSPARENT 19 /* BSD compatibility */ #define IP_RECVRETOPTS IP_RETOPTS diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 643e26be058..e97b66e2a9d 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -129,7 +129,8 @@ struct inet_sock { is_icsk:1, freebind:1, hdrincl:1, - mc_loop:1; + mc_loop:1, + transparent:1; int mc_index; __be32 mc_addr; struct ip_mc_socklist *mc_list; diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 91324908fcc..80e4977631b 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -128,7 +128,8 @@ struct inet_timewait_sock { __be16 tw_dport; __u16 tw_num; /* And these are ours. */ - __u8 tw_ipv6only:1; + __u8 tw_ipv6only:1, + tw_transparent:1; /* 15 bits hole, try to pack */ __u16 tw_ipv6_offset; unsigned long tw_ttd; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 743f011b9a8..1c5fd38f882 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -126,6 +126,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_reuse = sk->sk_reuse; tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; + tw->tw_transparent = inet->transparent; tw->tw_prot = sk->sk_prot_creator; twsk_net_set(tw, hold_net(sock_net(sk))); atomic_set(&tw->tw_refcnt, 1); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 105d92a039b..465abf0a986 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -419,7 +419,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, (1<= sizeof(int)) { @@ -878,6 +878,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, err = xfrm_user_policy(sk, optname, optval, optlen); break; + case IP_TRANSPARENT: + if (!capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + if (optlen < 1) + goto e_inval; + inet->transparent = !!val; + break; + default: err = -ENOPROTOOPT; break; @@ -1130,6 +1140,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_FREEBIND: val = inet->freebind; break; + case IP_TRANSPARENT: + val = inet->transparent; + break; default: release_sock(sk); return -ENOPROTOOPT; -- cgit v1.2.3 From b9fb15067ce93497bef852c05e406d7a96212a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B3th=20L=C3=A1szl=C3=B3=20Attila?= Date: Wed, 1 Oct 2008 07:31:24 -0700 Subject: ipv4: Allow binding to non-local addresses if IP_TRANSPARENT is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting IP_TRANSPARENT is not really useful without allowing non-local binds for the socket. To make user-space code simpler we allow these binds even if IP_TRANSPARENT is set but IP_FREEBIND is not. Signed-off-by: Tóth László Attila Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8a3ac1fa71a..1fbff5fa424 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -469,7 +469,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) */ err = -EADDRNOTAVAIL; if (!sysctl_ip_nonlocal_bind && - !inet->freebind && + !(inet->freebind || inet->transparent) && addr->sin_addr.s_addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && -- cgit v1.2.3 From 1668e010cbe1a7567c81d4c02d31dde9859e9da1 Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:33:10 -0700 Subject: ipv4: Make inet_sock.h independent of route.h inet_iif() in inet_sock.h requires route.h. Since users of inet_iif() usually require other route.h functionality anyway this patch moves inet_iif() to route.h. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/inet_sock.h | 7 ------- include/net/ip_vs.h | 1 + include/net/route.h | 5 +++++ net/ipv4/netfilter/nf_nat_helper.c | 1 + net/ipv6/af_inet6.c | 1 + 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index e97b66e2a9d..139b78b4dfe 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -24,7 +24,6 @@ #include #include #include -#include #include /** struct ip_options - IP Options @@ -195,12 +194,6 @@ static inline int inet_sk_ehashfn(const struct sock *sk) return inet_ehashfn(net, laddr, lport, faddr, fport); } - -static inline int inet_iif(const struct sk_buff *skb) -{ - return skb->rtable->rt_iif; -} - static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops) { struct request_sock *req = reqsk_alloc(ops); diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 33e2ac6ceb3..0b2071d9326 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -22,6 +22,7 @@ #include #include /* for union nf_inet_addr */ +#include #include /* for struct ipv6hdr */ #include /* for ipv6_addr_copy */ diff --git a/include/net/route.h b/include/net/route.h index 4f0d8c14736..31d1485b624 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -204,4 +204,9 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt) return rt->peer; } +static inline int inet_iif(const struct sk_buff *skb) +{ + return skb->rtable->rt_iif; +} + #endif /* _ROUTE_H */ diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 11976ea2988..112dcfa1290 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 95055f8c3f3..f018704ecb8 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 79876874ce20d37ecdc7f481ebf142466999152f Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:35:39 -0700 Subject: ipv4: Conditionally enable transparent flow flag when connecting Set FLOWI_FLAG_ANYSRC in flowi->flags if the socket has the transparent socket option set. This way we selectively enable certain connections with non-local source addresses to be routed. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/route.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/net/route.h b/include/net/route.h index 31d1485b624..4e8cae0e584 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -161,6 +161,10 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, int err; struct net *net = sock_net(sk); + + if (inet_sk(sk)->transparent) + fl.flags |= FLOWI_FLAG_ANYSRC; + if (!dst || !src) { err = __ip_route_output_key(net, rp, &fl); if (err) -- cgit v1.2.3 From 88ef4a5a78e63420dd1dd770f1bd1dc198926b04 Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:41:00 -0700 Subject: tcp: Handle TCP SYN+ACK/ACK/RST transparency The TCP stack sends out SYN+ACK/ACK/RST reply packets in response to incoming packets. The non-local source address check on output bites us again, as replies for transparently redirected traffic won't have a chance to leave the node. This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/inet_sock.h | 8 +++++++- include/net/ip.h | 3 +++ net/ipv4/tcp_ipv4.c | 12 +++++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 139b78b4dfe..dced3f64f97 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -72,7 +72,8 @@ struct inet_request_sock { sack_ok : 1, wscale_ok : 1, ecn_ok : 1, - acked : 1; + acked : 1, + no_srccheck: 1; struct ip_options *opt; }; @@ -204,4 +205,9 @@ static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops return req; } +static inline __u8 inet_sk_flowi_flags(const struct sock *sk) +{ + return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0; +} + #endif /* _INET_SOCK_H */ diff --git a/include/net/ip.h b/include/net/ip.h index 250e6ef025a..90b27f634b7 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -140,12 +140,15 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf) struct ip_reply_arg { struct kvec iov[1]; + int flags; __wsum csum; int csumoffset; /* u16 offset of csum in iov[0].iov_base */ /* -1 if not needed */ int bound_dev_if; }; +#define IP_REPLY_ARG_NOSRCCHECK 1 + void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, unsigned int len); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d13688e3558..8b24bd833cb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -591,6 +591,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) ip_hdr(skb)->saddr, /* XXX */ sizeof(struct tcphdr), IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr, check) / 2; + arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; net = dev_net(skb->dst->dev); ip_send_reply(net->ipv4.tcp_sock, skb, @@ -606,7 +607,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, int oif, - struct tcp_md5sig_key *key) + struct tcp_md5sig_key *key, + int reply_flags) { struct tcphdr *th = tcp_hdr(skb); struct { @@ -659,6 +661,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, ip_hdr(skb)->daddr, &rep.th); } #endif + arg.flags = reply_flags; arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr, /* XXX */ arg.iov[0].iov_len, IPPROTO_TCP, 0); @@ -681,7 +684,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent, tw->tw_bound_dev_if, - tcp_twsk_md5_key(tcptw) + tcp_twsk_md5_key(tcptw), + tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0 ); inet_twsk_put(tw); @@ -694,7 +698,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, 0, - tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr)); + tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), + inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0); } /* @@ -1244,6 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq->loc_addr = daddr; ireq->rmt_addr = saddr; + ireq->no_srccheck = inet_sk(sk)->transparent; ireq->opt = tcp_v4_save_options(sk, skb); if (!want_cookie) TCP_ECN_create_request(req, tcp_hdr(skb)); -- cgit v1.2.3 From 86b08d867d7de001ab224180ed7865fab93fd56e Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:44:42 -0700 Subject: ipv4: Make Netfilter's ip_route_me_harder() non-local address compatible Netfilter's ip_route_me_harder() tries to re-route packets either generated or re-routed by Netfilter. This patch changes ip_route_me_harder() to handle packets from non-locally-bound sockets with IP_TRANSPARENT set as local and to set the appropriate flowi flags when re-doing the routing lookup. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/ip.h | 6 ++++++ net/ipv4/inet_connection_sock.c | 1 + net/ipv4/ip_output.c | 4 +++- net/ipv4/netfilter.c | 3 +++ net/ipv4/syncookies.c | 2 ++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/net/ip.h b/include/net/ip.h index 90b27f634b7..d678ea3d474 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -29,6 +29,7 @@ #include #include +#include struct sock; @@ -149,6 +150,11 @@ struct ip_reply_arg { #define IP_REPLY_ARG_NOSRCCHECK 1 +static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) +{ + return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; +} + void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, unsigned int len); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 0c1ae68ee84..432c570c9f5 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -335,6 +335,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet_sk(sk)->sport, .dport = ireq->rmt_port } } }; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d533a89e08d..d2a8f8bb78a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -340,6 +340,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) .saddr = inet->saddr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet->sport, .dport = inet->dport } } }; @@ -1371,7 +1372,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar .uli_u = { .ports = { .sport = tcp_hdr(skb)->dest, .dport = tcp_hdr(skb)->source } }, - .proto = sk->sk_protocol }; + .proto = sk->sk_protocol, + .flags = ip_reply_arg_flowi_flags(arg) }; security_skb_classify_flow(skb, &fl); if (ip_route_output_key(sock_net(sk), &rt, &fl)) return; diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index f8edacdf991..01671ad51ed 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -20,6 +20,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) unsigned int type; type = inet_addr_type(&init_net, iph->saddr); + if (skb->sk && inet_sk(skb->sk)->transparent) + type = RTN_LOCAL; if (addr_type == RTN_UNSPEC) addr_type = type; @@ -33,6 +35,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; fl.mark = skb->mark; + fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; if (ip_route_output_key(&init_net, &rt, &fl) != 0) return -1; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 9d38005abba..929302b2ba9 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -16,6 +16,7 @@ #include #include #include +#include /* Timestamps: lowest 9 bits store TCP options */ #define TSBITS 9 @@ -337,6 +338,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = IPPROTO_TCP, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = th->dest, .dport = th->source } } }; -- cgit v1.2.3 From a3116ac5c216fc3c145906a46df9ce542ff7dcf2 Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:46:49 -0700 Subject: tcp: Port redirection support for TCP Current TCP code relies on the local port of the listening socket being the same as the destination address of the incoming connection. Port redirection used by many transparent proxying techniques obviously breaks this, so we have to store the original destination port address. This patch extends struct inet_request_sock and stores the incoming destination port value there. It also modifies the handshake code to use that value as the source port when sending reply packets. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/inet_sock.h | 2 +- include/net/tcp.h | 1 + net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/syncookies.c | 1 + net/ipv4/tcp_output.c | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index dced3f64f97..de0ecc71cf0 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -61,8 +61,8 @@ struct inet_request_sock { struct request_sock req; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u16 inet6_rsk_offset; - /* 2 bytes hole, try to pack */ #endif + __be16 loc_port; __be32 loc_addr; __be32 rmt_addr; __be16 rmt_port; diff --git a/include/net/tcp.h b/include/net/tcp.h index 12c9b4fec04..f6cc3414315 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -976,6 +976,7 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->acked = 0; ireq->ecn_ok = 0; ireq->rmt_port = tcp_hdr(skb)->source; + ireq->loc_port = tcp_hdr(skb)->dest; } extern void tcp_enter_memory_pressure(struct sock *sk); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 432c570c9f5..21fcc5a9045 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -516,6 +516,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, newicsk->icsk_bind_hash = NULL; inet_sk(newsk)->dport = inet_rsk(req)->rmt_port; + inet_sk(newsk)->num = ntohs(inet_rsk(req)->loc_port); + inet_sk(newsk)->sport = inet_rsk(req)->loc_port; newsk->sk_write_space = sk_stream_write_space; newicsk->icsk_retransmits = 0; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 929302b2ba9..d346c22aa6a 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -297,6 +297,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, treq->rcv_isn = ntohl(th->seq) - 1; treq->snt_isn = cookie; req->mss = mss; + ireq->loc_port = th->dest; ireq->rmt_port = th->source; ireq->loc_addr = ip_hdr(skb)->daddr; ireq->rmt_addr = ip_hdr(skb)->saddr; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a8499ef3234..493553c71d3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2275,7 +2275,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, th->syn = 1; th->ack = 1; TCP_ECN_make_synack(req, th); - th->source = inet_sk(sk)->sport; + th->source = ireq->loc_port; th->dest = ireq->rmt_port; /* Setting of flags are superfluous here for callers (and ECE is * not even correctly set) -- cgit v1.2.3 From bcd41303f422015ab662c9276d108414aa75b796 Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Wed, 1 Oct 2008 07:48:10 -0700 Subject: udp: Export UDP socket lookup function The iptables tproxy code has to be able to do UDP socket hash lookups, so we have to provide an exported lookup function for this purpose. Signed-off-by: KOVACS Krisztian Signed-off-by: David S. Miller --- include/net/udp.h | 4 ++++ net/ipv4/udp.c | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/include/net/udp.h b/include/net/udp.h index addcdc67234..d38f6f2419f 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -148,6 +148,10 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen, int (*push_pending_frames)(struct sock *)); +extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, + int dif); + DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); /* UDP-Lite does not have a standardized MIB yet, so we inherit from UDP */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 57e26fa6618..c83d0ef469c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -302,6 +302,13 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, return result; } +struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, int dif) +{ + return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash); +} +EXPORT_SYMBOL_GPL(udp4_lib_lookup); + static inline struct sock *udp_v4_mcast_next(struct sock *sk, __be16 loc_port, __be32 loc_addr, __be16 rmt_port, __be32 rmt_addr, -- cgit v1.2.3 From 2cd9b822bfa79fc1335d3e71a0449f3cd0b5078e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 19 Jun 2008 17:59:13 -0400 Subject: sctp: Only mark chunks as missing when there are gaps Frist small step in optimizing SACK processing. Do not call sctp_mark_missing() when there are no gaps reported and thus not missing chunks. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 4328ad5439c..ef5ea7423cc 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1129,12 +1129,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) unsigned outstanding; struct sctp_transport *primary = asoc->peer.primary_path; int count_of_newacks = 0; + int gap_ack_blocks; /* Grab the association's destination address list. */ transport_list = &asoc->peer.transport_addr_list; sack_ctsn = ntohl(sack->cum_tsn_ack); - + gap_ack_blocks = ntohs(sack->num_gap_ack_blocks); /* * SFR-CACC algorithm: * On receipt of a SACK the sender SHOULD execute the @@ -1161,7 +1162,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) * A) Initialize the cacc_saw_newack to 0 for all destination * addresses. */ - if (sack->num_gap_ack_blocks && + if (gap_ack_blocks && primary->cacc.changeover_active) { list_for_each_entry(transport, transport_list, transports) { transport->cacc.cacc_saw_newack = 0; @@ -1170,9 +1171,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) /* Get the highest TSN in the sack. */ highest_tsn = sack_ctsn; - if (sack->num_gap_ack_blocks) - highest_tsn += - ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); + if (gap_ack_blocks) + highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); if (TSN_lt(asoc->highest_sacked, highest_tsn)) { highest_new_tsn = highest_tsn; @@ -1181,11 +1181,11 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) highest_new_tsn = sctp_highest_new_tsn(sack, asoc); } + /* Run through the retransmit queue. Credit bytes received * and free those chunks that we can. */ sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); - sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); /* Run through the transmitted queue. * Credit bytes received and free those chunks which we can. @@ -1204,9 +1204,12 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) count_of_newacks ++; } - list_for_each_entry(transport, transport_list, transports) { - sctp_mark_missing(q, &transport->transmitted, transport, - highest_new_tsn, count_of_newacks); + if (gap_ack_blocks) { + sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); + + list_for_each_entry(transport, transport_list, transports) + sctp_mark_missing(q, &transport->transmitted, transport, + highest_new_tsn, count_of_newacks); } /* Move the Cumulative TSN Ack Point if appropriate. */ -- cgit v1.2.3 From ab5216a5bd453752f04bb79c29e8f01b11d69006 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 19 Jun 2008 18:17:24 -0400 Subject: sctp: Optimize SFR-CACC transport list walking during SACK processing There is a possibility of walking the transport list twice during SACK processing when doing SFR-CACC algorithm. We can restructure the code to only do this once. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index ef5ea7423cc..c8de4da57f3 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1145,27 +1145,31 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for * all destinations. - */ - if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { - primary->cacc.changeover_active = 0; - list_for_each_entry(transport, transport_list, - transports) { - transport->cacc.cycling_changeover = 0; - } - } - - /* - * SFR-CACC algorithm: * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE * is set the receiver of the SACK MUST take the following actions: * * A) Initialize the cacc_saw_newack to 0 for all destination * addresses. + * + * Only bother if changeover_active is set. Otherwise, this is + * totally suboptimal to do on every SACK. */ - if (gap_ack_blocks && - primary->cacc.changeover_active) { - list_for_each_entry(transport, transport_list, transports) { - transport->cacc.cacc_saw_newack = 0; + if (primary->cacc.changeover_active) { + u8 clear_cycling = 0; + + if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { + primary->cacc.changeover_active = 0; + clear_cycling = 1; + } + + if (clear_cycling || gap_ack_blocks) { + list_for_each_entry(transport, transport_list, + transports) { + if (clear_cycling) + transport->cacc.cycling_changeover = 0; + if (gap_ack_blocks) + transport->cacc.cacc_saw_newack = 0; + } } } -- cgit v1.2.3 From 845b8eda4d783a7ce2670d482a716840a650389e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 23 Jun 2008 15:26:20 -0400 Subject: sctp: Retransmit list is ineligable for missing indications Chunks placed on the retransmit list are marked as inelegible for fast retrasnmission. Since missing indications determine when fast reransmission is done, there is not point in calling sctp_mark_missing() on the retransmit list since those chunks will not be marked. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index c8de4da57f3..da8d846301c 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1209,8 +1209,6 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) } if (gap_ack_blocks) { - sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); - list_for_each_entry(transport, transport_list, transports) sctp_mark_missing(q, &transport->transmitted, transport, highest_new_tsn, count_of_newacks); -- cgit v1.2.3 From c226ef9b83694311327f3ab0036c6de9c22e9daf Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 25 Jul 2008 12:44:09 -0400 Subject: sctp: reduce memory footprint of sctp_chunk structure sctp_chunks should be put on a diet. This is some of the low hanging fruit that we can strip out. Changes all the __s8/__u8 flags to bitfields. Saves 12 bytes per chunk. Signed-off-by: Neil Horman Signed-off-by: Vlad Yasevich --- include/net/sctp/structs.h | 31 +++++++++++++++++-------------- net/sctp/output.c | 2 +- net/sctp/outqueue.c | 14 +++++++------- net/sctp/sm_make_chunk.c | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index ab1c472ea75..0dc1b7267c3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -731,20 +731,23 @@ struct sctp_chunk { */ struct sk_buff *auth_chunk; - __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ - __u8 resent; /* Has this chunk ever been retransmitted. */ - __u8 has_tsn; /* Does this chunk have a TSN yet? */ - __u8 has_ssn; /* Does this chunk have a SSN yet? */ - __u8 singleton; /* Was this the only chunk in the packet? */ - __u8 end_of_packet; /* Was this the last chunk in the packet? */ - __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ - __u8 pdiscard; /* Discard the whole packet now? */ - __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ - __s8 fast_retransmit; /* Is this chunk fast retransmitted? */ - __u8 tsn_missing_report; /* Data chunk missing counter. */ - __u8 data_accepted; /* At least 1 chunk in this packet accepted */ - __u8 auth; /* IN: was auth'ed | OUT: needs auth */ - __u8 has_asconf; /* IN: have seen an asconf before */ +#define SCTP_CAN_FRTX 0x0 +#define SCTP_NEED_FRTX 0x1 +#define SCTP_DONT_FRTX 0x2 + __u16 rtt_in_progress:1, /* This chunk used for RTT calc? */ + resent:1, /* Has this chunk ever been resent. */ + has_tsn:1, /* Does this chunk have a TSN yet? */ + has_ssn:1, /* Does this chunk have a SSN yet? */ + singleton:1, /* Only chunk in the packet? */ + end_of_packet:1, /* Last chunk in the packet? */ + ecn_ce_done:1, /* Have we processed the ECN CE bit? */ + pdiscard:1, /* Discard the whole packet now? */ + tsn_gap_acked:1, /* Is this chunk acked by a GAP ACK? */ + data_accepted:1, /* At least 1 chunk accepted */ + auth:1, /* IN: was auth'ed | OUT: needs auth */ + has_asconf:1, /* IN: have seen an asconf before */ + tsn_missing_report:2, /* Data chunk missing counter. */ + fast_retransmit:2; /* Is this chunk fast retransmitted? */ }; void sctp_chunk_hold(struct sctp_chunk *); diff --git a/net/sctp/output.c b/net/sctp/output.c index 225c7123c41..c3f417f7ec6 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -699,7 +699,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, * When a Fast Retransmit is being performed the sender SHOULD * ignore the value of cwnd and SHOULD NOT delay retransmission. */ - if (chunk->fast_retransmit <= 0) + if (chunk->fast_retransmit != SCTP_NEED_FRTX) if (transport->flight_size >= transport->cwnd) { retval = SCTP_XMIT_RWND_FULL; goto finish; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index da8d846301c..247ebc95c1e 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -420,7 +420,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, * be added to the retransmit queue. */ if ((reason == SCTP_RTXR_FAST_RTX && - (chunk->fast_retransmit > 0)) || + (chunk->fast_retransmit == SCTP_NEED_FRTX)) || (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { /* If this chunk was sent less then 1 rto ago, do not * retransmit this chunk, but give the peer time @@ -650,8 +650,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, /* Mark the chunk as ineligible for fast retransmit * after it is retransmitted. */ - if (chunk->fast_retransmit > 0) - chunk->fast_retransmit = -1; + if (chunk->fast_retransmit == SCTP_NEED_FRTX) + chunk->fast_retransmit = SCTP_DONT_FRTX; /* Force start T3-rtx timer when fast retransmitting * the earliest outstanding TSN @@ -680,8 +680,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, */ if (rtx_timeout || fast_rtx) { list_for_each_entry(chunk1, lqueue, transmitted_list) { - if (chunk1->fast_retransmit > 0) - chunk1->fast_retransmit = -1; + if (chunk1->fast_retransmit == SCTP_NEED_FRTX) + chunk1->fast_retransmit = SCTP_DONT_FRTX; } } @@ -1656,7 +1656,7 @@ static void sctp_mark_missing(struct sctp_outq *q, * chunk if it has NOT been fast retransmitted or marked for * fast retransmit already. */ - if (!chunk->fast_retransmit && + if (chunk->fast_retransmit == SCTP_CAN_FRTX && !chunk->tsn_gap_acked && TSN_lt(tsn, highest_new_tsn_in_sack)) { @@ -1681,7 +1681,7 @@ static void sctp_mark_missing(struct sctp_outq *q, */ if (chunk->tsn_missing_report >= 3) { - chunk->fast_retransmit = 1; + chunk->fast_retransmit = SCTP_NEED_FRTX; do_fast_retransmit = 1; } } diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index d68869f966c..99fe0747cc9 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1211,7 +1211,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, */ retval->tsn_missing_report = 0; retval->tsn_gap_acked = 0; - retval->fast_retransmit = 0; + retval->fast_retransmit = SCTP_CAN_FRTX; /* If this is a fragmented message, track all fragments * of the message (for SEND_FAILED). -- cgit v1.2.3 From 52cae8f06babf9eed327479c1aa024ce3732f912 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 18 Aug 2008 10:34:34 -0400 Subject: sctp: try harder to figure out address family when checking wildcards sctp_is_any() function that is used to check for wildcard addresses only looks at the address itself to determine the address family. This function is used in the API to check the address passed in from the user. If the user simply zerroes out the sockaddr_storage and pass that in, we'll end up failing. So, let's try harder to determine the address family by also checking the socket if it's possible. Signed-off-by: Vlad Yasevich --- include/net/sctp/structs.h | 2 +- net/sctp/bind_addr.c | 16 +++++++++++++--- net/sctp/ipv6.c | 5 +++-- net/sctp/socket.c | 10 +++++----- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0dc1b7267c3..94c62e4ddea 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1228,7 +1228,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len, sctp_scope_t sctp_scope(const union sctp_addr *); int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope); -int sctp_is_any(const union sctp_addr *addr); +int sctp_is_any(struct sock *sk, const union sctp_addr *addr); int sctp_addr_is_valid(const union sctp_addr *addr); diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f62bc246893..6d5944a745d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, { int error = 0; - if (sctp_is_any(addr)) { + if (sctp_is_any(NULL, addr)) { error = sctp_copy_local_addr_list(dest, scope, gfp, flags); } else if (sctp_in_scope(addr, scope)) { /* Now that the address is in scope, check to see if @@ -477,11 +477,21 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, } /* Is this a wildcard address? */ -int sctp_is_any(const union sctp_addr *addr) +int sctp_is_any(struct sock *sk, const union sctp_addr *addr) { - struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family); + unsigned short fam = 0; + struct sctp_af *af; + + /* Try to get the right address family */ + if (addr->sa.sa_family != AF_UNSPEC) + fam = addr->sa.sa_family; + else if (sk) + fam = sk->sk_family; + + af = sctp_get_af_specific(fam); if (!af) return 0; + return af->is_any(addr); } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 47f91afa021..c78da3c9dd3 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -837,6 +837,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, struct sctp_sock *opt) { struct sctp_af *af1, *af2; + struct sock *sk = sctp_opt2sk(opt); af1 = sctp_get_af_specific(addr1->sa.sa_family); af2 = sctp_get_af_specific(addr2->sa.sa_family); @@ -845,11 +846,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, return 0; /* If the socket is IPv6 only, v4 addrs will not match */ - if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) + if (__ipv6_only_sock(sk) && af1 != af2) return 0; /* Today, wildcard AF_INET/AF_INET6. */ - if (sctp_is_any(addr1) || sctp_is_any(addr2)) + if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) return 1; if (addr1->sa.sa_family != addr2->sa.sa_family) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5ffb9dec1c3..a1b904529d5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2309,7 +2309,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, /* If an address other than INADDR_ANY is specified, and * no transport is found, then the request is invalid. */ - if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { + if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { trans = sctp_addr_id2transport(sk, ¶ms.spp_address, params.spp_assoc_id); if (!trans) @@ -4062,7 +4062,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, /* If an address other than INADDR_ANY is specified, and * no transport is found, then the request is invalid. */ - if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { + if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { trans = sctp_addr_id2transport(sk, ¶ms.spp_address, params.spp_assoc_id); if (!trans) { @@ -4414,7 +4414,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(sk, &addr->a)) { rcu_read_lock(); list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { @@ -4602,7 +4602,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(sk, &addr->a)) { cnt = sctp_copy_laddrs_old(sk, bp->port, getaddrs.addr_num, addrs, &bytes_copied); @@ -4695,7 +4695,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, if (sctp_list_single_entry(&bp->address_list)) { addr = list_entry(bp->address_list.next, struct sctp_sockaddr_entry, list); - if (sctp_is_any(&addr->a)) { + if (sctp_is_any(sk, &addr->a)) { cnt = sctp_copy_laddrs(sk, bp->port, addrs, space_left, &bytes_copied); if (cnt < 0) { -- cgit v1.2.3 From 536428a9b9a98495f7ea54ad95cad83e22f1d47d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 5 Sep 2008 08:55:26 +0800 Subject: sctp: Fix to start T5-shutdown-guard timer while enter SHUTDOWN-SENT state RFC 4960: Section 9.2 The sender of the SHUTDOWN MAY also start an overall guard timer 'T5-shutdown-guard' to bound the overall time for the shutdown sequence. At the expiration of this timer, the sender SHOULD abort the association by sending an ABORT chunk. If the 'T5-shutdown- guard' timer is used, it SHOULD be set to the recommended value of 5 times 'RTO.Max'. The timer 'T5-shutdown-guard' is used to counter the overall time for shutdown sequence, and it's start by the sender of the SHUTDOWN. So timer 'T5-shutdown-guard' should be start when we send the first SHUTDOWN chunk and enter the SHUTDOWN-SENT state, not start when we receipt of the SHUTDOWN primitive and enter SHUTDOWN-PENDING state. If 'T5-shutdown-guard' timer is start at SHUTDOWN-PENDING state, the association may be ABORT while data is still transmitting. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich --- net/sctp/sm_statefuns.c | 24 +++++++----------------- net/sctp/sm_statetable.c | 2 +- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 7c622af2ce5..e57d1d3ad0a 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2076,10 +2076,6 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); - /* Stop the T5-shutdown guard timer. */ - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, - SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); - return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); } @@ -4543,13 +4539,6 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); - /* sctpimpguide-05 Section 2.12.2 - * The sender of the SHUTDOWN MAY also start an overall guard timer - * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, - SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); - disposition = SCTP_DISPOSITION_CONSUME; if (sctp_outq_is_empty(&asoc->outqueue)) { disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, @@ -4994,6 +4983,13 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); + /* RFC 4960 Section 9.2 + * The sender of the SHUTDOWN MAY also start an overall guard timer + * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, + SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); + if (asoc->autoclose) sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); @@ -5520,12 +5516,6 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); - /* sctpimpguide-05 Section 2.12.2 - * The sender of the SHUTDOWN MAY also start an overall guard timer - * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, - SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); disposition = SCTP_DISPOSITION_CONSUME; if (sctp_outq_is_empty(&asoc->outqueue)) { disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index d991237fb40..dd4ddc40c0a 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -897,7 +897,7 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ /* SCTP_STATE_ESTABLISHED */ \ TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ + TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ /* SCTP_STATE_SHUTDOWN_SENT */ \ TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ -- cgit v1.2.3 From 8190f89dfd09dae0c117fb0745f5a820bd19a5a4 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 8 Sep 2008 12:13:55 +0800 Subject: sctp: Fix the SNMP counter of SCTP_MIB_OUTOFBLUES RFC3873 defined SCTP_MIB_OUTOFBLUES: sctpOutOfBlues OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current DESCRIPTION "The number of out of the blue packets received by the host. An out of the blue packet is an SCTP packet correctly formed, including the proper checksum, but for which the receiver was unable to identify an appropriate association." REFERENCE "Section 8.4 in RFC2960 deals with the Out-Of-The-Blue (OOTB) packet definition and procedures." But OOTB packet INIT, INIT-ACK and SHUTDOWN-ACK(COOKIE-WAIT or COOKIE-ECHOED state) are not counted by SCTP_MIB_OUTOFBLUES. Case 1(INIT): Endpoint A Endpoint B (CLOSED) (CLOSED) INIT ----------> <---------- ABORT Case 2(INIT-ACK): Endpoint A Endpoint B (CLOSED) (CLOSED) INIT-ACK ----------> <---------- ABORT Case 3(SHUTDOWN-ACK): Endpoint A Endpoint B (CLOSED) (CLOSED) <---------- INIT SHUTDOWN-ACK ----------> <---------- SHUTDOWN-COMPLETE Case 4(SHUTDOWN-ACK): Endpoint A Endpoint B (CLOSED) (COOKIE-ECHOED) SHUTDOWN-ACK ----------> <---------- SHUTDOWN-COMPLETE This patch fixed the problem. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich --- net/sctp/sm_statefuns.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index e57d1d3ad0a..81dfaee49b7 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -315,8 +315,10 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, /* If the packet is an OOTB packet which is temporarily on the * control endpoint, respond with an ABORT. */ - if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) + if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { + SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + } /* 3.1 A packet containing an INIT chunk MUST have a zero Verification * Tag. @@ -635,8 +637,10 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, /* If the packet is an OOTB packet which is temporarily on the * control endpoint, respond with an ABORT. */ - if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) + if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { + SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + } /* Make sure that the COOKIE_ECHO chunk has a valid length. * In this case, we check that we have enough for at least a @@ -3378,6 +3382,8 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, * packet and the state function that handles OOTB SHUTDOWN_ACK is * called with a NULL association. */ + SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); + return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); } -- cgit v1.2.3 From 96cd0d3d710e64c55e034b77052d7ac46f094759 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 8 Sep 2008 14:00:26 -0400 Subject: sctp: enable cookie-echo retransmission transport switch This patch enables cookie-echo retransmission transport switch feature. If COOKIE-ECHO retransmission happens, it will be sent to the address other than the one last sent to. Signed-off-by: Gui Jianfeng Signed-off-by: Vlad Yasevich --- net/sctp/sm_sideeffect.c | 78 +++++++++++++++++++++++++++--------------------- net/sctp/sm_statefuns.c | 2 ++ 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 9732c797e8e..13d9eea5cf1 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -889,6 +889,35 @@ static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands, sctp_ulpq_tail_event(&asoc->ulpq, ev); } + +static void sctp_cmd_t1_timer_update(struct sctp_association *asoc, + sctp_event_timeout_t timer, + char *name) +{ + struct sctp_transport *t; + + t = asoc->init_last_sent_to; + asoc->init_err_counter++; + + if (t->init_sent_count > (asoc->init_cycle + 1)) { + asoc->timeouts[timer] *= 2; + if (asoc->timeouts[timer] > asoc->max_init_timeo) { + asoc->timeouts[timer] = asoc->max_init_timeo; + } + asoc->init_cycle++; + SCTP_DEBUG_PRINTK( + "T1 %s Timeout adjustment" + " init_err_counter: %d" + " cycle: %d" + " timeout: %ld\n", + name, + asoc->init_err_counter, + asoc->init_cycle, + asoc->timeouts[timer]); + } + +} + /* These three macros allow us to pull the debugging code out of the * main flow of sctp_do_sm() to keep attention focused on the real * functionality there. @@ -1196,6 +1225,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(cmd->obj.ptr)); + if (new_obj->transport) { + new_obj->transport->init_sent_count++; + asoc->init_last_sent_to = new_obj->transport; + } + /* FIXME - Eventually come up with a cleaner way to * enabling COOKIE-ECHO + DATA bundling during * multihoming stale cookie scenarios, the following @@ -1345,26 +1379,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, * all transports have been tried at the current * timeout. */ - t = asoc->init_last_sent_to; - asoc->init_err_counter++; - - if (t->init_sent_count > (asoc->init_cycle + 1)) { - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; - if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > - asoc->max_init_timeo) { - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = - asoc->max_init_timeo; - } - asoc->init_cycle++; - SCTP_DEBUG_PRINTK( - "T1 INIT Timeout adjustment" - " init_err_counter: %d" - " cycle: %d" - " timeout: %ld\n", - asoc->init_err_counter, - asoc->init_cycle, - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); - } + sctp_cmd_t1_timer_update(asoc, + SCTP_EVENT_TIMEOUT_T1_INIT, + "INIT"); sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); @@ -1377,20 +1394,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, * all transports have been tried at the current * timeout. */ - asoc->init_err_counter++; - - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; - if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > - asoc->max_init_timeo) { - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = - asoc->max_init_timeo; - } - SCTP_DEBUG_PRINTK( - "T1 COOKIE Timeout adjustment" - " init_err_counter: %d" - " timeout: %ld\n", - asoc->init_err_counter, - asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); + sctp_cmd_t1_timer_update(asoc, + SCTP_EVENT_TIMEOUT_T1_COOKIE, + "COOKIE"); /* If we've sent any data bundled with * COOKIE-ECHO we need to resend. @@ -1422,6 +1428,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_INIT_COUNTER_RESET: asoc->init_err_counter = 0; asoc->init_cycle = 0; + list_for_each_entry(t, &asoc->peer.transport_addr_list, + transports) { + t->init_sent_count = 0; + } break; case SCTP_CMD_REPORT_DUP: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 81dfaee49b7..ea3a34cbe47 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -5307,6 +5307,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep if (!repl) return SCTP_DISPOSITION_NOMEM; + sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, + SCTP_CHUNK(repl)); /* Issue a sideeffect to do the needed accounting. */ sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); -- cgit v1.2.3 From e69c4e0f1210450841e40716894ba6a877b31d52 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 15 Sep 2008 16:29:49 -0400 Subject: sctp: correctly save sctp_adaptation from parameter. The INIT perameter carries the adapatation value in network-byte order. We need to store it in host byte order as expected by data types and the user API. Signed-off-by: Vlad Yasevich --- net/sctp/sm_make_chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 99fe0747cc9..76726bcff3e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2467,7 +2467,7 @@ do_addr_param: break; case SCTP_PARAM_ADAPTATION_LAYER_IND: - asoc->peer.adaptation_ind = param.aind->adaptation_ind; + asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind); break; case SCTP_PARAM_SET_PRIMARY: -- cgit v1.2.3 From 7afb9dc9a5663befea612b03615efc694d5c3ce7 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 5 Oct 2008 09:20:28 -0700 Subject: netdrv: Fix unregister_netdev typos Found during the (partial) unregister_netdevice audit that we didn't have to have :) It looks like a couple of Sun NIC drivers had unregister_netdevice when they really meant unregister_netdev. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/myri_sbus.c | 2 +- drivers/net/sunbmac.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 656a260fc95..06e682334c7 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1118,7 +1118,7 @@ static int __devexit myri_sbus_remove(struct of_device *dev) struct myri_eth *mp = dev_get_drvdata(&dev->dev); struct net_device *net_dev = mp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); free_irq(net_dev->irq, net_dev); diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 0e4a88d1632..31e7384e312 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1274,7 +1274,7 @@ static int __devexit bigmac_sbus_remove(struct of_device *dev) struct bigmac *bp = dev_get_drvdata(&dev->dev); struct net_device *net_dev = bp->dev; - unregister_netdevice(net_dev); + unregister_netdev(net_dev); sbus_iounmap(bp->gregs, GLOB_REG_SIZE); sbus_iounmap(bp->creg, CREG_REG_SIZE); -- cgit v1.2.3 From 25532824fb727744a302edb25c6a6ac10b82cb63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:14:27 -0700 Subject: Phonet: modules auto-loading support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/af_phonet.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 1d8df6b7e3d..0a74aeaf5ad 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -64,6 +64,11 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol) } pnp = phonet_proto_get(protocol); +#ifdef CONFIG_KMOD + if (pnp == NULL && + request_module("net-pf-%d-proto-%d", PF_PHONET, protocol) == 0) + pnp = phonet_proto_get(protocol); +#endif if (pnp == NULL) return -EPROTONOSUPPORT; if (sock->type != pnp->sock_type) { @@ -94,7 +99,7 @@ out: } static struct net_proto_family phonet_proto_family = { - .family = AF_PHONET, + .family = PF_PHONET, .create = pn_socket_create, .owner = THIS_MODULE, }; @@ -447,7 +452,7 @@ static int __init phonet_init(void) err: phonet_sysctl_exit(); - sock_unregister(AF_PHONET); + sock_unregister(PF_PHONET); dev_remove_pack(&phonet_packet_type); phonet_device_exit(); return err; @@ -457,7 +462,7 @@ static void __exit phonet_exit(void) { isi_unregister(); phonet_sysctl_exit(); - sock_unregister(AF_PHONET); + sock_unregister(PF_PHONET); dev_remove_pack(&phonet_packet_type); phonet_device_exit(); } @@ -466,3 +471,4 @@ module_init(phonet_init); module_exit(phonet_exit); MODULE_DESCRIPTION("Phonet protocol stack for Linux"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETPROTO(PF_PHONET); -- cgit v1.2.3 From 9995a32b4d14dcda2f8df58030526bee91114c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:14:48 -0700 Subject: Phonet: connected sockets glue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- include/net/phonet/pep.h | 43 +++++++++++++++++++++ net/phonet/socket.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 include/net/phonet/pep.h diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h new file mode 100644 index 00000000000..b2f8c54c533 --- /dev/null +++ b/include/net/phonet/pep.h @@ -0,0 +1,43 @@ +/* + * File: pep.h + * + * Phonet Pipe End Point sockets definitions + * + * Copyright (C) 2008 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef NET_PHONET_PEP_H +#define NET_PHONET_PEP_H + +struct pep_sock { + struct pn_sock pn_sk; + + /* Listening socket stuff: */ + struct hlist_head ackq; + + /* Connected socket stuff: */ + u8 tx_credits; +}; + +static inline struct pep_sock *pep_sk(struct sock *sk) +{ + return (struct pep_sock *)sk; +} + +extern const struct proto_ops phonet_stream_ops; + +#endif diff --git a/net/phonet/socket.c b/net/phonet/socket.c index dfd4061646d..cea1136cbe4 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -25,11 +25,13 @@ #include #include +#include #include #include #include #include +#include #include static int pn_socket_release(struct socket *sock) @@ -166,6 +168,24 @@ static int pn_socket_autobind(struct socket *sock) return 0; /* socket was already bound */ } +static int pn_socket_accept(struct socket *sock, struct socket *newsock, + int flags) +{ + struct sock *sk = sock->sk; + struct sock *newsk; + int err; + + newsk = sk->sk_prot->accept(sk, flags, &err); + if (!newsk) + return err; + + lock_sock(newsk); + sock_graft(newsk, newsock); + newsock->state = SS_CONNECTED; + release_sock(newsk); + return 0; +} + static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, int *sockaddr_len, int peer) { @@ -182,6 +202,33 @@ static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, return 0; } +static unsigned int pn_socket_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + struct pep_sock *pn = pep_sk(sk); + unsigned int mask = 0; + + poll_wait(file, &sock->wait, wait); + + switch (sk->sk_state) { + case TCP_LISTEN: + return hlist_empty(&pn->ackq) ? 0 : POLLIN; + case TCP_CLOSE: + return POLLERR; + } + + if (!skb_queue_empty(&sk->sk_receive_queue)) + mask |= POLLIN | POLLRDNORM; + else if (sk->sk_state == TCP_CLOSE_WAIT) + return POLLHUP; + + if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; +} + static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { @@ -220,6 +267,30 @@ static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, return sk->sk_prot->ioctl(sk, cmd, arg); } +static int pn_socket_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + int err = 0; + + if (sock->state != SS_UNCONNECTED) + return -EINVAL; + if (pn_socket_autobind(sock)) + return -ENOBUFS; + + lock_sock(sk); + if (sk->sk_state != TCP_CLOSE) { + err = -EINVAL; + goto out; + } + + sk->sk_state = TCP_LISTEN; + sk->sk_ack_backlog = 0; + sk->sk_max_ack_backlog = backlog; +out: + release_sock(sk); + return err; +} + static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { @@ -256,6 +327,32 @@ const struct proto_ops phonet_dgram_ops = { .sendpage = sock_no_sendpage, }; +const struct proto_ops phonet_stream_ops = { + .family = AF_PHONET, + .owner = THIS_MODULE, + .release = pn_socket_release, + .bind = pn_socket_bind, + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .accept = pn_socket_accept, + .getname = pn_socket_getname, + .poll = pn_socket_poll, + .ioctl = pn_socket_ioctl, + .listen = pn_socket_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = sock_no_setsockopt, + .compat_getsockopt = compat_sock_no_getsockopt, +#endif + .sendmsg = pn_socket_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; +EXPORT_SYMBOL(phonet_stream_ops); + static DEFINE_MUTEX(port_mutex); /* allocate port for a socket */ -- cgit v1.2.3 From 9641458d3ec42def729fde64669abf07f3220cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:15:13 -0700 Subject: Phonet: Pipe End Point for Phonet Pipes protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This protocol provides some connection handling and negotiated congestion control. Nokia cellular modems use it for bulk transfers. It provides packet boundaries (hence SOCK_SEQPACKET). Congestion control is per packet rather per byte, so we do not re-use the generic socket memory accounting. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/phonet.h | 4 +- include/net/phonet/pep.h | 114 ++++++ net/phonet/Makefile | 4 +- net/phonet/af_phonet.c | 3 + net/phonet/pep.c | 908 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1031 insertions(+), 2 deletions(-) create mode 100644 net/phonet/pep.c diff --git a/include/linux/phonet.h b/include/linux/phonet.h index 3a027f588a4..f9218524207 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h @@ -27,7 +27,9 @@ #define PN_PROTO_TRANSPORT 0 /* Phonet datagram socket */ #define PN_PROTO_PHONET 1 -#define PHONET_NPROTO 2 +/* Phonet pipe */ +#define PN_PROTO_PIPE 2 +#define PHONET_NPROTO 3 #define PNADDR_ANY 0 #define PNPORT_RESOURCE_ROUTING 0 diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h index b2f8c54c533..fb024e18686 100644 --- a/include/net/phonet/pep.h +++ b/include/net/phonet/pep.h @@ -26,11 +26,21 @@ struct pep_sock { struct pn_sock pn_sk; + /* XXX: union-ify listening vs connected stuff ? */ /* Listening socket stuff: */ struct hlist_head ackq; + struct hlist_head hlist; /* Connected socket stuff: */ + struct sock *listener; + u16 peer_type; /* peer type/subtype */ + u8 pipe_handle; + + u8 rx_credits; u8 tx_credits; + u8 rx_fc; /* RX flow control */ + u8 tx_fc; /* TX flow control */ + u8 init_enable; /* auto-enable at creation */ }; static inline struct pep_sock *pep_sk(struct sock *sk) @@ -40,4 +50,108 @@ static inline struct pep_sock *pep_sk(struct sock *sk) extern const struct proto_ops phonet_stream_ops; +/* Pipe protocol definitions */ +struct pnpipehdr { + u8 utid; /* transaction ID */ + u8 message_id; + u8 pipe_handle; + union { + u8 state_after_connect; /* connect request */ + u8 state_after_reset; /* reset request */ + u8 error_code; /* any response */ + u8 pep_type; /* status indication */ + u8 data[1]; + }; +}; +#define other_pep_type data[1] + +static inline struct pnpipehdr *pnp_hdr(struct sk_buff *skb) +{ + return (struct pnpipehdr *)skb_transport_header(skb); +} + +#define MAX_PNPIPE_HEADER (MAX_PHONET_HEADER + 4) + +enum { + PNS_PIPE_DATA = 0x20, + + PNS_PEP_CONNECT_REQ = 0x40, + PNS_PEP_CONNECT_RESP, + PNS_PEP_DISCONNECT_REQ, + PNS_PEP_DISCONNECT_RESP, + PNS_PEP_RESET_REQ, + PNS_PEP_RESET_RESP, + PNS_PEP_ENABLE_REQ, + PNS_PEP_ENABLE_RESP, + PNS_PEP_CTRL_REQ, + PNS_PEP_CTRL_RESP, + PNS_PEP_DISABLE_REQ = 0x4C, + PNS_PEP_DISABLE_RESP, + + PNS_PEP_STATUS_IND = 0x60, + PNS_PIPE_CREATED_IND, + PNS_PIPE_RESET_IND = 0x63, + PNS_PIPE_ENABLED_IND, + PNS_PIPE_REDIRECTED_IND, + PNS_PIPE_DISABLED_IND = 0x66, +}; + +#define PN_PIPE_INVALID_HANDLE 0xff +#define PN_PEP_TYPE_COMMON 0x00 + +/* Phonet pipe status indication */ +enum { + PN_PEP_IND_FLOW_CONTROL, + PN_PEP_IND_ID_MCFC_GRANT_CREDITS, +}; + +/* Phonet pipe error codes */ +enum { + PN_PIPE_NO_ERROR, + PN_PIPE_ERR_INVALID_PARAM, + PN_PIPE_ERR_INVALID_HANDLE, + PN_PIPE_ERR_INVALID_CTRL_ID, + PN_PIPE_ERR_NOT_ALLOWED, + PN_PIPE_ERR_PEP_IN_USE, + PN_PIPE_ERR_OVERLOAD, + PN_PIPE_ERR_DEV_DISCONNECTED, + PN_PIPE_ERR_TIMEOUT, + PN_PIPE_ERR_ALL_PIPES_IN_USE, + PN_PIPE_ERR_GENERAL, + PN_PIPE_ERR_NOT_SUPPORTED, +}; + +/* Phonet pipe states */ +enum { + PN_PIPE_DISABLE, + PN_PIPE_ENABLE, +}; + +/* Phonet pipe sub-block types */ +enum { + PN_PIPE_SB_CREATE_REQ_PEP_SUB_TYPE, + PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE, + PN_PIPE_SB_REDIRECT_REQ_PEP_SUB_TYPE, + PN_PIPE_SB_NEGOTIATED_FC, + PN_PIPE_SB_REQUIRED_FC_TX, + PN_PIPE_SB_PREFERRED_FC_RX, +}; + +/* Phonet pipe flow control models */ +enum { + PN_NO_FLOW_CONTROL, + PN_LEGACY_FLOW_CONTROL, + PN_ONE_CREDIT_FLOW_CONTROL, + PN_MULTI_CREDIT_FLOW_CONTROL, +}; + +#define pn_flow_safe(fc) ((fc) >> 1) + +/* Phonet pipe flow control states */ +enum { + PEP_IND_EMPTY, + PEP_IND_BUSY, + PEP_IND_READY, +}; + #endif diff --git a/net/phonet/Makefile b/net/phonet/Makefile index ae9c3ed5be8..505df2a04a8 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_PHONET) += phonet.o +obj-$(CONFIG_PHONET) += phonet.o pn_pep.o phonet-objs := \ pn_dev.o \ @@ -7,3 +7,5 @@ phonet-objs := \ datagram.o \ sysctl.o \ af_phonet.o + +pn_pep-objs := pep.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 0a74aeaf5ad..9e9c6fce11a 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -58,6 +58,9 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol) case SOCK_DGRAM: protocol = PN_PROTO_PHONET; break; + case SOCK_SEQPACKET: + protocol = PN_PROTO_PIPE; + break; default: return -EPROTONOSUPPORT; } diff --git a/net/phonet/pep.c b/net/phonet/pep.c new file mode 100644 index 00000000000..c5dfecb207d --- /dev/null +++ b/net/phonet/pep.c @@ -0,0 +1,908 @@ +/* + * File: pep.c + * + * Phonet pipe protocol end point socket + * + * Copyright (C) 2008 Nokia Corporation. + * + * Author: Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* sk_state values: + * TCP_CLOSE sock not in use yet + * TCP_CLOSE_WAIT disconnected pipe + * TCP_LISTEN listening pipe endpoint + * TCP_SYN_RECV connected pipe in disabled state + * TCP_ESTABLISHED connected pipe in enabled state + * + * pep_sock locking: + * - sk_state, ackq, hlist: sock lock needed + * - listener: read only + * - pipe_handle: read only + */ + +#define CREDITS_MAX 10 +#define CREDITS_THR 7 + +static const struct sockaddr_pn pipe_srv = { + .spn_family = AF_PHONET, + .spn_resource = 0xD9, /* pipe service */ +}; + +#define pep_sb_size(s) (((s) + 5) & ~3) /* 2-bytes head, 32-bits aligned */ + +/* Get the next TLV sub-block. */ +static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen, + void *buf) +{ + void *data = NULL; + struct { + u8 sb_type; + u8 sb_len; + } *ph, h; + int buflen = *plen; + + ph = skb_header_pointer(skb, 0, 2, &h); + if (ph == NULL || ph->sb_len < 2 || !pskb_may_pull(skb, ph->sb_len)) + return NULL; + ph->sb_len -= 2; + *ptype = ph->sb_type; + *plen = ph->sb_len; + + if (buflen > ph->sb_len) + buflen = ph->sb_len; + data = skb_header_pointer(skb, 2, buflen, buf); + __skb_pull(skb, 2 + ph->sb_len); + return data; +} + +static int pep_reply(struct sock *sk, struct sk_buff *oskb, + u8 code, const void *data, int len, gfp_t priority) +{ + const struct pnpipehdr *oph = pnp_hdr(oskb); + struct pnpipehdr *ph; + struct sk_buff *skb; + + skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority); + if (!skb) + return -ENOMEM; + skb_set_owner_w(skb, sk); + + skb_reserve(skb, MAX_PNPIPE_HEADER); + __skb_put(skb, len); + skb_copy_to_linear_data(skb, data, len); + __skb_push(skb, sizeof(*ph)); + skb_reset_transport_header(skb); + ph = pnp_hdr(skb); + ph->utid = oph->utid; + ph->message_id = oph->message_id + 1; /* REQ -> RESP */ + ph->pipe_handle = oph->pipe_handle; + ph->error_code = code; + + return pn_skb_send(sk, skb, &pipe_srv); +} + +#define PAD 0x00 +static int pep_accept_conn(struct sock *sk, struct sk_buff *skb) +{ + static const u8 data[20] = { + PAD, PAD, PAD, 2 /* sub-blocks */, + PN_PIPE_SB_REQUIRED_FC_TX, pep_sb_size(5), 3, PAD, + PN_MULTI_CREDIT_FLOW_CONTROL, + PN_ONE_CREDIT_FLOW_CONTROL, + PN_LEGACY_FLOW_CONTROL, + PAD, + PN_PIPE_SB_PREFERRED_FC_RX, pep_sb_size(5), 3, PAD, + PN_MULTI_CREDIT_FLOW_CONTROL, + PN_ONE_CREDIT_FLOW_CONTROL, + PN_LEGACY_FLOW_CONTROL, + PAD, + }; + + might_sleep(); + return pep_reply(sk, skb, PN_PIPE_NO_ERROR, data, sizeof(data), + GFP_KERNEL); +} + +static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code) +{ + static const u8 data[4] = { PAD, PAD, PAD, 0 /* sub-blocks */ }; + WARN_ON(code == PN_PIPE_NO_ERROR); + return pep_reply(sk, skb, code, data, sizeof(data), GFP_ATOMIC); +} + +/* Control requests are not sent by the pipe service and have a specific + * message format. */ +static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code) +{ + const struct pnpipehdr *oph = pnp_hdr(oskb); + struct sk_buff *skb; + struct pnpipehdr *ph; + struct sockaddr_pn dst; + + skb = alloc_skb(MAX_PNPIPE_HEADER + 4, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + skb_set_owner_w(skb, sk); + + skb_reserve(skb, MAX_PHONET_HEADER); + ph = (struct pnpipehdr *)skb_put(skb, sizeof(*ph) + 4); + + ph->utid = oph->utid; + ph->message_id = PNS_PEP_CTRL_RESP; + ph->pipe_handle = oph->pipe_handle; + ph->data[0] = oph->data[1]; /* CTRL id */ + ph->data[1] = oph->data[0]; /* PEP type */ + ph->data[2] = code; /* error code, at an usual offset */ + ph->data[3] = PAD; + ph->data[4] = PAD; + + pn_skb_get_src_sockaddr(oskb, &dst); + return pn_skb_send(sk, skb, &dst); +} + +static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority) +{ + struct pep_sock *pn = pep_sk(sk); + struct pnpipehdr *ph; + struct sk_buff *skb; + + skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); + if (!skb) + return -ENOMEM; + skb_set_owner_w(skb, sk); + + skb_reserve(skb, MAX_PNPIPE_HEADER + 4); + __skb_push(skb, sizeof(*ph) + 4); + skb_reset_transport_header(skb); + ph = pnp_hdr(skb); + ph->utid = 0; + ph->message_id = PNS_PEP_STATUS_IND; + ph->pipe_handle = pn->pipe_handle; + ph->pep_type = PN_PEP_TYPE_COMMON; + ph->data[1] = type; + ph->data[2] = PAD; + ph->data[3] = PAD; + ph->data[4] = status; + + return pn_skb_send(sk, skb, &pipe_srv); +} + +/* Send our RX flow control information to the sender. + * Socket must be locked. */ +static void pipe_grant_credits(struct sock *sk) +{ + struct pep_sock *pn = pep_sk(sk); + + BUG_ON(sk->sk_state != TCP_ESTABLISHED); + + switch (pn->rx_fc) { + case PN_LEGACY_FLOW_CONTROL: /* TODO */ + break; + case PN_ONE_CREDIT_FLOW_CONTROL: + pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL, + PEP_IND_READY, GFP_ATOMIC); + pn->rx_credits = 1; + break; + case PN_MULTI_CREDIT_FLOW_CONTROL: + if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX) + break; + if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS, + CREDITS_MAX - pn->rx_credits, + GFP_ATOMIC) == 0) + pn->rx_credits = CREDITS_MAX; + break; + } +} + +static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) +{ + struct pep_sock *pn = pep_sk(sk); + struct pnpipehdr *hdr = pnp_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*hdr) + 4)) + return -EINVAL; + + if (hdr->data[0] != PN_PEP_TYPE_COMMON) { + LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n", + (unsigned)hdr->data[0]); + return -EOPNOTSUPP; + } + + switch (hdr->data[1]) { + case PN_PEP_IND_FLOW_CONTROL: + switch (pn->tx_fc) { + case PN_LEGACY_FLOW_CONTROL: + switch (hdr->data[4]) { + case PEP_IND_BUSY: + pn->tx_credits = 0; + break; + case PEP_IND_READY: + pn->tx_credits = 1; + break; + } + break; + case PN_ONE_CREDIT_FLOW_CONTROL: + if (hdr->data[4] == PEP_IND_READY) + pn->tx_credits = 1; + break; + } + break; + + case PN_PEP_IND_ID_MCFC_GRANT_CREDITS: + if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL) + break; + if (pn->tx_credits + hdr->data[4] > 0xff) + pn->tx_credits = 0xff; + else + pn->tx_credits += hdr->data[4]; + break; + + default: + LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP indication: %u\n", + (unsigned)hdr->data[1]); + return -EOPNOTSUPP; + } + if (pn->tx_credits) + sk->sk_write_space(sk); + return 0; +} + +static int pipe_rcv_created(struct sock *sk, struct sk_buff *skb) +{ + struct pep_sock *pn = pep_sk(sk); + struct pnpipehdr *hdr = pnp_hdr(skb); + u8 n_sb = hdr->data[0]; + + pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL; + __skb_pull(skb, sizeof(*hdr)); + while (n_sb > 0) { + u8 type, buf[2], len = sizeof(buf); + u8 *data = pep_get_sb(skb, &type, &len, buf); + + if (data == NULL) + return -EINVAL; + switch (type) { + case PN_PIPE_SB_NEGOTIATED_FC: + if (len < 2 || (data[0] | data[1]) > 3) + break; + pn->tx_fc = data[0] & 3; + pn->rx_fc = data[1] & 3; + break; + } + n_sb--; + } + return 0; +} + +/* Queue an skb to a connected sock. + * Socket lock must be held. */ +static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) +{ + struct pep_sock *pn = pep_sk(sk); + struct pnpipehdr *hdr = pnp_hdr(skb); + int err = 0; + + BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); + + switch (hdr->message_id) { + case PNS_PEP_CONNECT_REQ: + pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); + break; + + case PNS_PEP_DISCONNECT_REQ: + pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); + sk->sk_state = TCP_CLOSE_WAIT; + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_state_change(sk); + break; + + case PNS_PEP_ENABLE_REQ: + /* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */ + pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); + break; + + case PNS_PEP_RESET_REQ: + switch (hdr->state_after_reset) { + case PN_PIPE_DISABLE: + pn->init_enable = 0; + break; + case PN_PIPE_ENABLE: + pn->init_enable = 1; + break; + default: /* not allowed to send an error here!? */ + err = -EINVAL; + goto out; + } + /* fall through */ + case PNS_PEP_DISABLE_REQ: + pn->tx_credits = 0; + pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); + break; + + case PNS_PEP_CTRL_REQ: + /* TODO */ + pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR); + break; + + case PNS_PIPE_DATA: + __skb_pull(skb, 3); /* Pipe data header */ + if (!pn_flow_safe(pn->rx_fc)) { + err = sock_queue_rcv_skb(sk, skb); + if (!err) + return 0; + break; + } + + if (pn->rx_credits == 0) { + err = -ENOBUFS; + break; + } + pn->rx_credits--; + skb->dev = NULL; + skb_set_owner_r(skb, sk); + err = skb->len; + skb_queue_tail(&sk->sk_receive_queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, err); + return 0; + + case PNS_PEP_STATUS_IND: + pipe_rcv_status(sk, skb); + break; + + case PNS_PIPE_REDIRECTED_IND: + err = pipe_rcv_created(sk, skb); + break; + + case PNS_PIPE_CREATED_IND: + err = pipe_rcv_created(sk, skb); + if (err) + break; + /* fall through */ + case PNS_PIPE_RESET_IND: + if (!pn->init_enable) + break; + /* fall through */ + case PNS_PIPE_ENABLED_IND: + if (!pn_flow_safe(pn->tx_fc)) { + pn->tx_credits = 1; + sk->sk_write_space(sk); + } + if (sk->sk_state == TCP_ESTABLISHED) + break; /* Nothing to do */ + sk->sk_state = TCP_ESTABLISHED; + pipe_grant_credits(sk); + break; + + case PNS_PIPE_DISABLED_IND: + sk->sk_state = TCP_SYN_RECV; + pn->rx_credits = 0; + break; + + default: + LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP message: %u\n", + hdr->message_id); + err = -EINVAL; + } +out: + kfree_skb(skb); + return err; +} + +/* Destroy connected sock. */ +static void pipe_destruct(struct sock *sk) +{ + skb_queue_purge(&sk->sk_receive_queue); +} + +static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) +{ + struct sock *newsk; + struct pep_sock *newpn, *pn = pep_sk(sk); + struct pnpipehdr *hdr; + struct sockaddr_pn dst; + u16 peer_type; + u8 pipe_handle, enabled, n_sb; + + if (!pskb_pull(skb, sizeof(*hdr) + 4)) + return -EINVAL; + + hdr = pnp_hdr(skb); + pipe_handle = hdr->pipe_handle; + switch (hdr->state_after_connect) { + case PN_PIPE_DISABLE: + enabled = 0; + break; + case PN_PIPE_ENABLE: + enabled = 1; + break; + default: + pep_reject_conn(sk, skb, PN_PIPE_ERR_INVALID_PARAM); + return -EINVAL; + } + peer_type = hdr->other_pep_type << 8; + + if (unlikely(sk->sk_state != TCP_LISTEN) || sk_acceptq_is_full(sk)) { + pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); + return -ENOBUFS; + } + + /* Parse sub-blocks (options) */ + n_sb = hdr->data[4]; + while (n_sb > 0) { + u8 type, buf[1], len = sizeof(buf); + const u8 *data = pep_get_sb(skb, &type, &len, buf); + + if (data == NULL) + return -EINVAL; + switch (type) { + case PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE: + if (len < 1) + return -EINVAL; + peer_type = (peer_type & 0xff00) | data[0]; + break; + } + n_sb--; + } + + skb = skb_clone(skb, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + /* Create a new to-be-accepted sock */ + newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_ATOMIC, sk->sk_prot); + if (!newsk) { + kfree_skb(skb); + return -ENOMEM; + } + sock_init_data(NULL, newsk); + newsk->sk_state = TCP_SYN_RECV; + newsk->sk_backlog_rcv = pipe_do_rcv; + newsk->sk_protocol = sk->sk_protocol; + newsk->sk_destruct = pipe_destruct; + + newpn = pep_sk(newsk); + pn_skb_get_dst_sockaddr(skb, &dst); + newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst); + newpn->pn_sk.resource = pn->pn_sk.resource; + newpn->pipe_handle = pipe_handle; + newpn->peer_type = peer_type; + newpn->rx_credits = newpn->tx_credits = 0; + newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; + newpn->init_enable = enabled; + + BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); + skb_queue_head(&newsk->sk_receive_queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, 0); + + sk_acceptq_added(sk); + sk_add_node(newsk, &pn->ackq); + return 0; +} + +/* Listening sock must be locked */ +static struct sock *pep_find_pipe(const struct hlist_head *hlist, + const struct sockaddr_pn *dst, + u8 pipe_handle) +{ + struct hlist_node *node; + struct sock *sknode; + u16 dobj = pn_sockaddr_get_object(dst); + + sk_for_each(sknode, node, hlist) { + struct pep_sock *pnnode = pep_sk(sknode); + + /* Ports match, but addresses might not: */ + if (pnnode->pn_sk.sobject != dobj) + continue; + if (pnnode->pipe_handle != pipe_handle) + continue; + if (sknode->sk_state == TCP_CLOSE_WAIT) + continue; + + sock_hold(sknode); + return sknode; + } + return NULL; +} + +/* + * Deliver an skb to a listening sock. + * Socket lock must be held. + * We then queue the skb to the right connected sock (if any). + */ +static int pep_do_rcv(struct sock *sk, struct sk_buff *skb) +{ + struct pep_sock *pn = pep_sk(sk); + struct sock *sknode; + struct pnpipehdr *hdr = pnp_hdr(skb); + struct sockaddr_pn dst; + int err = NET_RX_SUCCESS; + u8 pipe_handle; + + if (!pskb_may_pull(skb, sizeof(*hdr))) + goto drop; + + hdr = pnp_hdr(skb); + pipe_handle = hdr->pipe_handle; + if (pipe_handle == PN_PIPE_INVALID_HANDLE) + goto drop; + + pn_skb_get_dst_sockaddr(skb, &dst); + + /* Look for an existing pipe handle */ + sknode = pep_find_pipe(&pn->hlist, &dst, pipe_handle); + if (sknode) + return sk_receive_skb(sknode, skb, 1); + + /* Look for a pipe handle pending accept */ + sknode = pep_find_pipe(&pn->ackq, &dst, pipe_handle); + if (sknode) { + sock_put(sknode); + if (net_ratelimit()) + printk(KERN_WARNING"Phonet unconnected PEP ignored"); + err = NET_RX_DROP; + goto drop; + } + + switch (hdr->message_id) { + case PNS_PEP_CONNECT_REQ: + err = pep_connreq_rcv(sk, skb); + break; + + case PNS_PEP_DISCONNECT_REQ: + pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); + break; + + case PNS_PEP_CTRL_REQ: + pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE); + break; + + case PNS_PEP_RESET_REQ: + case PNS_PEP_ENABLE_REQ: + case PNS_PEP_DISABLE_REQ: + /* invalid handle is not even allowed here! */ + default: + err = NET_RX_DROP; + } +drop: + kfree_skb(skb); + return err; +} + +/* associated socket ceases to exist */ +static void pep_sock_close(struct sock *sk, long timeout) +{ + struct pep_sock *pn = pep_sk(sk); + + sk_common_release(sk); + + lock_sock(sk); + if (sk->sk_state == TCP_LISTEN) { + /* Destroy the listen queue */ + struct sock *sknode; + struct hlist_node *p, *n; + + sk_for_each_safe(sknode, p, n, &pn->ackq) + sk_del_node_init(sknode); + sk->sk_state = TCP_CLOSE; + } + release_sock(sk); +} + +static int pep_wait_connreq(struct sock *sk, int noblock) +{ + struct task_struct *tsk = current; + struct pep_sock *pn = pep_sk(sk); + long timeo = sock_rcvtimeo(sk, noblock); + + for (;;) { + DEFINE_WAIT(wait); + + if (sk->sk_state != TCP_LISTEN) + return -EINVAL; + if (!hlist_empty(&pn->ackq)) + break; + if (!timeo) + return -EWOULDBLOCK; + if (signal_pending(tsk)) + return sock_intr_errno(timeo); + + prepare_to_wait_exclusive(&sk->sk_socket->wait, &wait, + TASK_INTERRUPTIBLE); + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + finish_wait(&sk->sk_socket->wait, &wait); + } + + return 0; +} + +static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp) +{ + struct pep_sock *pn = pep_sk(sk); + struct sock *newsk = NULL; + struct sk_buff *oskb; + int err; + + lock_sock(sk); + err = pep_wait_connreq(sk, flags & O_NONBLOCK); + if (err) + goto out; + + newsk = __sk_head(&pn->ackq); + + oskb = skb_dequeue(&newsk->sk_receive_queue); + err = pep_accept_conn(newsk, oskb); + if (err) { + skb_queue_head(&newsk->sk_receive_queue, oskb); + newsk = NULL; + goto out; + } + + sock_hold(sk); + pep_sk(newsk)->listener = sk; + + sock_hold(newsk); + sk_del_node_init(newsk); + sk_acceptq_removed(sk); + sk_add_node(newsk, &pn->hlist); + __sock_put(newsk); + +out: + release_sock(sk); + *errp = err; + return newsk; +} + +static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + int answ; + + switch (cmd) { + case SIOCINQ: + if (sk->sk_state == TCP_LISTEN) + return -EINVAL; + + lock_sock(sk); + if (!skb_queue_empty(&sk->sk_receive_queue)) + answ = skb_peek(&sk->sk_receive_queue)->len; + else + answ = 0; + release_sock(sk); + return put_user(answ, (int __user *)arg); + } + + return -ENOIOCTLCMD; +} + +static int pep_init(struct sock *sk) +{ + struct pep_sock *pn = pep_sk(sk); + + INIT_HLIST_HEAD(&pn->ackq); + INIT_HLIST_HEAD(&pn->hlist); + pn->pipe_handle = PN_PIPE_INVALID_HANDLE; + return 0; +} + +static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len) +{ + struct pep_sock *pn = pep_sk(sk); + struct sk_buff *skb = NULL; + struct pnpipehdr *ph; + long timeo; + int flags = msg->msg_flags; + int err, done; + + if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) + return -EOPNOTSUPP; + + lock_sock(sk); + timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); + if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { + err = -ENOTCONN; + goto out; + } + if (sk->sk_state != TCP_ESTABLISHED) { + /* Wait until the pipe gets to enabled state */ +disabled: + err = sk_stream_wait_connect(sk, &timeo); + if (err) + goto out; + + if (sk->sk_state == TCP_CLOSE_WAIT) { + err = -ECONNRESET; + goto out; + } + } + BUG_ON(sk->sk_state != TCP_ESTABLISHED); + + /* Wait until flow control allows TX */ + done = pn->tx_credits > 0; + while (!done) { + DEFINE_WAIT(wait); + + if (!timeo) { + err = -EAGAIN; + goto out; + } + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + goto out; + } + + prepare_to_wait(&sk->sk_socket->wait, &wait, + TASK_INTERRUPTIBLE); + done = sk_wait_event(sk, &timeo, pn->tx_credits > 0); + finish_wait(&sk->sk_socket->wait, &wait); + + if (sk->sk_state != TCP_ESTABLISHED) + goto disabled; + } + + if (!skb) { + skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, + flags & MSG_DONTWAIT, &err); + if (skb == NULL) + goto out; + skb_reserve(skb, MAX_PHONET_HEADER + 3); + + if (sk->sk_state != TCP_ESTABLISHED || !pn->tx_credits) + goto disabled; /* sock_alloc_send_skb might sleep */ + } + + err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + if (err < 0) + goto out; + + __skb_push(skb, 3); + skb_reset_transport_header(skb); + ph = pnp_hdr(skb); + ph->utid = 0; + ph->message_id = PNS_PIPE_DATA; + ph->pipe_handle = pn->pipe_handle; + if (pn_flow_safe(pn->tx_fc)) /* credit-based flow control */ + pn->tx_credits--; + + err = pn_skb_send(sk, skb, &pipe_srv); + if (err >= 0) + err = len; /* success! */ + skb = NULL; +out: + release_sock(sk); + kfree_skb(skb); + return err; +} + +static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len, int noblock, + int flags, int *addr_len) +{ + struct sk_buff *skb; + int err; + + if (unlikely(flags & MSG_OOB)) + return -EOPNOTSUPP; + if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) + return -ENOTCONN; + + skb = skb_recv_datagram(sk, flags, noblock, &err); + lock_sock(sk); + if (skb == NULL) { + if (err == -ENOTCONN && sk->sk_state == TCP_CLOSE_WAIT) + err = -ECONNRESET; + release_sock(sk); + return err; + } + + if (sk->sk_state == TCP_ESTABLISHED) + pipe_grant_credits(sk); + release_sock(sk); + + msg->msg_flags |= MSG_EOR; + + if (skb->len > len) + msg->msg_flags |= MSG_TRUNC; + else + len = skb->len; + + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); + if (!err) + err = (flags & MSG_TRUNC) ? skb->len : len; + + skb_free_datagram(sk, skb); + return err; +} + +static void pep_sock_unhash(struct sock *sk) +{ + struct pep_sock *pn = pep_sk(sk); + struct sock *skparent = NULL; + + lock_sock(sk); + if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) { + skparent = pn->listener; + sk_del_node_init(sk); + release_sock(sk); + + sk = skparent; + pn = pep_sk(skparent); + lock_sock(sk); + } + /* Unhash a listening sock only when it is closed + * and all of its active connected pipes are closed. */ + if (hlist_empty(&pn->hlist)) + pn_sock_unhash(&pn->pn_sk.sk); + release_sock(sk); + + if (skparent) + sock_put(skparent); +} + +static struct proto pep_proto = { + .close = pep_sock_close, + .accept = pep_sock_accept, + .ioctl = pep_ioctl, + .init = pep_init, + .sendmsg = pep_sendmsg, + .recvmsg = pep_recvmsg, + .backlog_rcv = pep_do_rcv, + .hash = pn_sock_hash, + .unhash = pep_sock_unhash, + .get_port = pn_sock_get_port, + .obj_size = sizeof(struct pep_sock), + .owner = THIS_MODULE, + .name = "PNPIPE", +}; + +static struct phonet_protocol pep_pn_proto = { + .ops = &phonet_stream_ops, + .prot = &pep_proto, + .sock_type = SOCK_SEQPACKET, +}; + +static int __init pep_register(void) +{ + return phonet_proto_register(PN_PROTO_PIPE, &pep_pn_proto); +} + +static void __exit pep_unregister(void) +{ + phonet_proto_unregister(PN_PROTO_PIPE, &pep_pn_proto); +} + +module_init(pep_register); +module_exit(pep_unregister); +MODULE_AUTHOR("Remi Denis-Courmont, Nokia"); +MODULE_DESCRIPTION("Phonet pipe protocol"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_NET_PF_PROTO(PF_PHONET, PN_PROTO_PIPE); -- cgit v1.2.3 From c41bd97f815720f9404f97da0c4f4400b52c243d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:15:43 -0700 Subject: Phonet: receive pipe control requests as out-of-band data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pep.h | 2 ++ net/phonet/pep.c | 65 ++++++++++++++++++++++++++++++++++-------------- net/phonet/socket.c | 4 ++- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h index fb024e18686..4d79564850a 100644 --- a/include/net/phonet/pep.h +++ b/include/net/phonet/pep.h @@ -33,6 +33,8 @@ struct pep_sock { /* Connected socket stuff: */ struct sock *listener; + struct sk_buff_head ctrlreq_queue; +#define PNPIPE_CTRLREQ_MAX 10 u16 peer_type; /* peer type/subtype */ u8 pipe_handle; diff --git a/net/phonet/pep.c b/net/phonet/pep.c index c5dfecb207d..d564d07cb79 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -137,14 +137,15 @@ static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code) /* Control requests are not sent by the pipe service and have a specific * message format. */ -static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code) +static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code, + gfp_t priority) { const struct pnpipehdr *oph = pnp_hdr(oskb); struct sk_buff *skb; struct pnpipehdr *ph; struct sockaddr_pn dst; - skb = alloc_skb(MAX_PNPIPE_HEADER + 4, GFP_ATOMIC); + skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); if (!skb) return -ENOMEM; skb_set_owner_w(skb, sk); @@ -305,6 +306,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) { struct pep_sock *pn = pep_sk(sk); struct pnpipehdr *hdr = pnp_hdr(skb); + struct sk_buff_head *queue; int err = 0; BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); @@ -345,9 +347,11 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) break; case PNS_PEP_CTRL_REQ: - /* TODO */ - pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR); - break; + if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) + break; + __skb_pull(skb, 4); + queue = &pn->ctrlreq_queue; + goto queue; case PNS_PIPE_DATA: __skb_pull(skb, 3); /* Pipe data header */ @@ -363,13 +367,8 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) break; } pn->rx_credits--; - skb->dev = NULL; - skb_set_owner_r(skb, sk); - err = skb->len; - skb_queue_tail(&sk->sk_receive_queue, skb); - if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk, err); - return 0; + queue = &sk->sk_receive_queue; + goto queue; case PNS_PEP_STATUS_IND: pipe_rcv_status(sk, skb); @@ -412,12 +411,24 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) out: kfree_skb(skb); return err; + +queue: + skb->dev = NULL; + skb_set_owner_r(skb, sk); + err = skb->len; + skb_queue_tail(queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, err); + return 0; } /* Destroy connected sock. */ static void pipe_destruct(struct sock *sk) { + struct pep_sock *pn = pep_sk(sk); + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&pn->ctrlreq_queue); } static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) @@ -490,6 +501,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) pn_skb_get_dst_sockaddr(skb, &dst); newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst); newpn->pn_sk.resource = pn->pn_sk.resource; + skb_queue_head_init(&newpn->ctrlreq_queue); newpn->pipe_handle = pipe_handle; newpn->peer_type = peer_type; newpn->rx_credits = newpn->tx_credits = 0; @@ -581,7 +593,7 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb) break; case PNS_PEP_CTRL_REQ: - pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE); + pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE, GFP_ATOMIC); break; case PNS_PEP_RESET_REQ: @@ -684,6 +696,7 @@ out: static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) { + struct pep_sock *pn = pep_sk(sk); int answ; switch (cmd) { @@ -692,7 +705,10 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) return -EINVAL; lock_sock(sk); - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (sock_flag(sk, SOCK_URGINLINE) + && !skb_queue_empty(&pn->ctrlreq_queue)) + answ = skb_peek(&pn->ctrlreq_queue)->len; + else if (!skb_queue_empty(&sk->sk_receive_queue)) answ = skb_peek(&sk->sk_receive_queue)->len; else answ = 0; @@ -709,6 +725,7 @@ static int pep_init(struct sock *sk) INIT_HLIST_HEAD(&pn->ackq); INIT_HLIST_HEAD(&pn->hlist); + skb_queue_head_init(&pn->ctrlreq_queue); pn->pipe_handle = PN_PIPE_INVALID_HANDLE; return 0; } @@ -810,11 +827,24 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, struct sk_buff *skb; int err; - if (unlikely(flags & MSG_OOB)) - return -EOPNOTSUPP; if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) return -ENOTCONN; + if ((flags & MSG_OOB) || sock_flag(sk, SOCK_URGINLINE)) { + /* Dequeue and acknowledge control request */ + struct pep_sock *pn = pep_sk(sk); + + skb = skb_dequeue(&pn->ctrlreq_queue); + if (skb) { + pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, + GFP_KERNEL); + msg->msg_flags |= MSG_OOB; + goto copy; + } + if (flags & MSG_OOB) + return -EINVAL; + } + skb = skb_recv_datagram(sk, flags, noblock, &err); lock_sock(sk); if (skb == NULL) { @@ -827,9 +857,8 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, if (sk->sk_state == TCP_ESTABLISHED) pipe_grant_credits(sk); release_sock(sk); - +copy: msg->msg_flags |= MSG_EOR; - if (skb->len > len) msg->msg_flags |= MSG_TRUNC; else diff --git a/net/phonet/socket.c b/net/phonet/socket.c index cea1136cbe4..a9c3d1f2e9d 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -220,7 +220,9 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock, if (!skb_queue_empty(&sk->sk_receive_queue)) mask |= POLLIN | POLLRDNORM; - else if (sk->sk_state == TCP_CLOSE_WAIT) + if (!skb_queue_empty(&pn->ctrlreq_queue)) + mask |= POLLPRI; + if (!mask && sk->sk_state == TCP_CLOSE_WAIT) return POLLHUP; if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits) -- cgit v1.2.3 From 02a47617cdce440f60c71a51f3a93f9f5fcc5a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:16:16 -0700 Subject: Phonet: implement GPRS virtual interface over PEP socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/linux/phonet.h | 8 ++ include/linux/socket.h | 1 + include/net/phonet/gprs.h | 38 +++++ include/net/phonet/pep.h | 1 + net/phonet/Makefile | 2 +- net/phonet/pep-gprs.c | 347 ++++++++++++++++++++++++++++++++++++++++++++++ net/phonet/pep.c | 161 +++++++++++++++++++-- net/phonet/socket.c | 8 +- 8 files changed, 550 insertions(+), 16 deletions(-) create mode 100644 include/net/phonet/gprs.h create mode 100644 net/phonet/pep-gprs.c diff --git a/include/linux/phonet.h b/include/linux/phonet.h index f9218524207..c9609f9aeda 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h @@ -31,9 +31,17 @@ #define PN_PROTO_PIPE 2 #define PHONET_NPROTO 3 +/* Socket options for SOL_PNPIPE level */ +#define PNPIPE_ENCAP 1 +#define PNPIPE_IFINDEX 2 + #define PNADDR_ANY 0 #define PNPORT_RESOURCE_ROUTING 0 +/* Values for PNPIPE_ENCAP option */ +#define PNPIPE_ENCAP_NONE 0 +#define PNPIPE_ENCAP_IP 1 + /* ioctls */ #define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0) diff --git a/include/linux/socket.h b/include/linux/socket.h index 818ca33bf79..20fc4bbfca4 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -297,6 +297,7 @@ struct ucred { #define SOL_RXRPC 272 #define SOL_PPPOL2TP 273 #define SOL_BLUETOOTH 274 +#define SOL_PNPIPE 275 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h new file mode 100644 index 00000000000..928daf595be --- /dev/null +++ b/include/net/phonet/gprs.h @@ -0,0 +1,38 @@ +/* + * File: pep_gprs.h + * + * GPRS over Phonet pipe end point socket + * + * Copyright (C) 2008 Nokia Corporation. + * + * Author: Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef NET_PHONET_GPRS_H +#define NET_PHONET_GPRS_H + +struct sock; +struct sk_buff; + +int pep_writeable(struct sock *sk); +int pep_write(struct sock *sk, struct sk_buff *skb); +struct sk_buff *pep_read(struct sock *sk); + +int gprs_attach(struct sock *sk); +void gprs_detach(struct sock *sk); + +#endif diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h index 4d79564850a..fcd793030e4 100644 --- a/include/net/phonet/pep.h +++ b/include/net/phonet/pep.h @@ -35,6 +35,7 @@ struct pep_sock { struct sock *listener; struct sk_buff_head ctrlreq_queue; #define PNPIPE_CTRLREQ_MAX 10 + int ifindex; u16 peer_type; /* peer type/subtype */ u8 pipe_handle; diff --git a/net/phonet/Makefile b/net/phonet/Makefile index 505df2a04a8..d62bbba649b 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -8,4 +8,4 @@ phonet-objs := \ sysctl.o \ af_phonet.o -pn_pep-objs := pep.o +pn_pep-objs := pep.o pep-gprs.o diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c new file mode 100644 index 00000000000..9978afbd9f2 --- /dev/null +++ b/net/phonet/pep-gprs.c @@ -0,0 +1,347 @@ +/* + * File: pep-gprs.c + * + * GPRS over Phonet pipe end point socket + * + * Copyright (C) 2008 Nokia Corporation. + * + * Author: Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define GPRS_DEFAULT_MTU 1400 + +struct gprs_dev { + struct sock *sk; + void (*old_state_change)(struct sock *); + void (*old_data_ready)(struct sock *, int); + void (*old_write_space)(struct sock *); + + struct net_device *net; + struct net_device_stats stats; + + struct sk_buff_head tx_queue; + struct work_struct tx_work; + spinlock_t tx_lock; + unsigned tx_max; +}; + +static int gprs_type_trans(struct sk_buff *skb) +{ + const u8 *pvfc; + u8 buf; + + pvfc = skb_header_pointer(skb, 0, 1, &buf); + if (!pvfc) + return 0; + /* Look at IP version field */ + switch (*pvfc >> 4) { + case 4: + return htons(ETH_P_IP); + case 6: + return htons(ETH_P_IPV6); + } + return 0; +} + +/* + * Socket callbacks + */ + +static void gprs_state_change(struct sock *sk) +{ + struct gprs_dev *dev = sk->sk_user_data; + + if (sk->sk_state == TCP_CLOSE_WAIT) { + netif_stop_queue(dev->net); + netif_carrier_off(dev->net); + } +} + +static int gprs_recv(struct gprs_dev *dev, struct sk_buff *skb) +{ + int err = 0; + u16 protocol = gprs_type_trans(skb); + + if (!protocol) { + err = -EINVAL; + goto drop; + } + + if (likely(skb_headroom(skb) & 3)) { + struct sk_buff *rskb, *fs; + int flen = 0; + + /* Phonet Pipe data header is misaligned (3 bytes), + * so wrap the IP packet as a single fragment of an head-less + * socket buffer. The network stack will pull what it needs, + * but at least, the whole IP payload is not memcpy'd. */ + rskb = netdev_alloc_skb(dev->net, 0); + if (!rskb) { + err = -ENOBUFS; + goto drop; + } + skb_shinfo(rskb)->frag_list = skb; + rskb->len += skb->len; + rskb->data_len += rskb->len; + rskb->truesize += rskb->len; + + /* Avoid nested fragments */ + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) + flen += fs->len; + skb->next = skb_shinfo(skb)->frag_list; + skb_shinfo(skb)->frag_list = NULL; + skb->len -= flen; + skb->data_len -= flen; + skb->truesize -= flen; + + skb = rskb; + } + + skb->protocol = protocol; + skb_reset_mac_header(skb); + skb->dev = dev->net; + + if (likely(dev->net->flags & IFF_UP)) { + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + netif_rx(skb); + skb = NULL; + } else + err = -ENODEV; + +drop: + if (skb) { + dev_kfree_skb(skb); + dev->stats.rx_dropped++; + } + return err; +} + +static void gprs_data_ready(struct sock *sk, int len) +{ + struct gprs_dev *dev = sk->sk_user_data; + struct sk_buff *skb; + + while ((skb = pep_read(sk)) != NULL) { + skb_orphan(skb); + gprs_recv(dev, skb); + } +} + +static void gprs_write_space(struct sock *sk) +{ + struct gprs_dev *dev = sk->sk_user_data; + unsigned credits = pep_writeable(sk); + + spin_lock_bh(&dev->tx_lock); + dev->tx_max = credits; + if (credits > skb_queue_len(&dev->tx_queue)) + netif_wake_queue(dev->net); + spin_unlock_bh(&dev->tx_lock); +} + +/* + * Network device callbacks + */ + +static int gprs_xmit(struct sk_buff *skb, struct net_device *net) +{ + struct gprs_dev *dev = netdev_priv(net); + + switch (skb->protocol) { + case htons(ETH_P_IP): + case htons(ETH_P_IPV6): + break; + default: + dev_kfree_skb(skb); + return 0; + } + + spin_lock(&dev->tx_lock); + if (likely(skb_queue_len(&dev->tx_queue) < dev->tx_max)) { + skb_queue_tail(&dev->tx_queue, skb); + skb = NULL; + } + if (skb_queue_len(&dev->tx_queue) >= dev->tx_max) + netif_stop_queue(net); + spin_unlock(&dev->tx_lock); + + schedule_work(&dev->tx_work); + if (unlikely(skb)) + dev_kfree_skb(skb); + return 0; +} + +static void gprs_tx(struct work_struct *work) +{ + struct gprs_dev *dev = container_of(work, struct gprs_dev, tx_work); + struct sock *sk = dev->sk; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&dev->tx_queue)) != NULL) { + int err; + + dev->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; + + skb_orphan(skb); + skb_set_owner_w(skb, sk); + + lock_sock(sk); + err = pep_write(sk, skb); + if (err) { + LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n", + dev->net->name, err); + dev->stats.tx_aborted_errors++; + dev->stats.tx_errors++; + } + release_sock(sk); + } + + lock_sock(sk); + gprs_write_space(sk); + release_sock(sk); +} + +static int gprs_set_mtu(struct net_device *net, int new_mtu) +{ + if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11))) + return -EINVAL; + + net->mtu = new_mtu; + return 0; +} + +static struct net_device_stats *gprs_get_stats(struct net_device *net) +{ + struct gprs_dev *dev = netdev_priv(net); + + return &dev->stats; +} + +static void gprs_setup(struct net_device *net) +{ + net->features = NETIF_F_FRAGLIST; + net->type = ARPHRD_NONE; + net->flags = IFF_POINTOPOINT | IFF_NOARP; + net->mtu = GPRS_DEFAULT_MTU; + net->hard_header_len = 0; + net->addr_len = 0; + net->tx_queue_len = 10; + + net->destructor = free_netdev; + net->hard_start_xmit = gprs_xmit; /* mandatory */ + net->change_mtu = gprs_set_mtu; + net->get_stats = gprs_get_stats; +} + +/* + * External interface + */ + +/* + * Attach a GPRS interface to a datagram socket. + * Returns the interface index on success, negative error code on error. + */ +int gprs_attach(struct sock *sk) +{ + static const char ifname[] = "gprs%d"; + struct gprs_dev *dev; + struct net_device *net; + int err; + + if (unlikely(sk->sk_type == SOCK_STREAM)) + return -EINVAL; /* need packet boundaries */ + + /* Create net device */ + net = alloc_netdev(sizeof(*dev), ifname, gprs_setup); + if (!net) + return -ENOMEM; + dev = netdev_priv(net); + dev->net = net; + dev->tx_max = 0; + spin_lock_init(&dev->tx_lock); + skb_queue_head_init(&dev->tx_queue); + INIT_WORK(&dev->tx_work, gprs_tx); + + netif_stop_queue(net); + err = register_netdev(net); + if (err) { + free_netdev(net); + return err; + } + + lock_sock(sk); + if (unlikely(sk->sk_user_data)) { + err = -EBUSY; + goto out_rel; + } + if (unlikely((1 << sk->sk_state & (TCPF_CLOSE|TCPF_LISTEN)) || + sock_flag(sk, SOCK_DEAD))) { + err = -EINVAL; + goto out_rel; + } + sk->sk_user_data = dev; + dev->old_state_change = sk->sk_state_change; + dev->old_data_ready = sk->sk_data_ready; + dev->old_write_space = sk->sk_write_space; + sk->sk_state_change = gprs_state_change; + sk->sk_data_ready = gprs_data_ready; + sk->sk_write_space = gprs_write_space; + release_sock(sk); + + sock_hold(sk); + dev->sk = sk; + + printk(KERN_DEBUG"%s: attached\n", net->name); + gprs_write_space(sk); /* kick off TX */ + return net->ifindex; + +out_rel: + release_sock(sk); + unregister_netdev(net); + return err; +} + +void gprs_detach(struct sock *sk) +{ + struct gprs_dev *dev = sk->sk_user_data; + struct net_device *net = dev->net; + + lock_sock(sk); + sk->sk_user_data = NULL; + sk->sk_state_change = dev->old_state_change; + sk->sk_data_ready = dev->old_data_ready; + sk->sk_write_space = dev->old_write_space; + release_sock(sk); + + printk(KERN_DEBUG"%s: detached\n", net->name); + unregister_netdev(net); + flush_scheduled_work(); + sock_put(sk); + skb_queue_purge(&dev->tx_queue); +} diff --git a/net/phonet/pep.c b/net/phonet/pep.c index d564d07cb79..bc6d50f8324 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -31,6 +31,7 @@ #include #include #include +#include /* sk_state values: * TCP_CLOSE sock not in use yet @@ -612,6 +613,7 @@ drop: static void pep_sock_close(struct sock *sk, long timeout) { struct pep_sock *pn = pep_sk(sk); + int ifindex = 0; sk_common_release(sk); @@ -625,7 +627,12 @@ static void pep_sock_close(struct sock *sk, long timeout) sk_del_node_init(sknode); sk->sk_state = TCP_CLOSE; } + ifindex = pn->ifindex; + pn->ifindex = 0; release_sock(sk); + + if (ifindex) + gprs_detach(sk); } static int pep_wait_connreq(struct sock *sk, int noblock) @@ -730,12 +737,107 @@ static int pep_init(struct sock *sk) return 0; } +static int pep_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int optlen) +{ + struct pep_sock *pn = pep_sk(sk); + int val = 0, err = 0; + + if (level != SOL_PNPIPE) + return -ENOPROTOOPT; + if (optlen >= sizeof(int)) { + if (get_user(val, (int __user *) optval)) + return -EFAULT; + } + + lock_sock(sk); + switch (optname) { + case PNPIPE_ENCAP: + if (val && val != PNPIPE_ENCAP_IP) { + err = -EINVAL; + break; + } + if (!pn->ifindex == !val) + break; /* Nothing to do! */ + if (!capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + if (val) { + release_sock(sk); + err = gprs_attach(sk); + if (err > 0) { + pn->ifindex = err; + err = 0; + } + } else { + pn->ifindex = 0; + release_sock(sk); + gprs_detach(sk); + err = 0; + } + goto out_norel; + default: + err = -ENOPROTOOPT; + } + release_sock(sk); + +out_norel: + return err; +} + +static int pep_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct pep_sock *pn = pep_sk(sk); + int len, val; + + if (level != SOL_PNPIPE) + return -ENOPROTOOPT; + if (get_user(len, optlen)) + return -EFAULT; + + switch (optname) { + case PNPIPE_ENCAP: + val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE; + break; + case PNPIPE_IFINDEX: + val = pn->ifindex; + break; + default: + return -ENOPROTOOPT; + } + + len = min_t(unsigned int, sizeof(int), len); + if (put_user(len, optlen)) + return -EFAULT; + if (put_user(val, (int __user *) optval)) + return -EFAULT; + return 0; +} + +static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) +{ + struct pep_sock *pn = pep_sk(sk); + struct pnpipehdr *ph; + + skb_push(skb, 3); + skb_reset_transport_header(skb); + ph = pnp_hdr(skb); + ph->utid = 0; + ph->message_id = PNS_PIPE_DATA; + ph->pipe_handle = pn->pipe_handle; + if (pn_flow_safe(pn->tx_fc) && pn->tx_credits) + pn->tx_credits--; + + return pn_skb_send(sk, skb, &pipe_srv); +} + static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { struct pep_sock *pn = pep_sk(sk); struct sk_buff *skb = NULL; - struct pnpipehdr *ph; long timeo; int flags = msg->msg_flags; int err, done; @@ -801,16 +903,7 @@ disabled: if (err < 0) goto out; - __skb_push(skb, 3); - skb_reset_transport_header(skb); - ph = pnp_hdr(skb); - ph->utid = 0; - ph->message_id = PNS_PIPE_DATA; - ph->pipe_handle = pn->pipe_handle; - if (pn_flow_safe(pn->tx_fc)) /* credit-based flow control */ - pn->tx_credits--; - - err = pn_skb_send(sk, skb, &pipe_srv); + err = pipe_skb_send(sk, skb); if (err >= 0) err = len; /* success! */ skb = NULL; @@ -820,6 +913,50 @@ out: return err; } +int pep_writeable(struct sock *sk) +{ + struct pep_sock *pn = pep_sk(sk); + + return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0; +} + +int pep_write(struct sock *sk, struct sk_buff *skb) +{ + struct sk_buff *rskb, *fs; + int flen = 0; + + rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); + if (!rskb) { + kfree_skb(skb); + return -ENOMEM; + } + skb_shinfo(rskb)->frag_list = skb; + rskb->len += skb->len; + rskb->data_len += rskb->len; + rskb->truesize += rskb->len; + + /* Avoid nested fragments */ + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) + flen += fs->len; + skb->next = skb_shinfo(skb)->frag_list; + skb_shinfo(skb)->frag_list = NULL; + skb->len -= flen; + skb->data_len -= flen; + skb->truesize -= flen; + + skb_reserve(rskb, MAX_PHONET_HEADER + 3); + return pipe_skb_send(sk, rskb); +} + +struct sk_buff *pep_read(struct sock *sk) +{ + struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); + + if (sk->sk_state == TCP_ESTABLISHED) + pipe_grant_credits(sk); + return skb; +} + static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len) @@ -902,6 +1039,8 @@ static struct proto pep_proto = { .accept = pep_sock_accept, .ioctl = pep_ioctl, .init = pep_init, + .setsockopt = pep_setsockopt, + .getsockopt = pep_getsockopt, .sendmsg = pep_sendmsg, .recvmsg = pep_recvmsg, .backlog_rcv = pep_do_rcv, diff --git a/net/phonet/socket.c b/net/phonet/socket.c index a9c3d1f2e9d..d81740187fb 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -342,11 +342,11 @@ const struct proto_ops phonet_stream_ops = { .ioctl = pn_socket_ioctl, .listen = pn_socket_listen, .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, #ifdef CONFIG_COMPAT - .compat_setsockopt = sock_no_setsockopt, - .compat_getsockopt = compat_sock_no_getsockopt, + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, #endif .sendmsg = pn_socket_sendmsg, .recvmsg = sock_common_recvmsg, -- cgit v1.2.3 From 95430c0b140c31cb9e39f876afe1c0e9947d1aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 5 Oct 2008 11:16:36 -0700 Subject: Phonet: pipe end-point protocol documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- Documentation/networking/phonet.txt | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt index 57d3e59edb1..0e6e592f4f5 100644 --- a/Documentation/networking/phonet.txt +++ b/Documentation/networking/phonet.txt @@ -112,6 +112,60 @@ However, connect() and getpeername() are not supported, as they did not seem useful with Phonet usages (could be added easily). +Phonet Pipe protocol +-------------------- + +The Phonet Pipe protocol is a simple sequenced packets protocol +with end-to-end congestion control. It uses the passive listening +socket paradigm. The listening socket is bound to an unique free object +ID. Each listening socket can handle up to 255 simultaneous +connections, one per accept()'d socket. + + int lfd, cfd; + + lfd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE); + listen (lfd, INT_MAX); + + /* ... */ + cfd = accept(lfd, NULL, NULL); + for (;;) + { + char buf[...]; + ssize_t len = read(cfd, buf, sizeof(buf)); + + /* ... */ + + write(cfd, msg, msglen); + } + +Connections are established between two endpoints by a "third party" +application. This means that both endpoints are passive; so connect() +is not possible. + +WARNING: +When polling a connected pipe socket for writability, there is an +intrinsic race condition whereby writability might be lost between the +polling and the writing system calls. In this case, the socket will +block until write because possible again, unless non-blocking mode +becomes enabled. + + +The pipe protocol provides two socket options at the SOL_PNPIPE level: + + PNPIPE_ENCAP accepts one integer value (int) of: + + PNPIPE_ENCAP_NONE: The socket operates normally (default). + + PNPIPE_ENCAP_IP: The socket is used as a backend for a virtual IP + interface. This requires CAP_NET_ADMIN capability. GPRS data + support on Nokia modems can use this. Note that the socket cannot + be reliably poll()'d or read() from while in this mode. + + PNPIPE_IFINDEX is a read-only integer value. It contains the + interface index of the network interface created by PNPIPE_ENCAP, + or zero if encapsulation is off. + + Authors ------- -- cgit v1.2.3 From 13c1d18931ebb5cf407cb348ef2cd6284d68902d Mon Sep 17 00:00:00 2001 From: Arnaud Ebalard Date: Sun, 5 Oct 2008 13:33:42 -0700 Subject: xfrm: MIGRATE enhancements (draft-ebalard-mext-pfkey-enhanced-migrate) Provides implementation of the enhancements of XFRM/PF_KEY MIGRATE mechanism specified in draft-ebalard-mext-pfkey-enhanced-migrate-00. Defines associated PF_KEY SADB_X_EXT_KMADDRESS extension and XFRM/netlink XFRMA_KMADDRESS attribute. Signed-off-by: Arnaud Ebalard Signed-off-by: David S. Miller --- include/linux/pfkeyv2.h | 13 +++++++- include/linux/xfrm.h | 10 ++++++ include/net/xfrm.h | 15 +++++++-- net/key/af_key.c | 86 +++++++++++++++++++++++++++++++++++++++---------- net/xfrm/xfrm_policy.c | 5 +-- net/xfrm/xfrm_state.c | 5 +-- net/xfrm/xfrm_user.c | 57 +++++++++++++++++++++++++------- 7 files changed, 154 insertions(+), 37 deletions(-) diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index 700725ddcaa..01b262959f2 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h @@ -226,6 +226,15 @@ struct sadb_x_sec_ctx { } __attribute__((packed)); /* sizeof(struct sadb_sec_ctx) = 8 */ +/* Used by MIGRATE to pass addresses IKE will use to perform + * negotiation with the peer */ +struct sadb_x_kmaddress { + uint16_t sadb_x_kmaddress_len; + uint16_t sadb_x_kmaddress_exttype; + uint32_t sadb_x_kmaddress_reserved; +} __attribute__((packed)); +/* sizeof(struct sadb_x_kmaddress) == 8 */ + /* Message types */ #define SADB_RESERVED 0 #define SADB_GETSPI 1 @@ -346,7 +355,9 @@ struct sadb_x_sec_ctx { #define SADB_X_EXT_NAT_T_DPORT 22 #define SADB_X_EXT_NAT_T_OA 23 #define SADB_X_EXT_SEC_CTX 24 -#define SADB_EXT_MAX 24 +/* Used with MIGRATE to pass @ to IKE for negotiation */ +#define SADB_X_EXT_KMADDRESS 25 +#define SADB_EXT_MAX 25 /* Identity Extension values */ #define SADB_IDENTTYPE_RESERVED 0 diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index fb0c215a305..4bc1e6b86cb 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -279,6 +279,7 @@ enum xfrm_attr_type_t { XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ XFRMA_MIGRATE, XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ + XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) @@ -415,6 +416,15 @@ struct xfrm_user_report { struct xfrm_selector sel; }; +/* Used by MIGRATE to pass addresses IKE should use to perform + * SA negotiation with the peer */ +struct xfrm_user_kmaddress { + xfrm_address_t local; + xfrm_address_t remote; + __u32 reserved; + __u16 family; +}; + struct xfrm_user_migrate { xfrm_address_t old_daddr; xfrm_address_t old_saddr; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b98d2056f27..11c890ad8eb 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -492,6 +492,13 @@ struct xfrm_policy struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; }; +struct xfrm_kmaddress { + xfrm_address_t local; + xfrm_address_t remote; + u32 reserved; + u16 family; +}; + struct xfrm_migrate { xfrm_address_t old_daddr; xfrm_address_t old_saddr; @@ -531,7 +538,7 @@ struct xfrm_mgr int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); - int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles); + int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k); }; extern int xfrm_register_km(struct xfrm_mgr *km); @@ -1432,12 +1439,14 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, #ifdef CONFIG_XFRM_MIGRATE extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_bundles); + struct xfrm_migrate *m, int num_bundles, + struct xfrm_kmaddress *k); extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, struct xfrm_migrate *m); extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_bundles); + struct xfrm_migrate *m, int num_bundles, + struct xfrm_kmaddress *k); #endif extern wait_queue_head_t km_waitq; diff --git a/net/key/af_key.c b/net/key/af_key.c index 7ae641df70b..362fe317e1f 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -398,6 +398,7 @@ static u8 sadb_ext_min_len[] = { [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), + [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), }; /* Verify sadb_address_{len,prefixlen} against sa_family. */ @@ -2384,24 +2385,21 @@ static int pfkey_sockaddr_pair_size(sa_family_t family) return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); } -static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, +static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, xfrm_address_t *saddr, xfrm_address_t *daddr, u16 *family) { - u8 *sa = (u8 *) (rq + 1); int af, socklen; - if (rq->sadb_x_ipsecrequest_len < - pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) + if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) return -EINVAL; - af = pfkey_sockaddr_extract((struct sockaddr *) sa, - saddr); + af = pfkey_sockaddr_extract(sa, saddr); if (!af) return -EINVAL; socklen = pfkey_sockaddr_len(af); - if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), + if (pfkey_sockaddr_extract((struct sockaddr *) (((u8 *)sa) + socklen), daddr) != af) return -EINVAL; @@ -2421,7 +2419,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, return -EINVAL; /* old endoints */ - err = parse_sockaddr_pair(rq1, &m->old_saddr, &m->old_daddr, + err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), + rq1->sadb_x_ipsecrequest_len, + &m->old_saddr, &m->old_daddr, &m->old_family); if (err) return err; @@ -2434,7 +2434,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, return -EINVAL; /* new endpoints */ - err = parse_sockaddr_pair(rq2, &m->new_saddr, &m->new_daddr, + err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), + rq2->sadb_x_ipsecrequest_len, + &m->new_saddr, &m->new_daddr, &m->new_family); if (err) return err; @@ -2460,29 +2462,40 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, int i, len, ret, err = -EINVAL; u8 dir; struct sadb_address *sa; + struct sadb_x_kmaddress *kma; struct sadb_x_policy *pol; struct sadb_x_ipsecrequest *rq; struct xfrm_selector sel; struct xfrm_migrate m[XFRM_MAX_DEPTH]; + struct xfrm_kmaddress k; if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1], - ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || + ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || !ext_hdrs[SADB_X_EXT_POLICY - 1]) { err = -EINVAL; goto out; } + kma = ext_hdrs[SADB_X_EXT_KMADDRESS - 1]; pol = ext_hdrs[SADB_X_EXT_POLICY - 1]; - if (!pol) { - err = -EINVAL; - goto out; - } if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) { err = -EINVAL; goto out; } + if (kma) { + /* convert sadb_x_kmaddress to xfrm_kmaddress */ + k.reserved = kma->sadb_x_kmaddress_reserved; + ret = parse_sockaddr_pair((struct sockaddr *)(kma + 1), + 8*(kma->sadb_x_kmaddress_len) - sizeof(*kma), + &k.local, &k.remote, &k.family); + if (ret < 0) { + err = ret; + goto out; + } + } + dir = pol->sadb_x_policy_dir - 1; memset(&sel, 0, sizeof(sel)); @@ -2527,7 +2540,8 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, goto out; } - return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i); + return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, + kma ? &k : NULL); out: return err; @@ -3319,6 +3333,32 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, return 0; } + +static int set_sadb_kmaddress(struct sk_buff *skb, struct xfrm_kmaddress *k) +{ + struct sadb_x_kmaddress *kma; + u8 *sa; + int family = k->family; + int socklen = pfkey_sockaddr_len(family); + int size_req; + + size_req = (sizeof(struct sadb_x_kmaddress) + + pfkey_sockaddr_pair_size(family)); + + kma = (struct sadb_x_kmaddress *)skb_put(skb, size_req); + memset(kma, 0, size_req); + kma->sadb_x_kmaddress_len = size_req / 8; + kma->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS; + kma->sadb_x_kmaddress_reserved = k->reserved; + + sa = (u8 *)(kma + 1); + if (!pfkey_sockaddr_fill(&k->local, 0, (struct sockaddr *)sa, family) || + !pfkey_sockaddr_fill(&k->remote, 0, (struct sockaddr *)(sa+socklen), family)) + return -EINVAL; + + return 0; +} + static int set_ipsecrequest(struct sk_buff *skb, uint8_t proto, uint8_t mode, int level, uint32_t reqid, uint8_t family, @@ -3351,7 +3391,8 @@ static int set_ipsecrequest(struct sk_buff *skb, #ifdef CONFIG_NET_KEY_MIGRATE static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_bundles) + struct xfrm_migrate *m, int num_bundles, + struct xfrm_kmaddress *k) { int i; int sasize_sel; @@ -3368,6 +3409,12 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH) return -EINVAL; + if (k != NULL) { + /* addresses for KM */ + size += PFKEY_ALIGN8(sizeof(struct sadb_x_kmaddress) + + pfkey_sockaddr_pair_size(k->family)); + } + /* selector */ sasize_sel = pfkey_sockaddr_size(sel->family); if (!sasize_sel) @@ -3404,6 +3451,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, hdr->sadb_msg_seq = 0; hdr->sadb_msg_pid = 0; + /* Addresses to be used by KM for negotiation, if ext is available */ + if (k != NULL && (set_sadb_kmaddress(skb, k) < 0)) + return -EINVAL; + /* selector src */ set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); @@ -3449,7 +3500,8 @@ err: } #else static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_bundles) + struct xfrm_migrate *m, int num_bundles, + struct xfrm_kmaddress *k) { return -ENOPROTOOPT; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b7ec08025ff..832b47c1de8 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2679,7 +2679,8 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate) } int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_migrate) + struct xfrm_migrate *m, int num_migrate, + struct xfrm_kmaddress *k) { int i, err, nx_cur = 0, nx_new = 0; struct xfrm_policy *pol = NULL; @@ -2723,7 +2724,7 @@ int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, } /* Stage 5 - announce */ - km_migrate(sel, dir, type, m, num_migrate); + km_migrate(sel, dir, type, m, num_migrate, k); xfrm_pol_put(pol); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 747fd8c291a..508337f9724 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1814,7 +1814,8 @@ EXPORT_SYMBOL(km_policy_expired); #ifdef CONFIG_XFRM_MIGRATE int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_migrate) + struct xfrm_migrate *m, int num_migrate, + struct xfrm_kmaddress *k) { int err = -EINVAL; int ret; @@ -1823,7 +1824,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, read_lock(&xfrm_km_lock); list_for_each_entry(km, &xfrm_km_list, list) { if (km->migrate) { - ret = km->migrate(sel, dir, type, m, num_migrate); + ret = km->migrate(sel, dir, type, m, num_migrate, k); if (!ret) err = ret; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 76f75df21e1..4a8a1abb59e 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, #ifdef CONFIG_XFRM_MIGRATE static int copy_from_user_migrate(struct xfrm_migrate *ma, + struct xfrm_kmaddress *k, struct nlattr **attrs, int *num) { struct nlattr *rt = attrs[XFRMA_MIGRATE]; struct xfrm_user_migrate *um; int i, num_migrate; + if (k != NULL) { + struct xfrm_user_kmaddress *uk; + + uk = nla_data(attrs[XFRMA_KMADDRESS]); + memcpy(&k->local, &uk->local, sizeof(k->local)); + memcpy(&k->remote, &uk->remote, sizeof(k->remote)); + k->family = uk->family; + k->reserved = uk->reserved; + } + um = nla_data(rt); num_migrate = nla_len(rt) / sizeof(*um); @@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, { struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); struct xfrm_migrate m[XFRM_MAX_DEPTH]; + struct xfrm_kmaddress km, *kmp; u8 type; int err; int n = 0; @@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, if (attrs[XFRMA_MIGRATE] == NULL) return -EINVAL; + kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; + err = copy_from_user_policy_type(&type, attrs); if (err) return err; - err = copy_from_user_migrate((struct xfrm_migrate *)m, - attrs, &n); + err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); if (err) return err; if (!n) return 0; - xfrm_migrate(&pi->sel, pi->dir, type, m, n); + xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); return 0; } @@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); } -static inline size_t xfrm_migrate_msgsize(int num_migrate) +static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) +{ + struct xfrm_user_kmaddress uk; + + memset(&uk, 0, sizeof(uk)); + uk.family = k->family; + uk.reserved = k->reserved; + memcpy(&uk.local, &k->local, sizeof(uk.local)); + memcpy(&uk.remote, &k->local, sizeof(uk.remote)); + + return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); +} + +static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) { return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) - + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) - + userpolicy_type_attrsize(); + + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) + + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) + + userpolicy_type_attrsize(); } static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, - int num_migrate, struct xfrm_selector *sel, - u8 dir, u8 type) + int num_migrate, struct xfrm_kmaddress *k, + struct xfrm_selector *sel, u8 dir, u8 type) { struct xfrm_migrate *mp; struct xfrm_userpolicy_id *pol_id; @@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); pol_id->dir = dir; + if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) + goto nlmsg_failure; + if (copy_to_user_policy_type(type, skb) < 0) goto nlmsg_failure; @@ -1836,23 +1866,25 @@ nlmsg_failure: } static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_migrate) + struct xfrm_migrate *m, int num_migrate, + struct xfrm_kmaddress *k) { struct sk_buff *skb; - skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); + skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); if (skb == NULL) return -ENOMEM; /* build migrate */ - if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) + if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) BUG(); return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); } #else static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_migrate *m, int num_migrate) + struct xfrm_migrate *m, int num_migrate, + struct xfrm_kmaddress *k) { return -ENOPROTOOPT; } @@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, + [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, }; static struct xfrm_link { -- cgit v1.2.3 From 554794de7949d1a6279336404c066f974d4c2bde Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 6 Oct 2008 09:54:39 -0700 Subject: pkt_sched: Fix handling of gso skbs on requeuing Jay Cliburn noticed and diagnosed a bug triggered in dev_gso_skb_destructor() after last change from qdisc->gso_skb to qdisc->requeue list. Since gso_segmented skbs can't be queued to another list this patch brings back qdisc->gso_skb for them. Reported-by: Jay Cliburn Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- include/net/sch_generic.h | 1 + net/sched/sch_generic.c | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 3b983e8a055..3fe49d80895 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -52,6 +52,7 @@ struct Qdisc u32 parent; atomic_t refcnt; unsigned long state; + struct sk_buff *gso_skb; struct sk_buff_head requeue; struct sk_buff_head q; struct netdev_queue *dev_queue; diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5e7e0bd38fe..3db4cf1bd26 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -44,7 +44,10 @@ static inline int qdisc_qlen(struct Qdisc *q) static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) { - __skb_queue_head(&q->requeue, skb); + if (unlikely(skb->next)) + q->gso_skb = skb; + else + __skb_queue_head(&q->requeue, skb); __netif_schedule(q); return 0; @@ -52,7 +55,10 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) static inline struct sk_buff *dequeue_skb(struct Qdisc *q) { - struct sk_buff *skb = skb_peek(&q->requeue); + struct sk_buff *skb = q->gso_skb; + + if (!skb) + skb = skb_peek(&q->requeue); if (unlikely(skb)) { struct net_device *dev = qdisc_dev(q); @@ -60,10 +66,15 @@ static inline struct sk_buff *dequeue_skb(struct Qdisc *q) /* check the reason of requeuing without tx lock first */ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); - if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) - __skb_unlink(skb, &q->requeue); - else + if (!netif_tx_queue_stopped(txq) && + !netif_tx_queue_frozen(txq)) { + if (q->gso_skb) + q->gso_skb = NULL; + else + __skb_unlink(skb, &q->requeue); + } else { skb = NULL; + } } else { skb = q->dequeue(q); } @@ -548,6 +559,7 @@ void qdisc_destroy(struct Qdisc *qdisc) module_put(ops->owner); dev_put(qdisc_dev(qdisc)); + kfree_skb(qdisc->gso_skb); __skb_queue_purge(&qdisc->requeue); kfree((char *) qdisc - qdisc->padded); -- cgit v1.2.3 From 6252352d16f7b45a0fd42224f7e70e0288dc4480 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 6 Oct 2008 10:41:50 -0700 Subject: pkt_sched: Simplify dev_requeue_skb and dequeue_skb qdisc->requeue was planned to universally replace all requeuing code, but at the top level we never requeue more than one skb, so qdisc-> gso_skb is enough for this. qdisc->requeue would be used on the lower levels only for one level deep requeuing (like in sch_hfsc) after finishing all the changes. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 3db4cf1bd26..31f6b614b59 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -44,12 +44,9 @@ static inline int qdisc_qlen(struct Qdisc *q) static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) { - if (unlikely(skb->next)) - q->gso_skb = skb; - else - __skb_queue_head(&q->requeue, skb); - + q->gso_skb = skb; __netif_schedule(q); + return 0; } @@ -57,24 +54,16 @@ static inline struct sk_buff *dequeue_skb(struct Qdisc *q) { struct sk_buff *skb = q->gso_skb; - if (!skb) - skb = skb_peek(&q->requeue); - if (unlikely(skb)) { struct net_device *dev = qdisc_dev(q); struct netdev_queue *txq; /* check the reason of requeuing without tx lock first */ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); - if (!netif_tx_queue_stopped(txq) && - !netif_tx_queue_frozen(txq)) { - if (q->gso_skb) - q->gso_skb = NULL; - else - __skb_unlink(skb, &q->requeue); - } else { + if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) + q->gso_skb = NULL; + else skb = NULL; - } } else { skb = q->dequeue(q); } -- cgit v1.2.3 From c7004482e8dcb7c3c72666395cfa98a216a4fb70 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 6 Oct 2008 10:43:54 -0700 Subject: tcp: Respect SO_RCVLOWAT in tcp_poll(). Based upon a report by Vito Caputo. Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1ab341e5d3e..7d81a1ee550 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -384,13 +384,17 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) /* Connected? */ if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) { + int target = sock_rcvlowat(sk, 0, INT_MAX); + + if (tp->urg_seq == tp->copied_seq && + !sock_flag(sk, SOCK_URGINLINE) && + tp->urg_data) + target--; + /* Potential race condition. If read of tp below will * escape above sk->sk_state, we can be illegally awaken * in SYN_* states. */ - if ((tp->rcv_nxt != tp->copied_seq) && - (tp->urg_seq != tp->copied_seq || - tp->rcv_nxt != tp->copied_seq + 1 || - sock_flag(sk, SOCK_URGINLINE) || !tp->urg_data)) + if (tp->rcv_nxt - tp->copied_seq >= target) mask |= POLLIN | POLLRDNORM; if (!(sk->sk_shutdown & SEND_SHUTDOWN)) { -- cgit v1.2.3