From 03efed8a2a1b8e00164eb4720a82a7dd5e368a8e Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Sat, 28 May 2011 00:34:19 +0800 Subject: ocfs2: Bugfix for hard readonly mount ocfs2 cannot currently mount a device that is readonly at the media ("hard readonly"). Fix the broken places. see detail: http://oss.oracle.com/bugzilla/show_bug.cgi?id=1322 [ Description edited -- Joel ] Signed-off-by: Tiger Yang Reviewed-by: Sunil Mushran Signed-off-by: Joel Becker --- fs/ocfs2/dlmglue.c | 21 +++++++++++++++------ fs/ocfs2/super.c | 3 ++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 7642d7ca73e5..da103f555a62 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1692,7 +1692,7 @@ int ocfs2_open_lock(struct inode *inode) mlog(0, "inode %llu take PRMODE open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - if (ocfs2_mount_local(osb)) + if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb)) goto out; lockres = &OCFS2_I(inode)->ip_open_lockres; @@ -1718,6 +1718,12 @@ int ocfs2_try_open_lock(struct inode *inode, int write) (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); + if (ocfs2_is_hard_readonly(osb)) { + if (write) + status = -EROFS; + goto out; + } + if (ocfs2_mount_local(osb)) goto out; @@ -2298,7 +2304,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode, if (ocfs2_is_hard_readonly(osb)) { if (ex) status = -EROFS; - goto bail; + goto getbh; } if (ocfs2_mount_local(osb)) @@ -2356,7 +2362,7 @@ local: mlog_errno(status); goto bail; } - +getbh: if (ret_bh) { status = ocfs2_assign_bh(inode, ret_bh, local_bh); if (status < 0) { @@ -2628,8 +2634,11 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex) BUG_ON(!dl); - if (ocfs2_is_hard_readonly(osb)) - return -EROFS; + if (ocfs2_is_hard_readonly(osb)) { + if (ex) + return -EROFS; + return 0; + } if (ocfs2_mount_local(osb)) return 0; @@ -2647,7 +2656,7 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex) struct ocfs2_dentry_lock *dl = dentry->d_fsdata; struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); - if (!ocfs2_mount_local(osb)) + if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(osb, &dl->dl_lockres, level); } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index cdbaf5e97308..029c4cd8a691 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1974,7 +1974,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) * If we failed before we got a uuid_str yet, we can't stop * heartbeat. Otherwise, do it. */ - if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str) + if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str && + !ocfs2_is_hard_readonly(osb)) hangup_needed = 1; if (osb->cconn) -- cgit From 3d75be7c4771c7e4d5b5fa586a599af8473de32c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:56:31 +0300 Subject: ocfs2: checking the wrong variable in ocfs2_move_extent() "new_phys_cpos" is always a valid pointer here. ocfs2_probe_alloc_group() allocates "*new_phys_cpos". Signed-off-by: Dan Carpenter Signed-off-by: Joel Becker --- fs/ocfs2/move_extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index cd9427023d2e..d3433d60dbb9 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c @@ -746,7 +746,7 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context, */ ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop, new_phys_cpos); - if (!new_phys_cpos) { + if (!*new_phys_cpos) { ret = -ENOSPC; goto out_commit; } -- cgit From 87f0d5c8db7aad85b9120c26723fdc63cd84a460 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 29 May 2011 22:57:16 +0300 Subject: ocfs2: null deref on allocation error The original code had a null derefence in the error handling. Signed-off-by: Dan Carpenter Signed-off-by: Joel Becker --- fs/ocfs2/ioctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index bc91072b7219..d9a6ce779266 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -381,7 +381,7 @@ int ocfs2_info_handle_freeinode(struct inode *inode, if (!oifi) { status = -ENOMEM; mlog_errno(status); - goto bail; + goto out_err; } if (o2info_from_user(*oifi, req)) @@ -431,7 +431,7 @@ bail: o2info_set_request_error(&oifi->ifi_req, req); kfree(oifi); - +out_err: return status; } @@ -666,7 +666,7 @@ int ocfs2_info_handle_freefrag(struct inode *inode, if (!oiff) { status = -ENOMEM; mlog_errno(status); - goto bail; + goto out_err; } if (o2info_from_user(*oiff, req)) @@ -716,7 +716,7 @@ bail: o2info_set_request_error(&oiff->iff_req, req); kfree(oiff); - +out_err: return status; } -- cgit From 730e663bd82c1a10a85ff00728d34152a5a67ec8 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 May 2011 21:58:05 +0900 Subject: ocfs2: use proper little-endian bitops Using __test_and_{set,clear}_bit_le() with ignoring its return value can be replaced with __{set,clear}_bit_le(). Signed-off-by: Akinobu Mita Cc: Joel Becker Cc: Mark Fasheh Cc: ocfs2-devel@oss.oracle.com Signed-off-by: Joel Becker --- fs/ocfs2/ocfs2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 409285854f64..bcde467acca3 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -836,13 +836,13 @@ static inline unsigned int ocfs2_clusters_to_megabytes(struct super_block *sb, static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap) { - __test_and_set_bit_le(bit, bitmap); + __set_bit_le(bit, bitmap); } #define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr)) static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap) { - __test_and_clear_bit_le(bit, bitmap); + __clear_bit_le(bit, bitmap); } #define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr)) -- cgit From d2eece376648d2f7ba0a7d78f3c4d0421e608ac2 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:21:54 -0700 Subject: ocfs2/cluster: Abort heartbeat start on hard-ro devices Currently if the heartbeat device is hard-ro, the o2hb thread keeps chugging along and dumping errors along the way. The user needs to manually stop the heartbeat. The patch addresses this shortcoming by adding a limit to the number of times the hb thread will iterate in an unsteady state. If the hb thread does not ready steady state in that many interation, the start is aborted. Signed-off-by: Sunil Mushran --- fs/ocfs2/cluster/heartbeat.c | 185 +++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 69 deletions(-) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 9a3e6bbff27b..4728a746281d 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -216,6 +216,7 @@ struct o2hb_region { struct list_head hr_all_item; unsigned hr_unclean_stop:1, + hr_aborted_start:1, hr_item_pinned:1, hr_item_dropped:1; @@ -254,6 +255,10 @@ struct o2hb_region { * a more complete api that doesn't lead to this sort of fragility. */ atomic_t hr_steady_iterations; + /* terminate o2hb thread if it does not reach steady state + * (hr_steady_iterations == 0) within hr_unsteady_iterations */ + atomic_t hr_unsteady_iterations; + char hr_dev_name[BDEVNAME_SIZE]; unsigned int hr_timeout_ms; @@ -324,6 +329,10 @@ static void o2hb_write_timeout(struct work_struct *work) static void o2hb_arm_write_timeout(struct o2hb_region *reg) { + /* Arm writeout only after thread reaches steady state */ + if (atomic_read(®->hr_steady_iterations) != 0) + return; + mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n", O2HB_MAX_WRITE_TIMEOUT_MS); @@ -537,9 +546,14 @@ static int o2hb_verify_crc(struct o2hb_region *reg, return read == computed; } -/* We want to make sure that nobody is heartbeating on top of us -- - * this will help detect an invalid configuration. */ -static void o2hb_check_last_timestamp(struct o2hb_region *reg) +/* + * Compare the slot data with what we wrote in the last iteration. + * If the match fails, print an appropriate error message. This is to + * detect errors like... another node hearting on the same slot, + * flaky device that is losing writes, etc. + * Returns 1 if check succeeds, 0 otherwise. + */ +static int o2hb_check_own_slot(struct o2hb_region *reg) { struct o2hb_disk_slot *slot; struct o2hb_disk_heartbeat_block *hb_block; @@ -548,13 +562,13 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg) slot = ®->hr_slots[o2nm_this_node()]; /* Don't check on our 1st timestamp */ if (!slot->ds_last_time) - return; + return 0; hb_block = slot->ds_raw_block; if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time && le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation && hb_block->hb_node == slot->ds_node_num) - return; + return 1; #define ERRSTR1 "Another node is heartbeating on device" #define ERRSTR2 "Heartbeat generation mismatch on device" @@ -574,6 +588,8 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg) (unsigned long long)slot->ds_last_time, hb_block->hb_node, (unsigned long long)le64_to_cpu(hb_block->hb_generation), (unsigned long long)le64_to_cpu(hb_block->hb_seq)); + + return 0; } static inline void o2hb_prepare_block(struct o2hb_region *reg, @@ -719,17 +735,24 @@ static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot) o2nm_node_put(node); } -static void o2hb_set_quorum_device(struct o2hb_region *reg, - struct o2hb_disk_slot *slot) +static void o2hb_set_quorum_device(struct o2hb_region *reg) { - assert_spin_locked(&o2hb_live_lock); - if (!o2hb_global_heartbeat_active()) return; - if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + /* Prevent race with o2hb_heartbeat_group_drop_item() */ + if (kthread_should_stop()) + return; + + /* Tag region as quorum only after thread reaches steady state */ + if (atomic_read(®->hr_steady_iterations) != 0) return; + spin_lock(&o2hb_live_lock); + + if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + goto unlock; + /* * A region can be added to the quorum only when it sees all * live nodes heartbeat on it. In other words, the region has been @@ -737,13 +760,10 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg, */ if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap, sizeof(o2hb_live_node_bitmap))) - return; - - if (slot->ds_changed_samples < O2HB_LIVE_THRESHOLD) - return; + goto unlock; - printk(KERN_NOTICE "o2hb: Region %s is now a quorum device\n", - config_item_name(®->hr_item)); + printk(KERN_NOTICE "o2hb: Region %s (%s) is now a quorum device\n", + config_item_name(®->hr_item), reg->hr_dev_name); set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); @@ -754,6 +774,8 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg, if (o2hb_pop_count(&o2hb_quorum_region_bitmap, O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF) o2hb_region_unpin(NULL); +unlock: + spin_unlock(&o2hb_live_lock); } static int o2hb_check_slot(struct o2hb_region *reg, @@ -925,8 +947,6 @@ fire_callbacks: slot->ds_equal_samples = 0; } out: - o2hb_set_quorum_device(reg, slot); - spin_unlock(&o2hb_live_lock); o2hb_run_event_list(&event); @@ -957,7 +977,8 @@ static int o2hb_highest_node(unsigned long *nodes, static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) { - int i, ret, highest_node, change = 0; + int i, ret, highest_node; + int membership_change = 0, own_slot_ok = 0; unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)]; unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; struct o2hb_bio_wait_ctxt write_wc; @@ -966,7 +987,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) sizeof(configured_nodes)); if (ret) { mlog_errno(ret); - return ret; + goto bail; } /* @@ -982,8 +1003,9 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES); if (highest_node >= O2NM_MAX_NODES) { - mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n"); - return -EINVAL; + mlog(ML_NOTICE, "o2hb: No configured nodes found!\n"); + ret = -EINVAL; + goto bail; } /* No sense in reading the slots of nodes that don't exist @@ -993,29 +1015,27 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) ret = o2hb_read_slots(reg, highest_node + 1); if (ret < 0) { mlog_errno(ret); - return ret; + goto bail; } /* With an up to date view of the slots, we can check that no * other node has been improperly configured to heartbeat in * our slot. */ - o2hb_check_last_timestamp(reg); + own_slot_ok = o2hb_check_own_slot(reg); /* fill in the proper info for our next heartbeat */ o2hb_prepare_block(reg, reg->hr_generation); - /* And fire off the write. Note that we don't wait on this I/O - * until later. */ ret = o2hb_issue_node_write(reg, &write_wc); if (ret < 0) { mlog_errno(ret); - return ret; + goto bail; } i = -1; while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { - change |= o2hb_check_slot(reg, ®->hr_slots[i]); + membership_change |= o2hb_check_slot(reg, ®->hr_slots[i]); } /* @@ -1030,18 +1050,39 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) * disk */ mlog(ML_ERROR, "Write error %d on device \"%s\"\n", write_wc.wc_error, reg->hr_dev_name); - return write_wc.wc_error; + ret = write_wc.wc_error; + goto bail; } - o2hb_arm_write_timeout(reg); + /* Skip disarming the timeout if own slot has stale/bad data */ + if (own_slot_ok) { + o2hb_set_quorum_device(reg); + o2hb_arm_write_timeout(reg); + } +bail: /* let the person who launched us know when things are steady */ - if (!change && (atomic_read(®->hr_steady_iterations) != 0)) { - if (atomic_dec_and_test(®->hr_steady_iterations)) + if (atomic_read(®->hr_steady_iterations) != 0) { + if (!ret && own_slot_ok && !membership_change) { + if (atomic_dec_and_test(®->hr_steady_iterations)) + wake_up(&o2hb_steady_queue); + } + } + + if (atomic_read(®->hr_steady_iterations) != 0) { + if (atomic_dec_and_test(®->hr_unsteady_iterations)) { + printk(KERN_NOTICE "o2hb: Unable to stabilize " + "heartbeart on region %s (%s)\n", + config_item_name(®->hr_item), + reg->hr_dev_name); + atomic_set(®->hr_steady_iterations, 0); + reg->hr_aborted_start = 1; wake_up(&o2hb_steady_queue); + ret = -EIO; + } } - return 0; + return ret; } /* Subtract b from a, storing the result in a. a *must* have a larger @@ -1095,7 +1136,8 @@ static int o2hb_thread(void *data) /* Pin node */ o2nm_depend_this_node(); - while (!kthread_should_stop() && !reg->hr_unclean_stop) { + while (!kthread_should_stop() && + !reg->hr_unclean_stop && !reg->hr_aborted_start) { /* We track the time spent inside * o2hb_do_disk_heartbeat so that we avoid more than * hr_timeout_ms between disk writes. On busy systems @@ -1103,10 +1145,7 @@ static int o2hb_thread(void *data) * likely to time itself out. */ do_gettimeofday(&before_hb); - i = 0; - do { - ret = o2hb_do_disk_heartbeat(reg); - } while (ret && ++i < 2); + ret = o2hb_do_disk_heartbeat(reg); do_gettimeofday(&after_hb); elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); @@ -1117,7 +1156,8 @@ static int o2hb_thread(void *data) after_hb.tv_sec, (unsigned long) after_hb.tv_usec, elapsed_msec); - if (elapsed_msec < reg->hr_timeout_ms) { + if (!kthread_should_stop() && + elapsed_msec < reg->hr_timeout_ms) { /* the kthread api has blocked signals for us so no * need to record the return value. */ msleep_interruptible(reg->hr_timeout_ms - elapsed_msec); @@ -1134,20 +1174,20 @@ static int o2hb_thread(void *data) * to timeout on this region when we could just as easily * write a clear generation - thus indicating to them that * this node has left this region. - * - * XXX: Should we skip this on unclean_stop? */ - o2hb_prepare_block(reg, 0); - ret = o2hb_issue_node_write(reg, &write_wc); - if (ret == 0) { - o2hb_wait_on_io(reg, &write_wc); - } else { - mlog_errno(ret); + */ + if (!reg->hr_unclean_stop && !reg->hr_aborted_start) { + o2hb_prepare_block(reg, 0); + ret = o2hb_issue_node_write(reg, &write_wc); + if (ret == 0) + o2hb_wait_on_io(reg, &write_wc); + else + mlog_errno(ret); } /* Unpin node */ o2nm_undepend_this_node(); - mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread exiting\n"); + mlog(ML_HEARTBEAT|ML_KTHREAD, "o2hb thread exiting\n"); return 0; } @@ -1426,6 +1466,8 @@ static void o2hb_region_release(struct config_item *item) struct page *page; struct o2hb_region *reg = to_o2hb_region(item); + mlog(ML_HEARTBEAT, "hb region release (%s)\n", reg->hr_dev_name); + if (reg->hr_tmp_block) kfree(reg->hr_tmp_block); @@ -1792,7 +1834,10 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, live_threshold <<= 1; spin_unlock(&o2hb_live_lock); } - atomic_set(®->hr_steady_iterations, live_threshold + 1); + ++live_threshold; + atomic_set(®->hr_steady_iterations, live_threshold); + /* unsteady_iterations is double the steady_iterations */ + atomic_set(®->hr_unsteady_iterations, (live_threshold << 1)); hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", reg->hr_item.ci_name); @@ -1809,14 +1854,12 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, ret = wait_event_interruptible(o2hb_steady_queue, atomic_read(®->hr_steady_iterations) == 0); if (ret) { - /* We got interrupted (hello ptrace!). Clean up */ - spin_lock(&o2hb_live_lock); - hb_task = reg->hr_task; - reg->hr_task = NULL; - spin_unlock(&o2hb_live_lock); + atomic_set(®->hr_steady_iterations, 0); + reg->hr_aborted_start = 1; + } - if (hb_task) - kthread_stop(hb_task); + if (reg->hr_aborted_start) { + ret = -EIO; goto out; } @@ -1833,8 +1876,8 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, ret = -EIO; if (hb_task && o2hb_global_heartbeat_active()) - printk(KERN_NOTICE "o2hb: Heartbeat started on region %s\n", - config_item_name(®->hr_item)); + printk(KERN_NOTICE "o2hb: Heartbeat started on region %s (%s)\n", + config_item_name(®->hr_item), reg->hr_dev_name); out: if (filp) @@ -2092,13 +2135,6 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group, /* stop the thread when the user removes the region dir */ spin_lock(&o2hb_live_lock); - if (o2hb_global_heartbeat_active()) { - clear_bit(reg->hr_region_num, o2hb_region_bitmap); - clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); - if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) - quorum_region = 1; - clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); - } hb_task = reg->hr_task; reg->hr_task = NULL; reg->hr_item_dropped = 1; @@ -2107,19 +2143,30 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group, if (hb_task) kthread_stop(hb_task); + if (o2hb_global_heartbeat_active()) { + spin_lock(&o2hb_live_lock); + clear_bit(reg->hr_region_num, o2hb_region_bitmap); + clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); + if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) + quorum_region = 1; + clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); + spin_unlock(&o2hb_live_lock); + printk(KERN_NOTICE "o2hb: Heartbeat %s on region %s (%s)\n", + ((atomic_read(®->hr_steady_iterations) == 0) ? + "stopped" : "start aborted"), config_item_name(item), + reg->hr_dev_name); + } + /* * If we're racing a dev_write(), we need to wake them. They will * check reg->hr_task */ if (atomic_read(®->hr_steady_iterations) != 0) { + reg->hr_aborted_start = 1; atomic_set(®->hr_steady_iterations, 0); wake_up(&o2hb_steady_queue); } - if (o2hb_global_heartbeat_active()) - printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n", - config_item_name(®->hr_item)); - config_item_put(item); if (!o2hb_global_heartbeat_active() || !quorum_region) -- cgit From 1dfecf810e0eacb35987905082f23e5c2cd26e91 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:22:54 -0700 Subject: ocfs2/cluster: Clean up messages in o2net o2net messages needed a facelift. Signed-off-by: Sunil Mushran --- fs/ocfs2/cluster/tcp.c | 119 ++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 66 deletions(-) diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index db5ee4b4f47a..6e97895ecf24 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -545,7 +545,7 @@ static void o2net_set_nn_state(struct o2net_node *nn, } if (was_valid && !valid) { - printk(KERN_NOTICE "o2net: no longer connected to " + printk(KERN_NOTICE "o2net: No longer connected to " SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc)); o2net_complete_nodes_nsw(nn); } @@ -555,7 +555,7 @@ static void o2net_set_nn_state(struct o2net_node *nn, cancel_delayed_work(&nn->nn_connect_expired); printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n", o2nm_this_node() > sc->sc_node->nd_num ? - "connected to" : "accepted connection from", + "Connected to" : "Accepted connection from", SC_NODEF_ARGS(sc)); } @@ -643,7 +643,7 @@ static void o2net_state_change(struct sock *sk) o2net_sc_queue_work(sc, &sc->sc_connect_work); break; default: - printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT + printk(KERN_INFO "o2net: Connection to " SC_NODEF_FMT " shutdown, state %d\n", SC_NODEF_ARGS(sc), sk->sk_state); o2net_sc_queue_work(sc, &sc->sc_shutdown_work); @@ -1284,11 +1284,11 @@ static int o2net_check_handshake(struct o2net_sock_container *sc) struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) { - mlog(ML_NOTICE, SC_NODEF_FMT " advertised net protocol " - "version %llu but %llu is required, disconnecting\n", - SC_NODEF_ARGS(sc), - (unsigned long long)be64_to_cpu(hand->protocol_version), - O2NET_PROTOCOL_VERSION); + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " Advertised net " + "protocol version %llu but %llu is required. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + (unsigned long long)be64_to_cpu(hand->protocol_version), + O2NET_PROTOCOL_VERSION); /* don't bother reconnecting if its the wrong version. */ o2net_ensure_shutdown(nn, sc, -ENOTCONN); @@ -1302,33 +1302,33 @@ static int o2net_check_handshake(struct o2net_sock_container *sc) */ if (be32_to_cpu(hand->o2net_idle_timeout_ms) != o2net_idle_timeout()) { - mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of " - "%u ms, but we use %u ms locally. disconnecting\n", - SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2net_idle_timeout_ms), - o2net_idle_timeout()); + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a network " + "idle timeout of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2net_idle_timeout_ms), + o2net_idle_timeout()); o2net_ensure_shutdown(nn, sc, -ENOTCONN); return -1; } if (be32_to_cpu(hand->o2net_keepalive_delay_ms) != o2net_keepalive_delay()) { - mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of " - "%u ms, but we use %u ms locally. disconnecting\n", - SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2net_keepalive_delay_ms), - o2net_keepalive_delay()); + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a keepalive " + "delay of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2net_keepalive_delay_ms), + o2net_keepalive_delay()); o2net_ensure_shutdown(nn, sc, -ENOTCONN); return -1; } if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) != O2HB_MAX_WRITE_TIMEOUT_MS) { - mlog(ML_NOTICE, SC_NODEF_FMT " uses a heartbeat timeout of " - "%u ms, but we use %u ms locally. disconnecting\n", - SC_NODEF_ARGS(sc), - be32_to_cpu(hand->o2hb_heartbeat_timeout_ms), - O2HB_MAX_WRITE_TIMEOUT_MS); + printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a heartbeat " + "timeout of %u ms, but we use %u ms locally. " + "Disconnecting.\n", SC_NODEF_ARGS(sc), + be32_to_cpu(hand->o2hb_heartbeat_timeout_ms), + O2HB_MAX_WRITE_TIMEOUT_MS); o2net_ensure_shutdown(nn, sc, -ENOTCONN); return -1; } @@ -1539,28 +1539,16 @@ static void o2net_idle_timer(unsigned long data) { struct o2net_sock_container *sc = (struct o2net_sock_container *)data; struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); - #ifdef CONFIG_DEBUG_FS - ktime_t now = ktime_get(); + unsigned long msecs = ktime_to_ms(ktime_get()) - + ktime_to_ms(sc->sc_tv_timer); +#else + unsigned long msecs = o2net_idle_timeout(); #endif - printk(KERN_NOTICE "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u " - "seconds, shutting it down.\n", SC_NODEF_ARGS(sc), - o2net_idle_timeout() / 1000, - o2net_idle_timeout() % 1000); - -#ifdef CONFIG_DEBUG_FS - mlog(ML_NOTICE, "Here are some times that might help debug the " - "situation: (Timer: %lld, Now %lld, DataReady %lld, Advance %lld-%lld, " - "Key 0x%08x, Func %u, FuncTime %lld-%lld)\n", - (long long)ktime_to_us(sc->sc_tv_timer), (long long)ktime_to_us(now), - (long long)ktime_to_us(sc->sc_tv_data_ready), - (long long)ktime_to_us(sc->sc_tv_advance_start), - (long long)ktime_to_us(sc->sc_tv_advance_stop), - sc->sc_msg_key, sc->sc_msg_type, - (long long)ktime_to_us(sc->sc_tv_func_start), - (long long)ktime_to_us(sc->sc_tv_func_stop)); -#endif + printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been " + "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc), + msecs / 1000, msecs % 1000); /* * Initialize the nn_timeout so that the next connection attempt @@ -1693,8 +1681,8 @@ static void o2net_start_connect(struct work_struct *work) out: if (ret) { - mlog(ML_NOTICE, "connect attempt to " SC_NODEF_FMT " failed " - "with errno %d\n", SC_NODEF_ARGS(sc), ret); + printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT + " failed with errno %d\n", SC_NODEF_ARGS(sc), ret); /* 0 err so that another will be queued and attempted * from set_nn_state */ if (sc) @@ -1717,8 +1705,8 @@ static void o2net_connect_expired(struct work_struct *work) spin_lock(&nn->nn_lock); if (!nn->nn_sc_valid) { - mlog(ML_ERROR, "no connection established with node %u after " - "%u.%u seconds, giving up and returning errors.\n", + printk(KERN_NOTICE "o2net: No connection established with " + "node %u after %u.%u seconds, giving up.\n", o2net_num_from_nn(nn), o2net_idle_timeout() / 1000, o2net_idle_timeout() % 1000); @@ -1861,21 +1849,21 @@ static int o2net_accept_one(struct socket *sock) node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); if (node == NULL) { - mlog(ML_NOTICE, "attempt to connect from unknown node at %pI4:%d\n", - &sin.sin_addr.s_addr, ntohs(sin.sin_port)); + printk(KERN_NOTICE "o2net: Attempt to connect from unknown " + "node at %pI4:%d\n", &sin.sin_addr.s_addr, + ntohs(sin.sin_port)); ret = -EINVAL; goto out; } if (o2nm_this_node() >= node->nd_num) { local_node = o2nm_get_node_by_num(o2nm_this_node()); - mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' (" - "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n", - local_node->nd_name, local_node->nd_num, - &(local_node->nd_ipv4_address), - ntohs(local_node->nd_ipv4_port), - node->nd_name, node->nd_num, &sin.sin_addr.s_addr, - ntohs(sin.sin_port)); + printk(KERN_NOTICE "o2net: Unexpected connect attempt seen " + "at node '%s' (%u, %pI4:%d) from node '%s' (%u, " + "%pI4:%d)\n", local_node->nd_name, local_node->nd_num, + &(local_node->nd_ipv4_address), + ntohs(local_node->nd_ipv4_port), node->nd_name, + node->nd_num, &sin.sin_addr.s_addr, ntohs(sin.sin_port)); ret = -EINVAL; goto out; } @@ -1900,10 +1888,10 @@ static int o2net_accept_one(struct socket *sock) ret = 0; spin_unlock(&nn->nn_lock); if (ret) { - mlog(ML_NOTICE, "attempt to connect from node '%s' at " - "%pI4:%d but it already has an open connection\n", - node->nd_name, &sin.sin_addr.s_addr, - ntohs(sin.sin_port)); + printk(KERN_NOTICE "o2net: Attempt to connect from node '%s' " + "at %pI4:%d but it already has an open connection\n", + node->nd_name, &sin.sin_addr.s_addr, + ntohs(sin.sin_port)); goto out; } @@ -1983,7 +1971,7 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port) ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); if (ret < 0) { - mlog(ML_ERROR, "unable to create socket, ret=%d\n", ret); + printk(KERN_ERR "o2net: Error %d while creating socket\n", ret); goto out; } @@ -2000,16 +1988,15 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port) sock->sk->sk_reuse = 1; ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin)); if (ret < 0) { - mlog(ML_ERROR, "unable to bind socket at %pI4:%u, " - "ret=%d\n", &addr, ntohs(port), ret); + printk(KERN_ERR "o2net: Error %d while binding socket at " + "%pI4:%u\n", ret, &addr, ntohs(port)); goto out; } ret = sock->ops->listen(sock, 64); - if (ret < 0) { - mlog(ML_ERROR, "unable to listen on %pI4:%u, ret=%d\n", - &addr, ntohs(port), ret); - } + if (ret < 0) + printk(KERN_ERR "o2net: Error %d while listening on %pI4:%u\n", + ret, &addr, ntohs(port)); out: if (ret) { -- cgit From 8decab3c8dadcdf4f54ffb30df6e6f67b398b6e0 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:23:54 -0700 Subject: ocfs2/dlm: Clean up messages in o2dlm o2dlm messages needed a facelift. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmdomain.c | 18 +++++++++------- fs/ocfs2/dlm/dlmlock.c | 22 ++++++++----------- fs/ocfs2/dlm/dlmmaster.c | 46 ++++++++++++++++++---------------------- fs/ocfs2/dlm/dlmrecovery.c | 53 +++++++++++++++++++++++++++------------------- fs/ocfs2/dlm/dlmthread.c | 2 -- 5 files changed, 71 insertions(+), 70 deletions(-) diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6ed6b95dcf93..ce225fb0cea7 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -539,17 +539,17 @@ again: static void __dlm_print_nodes(struct dlm_ctxt *dlm) { - int node = -1; + int node = -1, num = 0; assert_spin_locked(&dlm->spinlock); - printk(KERN_NOTICE "o2dlm: Nodes in domain %s: ", dlm->name); - + printk("( "); while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES, node + 1)) < O2NM_MAX_NODES) { printk("%d ", node); + ++num; } - printk("\n"); + printk(") %u nodes\n", num); } static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, @@ -566,11 +566,10 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, node = exit_msg->node_idx; - printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s\n", node, dlm->name); - spin_lock(&dlm->spinlock); clear_bit(node, dlm->domain_map); clear_bit(node, dlm->exit_domain_map); + printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s ", node, dlm->name); __dlm_print_nodes(dlm); /* notify anything attached to the heartbeat events */ @@ -755,6 +754,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) dlm_mark_domain_leaving(dlm); dlm_leave_domain(dlm); + printk(KERN_NOTICE "o2dlm: Leaving domain %s\n", dlm->name); dlm_force_free_mles(dlm); dlm_complete_dlm_shutdown(dlm); } @@ -970,7 +970,7 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, clear_bit(assert->node_idx, dlm->exit_domain_map); __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); - printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", + printk(KERN_NOTICE "o2dlm: Node %u joins domain %s ", assert->node_idx, dlm->name); __dlm_print_nodes(dlm); @@ -1701,8 +1701,10 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) bail: spin_lock(&dlm->spinlock); __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); - if (!status) + if (!status) { + printk(KERN_NOTICE "o2dlm: Joining domain %s ", dlm->name); __dlm_print_nodes(dlm); + } spin_unlock(&dlm->spinlock); if (ctxt) { diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index 8d39e0fd66f7..c7f3e22bda1e 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -319,27 +319,23 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, tmpret = o2net_send_message(DLM_CREATE_LOCK_MSG, dlm->key, &create, sizeof(create), res->owner, &status); if (tmpret >= 0) { - // successfully sent and received - ret = status; // this is already a dlm_status + ret = status; if (ret == DLM_REJECTED) { - mlog(ML_ERROR, "%s:%.*s: BUG. this is a stale lockres " - "no longer owned by %u. that node is coming back " - "up currently.\n", dlm->name, create.namelen, + mlog(ML_ERROR, "%s: res %.*s, Stale lockres no longer " + "owned by node %u. That node is coming back up " + "currently.\n", dlm->name, create.namelen, create.name, res->owner); dlm_print_one_lock_resource(res); BUG(); } } else { - mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to " - "node %u\n", tmpret, DLM_CREATE_LOCK_MSG, dlm->key, - res->owner); - if (dlm_is_host_down(tmpret)) { + mlog(ML_ERROR, "%s: res %.*s, Error %d send CREATE LOCK to " + "node %u\n", dlm->name, create.namelen, create.name, + tmpret, res->owner); + if (dlm_is_host_down(tmpret)) ret = DLM_RECOVERING; - mlog(0, "node %u died so returning DLM_RECOVERING " - "from lock message!\n", res->owner); - } else { + else ret = dlm_err_to_dlm_status(tmpret); - } } return ret; diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 11eefb8c12e9..9f3b093b629a 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -829,8 +829,8 @@ lookup: * but they might own this lockres. wait on them. */ bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " - "recover before lock mastery can begin\n", + mlog(0, "%s: res %.*s, At least one node (%d) " + "to recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; } @@ -864,8 +864,8 @@ redo_request: * dlm spinlock would be detectable be a change on the mle, * so we only need to clear out the recovery map once. */ if (dlm_is_recovery_lock(lockid, namelen)) { - mlog(ML_NOTICE, "%s: recovery map is not empty, but " - "must master $RECOVERY lock now\n", dlm->name); + mlog(0, "%s: Recovery map is not empty, but must " + "master $RECOVERY lock now\n", dlm->name); if (!dlm_pre_master_reco_lockres(dlm, res)) wait_on_recovery = 0; else { @@ -883,8 +883,8 @@ redo_request: spin_lock(&dlm->spinlock); bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " - "recover before lock mastery can begin\n", + mlog(0, "%s: res %.*s, At least one node (%d) " + "to recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; } else @@ -913,8 +913,8 @@ redo_request: * yet, keep going until it does. this is how the * master will know that asserts are needed back to * the lower nodes. */ - mlog(0, "%s:%.*s: requests only up to %u but master " - "is %u, keep going\n", dlm->name, namelen, + mlog(0, "%s: res %.*s, Requests only up to %u but " + "master is %u, keep going\n", dlm->name, namelen, lockid, nodenum, mle->master); } } @@ -924,13 +924,12 @@ wait: ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked); if (ret < 0) { wait_on_recovery = 1; - mlog(0, "%s:%.*s: node map changed, redo the " - "master request now, blocked=%d\n", - dlm->name, res->lockname.len, + mlog(0, "%s: res %.*s, Node map changed, redo the master " + "request now, blocked=%d\n", dlm->name, res->lockname.len, res->lockname.name, blocked); if (++tries > 20) { - mlog(ML_ERROR, "%s:%.*s: spinning on " - "dlm_wait_for_lock_mastery, blocked=%d\n", + mlog(ML_ERROR, "%s: res %.*s, Spinning on " + "dlm_wait_for_lock_mastery, blocked = %d\n", dlm->name, res->lockname.len, res->lockname.name, blocked); dlm_print_one_lock_resource(res); @@ -940,7 +939,8 @@ wait: goto redo_request; } - mlog(0, "lockres mastered by %u\n", res->owner); + mlog(0, "%s: res %.*s, Mastered by %u\n", dlm->name, res->lockname.len, + res->lockname.name, res->owner); /* make sure we never continue without this */ BUG_ON(res->owner == O2NM_MAX_NODES); @@ -2187,8 +2187,6 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) namelen = res->lockname.len; BUG_ON(namelen > O2NM_MAX_NAME_LEN); - mlog(0, "%s:%.*s: sending deref to %d\n", - dlm->name, namelen, lockname, res->owner); memset(&deref, 0, sizeof(deref)); deref.node_idx = dlm->node_num; deref.namelen = namelen; @@ -2197,14 +2195,12 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) ret = o2net_send_message(DLM_DEREF_LOCKRES_MSG, dlm->key, &deref, sizeof(deref), res->owner, &r); if (ret < 0) - mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to " - "node %u\n", ret, DLM_DEREF_LOCKRES_MSG, dlm->key, - res->owner); + mlog(ML_ERROR, "%s: res %.*s, error %d send DEREF to node %u\n", + dlm->name, namelen, lockname, ret, res->owner); else if (r < 0) { /* BAD. other node says I did not have a ref. */ - mlog(ML_ERROR,"while dropping ref on %s:%.*s " - "(master=%u) got %d.\n", dlm->name, namelen, - lockname, res->owner, r); + mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n", + dlm->name, namelen, lockname, res->owner, r); dlm_print_one_lock_resource(res); BUG(); } @@ -2916,9 +2912,9 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm, &migrate, sizeof(migrate), nodenum, &status); if (ret < 0) { - mlog(ML_ERROR, "Error %d when sending message %u (key " - "0x%x) to node %u\n", ret, DLM_MIGRATE_REQUEST_MSG, - dlm->key, nodenum); + mlog(ML_ERROR, "%s: res %.*s, Error %d send " + "MIGRATE_REQUEST to node %u\n", dlm->name, + migrate.namelen, migrate.name, ret, nodenum); if (!dlm_is_host_down(ret)) { mlog(ML_ERROR, "unhandled error=%d!\n", ret); BUG(); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 7efab6d28a21..a3c312c43b90 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -430,6 +430,8 @@ static void dlm_begin_recovery(struct dlm_ctxt *dlm) { spin_lock(&dlm->spinlock); BUG_ON(dlm->reco.state & DLM_RECO_STATE_ACTIVE); + printk(KERN_NOTICE "o2dlm: Begin recovery on domain %s for node %u\n", + dlm->name, dlm->reco.dead_node); dlm->reco.state |= DLM_RECO_STATE_ACTIVE; spin_unlock(&dlm->spinlock); } @@ -440,9 +442,18 @@ static void dlm_end_recovery(struct dlm_ctxt *dlm) BUG_ON(!(dlm->reco.state & DLM_RECO_STATE_ACTIVE)); dlm->reco.state &= ~DLM_RECO_STATE_ACTIVE; spin_unlock(&dlm->spinlock); + printk(KERN_NOTICE "o2dlm: End recovery on domain %s\n", dlm->name); wake_up(&dlm->reco.event); } +static void dlm_print_recovery_master(struct dlm_ctxt *dlm) +{ + printk(KERN_NOTICE "o2dlm: Node %u (%s) is the Recovery Master for the " + "dead node %u in domain %s\n", dlm->reco.new_master, + (dlm->node_num == dlm->reco.new_master ? "me" : "he"), + dlm->reco.dead_node, dlm->name); +} + static int dlm_do_recovery(struct dlm_ctxt *dlm) { int status = 0; @@ -505,9 +516,8 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) } mlog(0, "another node will master this recovery session.\n"); } - mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n", - dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), dlm->reco.new_master, - dlm->node_num, dlm->reco.dead_node); + + dlm_print_recovery_master(dlm); /* it is safe to start everything back up here * because all of the dead node's lock resources @@ -518,15 +528,13 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) return 0; master_here: - mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node " - "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task), - dlm->node_num, dlm->reco.dead_node, dlm->name); + dlm_print_recovery_master(dlm); status = dlm_remaster_locks(dlm, dlm->reco.dead_node); if (status < 0) { /* we should never hit this anymore */ - mlog(ML_ERROR, "error %d remastering locks for node %u, " - "retrying.\n", status, dlm->reco.dead_node); + mlog(ML_ERROR, "%s: Error %d remastering locks for node %u, " + "retrying.\n", dlm->name, status, dlm->reco.dead_node); /* yield a bit to allow any final network messages * to get handled on remaining nodes */ msleep(100); @@ -567,7 +575,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT); ndata->state = DLM_RECO_NODE_DATA_REQUESTING; - mlog(0, "requesting lock info from node %u\n", + mlog(0, "%s: Requesting lock info from node %u\n", dlm->name, ndata->node_num); if (ndata->node_num == dlm->node_num) { @@ -640,7 +648,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) spin_unlock(&dlm_reco_state_lock); } - mlog(0, "done requesting all lock info\n"); + mlog(0, "%s: Done requesting all lock info\n", dlm->name); /* nodes should be sending reco data now * just need to wait */ @@ -802,10 +810,9 @@ static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from, /* negative status is handled by caller */ if (ret < 0) - mlog(ML_ERROR, "Error %d when sending message %u (key " - "0x%x) to node %u\n", ret, DLM_LOCK_REQUEST_MSG, - dlm->key, request_from); - + mlog(ML_ERROR, "%s: Error %d send LOCK_REQUEST to node %u " + "to recover dead node %u\n", dlm->name, ret, + request_from, dead_node); // return from here, then // sleep until all received or error return ret; @@ -956,9 +963,9 @@ static int dlm_send_all_done_msg(struct dlm_ctxt *dlm, u8 dead_node, u8 send_to) ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg, sizeof(done_msg), send_to, &tmpret); if (ret < 0) { - mlog(ML_ERROR, "Error %d when sending message %u (key " - "0x%x) to node %u\n", ret, DLM_RECO_DATA_DONE_MSG, - dlm->key, send_to); + mlog(ML_ERROR, "%s: Error %d send RECO_DATA_DONE to node %u " + "to recover dead node %u\n", dlm->name, ret, send_to, + dead_node); if (!dlm_is_host_down(ret)) { BUG(); } @@ -1127,9 +1134,11 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm, if (ret < 0) { /* XXX: negative status is not handled. * this will end up killing this node. */ - mlog(ML_ERROR, "Error %d when sending message %u (key " - "0x%x) to node %u\n", ret, DLM_MIG_LOCKRES_MSG, - dlm->key, send_to); + mlog(ML_ERROR, "%s: res %.*s, Error %d send MIG_LOCKRES to " + "node %u (%s)\n", dlm->name, mres->lockname_len, + mres->lockname, ret, send_to, + (orig_flags & DLM_MRES_MIGRATION ? + "migration" : "recovery")); } else { /* might get an -ENOMEM back here */ ret = status; @@ -2324,9 +2333,9 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) dlm_revalidate_lvb(dlm, res, dead_node); if (res->owner == dead_node) { if (res->state & DLM_LOCK_RES_DROPPING_REF) { - mlog(ML_NOTICE, "Ignore %.*s for " + mlog(ML_NOTICE, "%s: res %.*s, Skip " "recovery as it is being freed\n", - res->lockname.len, + dlm->name, res->lockname.len, res->lockname.name); } else dlm_move_lockres_to_recovery_list(dlm, diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index 1d6d1d22c471..46faac20f16c 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c @@ -185,8 +185,6 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm, /* clear our bit from the master's refmap, ignore errors */ ret = dlm_drop_lockres_ref(dlm, res); if (ret < 0) { - mlog(ML_ERROR, "%s: deref %.*s failed %d\n", dlm->name, - res->lockname.len, res->lockname.name, ret); if (!dlm_is_host_down(ret)) BUG(); } -- cgit From 394eb3d38a3ecc549cc34a3040103a9164be516b Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:24:54 -0700 Subject: ocfs2: Clean up messages in stack_o2cb.c o2cb messages needed a facelift. Signed-off-by: Sunil Mushran --- fs/ocfs2/stack_o2cb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c index 19965b00c43c..be935d89a4e8 100644 --- a/fs/ocfs2/stack_o2cb.c +++ b/fs/ocfs2/stack_o2cb.c @@ -263,8 +263,8 @@ static void o2dlm_eviction_cb(int node_num, void *data) { struct ocfs2_cluster_connection *conn = data; - mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n", - node_num, conn->cc_namelen, conn->cc_name); + printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n", + node_num, conn->cc_namelen, conn->cc_name); conn->cc_recovery_handler(node_num, conn->cc_recovery_data); } -- cgit From 0afbba13226fcdbd4327f6b13a42f6efbb8c9caf Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:25:54 -0700 Subject: ocfs2/dlm: Cleanup up dlm_finish_local_lockres_recovery() dlm_finish_local_lockres_recovery() needed a facelift. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmrecovery.c | 57 ++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index a3c312c43b90..41e74f0e2d35 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -2093,6 +2093,9 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) { if (res->owner == dead_node) { + mlog(0, "%s: res %.*s, Changing owner from %u to %u\n", + dlm->name, res->lockname.len, res->lockname.name, + res->owner, new_master); list_del_init(&res->recovering); spin_lock(&res->spinlock); /* new_master has our reference from @@ -2114,40 +2117,30 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, for (i = 0; i < DLM_HASH_BUCKETS; i++) { bucket = dlm_lockres_hash(dlm, i); hlist_for_each_entry(res, hash_iter, bucket, hash_node) { - if (res->state & DLM_LOCK_RES_RECOVERING) { - if (res->owner == dead_node) { - mlog(0, "(this=%u) res %.*s owner=%u " - "was not on recovering list, but " - "clearing state anyway\n", - dlm->node_num, res->lockname.len, - res->lockname.name, new_master); - } else if (res->owner == dlm->node_num) { - mlog(0, "(this=%u) res %.*s owner=%u " - "was not on recovering list, " - "owner is THIS node, clearing\n", - dlm->node_num, res->lockname.len, - res->lockname.name, new_master); - } else - continue; + if (!(res->state & DLM_LOCK_RES_RECOVERING)) + continue; - if (!list_empty(&res->recovering)) { - mlog(0, "%s:%.*s: lockres was " - "marked RECOVERING, owner=%u\n", - dlm->name, res->lockname.len, - res->lockname.name, res->owner); - list_del_init(&res->recovering); - dlm_lockres_put(res); - } - spin_lock(&res->spinlock); - /* new_master has our reference from - * the lock state sent during recovery */ - dlm_change_lockres_owner(dlm, res, new_master); - res->state &= ~DLM_LOCK_RES_RECOVERING; - if (__dlm_lockres_has_locks(res)) - __dlm_dirty_lockres(dlm, res); - spin_unlock(&res->spinlock); - wake_up(&res->wq); + if (res->owner != dead_node && + res->owner != dlm->node_num) + continue; + + if (!list_empty(&res->recovering)) { + list_del_init(&res->recovering); + dlm_lockres_put(res); } + + /* new_master has our reference from + * the lock state sent during recovery */ + mlog(0, "%s: res %.*s, Changing owner from %u to %u\n", + dlm->name, res->lockname.len, res->lockname.name, + res->owner, new_master); + spin_lock(&res->spinlock); + dlm_change_lockres_owner(dlm, res, new_master); + res->state &= ~DLM_LOCK_RES_RECOVERING; + if (__dlm_lockres_has_locks(res)) + __dlm_dirty_lockres(dlm, res); + spin_unlock(&res->spinlock); + wake_up(&res->wq); } } } -- cgit From 8d400b81cc83b171ff872587723a37eb7fae9abe Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:26:54 -0700 Subject: ocfs2/dlm: Clean up refmap helpers Patch cleans up helpers that set/clear refmap bits and grab/drop inflight lock ref counts. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmcommon.h | 49 +++++--------------------- fs/ocfs2/dlm/dlmmaster.c | 88 ++++++++++++++++++++++++++++------------------ fs/ocfs2/dlm/dlmrecovery.c | 8 ++--- 3 files changed, 66 insertions(+), 79 deletions(-) diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index d602abb51b61..4a5d5804b130 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -902,46 +902,15 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm, const char *name, unsigned int namelen); -#define dlm_lockres_set_refmap_bit(bit,res) \ - __dlm_lockres_set_refmap_bit(bit,res,__FILE__,__LINE__) -#define dlm_lockres_clear_refmap_bit(bit,res) \ - __dlm_lockres_clear_refmap_bit(bit,res,__FILE__,__LINE__) - -static inline void __dlm_lockres_set_refmap_bit(int bit, - struct dlm_lock_resource *res, - const char *file, - int line) -{ - //printk("%s:%d:%.*s: setting bit %d\n", file, line, - // res->lockname.len, res->lockname.name, bit); - set_bit(bit, res->refmap); -} - -static inline void __dlm_lockres_clear_refmap_bit(int bit, - struct dlm_lock_resource *res, - const char *file, - int line) -{ - //printk("%s:%d:%.*s: clearing bit %d\n", file, line, - // res->lockname.len, res->lockname.name, bit); - clear_bit(bit, res->refmap); -} - -void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - const char *file, - int line); -void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - int new_lockres, - const char *file, - int line); -#define dlm_lockres_drop_inflight_ref(d,r) \ - __dlm_lockres_drop_inflight_ref(d,r,__FILE__,__LINE__) -#define dlm_lockres_grab_inflight_ref(d,r) \ - __dlm_lockres_grab_inflight_ref(d,r,0,__FILE__,__LINE__) -#define dlm_lockres_grab_inflight_ref_new(d,r) \ - __dlm_lockres_grab_inflight_ref(d,r,1,__FILE__,__LINE__) +void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, int bit); +void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, int bit); + +void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res); +void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res); void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock); void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock); diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 9f3b093b629a..11e446ffb67a 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -631,39 +631,58 @@ error: return NULL; } -void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - int new_lockres, - const char *file, - int line) +void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, int bit) { - if (!new_lockres) - assert_spin_locked(&res->spinlock); + assert_spin_locked(&res->spinlock); + + mlog(0, "res %.*s, set node %u, %ps()\n", res->lockname.len, + res->lockname.name, bit, __builtin_return_address(0)); + + set_bit(bit, res->refmap); +} + +void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, int bit) +{ + assert_spin_locked(&res->spinlock); + + mlog(0, "res %.*s, clr node %u, %ps()\n", res->lockname.len, + res->lockname.name, bit, __builtin_return_address(0)); + + clear_bit(bit, res->refmap); +} + + +void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) +{ + assert_spin_locked(&res->spinlock); if (!test_bit(dlm->node_num, res->refmap)) { BUG_ON(res->inflight_locks != 0); - dlm_lockres_set_refmap_bit(dlm->node_num, res); + dlm_lockres_set_refmap_bit(dlm, res, dlm->node_num); } res->inflight_locks++; - mlog(0, "%s:%.*s: inflight++: now %u\n", - dlm->name, res->lockname.len, res->lockname.name, - res->inflight_locks); + mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name, + res->lockname.len, res->lockname.name, res->inflight_locks, + __builtin_return_address(0)); } -void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - const char *file, - int line) +void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) { assert_spin_locked(&res->spinlock); BUG_ON(res->inflight_locks == 0); + res->inflight_locks--; - mlog(0, "%s:%.*s: inflight--: now %u\n", - dlm->name, res->lockname.len, res->lockname.name, - res->inflight_locks); + mlog(0, "%s: res %.*s, inflight--: now %u, %ps()\n", dlm->name, + res->lockname.len, res->lockname.name, res->inflight_locks, + __builtin_return_address(0)); + if (res->inflight_locks == 0) - dlm_lockres_clear_refmap_bit(dlm->node_num, res); + dlm_lockres_clear_refmap_bit(dlm, res, dlm->node_num); wake_up(&res->wq); } @@ -843,8 +862,10 @@ lookup: /* finally add the lockres to its hash bucket */ __dlm_insert_lockres(dlm, res); - /* since this lockres is new it doesn't not require the spinlock */ - dlm_lockres_grab_inflight_ref_new(dlm, res); + + spin_lock(&res->spinlock); + dlm_lockres_grab_inflight_ref(dlm, res); + spin_unlock(&res->spinlock); /* if this node does not become the master make sure to drop * this inflight reference below */ @@ -1426,9 +1447,7 @@ way_up_top: } if (res->owner == dlm->node_num) { - mlog(0, "%s:%.*s: setting bit %u in refmap\n", - dlm->name, namelen, name, request->node_idx); - dlm_lockres_set_refmap_bit(request->node_idx, res); + dlm_lockres_set_refmap_bit(dlm, res, request->node_idx); spin_unlock(&res->spinlock); response = DLM_MASTER_RESP_YES; if (mle) @@ -1493,10 +1512,8 @@ way_up_top: * go back and clean the mles on any * other nodes */ dispatch_assert = 1; - dlm_lockres_set_refmap_bit(request->node_idx, res); - mlog(0, "%s:%.*s: setting bit %u in refmap\n", - dlm->name, namelen, name, - request->node_idx); + dlm_lockres_set_refmap_bit(dlm, res, + request->node_idx); } else response = DLM_MASTER_RESP_NO; } else { @@ -1702,7 +1719,7 @@ again: "lockres, set the bit in the refmap\n", namelen, lockname, to); spin_lock(&res->spinlock); - dlm_lockres_set_refmap_bit(to, res); + dlm_lockres_set_refmap_bit(dlm, res, to); spin_unlock(&res->spinlock); } } @@ -2256,7 +2273,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data, else { BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF); if (test_bit(node, res->refmap)) { - dlm_lockres_clear_refmap_bit(node, res); + dlm_lockres_clear_refmap_bit(dlm, res, node); cleared = 1; } } @@ -2316,7 +2333,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data) BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF); if (test_bit(node, res->refmap)) { __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); - dlm_lockres_clear_refmap_bit(node, res); + dlm_lockres_clear_refmap_bit(dlm, res, node); cleared = 1; } spin_unlock(&res->spinlock); @@ -2798,7 +2815,8 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm, BUG_ON(!list_empty(&lock->bast_list)); BUG_ON(lock->ast_pending); BUG_ON(lock->bast_pending); - dlm_lockres_clear_refmap_bit(lock->ml.node, res); + dlm_lockres_clear_refmap_bit(dlm, res, + lock->ml.node); list_del_init(&lock->list); dlm_lock_put(lock); /* In a normal unlock, we would have added a @@ -2819,7 +2837,7 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm, mlog(0, "%s:%.*s: node %u had a ref to this " "migrating lockres, clearing\n", dlm->name, res->lockname.len, res->lockname.name, bit); - dlm_lockres_clear_refmap_bit(bit, res); + dlm_lockres_clear_refmap_bit(dlm, res, bit); } bit++; } @@ -2933,7 +2951,7 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm, dlm->name, res->lockname.len, res->lockname.name, nodenum); spin_lock(&res->spinlock); - dlm_lockres_set_refmap_bit(nodenum, res); + dlm_lockres_set_refmap_bit(dlm, res, nodenum); spin_unlock(&res->spinlock); } } @@ -3267,7 +3285,7 @@ int dlm_finish_migration(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, * mastery reference here since old_master will briefly have * a reference after the migration completes */ spin_lock(&res->spinlock); - dlm_lockres_set_refmap_bit(old_master, res); + dlm_lockres_set_refmap_bit(dlm, res, old_master); spin_unlock(&res->spinlock); mlog(0, "now time to do a migrate request to other nodes\n"); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 41e74f0e2d35..f1a3aa84ad89 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -1776,7 +1776,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, dlm->name, mres->lockname_len, mres->lockname, from); spin_lock(&res->spinlock); - dlm_lockres_set_refmap_bit(from, res); + dlm_lockres_set_refmap_bit(dlm, res, from); spin_unlock(&res->spinlock); added++; break; @@ -1974,7 +1974,7 @@ skip_lvb: mlog(0, "%s:%.*s: added lock for node %u, " "setting refmap bit\n", dlm->name, res->lockname.len, res->lockname.name, ml->node); - dlm_lockres_set_refmap_bit(ml->node, res); + dlm_lockres_set_refmap_bit(dlm, res, ml->node); added++; } spin_unlock(&res->spinlock); @@ -2254,12 +2254,12 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm, res->lockname.len, res->lockname.name, freed, dead_node); __dlm_print_one_lock_resource(res); } - dlm_lockres_clear_refmap_bit(dead_node, res); + dlm_lockres_clear_refmap_bit(dlm, res, dead_node); } else if (test_bit(dead_node, res->refmap)) { mlog(0, "%s:%.*s: dead node %u had a ref, but had " "no locks and had not purged before dying\n", dlm->name, res->lockname.len, res->lockname.name, dead_node); - dlm_lockres_clear_refmap_bit(dead_node, res); + dlm_lockres_clear_refmap_bit(dlm, res, dead_node); } /* do not kick thread yet */ -- cgit From e9f0b6a6233105c188064328c3f15e21942d0241 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:27:54 -0700 Subject: ocfs2/dlm: Trace insert/remove of resource to/from hash Add mlog to trace adding and removing the resource from/to the hash table. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmcommon.h | 5 ++--- fs/ocfs2/dlm/dlmdomain.c | 19 ++++++++++++------- fs/ocfs2/dlm/dlmthread.c | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 4a5d5804b130..b1748ac74751 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -877,9 +877,8 @@ static inline void dlm_lockres_get(struct dlm_lock_resource *res) kref_get(&res->refs); } void dlm_lockres_put(struct dlm_lock_resource *res); -void __dlm_unhash_lockres(struct dlm_lock_resource *res); -void __dlm_insert_lockres(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res); +void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res); +void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res); struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm, const char *name, unsigned int len, diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index ce225fb0cea7..200d9888ffee 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -157,16 +157,18 @@ static int dlm_protocol_compare(struct dlm_protocol_version *existing, static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm); -void __dlm_unhash_lockres(struct dlm_lock_resource *lockres) +void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { - if (!hlist_unhashed(&lockres->hash_node)) { - hlist_del_init(&lockres->hash_node); - dlm_lockres_put(lockres); - } + if (hlist_unhashed(&res->hash_node)) + return; + + mlog(0, "%s: Unhash res %.*s\n", dlm->name, res->lockname.len, + res->lockname.name); + hlist_del_init(&res->hash_node); + dlm_lockres_put(res); } -void __dlm_insert_lockres(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res) +void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { struct hlist_head *bucket; struct qstr *q; @@ -180,6 +182,9 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm, dlm_lockres_get(res); hlist_add_head(&res->hash_node, bucket); + + mlog(0, "%s: Hash res %.*s\n", dlm->name, res->lockname.len, + res->lockname.name); } struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm, diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index 46faac20f16c..4eff65e7e59e 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c @@ -207,7 +207,7 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm, BUG(); } - __dlm_unhash_lockres(res); + __dlm_unhash_lockres(dlm, res); /* lockres is not in the hash now. drop the flag and wake up * any processes waiting in dlm_get_lock_resource. */ -- cgit From ed8625c6fb93d750ed022db571a8a7b7a6724b3b Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:28:54 -0700 Subject: ocfs2/dlm: Cleanup dlm_wait_for_node_death() and dlm_wait_for_node_recovery() dlm_wait_for_node_death() and dlm_wait_for_node_recovery() needed a facelift. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmcommon.h | 4 ++-- fs/ocfs2/dlm/dlmrecovery.c | 46 ++++++++++++++++++++++------------------------ 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index b1748ac74751..a5952ceecba5 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -859,8 +859,8 @@ void dlm_complete_recovery_thread(struct dlm_ctxt *dlm); void dlm_wait_for_recovery(struct dlm_ctxt *dlm); void dlm_kick_recovery_thread(struct dlm_ctxt *dlm); int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node); -int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout); -int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout); +void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout); +void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout); void dlm_put(struct dlm_ctxt *dlm); struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index f1a3aa84ad89..01ebfd0bdad7 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -362,40 +362,38 @@ static int dlm_is_node_recovered(struct dlm_ctxt *dlm, u8 node) } -int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout) +void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout) { - if (timeout) { - mlog(ML_NOTICE, "%s: waiting %dms for notification of " - "death of node %u\n", dlm->name, timeout, node); + if (dlm_is_node_dead(dlm, node)) + return; + + printk(KERN_NOTICE "o2dlm: Waiting on the death of node %u in " + "domain %s\n", node, dlm->name); + + if (timeout) wait_event_timeout(dlm->dlm_reco_thread_wq, - dlm_is_node_dead(dlm, node), - msecs_to_jiffies(timeout)); - } else { - mlog(ML_NOTICE, "%s: waiting indefinitely for notification " - "of death of node %u\n", dlm->name, node); + dlm_is_node_dead(dlm, node), + msecs_to_jiffies(timeout)); + else wait_event(dlm->dlm_reco_thread_wq, dlm_is_node_dead(dlm, node)); - } - /* for now, return 0 */ - return 0; } -int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout) +void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout) { - if (timeout) { - mlog(0, "%s: waiting %dms for notification of " - "recovery of node %u\n", dlm->name, timeout, node); + if (dlm_is_node_recovered(dlm, node)) + return; + + printk(KERN_NOTICE "o2dlm: Waiting on the recovery of node %u in " + "domain %s\n", node, dlm->name); + + if (timeout) wait_event_timeout(dlm->dlm_reco_thread_wq, - dlm_is_node_recovered(dlm, node), - msecs_to_jiffies(timeout)); - } else { - mlog(0, "%s: waiting indefinitely for notification " - "of recovery of node %u\n", dlm->name, node); + dlm_is_node_recovered(dlm, node), + msecs_to_jiffies(timeout)); + else wait_event(dlm->dlm_reco_thread_wq, dlm_is_node_recovered(dlm, node)); - } - /* for now, return 0 */ - return 0; } /* callers of the top-level api calls (dlmlock/dlmunlock) should -- cgit From ff0a522e7db79625aa27a433467eb94c5e255718 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:29:54 -0700 Subject: ocfs2/dlm: Take inflight reference count for remotely mastered resources too The inflight reference count, in the lock resource, is taken to pin the resource in memory. We take it when a new resource is created and release it after a lock is attached to it. We do this to prevent the resource from getting purged prematurely. Earlier this reference count was being taken for locally mastered resources only. This patch extends the same functionality for remotely mastered ones. We are doing this because the same premature purging could occur for remotely mastered resources if the remote node were to die before completion of the create lock. Fix for Oracle bug#12405575. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmlock.c | 12 ++++++++---- fs/ocfs2/dlm/dlmmaster.c | 47 +++++++++++++++++------------------------------ fs/ocfs2/dlm/dlmthread.c | 12 +++++++----- 3 files changed, 32 insertions(+), 39 deletions(-) diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index c7f3e22bda1e..3ef2c1adfb8f 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -183,10 +183,6 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm, kick_thread = 1; } } - /* reduce the inflight count, this may result in the lockres - * being purged below during calc_usage */ - if (lock->ml.node == dlm->node_num) - dlm_lockres_drop_inflight_ref(dlm, res); spin_unlock(&res->spinlock); wake_up(&res->wq); @@ -737,6 +733,14 @@ retry_lock: } } + /* Inflight taken in dlm_get_lock_resource() is dropped here */ + spin_lock(&res->spinlock); + dlm_lockres_drop_inflight_ref(dlm, res); + spin_unlock(&res->spinlock); + + dlm_lockres_calc_usage(dlm, res); + dlm_kick_thread(dlm, res); + if (status != DLM_NORMAL) { lock->lksb->flags &= ~DLM_LKSB_GET_LVB; if (status != DLM_NOTQUEUED) diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 11e446ffb67a..005261c333b0 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -659,11 +659,8 @@ void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, { assert_spin_locked(&res->spinlock); - if (!test_bit(dlm->node_num, res->refmap)) { - BUG_ON(res->inflight_locks != 0); - dlm_lockres_set_refmap_bit(dlm, res, dlm->node_num); - } res->inflight_locks++; + mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name, res->lockname.len, res->lockname.name, res->inflight_locks, __builtin_return_address(0)); @@ -677,12 +674,11 @@ void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, BUG_ON(res->inflight_locks == 0); res->inflight_locks--; + mlog(0, "%s: res %.*s, inflight--: now %u, %ps()\n", dlm->name, res->lockname.len, res->lockname.name, res->inflight_locks, __builtin_return_address(0)); - if (res->inflight_locks == 0) - dlm_lockres_clear_refmap_bit(dlm, res, dlm->node_num); wake_up(&res->wq); } @@ -716,7 +712,6 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, unsigned int hash; int tries = 0; int bit, wait_on_recovery = 0; - int drop_inflight_if_nonlocal = 0; BUG_ON(!lockid); @@ -728,36 +723,33 @@ lookup: spin_lock(&dlm->spinlock); tmpres = __dlm_lookup_lockres_full(dlm, lockid, namelen, hash); if (tmpres) { - int dropping_ref = 0; - spin_unlock(&dlm->spinlock); - spin_lock(&tmpres->spinlock); - /* We wait for the other thread that is mastering the resource */ + /* Wait on the thread that is mastering the resource */ if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { __dlm_wait_on_lockres(tmpres); BUG_ON(tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN); + spin_unlock(&tmpres->spinlock); + dlm_lockres_put(tmpres); + tmpres = NULL; + goto lookup; } - if (tmpres->owner == dlm->node_num) { - BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF); - dlm_lockres_grab_inflight_ref(dlm, tmpres); - } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF) - dropping_ref = 1; - spin_unlock(&tmpres->spinlock); - - /* wait until done messaging the master, drop our ref to allow - * the lockres to be purged, start over. */ - if (dropping_ref) { - spin_lock(&tmpres->spinlock); - __dlm_wait_on_lockres_flags(tmpres, DLM_LOCK_RES_DROPPING_REF); + /* Wait on the resource purge to complete before continuing */ + if (tmpres->state & DLM_LOCK_RES_DROPPING_REF) { + BUG_ON(tmpres->owner == dlm->node_num); + __dlm_wait_on_lockres_flags(tmpres, + DLM_LOCK_RES_DROPPING_REF); spin_unlock(&tmpres->spinlock); dlm_lockres_put(tmpres); tmpres = NULL; goto lookup; } - mlog(0, "found in hash!\n"); + /* Grab inflight ref to pin the resource */ + dlm_lockres_grab_inflight_ref(dlm, tmpres); + + spin_unlock(&tmpres->spinlock); if (res) dlm_lockres_put(res); res = tmpres; @@ -863,14 +855,11 @@ lookup: /* finally add the lockres to its hash bucket */ __dlm_insert_lockres(dlm, res); + /* Grab inflight ref to pin the resource */ spin_lock(&res->spinlock); dlm_lockres_grab_inflight_ref(dlm, res); spin_unlock(&res->spinlock); - /* if this node does not become the master make sure to drop - * this inflight reference below */ - drop_inflight_if_nonlocal = 1; - /* get an extra ref on the mle in case this is a BLOCK * if so, the creator of the BLOCK may try to put the last * ref at this time in the assert master handler, so we @@ -973,8 +962,6 @@ wait: wake_waiters: spin_lock(&res->spinlock); - if (res->owner != dlm->node_num && drop_inflight_if_nonlocal) - dlm_lockres_drop_inflight_ref(dlm, res); res->state &= ~DLM_LOCK_RES_IN_PROGRESS; spin_unlock(&res->spinlock); wake_up(&res->wq); diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index 4eff65e7e59e..e73c833fc2a1 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c @@ -94,24 +94,26 @@ int __dlm_lockres_unused(struct dlm_lock_resource *res) { int bit; + assert_spin_locked(&res->spinlock); + if (__dlm_lockres_has_locks(res)) return 0; + /* Locks are in the process of being created */ + if (res->inflight_locks) + return 0; + if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY) return 0; if (res->state & DLM_LOCK_RES_RECOVERING) return 0; + /* Another node has this resource with this node as the master */ bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) return 0; - /* - * since the bit for dlm->node_num is not set, inflight_locks better - * be zero - */ - BUG_ON(res->inflight_locks != 0); return 1; } -- cgit From a2c0cc1579176bd0808ef7deea456767dfa80217 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:30:54 -0700 Subject: ocfs2/dlm: dlmlock_remote() needs to account for remastery In dlmlock_remote(), we wait for the resource to stop being active before setting the inprogress flag. Active includes recovery, migration, etc. The problem here is that if the resource was being recovered or migrated, the new owner could very well be that node itself (and thus not a remote node). This problem was observed in Oracle bug#12583620. The error messages observed were as follows: dlm_send_remote_lock_request:337 ERROR: Error -40 (ELOOP) when sending message 503 (key 0xd6d8c7) to node 2 dlmlock_remote:271 ERROR: dlm status = DLM_BADARGS dlmlock:751 ERROR: dlm status = DLM_BADARGS Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmlock.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index 3ef2c1adfb8f..f32fcba04923 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -227,10 +227,16 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, lock->ml.type, res->lockname.len, res->lockname.name, flags); + /* + * Wait if resource is getting recovered, remastered, etc. + * If the resource was remastered and new owner is self, then exit. + */ spin_lock(&res->spinlock); - - /* will exit this call with spinlock held */ __dlm_wait_on_lockres(res); + if (res->owner == dlm->node_num) { + spin_unlock(&res->spinlock); + return DLM_RECOVERING; + } res->state |= DLM_LOCK_RES_IN_PROGRESS; /* add lock to local (secondary) queue */ @@ -710,18 +716,10 @@ retry_lock: if (status == DLM_RECOVERING || status == DLM_MIGRATING || status == DLM_FORWARD) { - mlog(0, "retrying lock with migration/" - "recovery/in progress\n"); msleep(100); - /* no waiting for dlm_reco_thread */ if (recovery) { if (status != DLM_RECOVERING) goto retry_lock; - - mlog(0, "%s: got RECOVERING " - "for $RECOVERY lock, master " - "was %u\n", dlm->name, - res->owner); /* wait to see the node go down, then * drop down and allow the lockres to * get cleaned up. need to remaster. */ -- cgit From bb570a5d9e74f71d32751823052db4a97d6a5e7c Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:31:54 -0700 Subject: ocfs2/cluster: Fix output in file elapsed_time_in_ms The o2hb debugfs file, elapsed_time_in_ms, should return values only after the timer is armed atleast once. Signed-off-by: Sunil Mushran --- fs/ocfs2/cluster/heartbeat.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 4728a746281d..a4e855e3690e 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -1198,6 +1198,7 @@ static int o2hb_debug_open(struct inode *inode, struct file *file) struct o2hb_debug_buf *db = inode->i_private; struct o2hb_region *reg; unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned long lts; char *buf = NULL; int i = -1; int out = 0; @@ -1234,9 +1235,11 @@ static int o2hb_debug_open(struct inode *inode, struct file *file) case O2HB_DB_TYPE_REGION_ELAPSED_TIME: reg = (struct o2hb_region *)db->db_data; - out += snprintf(buf + out, PAGE_SIZE - out, "%u\n", - jiffies_to_msecs(jiffies - - reg->hr_last_timeout_start)); + lts = reg->hr_last_timeout_start; + /* If 0, it has never been set before */ + if (lts) + lts = jiffies_to_msecs(jiffies - lts); + out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts); goto done; case O2HB_DB_TYPE_REGION_PINNED: -- cgit From 3ba169ccec1c5ad0f678e04fd29b990197fdfe79 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:32:54 -0700 Subject: ocfs2/cluster: Add new function o2net_fill_node_map() Patch adds function o2net_fill_node_map() to return the bitmap of nodes that it is connected to. This bitmap is also accessible by the user via the debugfs file, /sys/kernel/debug/o2net/connected_nodes. Signed-off-by: Sunil Mushran --- fs/ocfs2/cluster/netdebug.c | 102 ++++++++++++++++++++++++++++++-------------- fs/ocfs2/cluster/tcp.c | 19 +++++++++ fs/ocfs2/cluster/tcp.h | 2 + 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c index 3a5835904b3d..dc45deb19e68 100644 --- a/fs/ocfs2/cluster/netdebug.c +++ b/fs/ocfs2/cluster/netdebug.c @@ -47,6 +47,7 @@ #define SC_DEBUG_NAME "sock_containers" #define NST_DEBUG_NAME "send_tracking" #define STATS_DEBUG_NAME "stats" +#define NODES_DEBUG_NAME "connected_nodes" #define SHOW_SOCK_CONTAINERS 0 #define SHOW_SOCK_STATS 1 @@ -55,6 +56,7 @@ static struct dentry *o2net_dentry; static struct dentry *sc_dentry; static struct dentry *nst_dentry; static struct dentry *stats_dentry; +static struct dentry *nodes_dentry; static DEFINE_SPINLOCK(o2net_debug_lock); @@ -491,53 +493,87 @@ static const struct file_operations sc_seq_fops = { .release = sc_fop_release, }; -int o2net_debugfs_init(void) +static int o2net_fill_bitmap(char *buf, int len) { - o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL); - if (!o2net_dentry) { - mlog_errno(-ENOMEM); - goto bail; - } + unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + int i = -1, out = 0; - nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR, - o2net_dentry, NULL, - &nst_seq_fops); - if (!nst_dentry) { - mlog_errno(-ENOMEM); - goto bail; - } + o2net_fill_node_map(map, sizeof(map)); - sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR, - o2net_dentry, NULL, - &sc_seq_fops); - if (!sc_dentry) { - mlog_errno(-ENOMEM); - goto bail; - } + while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) + out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); + out += snprintf(buf + out, PAGE_SIZE - out, "\n"); - stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, S_IFREG|S_IRUSR, - o2net_dentry, NULL, - &stats_seq_fops); - if (!stats_dentry) { - mlog_errno(-ENOMEM); - goto bail; - } + return out; +} + +static int nodes_fop_open(struct inode *inode, struct file *file) +{ + char *buf; + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE)); + + file->private_data = buf; return 0; -bail: - debugfs_remove(stats_dentry); - debugfs_remove(sc_dentry); - debugfs_remove(nst_dentry); - debugfs_remove(o2net_dentry); - return -ENOMEM; } +static int o2net_debug_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static ssize_t o2net_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return simple_read_from_buffer(buf, nbytes, ppos, file->private_data, + i_size_read(file->f_mapping->host)); +} + +static const struct file_operations nodes_fops = { + .open = nodes_fop_open, + .release = o2net_debug_release, + .read = o2net_debug_read, + .llseek = generic_file_llseek, +}; + void o2net_debugfs_exit(void) { + debugfs_remove(nodes_dentry); debugfs_remove(stats_dentry); debugfs_remove(sc_dentry); debugfs_remove(nst_dentry); debugfs_remove(o2net_dentry); } +int o2net_debugfs_init(void) +{ + mode_t mode = S_IFREG|S_IRUSR; + + o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL); + if (o2net_dentry) + nst_dentry = debugfs_create_file(NST_DEBUG_NAME, mode, + o2net_dentry, NULL, &nst_seq_fops); + if (nst_dentry) + sc_dentry = debugfs_create_file(SC_DEBUG_NAME, mode, + o2net_dentry, NULL, &sc_seq_fops); + if (sc_dentry) + stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, mode, + o2net_dentry, NULL, &stats_seq_fops); + if (stats_dentry) + nodes_dentry = debugfs_create_file(NODES_DEBUG_NAME, mode, + o2net_dentry, NULL, &nodes_fops); + if (nodes_dentry) + return 0; + + o2net_debugfs_exit(); + mlog_errno(-ENOMEM); + return -ENOMEM; +} + #endif /* CONFIG_DEBUG_FS */ diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 6e97895ecf24..ae13d5ca7908 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -1034,6 +1034,25 @@ static int o2net_tx_can_proceed(struct o2net_node *nn, return ret; } +/* Get a map of all nodes to which this node is currently connected to */ +void o2net_fill_node_map(unsigned long *map, unsigned bytes) +{ + struct o2net_sock_container *sc; + int node, ret; + + BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long))); + + memset(map, 0, bytes); + for (node = 0; node < O2NM_MAX_NODES; ++node) { + o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret); + if (!ret) { + set_bit(node, map); + sc_put(sc); + } + } +} +EXPORT_SYMBOL_GPL(o2net_fill_node_map); + int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, size_t caller_veclen, u8 target_node, int *status) { diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h index fd6179eb26d4..5bada2a69b50 100644 --- a/fs/ocfs2/cluster/tcp.h +++ b/fs/ocfs2/cluster/tcp.h @@ -106,6 +106,8 @@ int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, struct list_head *unreg_list); void o2net_unregister_handler_list(struct list_head *list); +void o2net_fill_node_map(unsigned long *map, unsigned bytes); + struct o2nm_node; int o2net_register_hb_callbacks(void); void o2net_unregister_hb_callbacks(void); -- cgit From 6b27f62fc750d85bc6fc3718b3b38ec60edc2d74 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:33:54 -0700 Subject: ocfs2/cluster: Cluster up now includes network connections too The cluster up check only checks to see if the node is heartbeating or not. If yes it continues assuming that the node is connected to all the nodes. But if that is not the case, the cluster join aborts with a stack of errors that are not easy to comprehend. This patch adds the network connect check upfront and prints the nodes that the node is not yet connected to, before aborting. Signed-off-by: Sunil Mushran --- fs/ocfs2/dlm/dlmdomain.c | 7 ----- fs/ocfs2/stack_o2cb.c | 67 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 200d9888ffee..92f2ead0fab6 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -2138,13 +2138,6 @@ struct dlm_ctxt * dlm_register_domain(const char *domain, goto leave; } - if (!o2hb_check_local_node_heartbeating()) { - mlog(ML_ERROR, "the local node has not been configured, or is " - "not heartbeating\n"); - ret = -EPROTO; - goto leave; - } - mlog(0, "register called for domain \"%s\"\n", domain); retry: diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c index be935d89a4e8..94368017edb3 100644 --- a/fs/ocfs2/stack_o2cb.c +++ b/fs/ocfs2/stack_o2cb.c @@ -28,6 +28,7 @@ #include "cluster/masklog.h" #include "cluster/nodemanager.h" #include "cluster/heartbeat.h" +#include "cluster/tcp.h" #include "stackglue.h" @@ -255,6 +256,61 @@ static void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb) dlm_print_one_lock(lksb->lksb_o2dlm.lockid); } +/* + * Check if this node is heartbeating and is connected to all other + * heartbeating nodes. + */ +static int o2cb_cluster_check(void) +{ + u8 node_num; + int i; + unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; + + node_num = o2nm_this_node(); + if (node_num == O2NM_MAX_NODES) { + printk(KERN_ERR "o2cb: This node has not been configured.\n"); + return -EINVAL; + } + + /* + * o2dlm expects o2net sockets to be created. If not, then + * dlm_join_domain() fails with a stack of errors which are both cryptic + * and incomplete. The idea here is to detect upfront whether we have + * managed to connect to all nodes or not. If not, then list the nodes + * to allow the user to check the configuration (incorrect IP, firewall, + * etc.) Yes, this is racy. But its not the end of the world. + */ +#define O2CB_MAP_STABILIZE_COUNT 60 + for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) { + o2hb_fill_node_map(hbmap, sizeof(hbmap)); + if (!test_bit(node_num, hbmap)) { + printk(KERN_ERR "o2cb: %s heartbeat has not been " + "started.\n", (o2hb_global_heartbeat_active() ? + "Global" : "Local")); + return -EINVAL; + } + o2net_fill_node_map(netmap, sizeof(netmap)); + /* Force set the current node to allow easy compare */ + set_bit(node_num, netmap); + if (!memcmp(hbmap, netmap, sizeof(hbmap))) + return 0; + if (i < O2CB_MAP_STABILIZE_COUNT) + msleep(1000); + } + + printk(KERN_ERR "o2cb: This node could not connect to nodes:"); + i = -1; + while ((i = find_next_bit(hbmap, O2NM_MAX_NODES, + i + 1)) < O2NM_MAX_NODES) { + if (!test_bit(i, netmap)) + printk(" %u", i); + } + printk(".\n"); + + return -ENOTCONN; +} + /* * Called from the dlm when it's about to evict a node. This is how the * classic stack signals node death. @@ -280,12 +336,11 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) BUG_ON(conn == NULL); BUG_ON(conn->cc_proto == NULL); - /* for now we only have one cluster/node, make sure we see it - * in the heartbeat universe */ - if (!o2hb_check_local_node_heartbeating()) { - if (o2hb_global_heartbeat_active()) - mlog(ML_ERROR, "Global heartbeat not started\n"); - rc = -EINVAL; + /* Ensure cluster stack is up and all nodes are connected */ + rc = o2cb_cluster_check(); + if (rc) { + printk(KERN_ERR "o2cb: Cluster check failed. Fix errors " + "before retrying.\n"); goto out; } -- cgit From 619c200de144b44f5e405305241bcd7edbb8c6cf Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:34:54 -0700 Subject: ocfs2: Clean up messages in the fs Convert useful messages from ML_NOTICE to KERN_NOTICE to improve readability. Signed-off-by: Sunil Mushran --- fs/ocfs2/journal.c | 9 ++++++--- fs/ocfs2/quota_local.c | 13 +++++++++---- fs/ocfs2/slot_map.c | 4 ++-- fs/ocfs2/super.c | 10 +++++----- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 295d56454e8b..8eaaa7854409 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1544,9 +1544,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, /* we need to run complete recovery for offline orphan slots */ ocfs2_replay_map_set_state(osb, REPLAY_NEEDED); - mlog(ML_NOTICE, "Recovering node %d from slot %d on device (%u,%u)\n", - node_num, slot_num, - MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); + printk(KERN_NOTICE "ocfs2: Begin replay journal (node %d, slot %d) on "\ + "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev), + MINOR(osb->sb->s_dev)); OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); @@ -1601,6 +1601,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, jbd2_journal_destroy(journal); + printk(KERN_NOTICE "ocfs2: End replay journal (node %d, slot %d) on "\ + "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev), + MINOR(osb->sb->s_dev)); done: /* drop the lock on this nodes journal */ if (got_lock) diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index dc8007fc9247..942fd65bdad3 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -404,7 +404,9 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery( int status = 0; struct ocfs2_quota_recovery *rec; - mlog(ML_NOTICE, "Beginning quota recovery in slot %u\n", slot_num); + printk(KERN_NOTICE "ocfs2: Beginning quota recovery on device (%s) for " + "slot %u\n", osb->dev_str, slot_num); + rec = ocfs2_alloc_quota_recovery(); if (!rec) return ERR_PTR(-ENOMEM); @@ -596,7 +598,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, struct inode *lqinode; unsigned int flags; - mlog(ML_NOTICE, "Finishing quota recovery in slot %u\n", slot_num); + printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for " + "slot %u\n", osb->dev_str, slot_num); + mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); for (type = 0; type < MAXQUOTAS; type++) { if (list_empty(&(rec->r_list[type]))) @@ -612,8 +616,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, /* Someone else is holding the lock? Then he must be * doing the recovery. Just skip the file... */ if (status == -EAGAIN) { - mlog(ML_NOTICE, "skipping quota recovery for slot %d " - "because quota file is locked.\n", slot_num); + printk(KERN_NOTICE "ocfs2: Skipping quota recovery on " + "device (%s) for slot %d because quota file is " + "locked.\n", osb->dev_str, slot_num); status = 0; goto out_put; } else if (status < 0) { diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index 26fc0014d509..1424c151cccc 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -493,8 +493,8 @@ int ocfs2_find_slot(struct ocfs2_super *osb) goto bail; } } else - mlog(ML_NOTICE, "slot %d is already allocated to this node!\n", - slot); + printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already " + "allocated to this node!\n", slot, osb->dev_str); ocfs2_set_slot(si, slot, osb->node_num); osb->slot_num = slot; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 56f61027236b..3e7850380d2b 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1107,9 +1107,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) ocfs2_set_ro_flag(osb, 1); - printk(KERN_NOTICE "Readonly device detected. No cluster " - "services will be utilized for this mount. Recovery " - "will be skipped.\n"); + printk(KERN_NOTICE "ocfs2: Readonly device (%s) detected. " + "Cluster services will not be used for this mount. " + "Recovery will be skipped.\n", osb->dev_str); } if (!ocfs2_is_hard_readonly(osb)) { @@ -2462,8 +2462,8 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) goto finally; } } else { - mlog(ML_NOTICE, "File system was not unmounted cleanly, " - "recovering volume.\n"); + printk(KERN_NOTICE "ocfs2: File system on device (%s) was not " + "unmounted cleanly, recovering it.\n", osb->dev_str); } local = ocfs2_mount_local(osb); -- cgit From a035bff6b82aca89c1223e2c614adc2d17ec8aa2 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Sun, 24 Jul 2011 10:35:54 -0700 Subject: ocfs2: Add comment about orphan scanning Add a comment that explains the reason as to why orphan scan scans all the slots. Signed-off-by: Sunil Mushran --- fs/ocfs2/journal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 8eaaa7854409..0a42ae96dca7 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1811,6 +1811,20 @@ static inline unsigned long ocfs2_orphan_scan_timeout(void) * every slot, queuing a recovery of the slot on the ocfs2_wq thread. This * is done to catch any orphans that are left over in orphan directories. * + * It scans all slots, even ones that are in use. It does so to handle the + * case described below: + * + * Node 1 has an inode it was using. The dentry went away due to memory + * pressure. Node 1 closes the inode, but it's on the free list. The node + * has the open lock. + * Node 2 unlinks the inode. It grabs the dentry lock to notify others, + * but node 1 has no dentry and doesn't get the message. It trylocks the + * open lock, sees that another node has a PR, and does nothing. + * Later node 2 runs its orphan dir. It igets the inode, trylocks the + * open lock, sees the PR still, and does nothing. + * Basically, we have to trigger an orphan iput on node 1. The only way + * for this to happen is if node 1 runs node 2's orphan dir. + * * ocfs2_queue_orphan_scan gets called every ORPHAN_SCAN_SCHEDULE_TIMEOUT * seconds. It gets an EX lock on os_lockres and checks sequence number * stored in LVB. If the sequence number has changed, it means some other -- cgit From 5cffff9e29866a3de98c2c25135b3199491f93b0 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Sun, 24 Jul 2011 10:36:54 -0700 Subject: ocfs2: Fix ocfs2_page_mkwrite() This patch address two shortcomings in ocfs2_page_mkwrite(): 1. Makes the function return better VM_FAULT_* errors. 2. It handles a error that is triggered when a page is dropped from the mapping due to memory pressure. This patch locks the page to prevent that. [Patch was cleaned up by Sunil Mushran.] Signed-off-by: Wengang Wang Signed-off-by: Sunil Mushran --- fs/ocfs2/aops.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- fs/ocfs2/mmap.c | 53 ++++++++++++++++++++++++----------------------------- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c1efe939c774..ff98c169b631 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -862,6 +862,12 @@ struct ocfs2_write_ctxt { struct page *w_pages[OCFS2_MAX_CTXT_PAGES]; struct page *w_target_page; + /* + * w_target_locked is used for page_mkwrite path indicating no unlocking + * against w_target_page in ocfs2_write_end_nolock. + */ + unsigned int w_target_locked:1; + /* * ocfs2_write_end() uses this to know what the real range to * write in the target should be. @@ -895,6 +901,24 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) { + int i; + + /* + * w_target_locked is only set to true in the page_mkwrite() case. + * The intent is to allow us to lock the target page from write_begin() + * to write_end(). The caller must hold a ref on w_target_page. + */ + if (wc->w_target_locked) { + BUG_ON(!wc->w_target_page); + for (i = 0; i < wc->w_num_pages; i++) { + if (wc->w_target_page == wc->w_pages[i]) { + wc->w_pages[i] = NULL; + break; + } + } + mark_page_accessed(wc->w_target_page); + page_cache_release(wc->w_target_page); + } ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); brelse(wc->w_di_bh); @@ -1132,20 +1156,17 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping, */ lock_page(mmap_page); + /* Exit and let the caller retry */ if (mmap_page->mapping != mapping) { + WARN_ON(mmap_page->mapping); unlock_page(mmap_page); - /* - * Sanity check - the locking in - * ocfs2_pagemkwrite() should ensure - * that this code doesn't trigger. - */ - ret = -EINVAL; - mlog_errno(ret); + ret = -EAGAIN; goto out; } page_cache_get(mmap_page); wc->w_pages[i] = mmap_page; + wc->w_target_locked = true; } else { wc->w_pages[i] = find_or_create_page(mapping, index, GFP_NOFS); @@ -1160,6 +1181,8 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping, wc->w_target_page = wc->w_pages[i]; } out: + if (ret) + wc->w_target_locked = false; return ret; } @@ -1817,11 +1840,23 @@ try_again: */ ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len, cluster_of_pages, mmap_page); - if (ret) { + if (ret && ret != -EAGAIN) { mlog_errno(ret); goto out_quota; } + /* + * ocfs2_grab_pages_for_write() returns -EAGAIN if it could not lock + * the target page. In this case, we exit with no error and no target + * page. This will trigger the caller, page_mkwrite(), to re-try + * the operation. + */ + if (ret == -EAGAIN) { + BUG_ON(wc->w_target_page); + ret = 0; + goto out_quota; + } + ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos, len); if (ret) { diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 3e9393ca39eb..9cd41083e991 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -61,7 +61,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, struct page *page) { - int ret; + int ret = VM_FAULT_NOPAGE; struct inode *inode = file->f_path.dentry->d_inode; struct address_space *mapping = inode->i_mapping; loff_t pos = page_offset(page); @@ -71,32 +71,25 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, void *fsdata; loff_t size = i_size_read(inode); - /* - * Another node might have truncated while we were waiting on - * cluster locks. - * We don't check size == 0 before the shift. This is borrowed - * from do_generic_file_read. - */ last_index = (size - 1) >> PAGE_CACHE_SHIFT; - if (unlikely(!size || page->index > last_index)) { - ret = -EINVAL; - goto out; - } /* - * The i_size check above doesn't catch the case where nodes - * truncated and then re-extended the file. We'll re-check the - * page mapping after taking the page lock inside of - * ocfs2_write_begin_nolock(). + * There are cases that lead to the page no longer bebongs to the + * mapping. + * 1) pagecache truncates locally due to memory pressure. + * 2) pagecache truncates when another is taking EX lock against + * inode lock. see ocfs2_data_convert_worker. + * + * The i_size check doesn't catch the case where nodes truncated and + * then re-extended the file. We'll re-check the page mapping after + * taking the page lock inside of ocfs2_write_begin_nolock(). + * + * Let VM retry with these cases. */ - if (!PageUptodate(page) || page->mapping != inode->i_mapping) { - /* - * the page has been umapped in ocfs2_data_downconvert_worker. - * So return 0 here and let VFS retry. - */ - ret = 0; + if ((page->mapping != inode->i_mapping) || + (!PageUptodate(page)) || + (page_offset(page) >= size)) goto out; - } /* * Call ocfs2_write_begin() and ocfs2_write_end() to take @@ -116,17 +109,21 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, if (ret) { if (ret != -ENOSPC) mlog_errno(ret); + if (ret == -ENOMEM) + ret = VM_FAULT_OOM; + else + ret = VM_FAULT_SIGBUS; goto out; } - ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page, - fsdata); - if (ret < 0) { - mlog_errno(ret); + if (!locked_page) { + ret = VM_FAULT_NOPAGE; goto out; } + ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page, + fsdata); BUG_ON(ret != len); - ret = 0; + ret = VM_FAULT_LOCKED; out: return ret; } @@ -168,8 +165,6 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) out: ocfs2_unblock_signals(&oldset); - if (ret) - ret = VM_FAULT_SIGBUS; return ret; } -- cgit From 93862d5e1ab875664c6cc95254fc365028a48bb1 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Mon, 25 Jul 2011 14:58:15 -0700 Subject: ocfs2: Implement llseek() ocfs2 implements its own llseek() to provide the SEEK_HOLE/SEEK_DATA functionality. SEEK_HOLE sets the file pointer to the start of either a hole or an unwritten (preallocated) extent, that is greater than or equal to the supplied offset. SEEK_DATA sets the file pointer to the start of an allocated extent (not unwritten) that is greater than or equal to the supplied offset. If the supplied offset is on a desired region, then the file pointer is set to it. Offsets greater than or equal to the file size return -ENXIO. Unwritten (preallocated) extents are considered holes because the file system treats reads to such regions in the same way as it does to holes. Signed-off-by: Sunil Mushran --- fs/ocfs2/extent_map.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/extent_map.h | 2 ++ fs/ocfs2/file.c | 55 +++++++++++++++++++++++++++-- 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 23457b491e8c..2f5b92ef0e53 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -832,6 +832,102 @@ out: return ret; } +int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin) +{ + struct inode *inode = file->f_mapping->host; + int ret; + unsigned int is_last = 0, is_data = 0; + u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits; + u32 cpos, cend, clen, hole_size; + u64 extoff, extlen; + struct buffer_head *di_bh = NULL; + struct ocfs2_extent_rec rec; + + BUG_ON(origin != SEEK_DATA && origin != SEEK_HOLE); + + ret = ocfs2_inode_lock(inode, &di_bh, 0); + if (ret) { + mlog_errno(ret); + goto out; + } + + down_read(&OCFS2_I(inode)->ip_alloc_sem); + + if (*offset >= inode->i_size) { + ret = -ENXIO; + goto out_unlock; + } + + if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { + if (origin == SEEK_HOLE) + *offset = inode->i_size; + goto out_unlock; + } + + clen = 0; + cpos = *offset >> cs_bits; + cend = ocfs2_clusters_for_bytes(inode->i_sb, inode->i_size); + + while (cpos < cend && !is_last) { + ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size, + &rec, &is_last); + if (ret) { + mlog_errno(ret); + goto out_unlock; + } + + extoff = cpos; + extoff <<= cs_bits; + + if (rec.e_blkno == 0ULL) { + clen = hole_size; + is_data = 0; + } else { + clen = le16_to_cpu(rec.e_leaf_clusters) - + (cpos - le32_to_cpu(rec.e_cpos)); + is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ? 0 : 1; + } + + if ((!is_data && origin == SEEK_HOLE) || + (is_data && origin == SEEK_DATA)) { + if (extoff > *offset) + *offset = extoff; + goto out_unlock; + } + + if (!is_last) + cpos += clen; + } + + if (origin == SEEK_HOLE) { + extoff = cpos; + extoff <<= cs_bits; + extlen = clen; + extlen <<= cs_bits; + + if ((extoff + extlen) > inode->i_size) + extlen = inode->i_size - extoff; + extoff += extlen; + if (extoff > *offset) + *offset = extoff; + goto out_unlock; + } + + ret = -ENXIO; + +out_unlock: + + brelse(di_bh); + + up_read(&OCFS2_I(inode)->ip_alloc_sem); + + ocfs2_inode_unlock(inode, 0); +out: + if (ret && ret != -ENXIO) + ret = -ENXIO; + return ret; +} + int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, struct buffer_head *bhs[], int flags, int (*validate)(struct super_block *sb, diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h index e79d41c2c909..67ea57d2fd59 100644 --- a/fs/ocfs2/extent_map.h +++ b/fs/ocfs2/extent_map.h @@ -53,6 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 map_start, u64 map_len); +int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin); + int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, u32 *num_clusters, struct ocfs2_extent_list *el, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 0fc2bd34039d..c0f015e11c28 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2591,6 +2591,57 @@ bail: return ret; } +/* Refer generic_file_llseek_unlocked() */ +static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin) +{ + struct inode *inode = file->f_mapping->host; + int ret = 0; + + mutex_lock(&inode->i_mutex); + + switch (origin) { + case SEEK_SET: + break; + case SEEK_END: + offset += inode->i_size; + break; + case SEEK_CUR: + if (offset == 0) { + offset = file->f_pos; + goto out; + } + offset += file->f_pos; + break; + case SEEK_DATA: + case SEEK_HOLE: + ret = ocfs2_seek_data_hole_offset(file, &offset, origin); + if (ret) + goto out; + break; + default: + ret = -EINVAL; + goto out; + } + + if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) + ret = -EINVAL; + if (!ret && offset > inode->i_sb->s_maxbytes) + ret = -EINVAL; + if (ret) + goto out; + + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_version = 0; + } + +out: + mutex_unlock(&inode->i_mutex); + if (ret) + return ret; + return offset; +} + const struct inode_operations ocfs2_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, @@ -2615,7 +2666,7 @@ const struct inode_operations ocfs2_special_file_iops = { * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks! */ const struct file_operations ocfs2_fops = { - .llseek = generic_file_llseek, + .llseek = ocfs2_file_llseek, .read = do_sync_read, .write = do_sync_write, .mmap = ocfs2_mmap, @@ -2663,7 +2714,7 @@ const struct file_operations ocfs2_dops = { * the cluster. */ const struct file_operations ocfs2_fops_no_plocks = { - .llseek = generic_file_llseek, + .llseek = ocfs2_file_llseek, .read = do_sync_read, .write = do_sync_write, .mmap = ocfs2_mmap, -- cgit From a11f7e63c59810a81494d4c4b028af707d4c7ca4 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 22 Jun 2011 14:23:38 -0700 Subject: ocfs2: serialize unaligned aio Fix a corruption that can happen when we have (two or more) outstanding aio's to an overlapping unaligned region. Ext4 (e9e3bcecf44c04b9e6b505fd8e2eb9cea58fb94d) and xfs recently had to fix similar issues. In our case what happens is that we can have an outstanding aio on a region and if a write comes in with some bytes overlapping the original aio we may decide to read that region into a page before continuing (typically because of buffered-io fallback). Since we have no ordering guarantees with the aio, we can read stale or bad data into the page and then write it back out. If the i/o is page and block aligned, then we avoid this issue as there won't be any need to read data from disk. I took the same approach as Eric in the ext4 patch and introduced some serialization of unaligned async direct i/o. I don't expect this to have an effect on the most common cases of AIO. Unaligned aio will be slower though, but that's far more acceptable than data corruption. Signed-off-by: Mark Fasheh Signed-off-by: Joel Becker --- fs/ocfs2/aops.c | 10 ++++++++++ fs/ocfs2/aops.h | 14 ++++++++++++++ fs/ocfs2/file.c | 38 ++++++++++++++++++++++++++++++++++++++ fs/ocfs2/inode.h | 3 +++ fs/ocfs2/super.c | 10 ++++++++-- 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index ac97bca282d2..4c1ec8f2d8c1 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -564,6 +564,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, { struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; int level; + wait_queue_head_t *wq = ocfs2_ioend_wq(inode); /* this io's submitter should not have unlocked this before we could */ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); @@ -573,6 +574,15 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, ocfs2_iocb_clear_sem_locked(iocb); } + if (ocfs2_iocb_is_unaligned_aio(iocb)) { + ocfs2_iocb_clear_unaligned_aio(iocb); + + if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) && + waitqueue_active(wq)) { + wake_up_all(wq); + } + } + ocfs2_iocb_clear_rw_locked(iocb); level = ocfs2_iocb_rw_locked_level(iocb); diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index 75cf3ad987a6..ffb2da370a99 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -78,6 +78,7 @@ enum ocfs2_iocb_lock_bits { OCFS2_IOCB_RW_LOCK = 0, OCFS2_IOCB_RW_LOCK_LEVEL, OCFS2_IOCB_SEM, + OCFS2_IOCB_UNALIGNED_IO, OCFS2_IOCB_NUM_LOCKS }; @@ -91,4 +92,17 @@ enum ocfs2_iocb_lock_bits { clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) #define ocfs2_iocb_is_sem_locked(iocb) \ test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) + +#define ocfs2_iocb_set_unaligned_aio(iocb) \ + set_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) +#define ocfs2_iocb_clear_unaligned_aio(iocb) \ + clear_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) +#define ocfs2_iocb_is_unaligned_aio(iocb) \ + test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) + +#define OCFS2_IOEND_WQ_HASH_SZ 37 +#define ocfs2_ioend_wq(v) (&ocfs2__ioend_wq[((unsigned long)(v)) %\ + OCFS2_IOEND_WQ_HASH_SZ]) +extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; + #endif /* OCFS2_FILE_H */ diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b1e35a392ca5..145f4533a936 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2038,6 +2038,23 @@ out: return ret; } +static void ocfs2_aiodio_wait(struct inode *inode) +{ + wait_queue_head_t *wq = ocfs2_ioend_wq(inode); + + wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0)); +} + +static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos) +{ + int blockmask = inode->i_sb->s_blocksize - 1; + loff_t final_size = pos + count; + + if ((pos & blockmask) || (final_size & blockmask)) + return 1; + return 0; +} + static int ocfs2_prepare_inode_for_refcount(struct inode *inode, struct file *file, loff_t pos, size_t count, @@ -2216,6 +2233,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); int full_coherency = !(osb->s_mount_opt & OCFS2_MOUNT_COHERENCY_BUFFERED); + int unaligned_dio = 0; trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry, (unsigned long long)OCFS2_I(inode)->ip_blkno, @@ -2284,6 +2302,10 @@ relock: goto out; } + if (direct_io && !is_sync_kiocb(iocb)) + unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left, + *ppos); + /* * We can't complete the direct I/O as requested, fall back to * buffered I/O. @@ -2299,6 +2321,18 @@ relock: goto relock; } + if (unaligned_dio) { + /* + * Wait on previous unaligned aio to complete before + * proceeding. + */ + ocfs2_aiodio_wait(inode); + + /* Mark the iocb as needing a decrement in ocfs2_dio_end_io */ + atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio); + ocfs2_iocb_set_unaligned_aio(iocb); + } + /* * To later detect whether a journal commit for sync writes is * necessary, we sample i_size, and cluster count here. @@ -2371,8 +2405,12 @@ out_dio: if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) { rw_level = -1; have_alloc_sem = 0; + unaligned_dio = 0; } + if (unaligned_dio) + atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio); + out: if (rw_level != -1) ocfs2_rw_unlock(inode, rw_level); diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 1c508b149b3a..88924a3133fa 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -43,6 +43,9 @@ struct ocfs2_inode_info /* protects extended attribute changes on this inode */ struct rw_semaphore ip_xattr_sem; + /* Number of outstanding AIO's which are not page aligned */ + atomic_t ip_unaligned_aio; + /* These fields are protected by ip_lock */ spinlock_t ip_lock; u32 ip_open_count; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 029c4cd8a691..603f5fe9f816 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -54,6 +54,7 @@ #include "ocfs1_fs_compat.h" #include "alloc.h" +#include "aops.h" #include "blockcheck.h" #include "dlmglue.h" #include "export.h" @@ -1616,12 +1617,17 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) return 0; } +wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; + static int __init ocfs2_init(void) { - int status; + int status, i; ocfs2_print_version(); + for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++) + init_waitqueue_head(&ocfs2__ioend_wq[i]); + status = init_ocfs2_uptodate_cache(); if (status < 0) { mlog_errno(status); @@ -1760,7 +1766,7 @@ static void ocfs2_inode_init_once(void *data) ocfs2_extent_map_init(&oi->vfs_inode); INIT_LIST_HEAD(&oi->ip_io_markers); oi->ip_dir_start_lookup = 0; - + atomic_set(&oi->ip_unaligned_aio, 0); init_rwsem(&oi->ip_alloc_sem); init_rwsem(&oi->ip_xattr_sem); mutex_init(&oi->ip_io_mutex); -- cgit From c7e25e6e0b0486492c5faaf6312b37413642c48e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 23 Jun 2011 22:51:47 +0200 Subject: ocfs2: Avoid livelock in ocfs2_readpage() When someone writes to an inode, readers accessing the same inode via ocfs2_readpage() just busyloop trying to get ip_alloc_sem because do_generic_file_read() looks up the page again and retries ->readpage() when previous attempt failed with AOP_TRUNCATED_PAGE. When there are enough readers, they can occupy all CPUs and in non-preempt kernel the system is deadlocked because writer holding ip_alloc_sem is never run to release the semaphore. Fix the problem by making reader block on ip_alloc_sem to break the busy loop. Signed-off-by: Jan Kara Signed-off-by: Joel Becker --- fs/ocfs2/aops.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 4c1ec8f2d8c1..ba3ca1e63b51 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -290,7 +290,15 @@ static int ocfs2_readpage(struct file *file, struct page *page) } if (down_read_trylock(&oi->ip_alloc_sem) == 0) { + /* + * Unlock the page and cycle ip_alloc_sem so that we don't + * busyloop waiting for ip_alloc_sem to unlock + */ ret = AOP_TRUNCATED_PAGE; + unlock_page(page); + unlock = 0; + down_read(&oi->ip_alloc_sem); + up_read(&oi->ip_alloc_sem); goto out_inode_unlock; } -- cgit From ece9528e5f88cee11303fceefe39382f1030cd4e Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 12 Jul 2011 08:18:15 -0700 Subject: gpio/omap: replace MOD_REG_BIT macro with static inline This macro is ugly and confusing, especially since it passes in most arguments, but uses an implied 'base' from the caller. Replace it with an equivalent static inline. Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 54 ++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0599854e2217..34a7110d9bc8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -148,13 +148,17 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0; } -#define MOD_REG_BIT(reg, bit_mask, set) \ -do { \ - int l = __raw_readl(base + reg); \ - if (set) l |= bit_mask; \ - else l &= ~bit_mask; \ - __raw_writel(l, base + reg); \ -} while(0) +static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) +{ + int l = __raw_readl(base + reg); + + if (set) + l |= mask; + else + l &= ~mask; + + __raw_writel(l, base + reg); +} /** * _set_gpio_debounce - low level gpio debounce time @@ -210,28 +214,28 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, u32 gpio_bit = 1 << gpio; if (cpu_is_omap44xx()) { - MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); + _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit, + trigger & IRQ_TYPE_LEVEL_LOW); + _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit, + trigger & IRQ_TYPE_LEVEL_HIGH); + _gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_RISING); + _gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_FALLING); } else { - MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); + _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, + trigger & IRQ_TYPE_LEVEL_LOW); + _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, + trigger & IRQ_TYPE_LEVEL_HIGH); + _gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_RISING); + _gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_FALLING); } if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { if (cpu_is_omap44xx()) { - MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit, - trigger != 0); + _gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit, + trigger != 0); } else { /* * GPIO wakeup request can only be generated on edge -- cgit From 832337490f22987a1b739ba840e105c0c9af01bc Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Mon, 18 Jul 2011 07:43:14 -0700 Subject: gpio/omap: check return value from irq_alloc_generic_chip Ensure return value of irq_alloc_generic_chip() is checked before continuing on to use it. Signed-off-by: Todd Poynor Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 34a7110d9bc8..f0208a958185 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1090,6 +1090,11 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base, handle_simple_irq); + if (!gc) { + dev_err(bank->dev, "Memory alloc failed for gc\n"); + return; + } + ct = gc->chip_types; /* NOTE: No ack required, reading IRQ status clears it. */ -- cgit From a78f6787a3dd7223bf185895fdcea661b408dc0a Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 17:18:08 +0000 Subject: DocBook/drm: Eradicate inappropriate uses of the future tense Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index c27915893974..0527ff2be37e 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -57,10 +57,10 @@ existing drivers. - First, we'll go over some typical driver initialization + First, we go over some typical driver initialization requirements, like setting up command buffers, creating an initial output configuration, and initializing core services. - Subsequent sections will cover core internals in more detail, + Subsequent sections cover core internals in more detail, providing implementation notes and examples. @@ -74,7 +74,7 @@ The core of every DRM driver is struct drm_driver. Drivers - will typically statically initialize a drm_driver structure, + typically statically initialize a drm_driver structure, then pass it to drm_init() at load time. @@ -155,7 +155,7 @@ In the example above, taken from the i915 DRM driver, the driver sets several flags indicating what core features it supports. - We'll go over the individual callbacks in later sections. Since + We go over the individual callbacks in later sections. Since flags indicate which features your driver supports to the DRM core, you need to set most of them prior to calling drm_init(). Some, like DRIVER_MODESET can be set later based on user supplied parameters, @@ -238,7 +238,7 @@ In this specific case, the driver requires AGP and supports - IRQs. DMA, as we'll see, is handled by device specific ioctls + IRQs. DMA, as discussed later, is handled by device specific ioctls in this case. It also supports the kernel mode setting APIs, though unlike in the actual i915 driver source, this example unconditionally exports KMS capability. @@ -315,7 +315,7 @@ Configuring the device - Obviously, device configuration will be device specific. + Obviously, device configuration is device specific. However, there are several common operations: finding a device's PCI resources, mapping them, and potentially setting up an IRQ handler. @@ -326,7 +326,7 @@ drm_get_resource_len() can be used to find BARs on the given drm_device struct. Once those values have been retrieved, the driver load function can call drm_addmap() to create a new - mapping for the BAR in question. Note you'll probably want a + mapping for the BAR in question. Note you probably want a drm_local_map_t in your driver private structure to track any mappings you create. @@ -357,7 +357,7 @@ - Once your interrupt handler is registered (it'll use your + Once your interrupt handler is registered (it uses your drm_driver.irq_handler as the actual interrupt handling function), you can safely enable interrupts on your device, assuming any other state your interrupt handler uses is also @@ -389,7 +389,7 @@ should support a memory manager. - If your driver supports memory management (it should!), you'll + If your driver supports memory management (it should!), you need to set that up at load time as well. How you initialize it depends on which memory manager you're using, TTM or GEM. @@ -430,13 +430,13 @@ have a type of TTM_GLOBAL_TTM_MEM. The size field for the global object should be sizeof(struct ttm_mem_global), and the init and release hooks should point at your driver specific init and - release routines, which will probably eventually call + release routines, which probably eventually call ttm_mem_global_init and ttm_mem_global_release respectively. Once your global TTM accounting structure is set up and initialized (done by calling ttm_global_item_ref on the global object you - just created), you'll need to create a buffer object TTM to + just created), you need to create a buffer object TTM to provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, @@ -455,8 +455,8 @@ than TTM, but has no VRAM management capability. Core GEM initialization is comprised of a basic drm_mm_init call to create a GTT DRM MM object, which provides an address space pool for - object allocation. In a KMS configuration, the driver will - need to allocate and initialize a command ring buffer following + object allocation. In a KMS configuration, the driver + needs to allocate and initialize a command ring buffer following basic GEM initialization. Most UMA devices have a so-called "stolen" memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the @@ -464,16 +464,16 @@ be initialized separately into its own DRM MM object. - Initialization will be driver specific, and will depend on + Initialization is driver specific, and depends on the architecture of the device. In the case of Intel integrated graphics chips like 965GM, GEM initialization can be done by calling the internal GEM init function, i915_gem_do_init(). Since the 965GM is a UMA device - (i.e. it doesn't have dedicated VRAM), GEM will manage + (i.e. it doesn't have dedicated VRAM), GEM manages making regular RAM available for GPU operations. Memory set aside by the BIOS (called "stolen" memory by the i915 - driver) will be managed by the DRM memrange allocator; the - rest of the aperture will be managed by GEM. + driver) is managed by the DRM memrange allocator; the + rest of the aperture is managed by GEM. /* Basic memrange allocator for stolen space (aka vram) */ drm_memrange_init(&dev_priv->vram, 0, prealloc_size); @@ -616,7 +616,7 @@ void intel_crt_init(struct drm_device *dev) DRM_IOCTL_MODESET_CTL should be called by application level drivers before and after mode setting, since on many devices the - vertical blank counter will be reset at that time. Internally, + vertical blank counter is reset at that time. Internally, the DRM snapshots the last vblank count when the ioctl is called with the _DRM_PRE_MODESET command so that the counter won't go backwards (which is dealt with when _DRM_POST_MODESET is used). @@ -632,8 +632,8 @@ void intel_crt_init(struct drm_device *dev) register. The enable and disable vblank callbacks should enable and disable vertical blank interrupts, respectively. In the absence of DRM clients waiting on vblank events, the core DRM - code will use the disable_vblank() function to disable - interrupts, which saves power. They'll be re-enabled again when + code uses the disable_vblank() function to disable + interrupts, which saves power. They are re-enabled again when a client calls the vblank wait ioctl above. @@ -699,14 +699,14 @@ void intel_crt_init(struct drm_device *dev) performs any necessary flushing or synchronization to put the object into the desired coherency domain (note that the object may be busy, i.e. an active render target; in that case the set domain function - will block the client and wait for rendering to complete before + blocks the client and waits for rendering to complete before performing any necessary flushing operations). Perhaps the most important GEM function is providing a command execution interface to clients. Client programs construct command buffers containing references to previously allocated memory objects - and submit them to GEM. At that point, GEM will take care to bind + and submit them to GEM. At that point, GEM takes care to bind all the objects into the GTT, execute the buffer, and provide necessary synchronization between clients accessing the same buffers. This often involves evicting some objects from the GTT and re-binding @@ -767,7 +767,7 @@ void intel_crt_init(struct drm_device *dev) In order to set a mode on a given CRTC, encoder and connector configuration, clients need to provide a framebuffer object which - will provide a source of pixels for the CRTC to deliver to the encoder(s) + provides a source of pixels for the CRTC to deliver to the encoder(s) and ultimately the connector(s) in the configuration. A framebuffer is fundamentally a driver specific memory object, made into an opaque handle by the DRM addfb function. Once an fb has been created this @@ -789,7 +789,7 @@ void intel_crt_init(struct drm_device *dev) The DRM core provides some suspend/resume code, but drivers wanting full suspend/resume support should provide save() and - restore() functions. These will be called at suspend, + restore() functions. These are called at suspend, hibernate, or resume time, and should perform any state save or restore required by your device across suspend or hibernate states. @@ -823,7 +823,7 @@ void intel_crt_init(struct drm_device *dev) Cover generic ioctls and sysfs layout here. Only need high - level info, since man pages will cover the rest. + level info, since man pages should cover the rest. -- cgit From f11aca045c165b9d4c9c4fce29f51ec24bcf64d3 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 17:21:31 +0000 Subject: DocBook/drm: can -> may Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 0527ff2be37e..b9079386040d 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -32,7 +32,7 @@ The Linux DRM layer contains code intended to support the needs of complex graphics devices, usually containing programmable pipelines well suited to 3D graphics acceleration. Graphics - drivers in the kernel can make use of DRM functions to make + drivers in the kernel may make use of DRM functions to make tasks like memory management, interrupt handling and DMA easier, and provide a uniform interface to applications. @@ -293,12 +293,12 @@ can be used for tracking various device specific bits of information, like register offsets, command buffer status, register state for suspend/resume, etc. At load time, a - driver can simply allocate one and set drm_device.dev_priv + driver may simply allocate one and set drm_device.dev_priv appropriately; at unload the driver can free it and set drm_device.dev_priv to NULL. - The DRM supports several counters which can be used for rough + The DRM supports several counters which may be used for rough performance characterization. Note that the DRM stat counter system is not often used by applications, and supporting additional counters is completely optional. @@ -323,7 +323,7 @@ Finding & mapping resources is fairly straightforward. The DRM wrapper functions, drm_get_resource_start() and - drm_get_resource_len() can be used to find BARs on the given + drm_get_resource_len() may be used to find BARs on the given drm_device struct. Once those values have been retrieved, the driver load function can call drm_addmap() to create a new mapping for the BAR in question. Note you probably want a @@ -335,12 +335,12 @@ if compatibility with other operating systems isn't a concern (DRM drivers can run under various BSD variants and OpenSolaris), - native Linux calls can be used for the above, e.g. pci_resource_* + native Linux calls may be used for the above, e.g. pci_resource_* and iomap*/iounmap. See the Linux device driver book for more info. - Once you have a register map, you can use the DRM_READn() and + Once you have a register map, you may use the DRM_READn() and DRM_WRITEn() macros to access the registers on your device, or use driver specific versions to offset into your MMIO space relative to a driver specific base pointer (see I915_READ for @@ -440,7 +440,7 @@ provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, - driver specific init and release functions can be provided, + driver specific init and release functions may be provided, likely eventually calling ttm_bo_global_init and ttm_bo_global_release, respectively. Also like the previous object, ttm_global_item_ref is used to create an initial reference @@ -483,7 +483,7 @@ - Once the memory manager has been set up, we can allocate the + Once the memory manager has been set up, we may allocate the command buffer. In the i915 case, this is also done with a GEM function, i915_gem_init_ringbuffer(). @@ -572,7 +572,7 @@ void intel_crt_init(struct drm_device *dev) devices with PC-style architectures (i.e. a set of display planes for feeding pixels to encoders which are in turn routed to connectors). Devices with more complex requirements needing - finer grained management can opt to use the core callbacks + finer grained management may opt to use the core callbacks directly. @@ -637,7 +637,7 @@ void intel_crt_init(struct drm_device *dev) a client calls the vblank wait ioctl above. - Devices that don't provide a count register can simply use an + Devices that don't provide a count register may simply use an internal atomic counter incremented on every vertical blank interrupt, and can make their enable and disable vblank functions into no-ops. -- cgit From 0c54781bc5aaec1e23bc50a4ef757b8e8bfc693b Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 17:55:54 +0000 Subject: DocBook/drm: Clean up code comment Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index b9079386040d..4ddc99928668 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -88,8 +88,8 @@ static struct drm_driver driver = { - /* don't use mtrr's here, the Xserver or user space app should - * deal with them for intel hardware. + /* Don't use MTRRs here; the Xserver or userspace app should + * deal with them for Intel hardware. */ .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ce045a8cf82c..acf4ea84c801 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -785,8 +785,8 @@ static struct vm_operations_struct i915_gem_vm_ops = { }; static struct drm_driver driver = { - /* don't use mtrr's here, the Xserver or user space app should - * deal with them for intel hardware. + /* Don't use MTRRs here; the Xserver or userspace app should + * deal with them for Intel hardware. */ .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ -- cgit From 2c267e9e016da3e19a95261875a5f3b19dd6e9f6 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:10:12 +0000 Subject: DocBook/drm: Use a semicolon Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 4ddc99928668..aa13e0883510 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -154,8 +154,8 @@ In the example above, taken from the i915 DRM driver, the driver - sets several flags indicating what core features it supports. - We go over the individual callbacks in later sections. Since + sets several flags indicating what core features it supports; + we go over the individual callbacks in later sections. Since flags indicate which features your driver supports to the DRM core, you need to set most of them prior to calling drm_init(). Some, like DRIVER_MODESET can be set later based on user supplied parameters, @@ -647,8 +647,8 @@ void intel_crt_init(struct drm_device *dev) Memory management - The memory manager lies at the heart of many DRM operations, and - is also required to support advanced client features like OpenGL + The memory manager lies at the heart of many DRM operations; it + is required to support advanced client features like OpenGL pbuffers. The DRM currently contains two memory managers, TTM and GEM. -- cgit From 02391f1fe7b4e5434e4c558dcae99b9368c84bf3 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:20:54 +0000 Subject: DocBook/drm: a -> an Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index aa13e0883510..5b815b83c30b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -203,7 +203,7 @@ DRIVER_HAVE_IRQDRIVER_IRQ_SHARED - DRIVER_HAVE_IRQ indicates whether the driver has a IRQ + DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler, DRIVER_IRQ_SHARED indicates whether the device & handler support shared IRQs (note that this is required of PCI drivers). -- cgit From b1f95bdc1eb10e3d3c8a85b2f0bc08fa6c08ae5d Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:21:29 +0000 Subject: DocBook/drm: , -> . Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 5b815b83c30b..a0f0f984f04f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -204,7 +204,7 @@ DRIVER_HAVE_IRQ indicates whether the driver has an IRQ - handler, DRIVER_IRQ_SHARED indicates whether the device & + handler. DRIVER_IRQ_SHARED indicates whether the device & handler support shared IRQs (note that this is required of PCI drivers). -- cgit From 80c84e6f3c2c707ccb5d7b500e25bda69f0e1895 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:23:21 +0000 Subject: DocBook/drm: Move `should be set' to the beginning of the sentence Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index a0f0f984f04f..42368f4f7bab 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -214,8 +214,8 @@ DRIVER_DMA_QUEUE - If the driver queues DMA requests and completes them - asynchronously, this flag should be set. Deprecated. + Should be set if the driver queues DMA requests and completes them + asynchronously. Deprecated. -- cgit From 58f1d652def02db0bdcdf03d01f3483fc18ec392 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:31:42 +0000 Subject: DocBook/drm: Clean up `pre-memory management aware' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 42368f4f7bab..e9242c09ac54 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -273,7 +273,7 @@ conflict with DRM client requirements. For instance, if user level mode setting drivers are in use, it would be problematic to perform output discovery & configuration at load time. - Likewise, if pre-memory management aware user level drivers are + Likewise, if user-level drivers unaware of memory management are in use, memory management and command buffer setup may need to be omitted. These requirements are driver specific, and care needs to be taken to keep both old and new applications and -- cgit From 75aa9df5a2bf2ae90a1f0f6f283278f634ca4233 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:34:49 +0000 Subject: DocBook/drm: Rearrange wording to make more sense Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index e9242c09ac54..eb28cc02d41b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -281,9 +281,9 @@ module parameter to control whether advanced features are enabled at load time or in legacy fashion. If compatibility is a concern (e.g. with drivers converted over to the new interfaces - from the old ones), care must be taken to prevent incompatible - device initialization and control with the currently active - userspace drivers. + from the old ones), care must be taken to prevent device + initialization and control that is incompatible with + currently active userspace drivers. -- cgit From 6e375f44b6073dd320895753ff05cbfd3f410f66 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:37:05 +0000 Subject: DocBook/drm: Replace the paragraph's first sentence with its last sentence Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index eb28cc02d41b..9eda9b6df51d 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -269,8 +269,10 @@ initial output configuration. - Note that the tasks performed at driver load time must not - conflict with DRM client requirements. For instance, if user + If compatibility is a concern (e.g. with drivers converted over + to the new interfaces from the old ones), care must be taken to + prevent device initialization and control that is incompatible with + currently active userspace drivers. For instance, if user level mode setting drivers are in use, it would be problematic to perform output discovery & configuration at load time. Likewise, if user-level drivers unaware of memory management are @@ -279,11 +281,7 @@ needs to be taken to keep both old and new applications and libraries working. The i915 driver supports the "modeset" module parameter to control whether advanced features are - enabled at load time or in legacy fashion. If compatibility is - a concern (e.g. with drivers converted over to the new interfaces - from the old ones), care must be taken to prevent device - initialization and control that is incompatible with - currently active userspace drivers. + enabled at load time or in legacy fashion. -- cgit From 06fa7b8066d4dc3f6c9d4c4bf34f385d5a823f13 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:40:55 +0000 Subject: DocBook/drm: Better wording Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9eda9b6df51d..b4196c1a239d 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -292,8 +292,8 @@ information, like register offsets, command buffer status, register state for suspend/resume, etc. At load time, a driver may simply allocate one and set drm_device.dev_priv - appropriately; at unload the driver can free it and set - drm_device.dev_priv to NULL. + appropriately; it should be freed and drm_device.dev_priv set + to NULL when the driver is unloaded. The DRM supports several counters which may be used for rough -- cgit From 57a15fd663d6680dc100a537f0ed328993c33af2 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:42:36 +0000 Subject: DocBook/drm: Clearer wording with `for consumption by' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index b4196c1a239d..33290e3e3ffa 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -305,8 +305,8 @@ These interfaces are deprecated and should not be used. If performance monitoring is desired, the developer should investigate and potentially enhance the kernel perf and tracing infrastructure to export - GPU related performance information to performance monitoring - tools and applications. + GPU related performance information for consumption by performance + monitoring tools and applications. -- cgit From 8814630f0b59421e558f4403b79f5dc3a025a386 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:46:10 +0000 Subject: DocBook/drm: Insert missing `that' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 33290e3e3ffa..25e0f460a973 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -321,10 +321,10 @@ Finding & mapping resources is fairly straightforward. The DRM wrapper functions, drm_get_resource_start() and - drm_get_resource_len() may be used to find BARs on the given + drm_get_resource_len(), may be used to find BARs on the given drm_device struct. Once those values have been retrieved, the driver load function can call drm_addmap() to create a new - mapping for the BAR in question. Note you probably want a + mapping for the BAR in question. Note that you probably want a drm_local_map_t in your driver private structure to track any mappings you create. -- cgit From f07faf693c59b449b6637ea056e5826c85dcd265 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:48:15 +0000 Subject: DocBook/drm: Insert missing `an' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 25e0f460a973..1b2e3c37e377 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -342,7 +342,7 @@ DRM_WRITEn() macros to access the registers on your device, or use driver specific versions to offset into your MMIO space relative to a driver specific base pointer (see I915_READ for - example). + an example). If your device supports interrupt generation, you may want to -- cgit From 5b658bf2bf9e47f9a67cd26b1c69e4441eaf04fc Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:49:11 +0000 Subject: DocBook/drm: `setup' is the noun; `to set up' is the verb Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 1b2e3c37e377..d2f1ddaa3ca0 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -346,7 +346,7 @@ If your device supports interrupt generation, you may want to - setup an interrupt handler at driver load time as well. This + set up an interrupt handler at driver load time as well. This is done using the drm_irq_install() function. If your device supports vertical blank interrupts, it should call drm_vblank_init() to initialize the core vblank handling code before -- cgit From bb49a6a1f3303f9cf23a19f403c9b90cdff0e7da Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:50:14 +0000 Subject: DocBook/drm: `at driver load time' -> `when the driver is loaded' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index d2f1ddaa3ca0..7001937f6b7d 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -346,7 +346,7 @@ If your device supports interrupt generation, you may want to - set up an interrupt handler at driver load time as well. This + set up an interrupt handler when the driver is loaded. This is done using the drm_irq_install() function. If your device supports vertical blank interrupts, it should call drm_vblank_init() to initialize the core vblank handling code before -- cgit From 9c2416adac986d7d90814d7985a0ea80ebea416f Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:56:12 +0000 Subject: DocBook/drm: Use the passive voice Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 7001937f6b7d..03321ebaf4a7 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -369,9 +369,9 @@ using the pci_map_rom() call, a convenience function that takes care of mapping the actual ROM, whether it has been shadowed into memory (typically at address 0xc0000) or exists - on the PCI device in the ROM BAR. Note that once you've - mapped the ROM and extracted any necessary information, be - sure to unmap it; on many devices the ROM address decoder is + on the PCI device in the ROM BAR. Note that after the ROM + has been mapped and any necessary information has been extracted, + it should be unmapped; on many devices the ROM address decoder is shared with other BARs, so leaving it mapped can cause undesired behavior like hangs or memory corruption. -- cgit From 118bdd70bdd73b08dcc3920fa30a21be5bbbffae Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:57:04 +0000 Subject: DocBook/drm: Offset modifiers with commas Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 03321ebaf4a7..ce145babef6e 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -371,7 +371,7 @@ shadowed into memory (typically at address 0xc0000) or exists on the PCI device in the ROM BAR. Note that after the ROM has been mapped and any necessary information has been extracted, - it should be unmapped; on many devices the ROM address decoder is + it should be unmapped; on many devices, the ROM address decoder is shared with other BARs, so leaving it mapped can cause undesired behavior like hangs or memory corruption. @@ -440,7 +440,7 @@ and its size should be sizeof(struct ttm_bo_global). Again, driver specific init and release functions may be provided, likely eventually calling ttm_bo_global_init and - ttm_bo_global_release, respectively. Also like the previous + ttm_bo_global_release, respectively. Also, like the previous object, ttm_global_item_ref is used to create an initial reference count for the TTM, which will call your initialization function. @@ -613,7 +613,7 @@ void intel_crt_init(struct drm_device *dev) DRM_IOCTL_MODESET_CTL should be called by application level - drivers before and after mode setting, since on many devices the + drivers before and after mode setting, since on many devices, the vertical blank counter is reset at that time. Internally, the DRM snapshots the last vblank count when the ioctl is called with the _DRM_PRE_MODESET command so that the counter won't go @@ -696,7 +696,7 @@ void intel_crt_init(struct drm_device *dev) set domain function, which evaluates an object's current domain and performs any necessary flushing or synchronization to put the object into the desired coherency domain (note that the object may be busy, - i.e. an active render target; in that case the set domain function + i.e. an active render target; in that case, the set domain function blocks the client and waits for rendering to complete before performing any necessary flushing operations). -- cgit From 8d36ffae67d89a86e37e7745503743fec1ac695c Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:57:37 +0000 Subject: DocBook/drm: can -> could Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index ce145babef6e..60ddf4be11c7 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -372,7 +372,7 @@ on the PCI device in the ROM BAR. Note that after the ROM has been mapped and any necessary information has been extracted, it should be unmapped; on many devices, the ROM address decoder is - shared with other BARs, so leaving it mapped can cause + shared with other BARs, so leaving it mapped could cause undesired behavior like hangs or memory corruption. -- cgit From eb2b8d4273fb8b73821ca8dbc9c0de10e9879833 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 18:58:42 +0000 Subject: DocBook/drm: , -> : Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 60ddf4be11c7..953c4cb726bb 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -389,7 +389,7 @@ If your driver supports memory management (it should!), you need to set that up at load time as well. How you initialize - it depends on which memory manager you're using, TTM or GEM. + it depends on which memory manager you're using: TTM or GEM. TTM initialization @@ -647,7 +647,7 @@ void intel_crt_init(struct drm_device *dev) The memory manager lies at the heart of many DRM operations; it is required to support advanced client features like OpenGL - pbuffers. The DRM currently contains two memory managers, TTM + pbuffers. The DRM currently contains two memory managers: TTM and GEM. -- cgit From 005d7f4a01d3c755c3abab38b7e380f0bbff475d Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:02:52 +0000 Subject: DocBook/drm: Insert missing comma Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 953c4cb726bb..230c738c22f0 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -429,7 +429,7 @@ object should be sizeof(struct ttm_mem_global), and the init and release hooks should point at your driver specific init and release routines, which probably eventually call - ttm_mem_global_init and ttm_mem_global_release respectively. + ttm_mem_global_init and ttm_mem_global_release, respectively. Once your global TTM accounting structure is set up and initialized @@ -499,8 +499,8 @@ Output discovery and initialization - Several core functions exist to create CRTCs, encoders and - connectors, namely drm_crtc_init(), drm_connector_init() and + Several core functions exist to create CRTCs, encoders, and + connectors, namely drm_crtc_init(), drm_connector_init(), and drm_encoder_init(), along with several "helper" functions to perform common tasks. @@ -578,7 +578,7 @@ void intel_crt_init(struct drm_device *dev) - For each encoder, CRTC and connector, several functions must + For each encoder, CRTC, and connector, several functions must be provided, depending on the object type. Encoder objects need to provide a DPMS (basically on/off) function, mode fixup (for converting requested modes into native hardware timings), @@ -727,7 +727,7 @@ void intel_crt_init(struct drm_device *dev) Output management At the core of the DRM output management code is a set of - structures representing CRTCs, encoders and connectors. + structures representing CRTCs, encoders, and connectors. A CRTC is an abstraction representing a part of the chip that -- cgit From 1c86de2216f678bfb6e2472af6e5c25b0df8d91f Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:14:26 +0000 Subject: DocBook/drm: Remove parentheses and unnecessary repetition Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 230c738c22f0..6b2a80369f6b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -433,8 +433,8 @@ Once your global TTM accounting structure is set up and initialized - (done by calling ttm_global_item_ref on the global object you - just created), you need to create a buffer object TTM to + by calling ttm_global_item_ref on it, + you need to create a buffer object TTM to provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, -- cgit From ae63d793a43888eeb1c16422252d987aa37ab96c Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:19:18 +0000 Subject: DocBook/drm: Insert `()' after function name Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 6b2a80369f6b..6977cd91779c 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -433,15 +433,15 @@ Once your global TTM accounting structure is set up and initialized - by calling ttm_global_item_ref on it, + by calling ttm_global_item_ref() on it, you need to create a buffer object TTM to provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, driver specific init and release functions may be provided, - likely eventually calling ttm_bo_global_init and - ttm_bo_global_release, respectively. Also, like the previous - object, ttm_global_item_ref is used to create an initial reference + likely eventually calling ttm_bo_global_init() and + ttm_bo_global_release(), respectively. Also, like the previous + object, ttm_global_item_ref() is used to create an initial reference count for the TTM, which will call your initialization function. -- cgit From 049cc903e714a27805eae0c34a4c34902a385032 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:21:17 +0000 Subject: DocBook/drm: Streamline wording of GEM initialization Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 6977cd91779c..7c11d790f749 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -451,7 +451,7 @@ GEM is an alternative to TTM, designed specifically for UMA devices. It has simpler initialization and execution requirements than TTM, but has no VRAM management capability. Core GEM - initialization is comprised of a basic drm_mm_init call to create + is initialized by calling drm_mm_init() to create a GTT DRM MM object, which provides an address space pool for object allocation. In a KMS configuration, the driver needs to allocate and initialize a command ring buffer following -- cgit From 482b2ad8e488e609bb3bb408a8e9ca17b73b17c6 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:37:24 +0000 Subject: DocBook/drm: basic -> core Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 7c11d790f749..d385e902f5ff 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -455,7 +455,7 @@ a GTT DRM MM object, which provides an address space pool for object allocation. In a KMS configuration, the driver needs to allocate and initialize a command ring buffer following - basic GEM initialization. Most UMA devices have a so-called + core GEM initialization. Most UMA devices have a so-called "stolen" memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the device. This space is not typically managed by GEM, and must -- cgit From 54f2cb8fc930e08fd6156519b28c45d576615f82 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:41:37 +0000 Subject: DocBook/drm: Use a singular subject for grammatical cleanliness Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index d385e902f5ff..3470c6b2f843 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -455,7 +455,7 @@ a GTT DRM MM object, which provides an address space pool for object allocation. In a KMS configuration, the driver needs to allocate and initialize a command ring buffer following - core GEM initialization. Most UMA devices have a so-called + core GEM initialization. A UMA device usually has a so-called "stolen" memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the device. This space is not typically managed by GEM, and must @@ -635,10 +635,10 @@ void intel_crt_init(struct drm_device *dev) a client calls the vblank wait ioctl above. - Devices that don't provide a count register may simply use an + A device that doesn't provide a count register may simply use an internal atomic counter incremented on every vertical blank - interrupt, and can make their enable and disable vblank - functions into no-ops. + interrupt (and then treat the enable_vblank() and disable_vblank() + callbacks as no-ops). -- cgit From 9029bd7a42e3c32783866630ee3eb6b82e273544 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:42:20 +0000 Subject: DocBook/drm: The word `so-called'; I do not think it connotes what you think it connotes From Webster's Revised Unabridged Dictionary (1913) [web1913]: So-called \So"-called`\, a. So named; called by such a name (but perhaps called thus with doubtful propriety). From WordNet (r) 2.0 [wn]: so-called adj : doubtful or suspect; "these so-called experts are no help" [syn: {alleged(a)}, {supposed}] My strong conviction is that widespread use of 'so gennant' or 'sogennant' in German has led to the creeping misuse of 'so-called' in English (especially through technical writings). In English, it would be better to use: what is called or a better translation of 'so gennant': so named Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 3470c6b2f843..66a114a05c6f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -455,7 +455,7 @@ a GTT DRM MM object, which provides an address space pool for object allocation. In a KMS configuration, the driver needs to allocate and initialize a command ring buffer following - core GEM initialization. A UMA device usually has a so-called + core GEM initialization. A UMA device usually has what is called a "stolen" memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the device. This space is not typically managed by GEM, and must -- cgit From 1dbd39c3ea3967c41a09e81c826499f7ae9c8180 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:48:32 +0000 Subject: DocBook/drm: Insert `it' for smooth reading Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 66a114a05c6f..15541b1fc052 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -458,7 +458,7 @@ core GEM initialization. A UMA device usually has what is called a "stolen" memory region, which provides space for the initial framebuffer and large, contiguous memory regions required by the - device. This space is not typically managed by GEM, and must + device. This space is not typically managed by GEM, and it must be initialized separately into its own DRM MM object. -- cgit From 3bf7df615612671271512aada7d83285f3fa731b Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 19:49:10 +0000 Subject: DocBook/drm: Remove redundancy Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 15541b1fc052..c24f50ce7862 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -462,8 +462,7 @@ be initialized separately into its own DRM MM object. - Initialization is driver specific, and depends on - the architecture of the device. In the case of Intel + Initialization is driver specific. In the case of Intel integrated graphics chips like 965GM, GEM initialization can be done by calling the internal GEM init function, i915_gem_do_init(). Since the 965GM is a UMA device -- cgit From 327d6fb962f227a31d4b03869774287efca49c50 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 20:18:14 +0000 Subject: DocBook/drm: Clarify `final initialization' via better formatting Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index c24f50ce7862..1bbeea72a01f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -490,10 +490,19 @@ Output configuration - The final initialization task is output configuration. This involves - finding and initializing the CRTCs, encoders and connectors - for your device, creating an initial configuration and - registering a framebuffer console driver. + The final initialization task is output configuration. This involves: + + + Finding and initializing the CRTCs, encoders, and connectors + for the device. + + + Creating an initial configuration. + + + Registering a framebuffer console driver. + + Output discovery and initialization -- cgit From 8a9ba910ac3962e5adb4ce1f086adf1e21fa04d1 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 20:21:22 +0000 Subject: DocBook/drm: Use a colon Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 1bbeea72a01f..790e634e5635 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -508,7 +508,7 @@ Output discovery and initialization Several core functions exist to create CRTCs, encoders, and - connectors, namely drm_crtc_init(), drm_connector_init(), and + connectors, namely: drm_crtc_init(), drm_connector_init(), and drm_encoder_init(), along with several "helper" functions to perform common tasks. -- cgit From 896ee65fb646f9a98243a9f69e5904dff394c78a Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 20:26:17 +0000 Subject: DocBook/drm: Remove extraneous commas Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 790e634e5635..d2aee84f18af 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -562,9 +562,9 @@ void intel_crt_init(struct drm_device *dev) In the example above (again, taken from the i915 driver), a CRT connector and encoder combination is created. A device - specific i2c bus is also created, for fetching EDID data and + specific i2c bus is also created for fetching EDID data and performing monitor detection. Once the process is complete, - the new connector is registered with sysfs, to make its + the new connector is registered with sysfs to make its properties available to applications. -- cgit From 4dc0152d5780f04573046b06a3fb7c7ad9b81afa Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 20:29:32 +0000 Subject: DocBook/drm: Insert `the' for readability, and change `set' to `setting' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index d2aee84f18af..09e02f7c668c 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -573,8 +573,8 @@ void intel_crt_init(struct drm_device *dev) Since many PC-class graphics devices have similar display output designs, the DRM provides a set of helper functions to make output management easier. The core helper routines handle - encoder re-routing and disabling of unused functions following - mode set. Using the helpers is optional, but recommended for + encoder re-routing and the disabling of unused functions following + mode setting. Using the helpers is optional, but recommended for devices with PC-style architectures (i.e. a set of display planes for feeding pixels to encoders which are in turn routed to connectors). Devices with more complex requirements needing -- cgit From 65ffef508f23d5e67940cadc8eca2ae34738018a Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 20:55:58 +0000 Subject: DocBook/drm: Use an itemizedlist for what an encoder needs to provide Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 09e02f7c668c..da011f2af9cb 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -586,17 +586,25 @@ void intel_crt_init(struct drm_device *dev) - For each encoder, CRTC, and connector, several functions must - be provided, depending on the object type. Encoder objects - need to provide a DPMS (basically on/off) function, mode fixup - (for converting requested modes into native hardware timings), - and prepare, set and commit functions for use by the core DRM - helper functions. Connector helpers need to provide mode fetch and - validity functions as well as an encoder matching function for - returning an ideal encoder for a given connector. The core - connector functions include a DPMS callback, (deprecated) - save/restore routines, detection, mode probing, property handling, - and cleanup functions. + Each encoder object needs to provide: + + + A DPMS (basically on/off) function. + + + A mode-fixup function (for converting requested modes into + native hardware timings). + + + Functions (prepare, set, and commit) for use by the core DRM + helper functions. + + + Connector helpers need to provide functions (mode-fetch, validity, + and encoder-matching) for returning an ideal encoder for a given + connector. The core connector functions include a DPMS callback, + save/restore routines (deprecated), detection, mode probing, + property handling, and cleanup functions. -- cgit From 51b9500de28a1e5e7a2090de5d345d6d98581617 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 21:11:30 +0000 Subject: DocBook/drm: Use a for vblank ioctls Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index da011f2af9cb..457d56a1a966 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -619,22 +619,33 @@ void intel_crt_init(struct drm_device *dev) VBlank event handling The DRM core exposes two vertical blank related ioctls: - DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL. + + + DRM_IOCTL_WAIT_VBLANK + + + This takes a struct drm_wait_vblank structure as its argument, + and it is used to block or request a signal when a specified + vblank event occurs. + + + + + DRM_IOCTL_MODESET_CTL + + + This should be called by application level drivers before and + after mode setting, since on many devices the vertical blank + counter is reset at that time. Internally, the DRM snapshots + the last vblank count when the ioctl is called with the + _DRM_PRE_MODESET command so that the counter won't go backwards + (which is dealt with when _DRM_POST_MODESET is used). + + + + - - DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure - as its argument, and is used to block or request a signal when a - specified vblank event occurs. - - - DRM_IOCTL_MODESET_CTL should be called by application level - drivers before and after mode setting, since on many devices, the - vertical blank counter is reset at that time. Internally, - the DRM snapshots the last vblank count when the ioctl is called - with the _DRM_PRE_MODESET command so that the counter won't go - backwards (which is dealt with when _DRM_POST_MODESET is used). - To support the functions above, the DRM core provides several helper functions for tracking vertical blank counters, and -- cgit From f877bd4ad5508e2f0653c31d05ffe0ad4e2bfe11 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Thu, 25 Aug 2011 21:16:15 +0000 Subject: DocBook/drm: Insert a comma Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 457d56a1a966..0387970234b3 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -638,7 +638,7 @@ void intel_crt_init(struct drm_device *dev) after mode setting, since on many devices the vertical blank counter is reset at that time. Internally, the DRM snapshots the last vblank count when the ioctl is called with the - _DRM_PRE_MODESET command so that the counter won't go backwards + _DRM_PRE_MODESET command, so that the counter won't go backwards (which is dealt with when _DRM_POST_MODESET is used). -- cgit From 0c2d91a80a156208d2f9f3dfb01871ebcf4a9338 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 15:59:56 +0000 Subject: DocBook/drm: Use an for fundamental GEM operations Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 0387970234b3..c358367f9f85 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -709,9 +709,13 @@ void intel_crt_init(struct drm_device *dev) read & write, mapping, and domain ownership transfers. - On a fundamental level, GEM involves several operations: memory - allocation and freeing, command execution, and aperture management - at command execution time. Buffer object allocation is relatively + On a fundamental level, GEM involves several operations: + + Memory allocation and freeing + Command execution + Aperture management at command execution time + + Buffer object allocation is relatively straightforward and largely provided by Linux's shmem layer, which provides memory to back each object. When mapped into the GTT or used in a command buffer, the backing pages for an object are -- cgit From 2d43f5d667273ba4975cb79782a46aa374dd8607 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 16:00:55 +0000 Subject: DocBook/drm: Improve flow of GPU/CPU coherence sentence Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index c358367f9f85..ba20f9fbb62b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -720,8 +720,9 @@ void intel_crt_init(struct drm_device *dev) provides memory to back each object. When mapped into the GTT or used in a command buffer, the backing pages for an object are flushed to memory and marked write combined so as to be coherent - with the GPU. Likewise, when the GPU finishes rendering to an object, - if the CPU accesses it, it must be made coherent with the CPU's view + with the GPU. Likewise, if the CPU accesses an object after the GPU + has finished rendering to the object, then the object must be made + coherent with the CPU's view of memory, usually involving GPU cache flushing of various kinds. This core CPU<->GPU coherency management is provided by the GEM set domain function, which evaluates an object's current domain and -- cgit From b8c6e0fe46fcd60f58089365dd96dcf04f95263b Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 17:34:00 +0000 Subject: DocBook/drm: Refer to the domain-setting function as a device-specific ioctl Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index ba20f9fbb62b..9ae328aa1dd3 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -724,11 +724,11 @@ void intel_crt_init(struct drm_device *dev) has finished rendering to the object, then the object must be made coherent with the CPU's view of memory, usually involving GPU cache flushing of various kinds. - This core CPU<->GPU coherency management is provided by the GEM - set domain function, which evaluates an object's current domain and + This core CPU<->GPU coherency management is provided by a + device-specific ioctl, which evaluates an object's current domain and performs any necessary flushing or synchronization to put the object into the desired coherency domain (note that the object may be busy, - i.e. an active render target; in that case, the set domain function + i.e. an active render target; in that case, setting the domain blocks the client and waits for rendering to complete before performing any necessary flushing operations). -- cgit From e355b2014da06458385902c47edf193a997895fc Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 17:38:48 +0000 Subject: DocBook/drm: Better flow with `, and then' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9ae328aa1dd3..0b6c59d6aa5f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -735,8 +735,8 @@ void intel_crt_init(struct drm_device *dev) Perhaps the most important GEM function is providing a command execution interface to clients. Client programs construct command - buffers containing references to previously allocated memory objects - and submit them to GEM. At that point, GEM takes care to bind + buffers containing references to previously allocated memory objects, + and then submit them to GEM. At that point, GEM takes care to bind all the objects into the GTT, execute the buffer, and provide necessary synchronization between clients accessing the same buffers. This often involves evicting some objects from the GTT and re-binding -- cgit From 964d32dcbefcfda015bc33dc76414b05c6f512de Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 17:41:31 +0000 Subject: DocBook/drm: Use `; otherwise,' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 0b6c59d6aa5f..606a989d8895 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -743,7 +743,7 @@ void intel_crt_init(struct drm_device *dev) others (a fairly expensive operation), and providing relocation support which hides fixed GTT offsets from clients. Clients must take care not to submit command buffers that reference more objects - than can fit in the GTT or GEM will reject them and no rendering + than can fit in the GTT; otherwise, GEM will reject them and no rendering will occur. Similarly, if several objects in the buffer require fence registers to be allocated for correct rendering (e.g. 2D blits on pre-965 chips), care must be taken not to require more fence -- cgit From 5a462d58c84a2f5ed161daced2c7df34357c6d3d Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 17:58:46 +0000 Subject: DocBook/drm: Clean up the paragraph on framebuffer objects Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 606a989d8895..a39e76bae03d 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -795,14 +795,12 @@ void intel_crt_init(struct drm_device *dev) Framebuffer management - In order to set a mode on a given CRTC, encoder and connector - configuration, clients need to provide a framebuffer object which - provides a source of pixels for the CRTC to deliver to the encoder(s) - and ultimately the connector(s) in the configuration. A framebuffer - is fundamentally a driver specific memory object, made into an opaque - handle by the DRM addfb function. Once an fb has been created this - way it can be passed to the KMS mode setting routines for use in - a configuration. + Clients need to provide a framebuffer object which provides a source + of pixels for a CRTC to deliver to the encoder(s) and ultimately the + connector(s). A framebuffer is fundamentally a driver specific memory + object, made into an opaque handle by the DRM's addfb() function. + Once a framebuffer has been created this way, it may be passed to the + KMS mode setting routines for use in a completed configuration. -- cgit From a5294e01f2777649834d218583e7a32b2dacb699 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 18:05:52 +0000 Subject: DocBook/drm: `(device|driver) specific' -> `(device|driver)-specific' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index a39e76bae03d..65e14f96f943 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -238,7 +238,7 @@ In this specific case, the driver requires AGP and supports - IRQs. DMA, as discussed later, is handled by device specific ioctls + IRQs. DMA, as discussed later, is handled by device-specific ioctls in this case. It also supports the kernel mode setting APIs, though unlike in the actual i915 driver source, this example unconditionally exports KMS capability. @@ -277,7 +277,7 @@ to perform output discovery & configuration at load time. Likewise, if user-level drivers unaware of memory management are in use, memory management and command buffer setup may need to - be omitted. These requirements are driver specific, and care + be omitted. These requirements are driver-specific, and care needs to be taken to keep both old and new applications and libraries working. The i915 driver supports the "modeset" module parameter to control whether advanced features are @@ -288,7 +288,7 @@ Driver private & performance counters The driver private hangs off the main drm_device structure and - can be used for tracking various device specific bits of + can be used for tracking various device-specific bits of information, like register offsets, command buffer status, register state for suspend/resume, etc. At load time, a driver may simply allocate one and set drm_device.dev_priv @@ -313,7 +313,7 @@ Configuring the device - Obviously, device configuration is device specific. + Obviously, device configuration is device-specific. However, there are several common operations: finding a device's PCI resources, mapping them, and potentially setting up an IRQ handler. @@ -340,8 +340,8 @@ Once you have a register map, you may use the DRM_READn() and DRM_WRITEn() macros to access the registers on your device, or - use driver specific versions to offset into your MMIO space - relative to a driver specific base pointer (see I915_READ for + use driver-specific versions to offset into your MMIO space + relative to a driver-specific base pointer (see I915_READ for an example). @@ -399,7 +399,7 @@ and devices with dedicated video RAM (VRAM), i.e. most discrete graphics devices. If your device has dedicated RAM, supporting TTM is desirable. TTM also integrates tightly with your - driver specific buffer execution function. See the radeon + driver-specific buffer execution function. See the radeon driver for examples. @@ -427,7 +427,7 @@ created by the memory manager at runtime. Your global TTM should have a type of TTM_GLOBAL_TTM_MEM. The size field for the global object should be sizeof(struct ttm_mem_global), and the init and - release hooks should point at your driver specific init and + release hooks should point at your driver-specific init and release routines, which probably eventually call ttm_mem_global_init and ttm_mem_global_release, respectively. @@ -438,7 +438,7 @@ provide a pool for buffer object allocation by clients and the kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, and its size should be sizeof(struct ttm_bo_global). Again, - driver specific init and release functions may be provided, + driver-specific init and release functions may be provided, likely eventually calling ttm_bo_global_init() and ttm_bo_global_release(), respectively. Also, like the previous object, ttm_global_item_ref() is used to create an initial reference @@ -462,7 +462,7 @@ be initialized separately into its own DRM MM object. - Initialization is driver specific. In the case of Intel + Initialization is driver-specific. In the case of Intel integrated graphics chips like 965GM, GEM initialization can be done by calling the internal GEM init function, i915_gem_do_init(). Since the 965GM is a UMA device @@ -561,8 +561,8 @@ void intel_crt_init(struct drm_device *dev) In the example above (again, taken from the i915 driver), a - CRT connector and encoder combination is created. A device - specific i2c bus is also created for fetching EDID data and + CRT connector and encoder combination is created. A device-specific + i2c bus is also created for fetching EDID data and performing monitor detection. Once the process is complete, the new connector is registered with sysfs to make its properties available to applications. @@ -704,8 +704,8 @@ void intel_crt_init(struct drm_device *dev) GEM-enabled drivers must provide gem_init_object() and gem_free_object() callbacks to support the core memory - allocation routines. They should also provide several driver - specific ioctls to support command execution, pinning, buffer + allocation routines. They should also provide several driver-specific + ioctls to support command execution, pinning, buffer read & write, mapping, and domain ownership transfers. @@ -797,7 +797,7 @@ void intel_crt_init(struct drm_device *dev) Clients need to provide a framebuffer object which provides a source of pixels for a CRTC to deliver to the encoder(s) and ultimately the - connector(s). A framebuffer is fundamentally a driver specific memory + connector(s). A framebuffer is fundamentally a driver-specific memory object, made into an opaque handle by the DRM's addfb() function. Once a framebuffer has been created this way, it may be passed to the KMS mode setting routines for use in a completed configuration. @@ -807,7 +807,7 @@ void intel_crt_init(struct drm_device *dev) Command submission & fencing - This should cover a few device specific command submission + This should cover a few device-specific command submission implementations. @@ -840,7 +840,7 @@ void intel_crt_init(struct drm_device *dev) The DRM core exports several interfaces to applications, generally intended to be used through corresponding libdrm - wrapper functions. In addition, drivers export device specific + wrapper functions. In addition, drivers export device-specific interfaces for use by userspace drivers & device aware applications through ioctls and sysfs files. -- cgit From 7f0925aca586b4a0cce81b06af7383d6aec59cc1 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 18:07:13 +0000 Subject: DocBook/drm: `device aware' -> `device-aware' Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 65e14f96f943..9da9b2831370 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -841,7 +841,7 @@ void intel_crt_init(struct drm_device *dev) The DRM core exports several interfaces to applications, generally intended to be used through corresponding libdrm wrapper functions. In addition, drivers export device-specific - interfaces for use by userspace drivers & device aware + interfaces for use by userspace drivers & device-aware applications through ioctls and sysfs files. -- cgit From bcd3cfc1213894ff955771508d46fa18d66e9328 Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Mon, 29 Aug 2011 19:29:16 +0000 Subject: DocBook/drm: Clean up a todo-note Signed-off-by: Michael Witten --- Documentation/DocBook/drm.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9da9b2831370..196b8b9dba11 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -850,8 +850,8 @@ void intel_crt_init(struct drm_device *dev) management, memory management, and output management. - Cover generic ioctls and sysfs layout here. Only need high - level info, since man pages should cover the rest. + Cover generic ioctls and sysfs layout here. We only need high-level + info, since man pages should cover the rest. -- cgit From 2cafbb37a135945ecc07d17f3484ed0dea1aa8b1 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Mon, 2 May 2011 16:30:52 -0600 Subject: powerpc/5200: add support for charon board Signed-off-by: Heiko Schocher Acked-by: Benjamin Herrenschmidt Acked-by: Wolfram Sang [squashed with patch to add sm501 node] Signed-off-by: Grant Likely Signed-off-by: Anatolij Gustschin --- arch/powerpc/boot/dts/charon.dts | 236 +++++++++++++++++++++++++++ arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 + 2 files changed, 237 insertions(+) create mode 100644 arch/powerpc/boot/dts/charon.dts diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts new file mode 100644 index 000000000000..0e00e508eaa6 --- /dev/null +++ b/arch/powerpc/boot/dts/charon.dts @@ -0,0 +1,236 @@ +/* + * charon board Device Tree Source + * + * Copyright (C) 2007 Semihalf + * Marian Balakowicz + * + * Copyright (C) 2010 DENX Software Engineering GmbH + * Heiko Schocher + * + * 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. + */ + +/dts-v1/; + +/ { + model = "anon,charon"; + compatible = "anon,charon"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&mpc5200_pic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,5200@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <32>; + i-cache-line-size = <32>; + d-cache-size = <0x4000>; // L1, 16K + i-cache-size = <0x4000>; // L1, 16K + timebase-frequency = <0>; // from bootloader + bus-frequency = <0>; // from bootloader + clock-frequency = <0>; // from bootloader + }; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x08000000>; // 128MB + }; + + soc5200@f0000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc5200-immr"; + ranges = <0 0xf0000000 0x0000c000>; + reg = <0xf0000000 0x00000100>; + bus-frequency = <0>; // from bootloader + system-frequency = <0>; // from bootloader + + cdm@200 { + compatible = "fsl,mpc5200-cdm"; + reg = <0x200 0x38>; + }; + + mpc5200_pic: interrupt-controller@500 { + // 5200 interrupts are encoded into two levels; + interrupt-controller; + #interrupt-cells = <3>; + compatible = "fsl,mpc5200-pic"; + reg = <0x500 0x80>; + }; + + timer@600 { // General Purpose Timer + compatible = "fsl,mpc5200-gpt"; + reg = <0x600 0x10>; + interrupts = <1 9 0>; + fsl,has-wdt; + }; + + can@900 { + compatible = "fsl,mpc5200-mscan"; + interrupts = <2 17 0>; + reg = <0x900 0x80>; + }; + + can@980 { + compatible = "fsl,mpc5200-mscan"; + interrupts = <2 18 0>; + reg = <0x980 0x80>; + }; + + gpio_simple: gpio@b00 { + compatible = "fsl,mpc5200-gpio"; + reg = <0xb00 0x40>; + interrupts = <1 7 0>; + gpio-controller; + #gpio-cells = <2>; + }; + + usb@1000 { + compatible = "fsl,mpc5200-ohci","ohci-be"; + reg = <0x1000 0xff>; + interrupts = <2 6 0>; + }; + + dma-controller@1200 { + device_type = "dma-controller"; + compatible = "fsl,mpc5200-bestcomm"; + reg = <0x1200 0x80>; + interrupts = <3 0 0 3 1 0 3 2 0 3 3 0 + 3 4 0 3 5 0 3 6 0 3 7 0 + 3 8 0 3 9 0 3 10 0 3 11 0 + 3 12 0 3 13 0 3 14 0 3 15 0>; + }; + + xlb@1f00 { + compatible = "fsl,mpc5200-xlb"; + reg = <0x1f00 0x100>; + }; + + serial@2000 { // PSC1 + compatible = "fsl,mpc5200-psc-uart"; + reg = <0x2000 0x100>; + interrupts = <2 1 0>; + }; + + serial@2400 { // PSC3 + compatible = "fsl,mpc5200-psc-uart"; + reg = <0x2400 0x100>; + interrupts = <2 3 0>; + }; + + ethernet@3000 { + compatible = "fsl,mpc5200-fec"; + reg = <0x3000 0x400>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <2 5 0>; + fixed-link = <1 1 100 0 0>; + }; + + mdio@3000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5200-mdio"; + reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts + interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co. + }; + + ata@3a00 { + compatible = "fsl,mpc5200-ata"; + reg = <0x3a00 0x100>; + interrupts = <2 7 0>; + }; + + i2c@3d00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5200-i2c","fsl-i2c"; + reg = <0x3d00 0x40>; + interrupts = <2 15 0>; + }; + + + i2c@3d40 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5200-i2c","fsl-i2c"; + reg = <0x3d40 0x40>; + interrupts = <2 16 0>; + + dtt@28 { + compatible = "national,lm80"; + reg = <0x28>; + }; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + }; + }; + + sram@8000 { + compatible = "fsl,mpc5200-sram"; + reg = <0x8000 0x4000>; + }; + }; + + localbus { + compatible = "fsl,mpc5200-lpb","simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = < 0 0 0xfc000000 0x02000000 + 1 0 0xe0000000 0x04000000 // CS1 range, SM501 + 3 0 0xe8000000 0x00080000>; + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x02000000>; + bank-width = <4>; + device-width = <2>; + #size-cells = <1>; + #address-cells = <1>; + }; + + display@1,0 { + compatible = "smi,sm501"; + reg = <1 0x00000000 0x00800000 + 1 0x03e00000 0x00200000>; + mode = "640x480-32@60"; + interrupts = <1 1 3>; + little-endian; + }; + + mram0@3,0 { + compatible = "mtd-ram"; + reg = <3 0x00000 0x80000>; + bank-width = <1>; + }; + }; + + pci@f0000d00 { + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + device_type = "pci"; + compatible = "fsl,mpc5200-pci"; + reg = <0xf0000d00 0x100>; + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 + 0xc000 0 0 2 &mpc5200_pic 0 0 3 + 0xc000 0 0 3 &mpc5200_pic 0 0 3 + 0xc000 0 0 4 &mpc5200_pic 0 0 3>; + clock-frequency = <0>; // From boot loader + interrupts = <2 8 0 2 9 0 2 10 0>; + bus-range = <0 0>; + ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000 + 0x02000000 0 0x90000000 0x90000000 0 0x10000000 + 0x01000000 0 0x00000000 0xa0000000 0 0x01000000>; + }; +}; diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c index e36d6e232ae6..846b789fb195 100644 --- a/arch/powerpc/platforms/52xx/mpc5200_simple.c +++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c @@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void) /* list of the supported boards */ static const char *board[] __initdata = { + "anon,charon", "intercontrol,digsy-mtc", "manroland,mucmc52", "manroland,uc101", -- cgit From 6ecc07b966977bb0855db1fa52d233c39fb3cafb Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 22 Mar 2011 09:27:32 +0100 Subject: powerpc, tqm5200: update tqm5200_defconfig to fit for charon board. added: CONFIG_MTD_OF_PARTS CONFIG_MTD_PLATRAM CONFIG_FIXED_PHY CONFIG_SENSORS_LM80 CONFIG_MFD_SM501 CONFIG_FB CONFIG_FB_FOREIGN_ENDIAN CONFIG_FB_SM501 CONFIG_FRAMEBUFFER_CONSOLE CONFIG_RTC_DRV_DS1374 Signed-off-by: Heiko Schocher Signed-off-by: Grant Likely Signed-off-by: Anatolij Gustschin --- arch/powerpc/configs/52xx/tqm5200_defconfig | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig index 959cd2cfc275..716a37be16e3 100644 --- a/arch/powerpc/configs/52xx/tqm5200_defconfig +++ b/arch/powerpc/configs/52xx/tqm5200_defconfig @@ -1,9 +1,10 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_SPARSE_IRQ=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EXPERT=y +CONFIG_EMBEDDED=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_KALLSYMS is not set # CONFIG_EPOLL is not set @@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y CONFIG_PPC_MPC5200_BUGFIX=y # CONFIG_PPC_PMAC is not set CONFIG_PPC_BESTCOMM=y -CONFIG_SPARSE_IRQ=y CONFIG_PM=y # CONFIG_PCI is not set CONFIG_NET=y @@ -38,17 +38,18 @@ CONFIG_MTD=y CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_ROM=y CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_PLATRAM=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=32768 -# CONFIG_MISC_DEVICES is not set CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_ATA=y @@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y CONFIG_PATA_PLATFORM=y CONFIG_NETDEVICES=y CONFIG_LXT_PHY=y +CONFIG_FIXED_PHY=y CONFIG_NET_ETHERNET=y CONFIG_FEC_MPC52xx=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set CONFIG_SERIAL_MPC52xx=y CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 @@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MPC=y +CONFIG_SENSORS_LM80=y CONFIG_WATCHDOG=y +CONFIG_MFD_SM501=y +CONFIG_FB=y +CONFIG_FB_FOREIGN_ENDIAN=y +CONFIG_FB_SM501=y +CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set @@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y CONFIG_USB_STORAGE=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS1374=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_INOTIFY=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_PROC_KCORE=y @@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_PCBC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -- cgit From dc9c0beecfeb4866fdbc245c295cf30d340b702c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 11 Oct 2011 15:19:43 -0400 Subject: piix: ICH7 MWDMA1 errata Based on libata commit c611bed7. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: David S. Miller --- drivers/ide/piix.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index b59d04c72051..1892e81fb00f 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -331,7 +331,7 @@ static const struct ide_port_ops ich_port_ops = { .udma_mask = udma, \ } -#define DECLARE_ICH_DEV(udma) \ +#define DECLARE_ICH_DEV(mwdma, udma) \ { \ .name = DRV_NAME, \ .init_chipset = init_chipset_ich, \ @@ -340,7 +340,7 @@ static const struct ide_port_ops ich_port_ops = { .port_ops = &ich_port_ops, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ - .mwdma_mask = ATA_MWDMA12_ONLY, \ + .mwdma_mask = mwdma, \ .udma_mask = udma, \ } @@ -362,13 +362,15 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = { /* 2: PIIX4 */ DECLARE_PIIX_DEV(ATA_UDMA2), /* 3: ICH0 */ - DECLARE_ICH_DEV(ATA_UDMA2), + DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA2), /* 4: ICH */ - DECLARE_ICH_DEV(ATA_UDMA4), + DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA4), /* 5: PIIX4 */ DECLARE_PIIX_DEV(ATA_UDMA4), - /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */ - DECLARE_ICH_DEV(ATA_UDMA5), + /* 6: ICH[2-6]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */ + DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA5), + /* 7: ICH7/7-R, no MWDMA1 */ + DECLARE_ICH_DEV(ATA_MWDMA2_ONLY, ATA_UDMA5), }; /** @@ -438,9 +440,9 @@ static const struct pci_device_id piix_pci_tbl[] = { #endif { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 7 }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 7 }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 }, { 0, }, }; -- cgit From 839e7306e5d1ebd57cf12e83d9910b8b2dbe79ba Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 12 Oct 2011 04:31:51 +0000 Subject: IDE: Don't powerdown Compaq Triflex IDE device on suspend Don't powerdown Compaq Triflex IDE device on suspend This fixes APM suspend on Compaq Armada 7400. APM BIOS doesn't suspend if IDE is powered down when suspending. The Triflex controller is found only on old Compaq boards, so this patch will hopefully have no side effects. This patch fixes a suspend regression introduced in feb22b7f8e62b1b987a3a1dbad95af767a1df832 ("ide: add proper PCI PM support (v2)"). Signed-off-by: Mikulas Patocka [bart: add commit's summary in parens] Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: David S. Miller --- drivers/ide/triflex.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c index e53a1b78378b..281c91426345 100644 --- a/drivers/ide/triflex.c +++ b/drivers/ide/triflex.c @@ -113,12 +113,26 @@ static const struct pci_device_id triflex_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); +#ifdef CONFIG_PM +static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state) +{ + /* + * We must not disable or powerdown the device. + * APM bios refuses to suspend if IDE is not accessible. + */ + pci_save_state(dev); + return 0; +} +#else +#define triflex_ide_pci_suspend NULL +#endif + static struct pci_driver triflex_pci_driver = { .name = "TRIFLEX_IDE", .id_table = triflex_pci_tbl, .probe = triflex_init_one, .remove = ide_pci_remove, - .suspend = ide_pci_suspend, + .suspend = triflex_ide_pci_suspend, .resume = ide_pci_resume, }; -- cgit From acc8dbe7f44f1bab6fcf21f2d5efb32ea92e19fd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 12 Oct 2011 04:45:34 +0000 Subject: icside: DMA support fix Fix problem introduced by commit 5e37bdc ("ide: add struct ide_dma_ops (take 3)"): d.dma_ops shouldn't be cleared if we are going to use DMA. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: David S. Miller --- drivers/ide/icside.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 4a697a238e28..8716066a2f2b 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -521,8 +521,8 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { d.init_dma = icside_dma_init; d.port_ops = &icside_v6_port_ops; + } else d.dma_ops = NULL; - } ret = ide_host_register(host, &d, hws); if (ret) -- cgit From 0ab3d8b3213c8bb55370b11fcc5321ee4f2c5e92 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 13 Oct 2011 00:28:54 +0000 Subject: cy82c693: fix PCI device selection Wrong PCI device may be selected by cy82c693_set_pio_mode() if modular IDE host drivers are used and there are additional IDE PCI devices installed in the system. Fix it. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: David S. Miller --- drivers/ide/cy82c693.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 67cbcfa35122..847553fd8b96 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -1,7 +1,7 @@ /* * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer * Copyright (C) 1998-2002 Andre Hedrick , Integrator - * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz + * Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz * * CYPRESS CY82C693 chipset IDE controller * @@ -90,7 +90,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) u8 time_16, time_8; /* select primary or secondary channel */ - if (hwif->index > 0) { /* drive is on the secondary channel */ + if (drive->dn > 1) { /* drive is on the secondary channel */ dev = pci_get_slot(dev->bus, dev->devfn+1); if (!dev) { printk(KERN_ERR "%s: tune_drive: " @@ -141,7 +141,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16); pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8); } - if (hwif->index > 0) + if (drive->dn > 1) pci_dev_put(dev); } -- cgit From cd8e368f475251c0e3c42203f21e68fa25afbb3d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 18 Aug 2011 16:35:44 -0400 Subject: ktest: Add TEST_TYPE install option In testing one of my boxes, I found that I only wanted to build and install the kernel. I wanted to manually reboot the box and test it. Adding a TEST_TYPE option "install" allows this to happen. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 7 +++++++ tools/testing/ktest/sample.conf | 7 ++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8d02ccb10c59..e087cb411c9b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -2929,6 +2929,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { build $build_type or next; } + if ($test_type eq "install") { + get_version; + install; + success $i; + next; + } + if ($test_type ne "build") { my $failed = 0; start_monitor_and_boot or $failed = 1; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index b8bcd14b5a4d..eadca3eb6f5a 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -253,9 +253,10 @@ # The default test type (default test) # The test types may be: -# build - only build the kernel, do nothing else -# boot - build and boot the kernel -# test - build, boot and if TEST is set, run the test script +# build - only build the kernel, do nothing else +# install - build and install, but do nothing else (does not reboot) +# boot - build, install, and boot the kernel +# test - build, boot and if TEST is set, run the test script # (If TEST is not set, it defaults back to boot) # bisect - Perform a bisect on the kernel (see BISECT_TYPE below) # patchcheck - Do a test on a series of commits in git (see PATCHCHECK below) -- cgit From a908a6659ba3e7eb52ea74a78e2f342978aa5f5b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 12 Aug 2011 15:32:03 +0200 Subject: ktest: Create outputdir if it does not exist Signed-off-by: Andrew Jones Link: http://lkml.kernel.org/r/1313155932-20092-2-git-send-email-drjones@redhat.com Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e087cb411c9b..253e9a2cfbd5 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -2850,9 +2850,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { chdir $builddir || die "can't change directory to $builddir"; - if (!-d $tmpdir) { - mkpath($tmpdir) or - die "can't create $tmpdir"; + foreach my $dir ($tmpdir, $outputdir) { + if (!-d $dir) { + mkpath($dir) or + die "can't create $dir"; + } } $ENV{"SSH_USER"} = $ssh_user; -- cgit From 134882311cb9c2dca2ffadeabc5f8f9faa0fca81 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 12 Aug 2011 15:32:04 +0200 Subject: ktest: Only need to save .config when doing mrproper Only save the .config file if we're doing mrproper Signed-off-by: Andrew Jones Link: http://lkml.kernel.org/r/1313155932-20092-3-git-send-email-drjones@redhat.com Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 253e9a2cfbd5..20b0e736b98b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1272,15 +1272,15 @@ sub build { # allow for empty configs run_command "touch $output_config"; - run_command "mv $output_config $outputdir/config_temp" or - dodie "moving .config"; + if (!$noclean) { + run_command "mv $output_config $outputdir/config_temp" or + dodie "moving .config"; - if (!$noclean && !run_command "$make mrproper") { - dodie "make mrproper"; - } + run_command "$make mrproper" or dodie "make mrproper"; - run_command "mv $outputdir/config_temp $output_config" or - dodie "moving config_temp"; + run_command "mv $outputdir/config_temp $output_config" or + dodie "moving config_temp"; + } } elsif (!$noclean) { unlink "$output_config"; -- cgit From 2728be418db65aa873ee354168b56f028845e956 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Fri, 12 Aug 2011 15:32:05 +0200 Subject: ktest: Include monitor in reboot code Several places that call reboot do the same thing with respect to the monitor. By adding this code into the reboot code, redundant code is removed and it paves the way for the the reset time patch. Signed-off-by: Andrew Jones Link: http://lkml.kernel.org/r/1313155932-20092-4-git-send-email-drjones@redhat.com Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 20b0e736b98b..debc6898e60b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -603,8 +603,13 @@ sub doprint { } sub run_command; +sub start_monitor; +sub end_monitor; +sub wait_for_monitor; sub reboot { + my ($time) = @_; + # try to reboot normally if (run_command $reboot) { if (defined($powercycle_after_reboot)) { @@ -615,6 +620,12 @@ sub reboot { # nope? power cycle it. run_command "$power_cycle"; } + + if (defined($time)) { + start_monitor; + wait_for_monitor $time; + end_monitor; + } } sub do_not_reboot { @@ -719,10 +730,7 @@ sub fail { # no need to reboot for just building. if (!do_not_reboot) { doprint "REBOOTING\n"; - reboot; - start_monitor; - wait_for_monitor $sleep_time; - end_monitor; + reboot $sleep_time; } my $name = ""; @@ -1356,10 +1364,7 @@ sub success { if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { doprint "Reboot and wait $sleep_time seconds\n"; - reboot; - start_monitor; - wait_for_monitor $sleep_time; - end_monitor; + reboot $sleep_time; } } @@ -1500,10 +1505,7 @@ sub run_git_bisect { sub bisect_reboot { doprint "Reboot and sleep $bisect_sleep_time seconds\n"; - reboot; - start_monitor; - wait_for_monitor $bisect_sleep_time; - end_monitor; + reboot $bisect_sleep_time; } # returns 1 on success, 0 on failure, -1 on skip @@ -2066,10 +2068,7 @@ sub config_bisect { sub patchcheck_reboot { doprint "Reboot and sleep $patchcheck_sleep_time seconds\n"; - reboot; - start_monitor; - wait_for_monitor $patchcheck_sleep_time; - end_monitor; + reboot $patchcheck_sleep_time; } sub patchcheck { @@ -2659,10 +2658,7 @@ sub make_min_config { } doprint "Reboot and wait $sleep_time seconds\n"; - reboot; - start_monitor; - wait_for_monitor $sleep_time; - end_monitor; + reboot $sleep_time; } success $i; -- cgit From eaa1fe25ea79e94c6727a67baaca3da0791da5de Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 14 Sep 2011 17:20:39 -0400 Subject: ktest: Fail when grub menu not found Currently if the grub menu that is supplied is not found, it will just boot into the last grub menu in menu.lst. Fail instead of confusing the user why their kernel is not booting. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index debc6898e60b..ca6ff99ab1a5 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -862,9 +862,12 @@ sub get_grub_index { open(IN, "$ssh_grub |") or die "unable to get menu.lst"; + my $found = 0; + while () { if (/^\s*title\s+$grub_menu\s*$/) { $grub_number++; + $found = 1; last; } elsif (/^\s*title\s/) { $grub_number++; @@ -873,7 +876,7 @@ sub get_grub_index { close(IN); die "Could not find '$grub_menu' in /boot/grub/menu on $machine" - if ($grub_number < 0); + if (!$found); doprint "$grub_number\n"; } -- cgit From e0a8742e3d4b7649be2ca6f22e7d45153505fc81 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 17:50:48 -0400 Subject: ktest: Add NO_INSTALL option to not install for a test There's cases where running the same kernel over and over again is useful, and being able to not install the same kernel can save time between tests. Add a NO_INSTALL option that tells ktest.pl to not install the new kernel. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 10 +++++++++- tools/testing/ktest/sample.conf | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index ca6ff99ab1a5..74fb2acae18d 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -42,6 +42,7 @@ $default{"BISECT_MANUAL"} = 0; $default{"BISECT_SKIP"} = 1; $default{"SUCCESS_LINE"} = "login:"; $default{"DETECT_TRIPLE_FAULT"} = 1; +$default{"NO_INSTALL"} = 0; $default{"BOOTED_TIMEOUT"} = 1; $default{"DIE_ON_FAILURE"} = 1; $default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; @@ -84,6 +85,7 @@ my $grub_number; my $target; my $make; my $post_install; +my $no_install; my $noclean; my $minconfig; my $start_minconfig; @@ -1094,6 +1096,8 @@ sub do_post_install { sub install { + return if ($no_install); + run_scp "$outputdir/$build_target", "$target_image" or dodie "failed to copy image"; @@ -2810,6 +2814,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $reboot_type = set_test_option("REBOOT_TYPE", $i); $grub_menu = set_test_option("GRUB_MENU", $i); $post_install = set_test_option("POST_INSTALL", $i); + $no_install = set_test_option("NO_INSTALL", $i); $reboot_script = set_test_option("REBOOT_SCRIPT", $i); $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i); $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i); @@ -2890,8 +2895,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $run_type = "ERROR"; } + my $installme = ""; + $installme = " no_install" if ($no_install); + doprint "\n\n"; - doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n"; + doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; unlink $dmesg; unlink $buildlog; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index eadca3eb6f5a..b3e0dc11fc8a 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -294,6 +294,13 @@ # or on some systems: #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION +# If for some reason you just want to boot the kernel and you do not +# want the test to install anything new. For example, you may just want +# to boot test the same kernel over and over and do not want to go through +# the hassle of installing anything, you can set this option to 1 +# (default 0) +#NO_INSTALL = 1 + # If there is a script that you require to run before the build is done # you can specify it with PRE_BUILD. # -- cgit From 2b803365a6fa177ea7e1f64f645be1cb5dd39d55 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 18:00:23 -0400 Subject: ktest: Add option REBOOT_SUCCESS_LINE to stop waiting after a reboot When ktest.pl reboots, it will usuall wait SLEEP_TIME seconds of idle console before starting the next test. By setting the REBOOT_SUCCESS_LINE, ktest will not wait SLEEP_TIME when it detects the line while rebooting to a new kernel. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 33 +++++++++++++++++++++++++++------ tools/testing/ktest/sample.conf | 10 ++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 74fb2acae18d..51ddaa5ed556 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -117,6 +117,7 @@ my $timeout; my $booted_timeout; my $detect_triplefault; my $console; +my $reboot_success_line; my $success_line; my $stop_after_success; my $stop_after_failure; @@ -612,6 +613,13 @@ sub wait_for_monitor; sub reboot { my ($time) = @_; + if (defined($time)) { + start_monitor; + # flush out current monitor + # May contain the reboot success line + wait_for_monitor 1; + } + # try to reboot normally if (run_command $reboot) { if (defined($powercycle_after_reboot)) { @@ -624,8 +632,7 @@ sub reboot { } if (defined($time)) { - start_monitor; - wait_for_monitor $time; + wait_for_monitor($time, $reboot_success_line); end_monitor; } } @@ -706,16 +713,29 @@ sub end_monitor { } sub wait_for_monitor { - my ($time) = @_; + my ($time, $stop) = @_; + my $full_line = ""; my $line; + my $booted = 0; doprint "** Wait for monitor to settle down **\n"; # read the monitor and wait for the system to calm down - do { + while (!$booted) { $line = wait_for_input($monitor_fp, $time); - print "$line" if (defined($line)); - } while (defined($line)); + last if (!defined($line)); + print "$line"; + $full_line .= $line; + + if (defined($stop) && $full_line =~ /$stop/) { + doprint "wait for monitor detected $stop\n"; + $booted = 1; + } + + if ($line =~ /\n/) { + $full_line = ""; + } + } print "** Monitor flushed **\n"; } @@ -2836,6 +2856,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $console = set_test_option("CONSOLE", $i); $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); $success_line = set_test_option("SUCCESS_LINE", $i); + $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i); $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); $stop_test_after = set_test_option("STOP_TEST_AFTER", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index b3e0dc11fc8a..67bc4e06922c 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -423,6 +423,14 @@ # (default "login:") #SUCCESS_LINE = login: +# To speed up between reboots, defining a line that the +# default kernel produces that represents that the default +# kernel has successfully booted and can be used to pass +# a new test kernel to it. Otherwise ktest.pl will wait till +# SLEEP_TIME to continue. +# (default undefined) +#REBOOT_SUCCESS_LINE = login: + # In case the console constantly fills the screen, having # a specified time to stop the test after success is recommended. # (in seconds) @@ -488,6 +496,8 @@ # another test. If a reboot to the reliable kernel happens, # we wait SLEEP_TIME for the console to stop producing output # before starting the next test. +# +# You can speed up reboot times even more by setting REBOOT_SUCCESS_LINE. # (default 60) #SLEEP_TIME = 60 -- cgit From 4ab1cce5bdd87948b75ed4fe4a8629c0f76267ae Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 18:12:20 -0400 Subject: ktest: Do not reboot on config or build issues Even if REBOOT_ON_ERROR is set, it becomes annoying that the target machine is rebooted when a config option is incorrect or a build fails. There's no reason to reboot the target for host only issues. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 51ddaa5ed556..057676a8e785 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -133,6 +133,9 @@ my %config_help; my %variable; my %force_config; +# do not force reboots on config problems +my $no_reboot = 1; + $config_help{"MACHINE"} = << "EOF" The machine hostname that you will test. EOF @@ -640,7 +643,7 @@ sub reboot { sub do_not_reboot { my $i = $iteration; - return $test_type eq "build" || + return $test_type eq "build" || $no_reboot || ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") || ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build"); } @@ -1285,6 +1288,10 @@ sub build { unlink $buildlog; + # Failed builds should not reboot the target + my $save_no_reboot = $no_reboot; + $no_reboot = 1; + if (defined($pre_build)) { my $ret = run_command $pre_build; if (!$ret && defined($pre_build_die) && @@ -1353,10 +1360,15 @@ sub build { if (!$build_ret) { # bisect may need this to pass - return 0 if ($in_bisect); + if ($in_bisect) { + $no_reboot = $save_no_reboot; + return 0; + } fail "failed build" and return 0; } + $no_reboot = $save_no_reboot; + return 1; } @@ -2806,6 +2818,9 @@ sub set_test_option { # First we need to do is the builds for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { + # Do not reboot on failing test options + $no_reboot = 1; + $iteration = $i; my $makecmd = set_test_option("MAKE_CMD", $i); @@ -2941,6 +2956,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { die "failed to checkout $checkout"; } + $no_reboot = 0; + + if ($test_type eq "bisect") { bisect $i; next; -- cgit From 45d73a5d8a98dbabcdf37e2da5ef5b0412244643 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 19:44:53 -0400 Subject: ktest: Add IF and ELSE to config sections Add IF keyword to sections within the config. Also added an ELSE keyword that allows different config options to be set for a given section. For example: TYPE := 1 STATUS := 0 DEFAULTS IF ${TYPE} [...] ELSE IF ${STATUS} [...] ELSE [...] The above will process the first section as $TYPE is true. If it was false, it would process the last section as $STATUS is false. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 64 ++++++++++++++++++++++++++++++++++++++--- tools/testing/ktest/sample.conf | 38 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 057676a8e785..c76e18f00c44 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -361,6 +361,21 @@ sub set_variable { } } +sub process_if { + my ($name, $value) = @_; + + my $val = process_variables($value); + + if ($val =~ /^\s*0\s*$/) { + return 0; + } elsif ($val =~ /^\s*\d+\s*$/) { + return 1; + } + + die ("$name: $.: Undefined variable $val in if statement\n"); + return 1; +} + sub read_config { my ($config) = @_; @@ -376,6 +391,8 @@ sub read_config { my $skip = 0; my $rest; my $test_case = 0; + my $if = 0; + my $if_set = 0; while () { @@ -397,7 +414,7 @@ sub read_config { $default = 0; $repeat = 1; - if ($rest =~ /\s+SKIP(.*)/) { + if ($rest =~ /\s+SKIP\b(.*)/) { $rest = $1; $skip = 1; } else { @@ -411,9 +428,16 @@ sub read_config { $repeat_tests{"$test_num"} = $repeat; } - if ($rest =~ /\s+SKIP(.*)/) { - $rest = $1; - $skip = 1; + if ($rest =~ /\sIF\s+(\S*)(.*)/) { + $rest = $2; + if (process_if($name, $1)) { + $if_set = 1; + } else { + $skip = 1; + } + $if = 1; + } else { + $if = 0; } if ($rest !~ /^\s*$/) { @@ -437,10 +461,42 @@ sub read_config { $skip = 0; } + if ($rest =~ /\sIF\s+(\S*)(.*)/) { + $if = 1; + $rest = $2; + if (process_if($name, $1)) { + $if_set = 1; + } else { + $skip = 1; + } + } else { + $if = 0; + } + if ($rest !~ /^\s*$/) { die "$name: $.: Gargbage found after DEFAULTS\n$_"; } + } elsif (/^\s*ELSE(.*)$/) { + if (!$if) { + die "$name: $.: ELSE found with out matching IF section\n$_"; + } + $rest = $1; + if ($if_set) { + $skip = 1; + } else { + $skip = 0; + + if ($rest =~ /\sIF\s+(\S*)(.*)/) { + # May be a ELSE IF section. + if (!process_if($name, $1)) { + $skip = 1; + } + } else { + $if = 0; + } + } + } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { next if ($skip); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 67bc4e06922c..6a0a0ba59975 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -72,6 +72,44 @@ # the same option name under the same test or as default # ktest will fail to execute, and no tests will run. # +# Both TEST_START and DEFAULTS sections can also have the IF keyword +# The value after the IF must evaluate into a 0 or non 0 positive +# integer, and can use the config variables (explained below). +# +# DEFAULTS IF ${IS_X86_32} +# +# The above will process the DEFAULTS section if the config +# variable IS_X86_32 evaluates to a non zero positive integer +# otherwise if it evaluates to zero, it will act the same +# as if the SKIP keyword was used. +# +# The ELSE keyword can be used directly after a section with +# a IF statement. +# +# TEST_START IF ${RUN_NET_TESTS} +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network +# +# ELSE +# +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-normal +# +# +# The ELSE keyword can also contain an IF statement to allow multiple +# if then else sections. But all the sections must be either +# DEFAULT or TEST_START, they can not be a mixture. +# +# TEST_START IF ${RUN_NET_TESTS} +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network +# +# ELSE IF ${RUN_DISK_TESTS} +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-tests +# +# ELSE IF ${RUN_CPU_TESTS} +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-cpu +# +# ELSE +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network +# #### Config variables #### # -- cgit From ab7a3f52cef5ff1c784de7adfbda3421b10754a4 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 20:24:07 -0400 Subject: ktest: Let IF keyword take comparisons Allow ==, !=, <=, >=, <, and > to be used in IF statements to compare if a section should be processed or not. For example: BITS := 32 DEFAULTS IF ${BITS} == 32 MIN_CONFIG = ${CONFIG_DIR}/config-32 ELSE MIN_CONFIG = ${CONFIG_DIR}/config-64 Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 54 ++++++++++++++++++++++++++++++++++++----- tools/testing/ktest/sample.conf | 14 +++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index c76e18f00c44..ed20d6881ec9 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -361,11 +361,47 @@ sub set_variable { } } +sub process_compare { + my ($lval, $cmp, $rval) = @_; + + # remove whitespace + + $lval =~ s/^\s*//; + $lval =~ s/\s*$//; + + $rval =~ s/^\s*//; + $rval =~ s/\s*$//; + + if ($cmp eq "==") { + return $lval eq $rval; + } elsif ($cmp eq "!=") { + return $lval ne $rval; + } + + my $statement = "$lval $cmp $rval"; + my $ret = eval $statement; + + # $@ stores error of eval + if ($@) { + return -1; + } + + return $ret; +} + sub process_if { my ($name, $value) = @_; my $val = process_variables($value); + if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) { + my $ret = process_compare($1, $2, $3); + if ($ret < 0) { + die "$name: $.: Unable to process comparison\n"; + } + return $ret; + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { @@ -428,8 +464,8 @@ sub read_config { $repeat_tests{"$test_num"} = $repeat; } - if ($rest =~ /\sIF\s+(\S*)(.*)/) { - $rest = $2; + if ($rest =~ /\sIF\s+(.*)/) { + $rest = ""; if (process_if($name, $1)) { $if_set = 1; } else { @@ -461,14 +497,14 @@ sub read_config { $skip = 0; } - if ($rest =~ /\sIF\s+(\S*)(.*)/) { + if ($rest =~ /\sIF\s+(.*)/) { $if = 1; - $rest = $2; if (process_if($name, $1)) { $if_set = 1; } else { $skip = 1; } + $rest = ""; } else { $if = 0; } @@ -477,26 +513,32 @@ sub read_config { die "$name: $.: Gargbage found after DEFAULTS\n$_"; } - } elsif (/^\s*ELSE(.*)$/) { + } elsif (/^\s*ELSE\b(.*)$/) { if (!$if) { die "$name: $.: ELSE found with out matching IF section\n$_"; } $rest = $1; if ($if_set) { $skip = 1; + $rest = ""; } else { $skip = 0; - if ($rest =~ /\sIF\s+(\S*)(.*)/) { + if ($rest =~ /\sIF\s+(.*)/) { # May be a ELSE IF section. if (!process_if($name, $1)) { $skip = 1; } + $rest = ""; } else { $if = 0; } } + if ($rest !~ /^\s*$/) { + die "$name: $.: Gargbage found after DEFAULTS\n$_"; + } + } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { next if ($skip); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 6a0a0ba59975..4e8fb91fd517 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -72,6 +72,8 @@ # the same option name under the same test or as default # ktest will fail to execute, and no tests will run. # +# +# # Both TEST_START and DEFAULTS sections can also have the IF keyword # The value after the IF must evaluate into a 0 or non 0 positive # integer, and can use the config variables (explained below). @@ -110,6 +112,18 @@ # ELSE # BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network # +# The if statement may also have comparisons that will and for +# == and !=, strings may be used for both sides. +# +# BOX_TYPE := x86_32 +# +# DEFAULTS IF ${BOX_TYPE} == x86_32 +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-32 +# ELSE +# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64 +# + + #### Config variables #### # -- cgit From 2ed3b16128e93309758e62937e7f137ac9844227 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 21:00:00 -0400 Subject: ktest: Add INCLUDE keyword to include other config files Have the reading of the config file allow reading of other config files using the INCLUDE keyword. This allows multiple config files to share config options. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 55 +++++++++++++++++++++++++++++++++++------ tools/testing/ktest/sample.conf | 32 ++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index ed20d6881ec9..62de47de2b04 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -412,15 +412,16 @@ sub process_if { return 1; } -sub read_config { - my ($config) = @_; +sub __read_config { + my ($config, $current_test_num) = @_; - open(IN, $config) || die "can't read file $config"; + my $in; + open($in, $config) || die "can't read file $config"; my $name = $config; $name =~ s,.*/(.*),$1,; - my $test_num = 0; + my $test_num = $$current_test_num; my $default = 1; my $repeat = 1; my $num_tests_set = 0; @@ -430,7 +431,7 @@ sub read_config { my $if = 0; my $if_set = 0; - while () { + while (<$in>) { # ignore blank lines and comments next if (/^\s*$/ || /\s*\#/); @@ -539,6 +540,33 @@ sub read_config { die "$name: $.: Gargbage found after DEFAULTS\n$_"; } + } elsif (/^\s*INCLUDE\s+(\S+)/) { + + next if ($skip); + + if (!$default) { + die "$name: $.: INCLUDE can only be done in default sections\n$_"; + } + + my $file = process_variables($1); + + if ($file !~ m,^/,) { + # check the path of the config file first + if ($config =~ m,(.*)/,) { + if (-f "$1/$file") { + $file = "$1/$file"; + } + } + } + + if ( ! -r $file ) { + die "$name: $.: Can't read file $file\n$_"; + } + + if (__read_config($file, \$test_num)) { + $test_case = 1; + } + } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) { next if ($skip); @@ -594,13 +622,26 @@ sub read_config { } } - close(IN); - if ($test_num) { $test_num += $repeat - 1; $opt{"NUM_TESTS"} = $test_num; } + close($in); + + $$current_test_num = $test_num; + + return $test_case; +} + +sub read_config { + my ($config) = @_; + + my $test_case; + my $test_num = 0; + + $test_case = __read_config $config, \$test_num; + # make sure we have all mandatory configs get_ktest_configs; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 4e8fb91fd517..ae2a93c732ac 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -122,8 +122,36 @@ # ELSE # BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64 # - - +# +# INCLUDE file +# +# The INCLUDE keyword may be used in DEFAULT sections. This will +# read another config file and process that file as well. The included +# file can include other files, add new test cases or default +# statements. Config variables will be passed to these files and changes +# to config variables will be seen by top level config files. Including +# a file is processed just like the contents of the file was cut and pasted +# into the top level file, except, that include files that end with +# TEST_START sections will have that section ended at the end of +# the include file. That is, an included file is included followed +# by another DEFAULT keyword. +# +# Unlike other files referenced in this config, the file path does not need +# to be absolute. If the file does not start with '/', then the directory +# that the current config file was located in is used. If no config by the +# given name is found there, then the current directory is searched. +# +# INCLUDE myfile +# DEFAULT +# +# is the same as: +# +# INCLUDE myfile +# +# Note, if the include file does not contain a full path, the file is +# searched first by the location of the original include file, and then +# by the location that ktest.pl was executed in. +# #### Config variables #### # -- cgit From 0050b6bbef01d871a34a77685047190aa428b210 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 21:10:30 -0400 Subject: ktest: Consolidate TEST_TYPE and DEFAULT code The code that handles parsing the TEST_TYPE and DEFAULT code share a lot of common functionality. Combine the two and add a if statement that does what is different between them. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 61 +++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 62de47de2b04..b4f32e734745 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -436,20 +436,29 @@ sub __read_config { # ignore blank lines and comments next if (/^\s*$/ || /\s*\#/); - if (/^\s*TEST_START(.*)/) { + if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) { - $rest = $1; + my $type = $1; + $rest = $2; - if ($num_tests_set) { - die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; - } + my $old_test_num; + my $old_repeat; + + if ($type eq "TEST_START") { - my $old_test_num = $test_num; - my $old_repeat = $repeat; + if ($num_tests_set) { + die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n"; + } - $test_num += $repeat; - $default = 0; - $repeat = 1; + $old_test_num = $test_num; + $old_repeat = $repeat; + + $test_num += $repeat; + $default = 0; + $repeat = 1; + } else { + $default = 1; + } if ($rest =~ /\s+SKIP\b(.*)/) { $rest = $1; @@ -478,42 +487,14 @@ sub __read_config { } if ($rest !~ /^\s*$/) { - die "$name: $.: Gargbage found after TEST_START\n$_"; + die "$name: $.: Gargbage found after $type\n$_"; } - if ($skip) { + if ($skip && $type eq "TEST_START") { $test_num = $old_test_num; $repeat = $old_repeat; } - } elsif (/^\s*DEFAULTS(.*)$/) { - $default = 1; - - $rest = $1; - - if ($rest =~ /\s+SKIP(.*)/) { - $rest = $1; - $skip = 1; - } else { - $skip = 0; - } - - if ($rest =~ /\sIF\s+(.*)/) { - $if = 1; - if (process_if($name, $1)) { - $if_set = 1; - } else { - $skip = 1; - } - $rest = ""; - } else { - $if = 0; - } - - if ($rest !~ /^\s*$/) { - die "$name: $.: Gargbage found after DEFAULTS\n$_"; - } - } elsif (/^\s*ELSE\b(.*)$/) { if (!$if) { die "$name: $.: ELSE found with out matching IF section\n$_"; -- cgit From 3d1cc41432b0491a39a3185b52bfa1d0411bba10 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 22:14:21 -0400 Subject: ktest: Add OVERRIDE keyword to DEFAULTS section The OVERRIDE keyword will allow options defined in the given DEFAULTS section to override options defined in previous DEFAULT sections. Normally, options will error if they were previous defined. The OVERRIDE keyword allows options that have been previously defined to be changed in the given section. Note, the same option can not be defined in the same DEFAULT section even if that section is marked as OVERRIDE. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 37 +++++++++++++++++++++++++++++-------- tools/testing/ktest/sample.conf | 15 +++++++++++++++ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index b4f32e734745..7bce412bbdcc 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -337,10 +337,17 @@ sub process_variables { } sub set_value { - my ($lvalue, $rvalue) = @_; + my ($lvalue, $rvalue, $override, $overrides, $name) = @_; if (defined($opt{$lvalue})) { - die "Error: Option $lvalue defined more than once!\n"; + if (!$override || defined(${$overrides}{$lvalue})) { + my $extra = ""; + if ($override) { + $extra = "In the same override section!\n"; + } + die "$name: $.: Option $lvalue defined more than once!\n$extra"; + } + ${$overrides}{$lvalue} = $rvalue; } if ($rvalue =~ /^\s*$/) { delete $opt{$lvalue}; @@ -430,6 +437,9 @@ sub __read_config { my $test_case = 0; my $if = 0; my $if_set = 0; + my $override = 0; + + my %overrides; while (<$in>) { @@ -443,6 +453,7 @@ sub __read_config { my $old_test_num; my $old_repeat; + $override = 0; if ($type eq "TEST_START") { @@ -468,10 +479,20 @@ sub __read_config { $skip = 0; } - if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { - $repeat = $1; - $rest = $2; - $repeat_tests{"$test_num"} = $repeat; + if (!$skip) { + if ($type eq "TEST_START") { + if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { + $repeat = $1; + $rest = $2; + $repeat_tests{"$test_num"} = $repeat; + } + } elsif ($rest =~ /\sOVERRIDE\b(.*)/) { + # DEFAULT only + $rest = $1; + $override = 1; + # Clear previous overrides + %overrides = (); + } } if ($rest =~ /\sIF\s+(.*)/) { @@ -573,10 +594,10 @@ sub __read_config { } if ($default || $lvalue =~ /\[\d+\]$/) { - set_value($lvalue, $rvalue); + set_value($lvalue, $rvalue, $override, \%overrides, $name); } else { my $val = "$lvalue\[$test_num\]"; - set_value($val, $rvalue); + set_value($val, $rvalue, $override, \%overrides, $name); if ($repeat > 1) { $repeats{$val} = $repeat; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index ae2a93c732ac..0fd3ca30ad0c 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -72,6 +72,21 @@ # the same option name under the same test or as default # ktest will fail to execute, and no tests will run. # +# DEFAULTS OVERRIDE +# +# Options defined in the DEFAULTS section can not be duplicated +# even if they are defined in two different DEFAULT sections. +# This is done to catch mistakes where an option is added but +# the previous option was forgotten about and not commented. +# +# The OVERRIDE keyword can be added to a section to allow this +# section to override other DEFAULT sections values that have +# been defined previously. It will only override options that +# have been defined before its use. Options defined later +# in a non override section will still error. The same option +# can not be defined in the same section even if that section +# is marked OVERRIDE. +# # # # Both TEST_START and DEFAULTS sections can also have the IF keyword -- cgit From 9900b5dc067551fcdcaec63d013b1d95b36835ae Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 30 Sep 2011 22:41:14 -0400 Subject: ktest: Add DEFINED keyword for IF statements Have IF statements process if a config variable or option has been defined or not. Can use NOT DEFINED in the case for telling if a variable or option has not been defined. DEFAULTS IF NOT DEFINED SSH_USER SSH_USER = root Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 17 ++++++++++++++++- tools/testing/ktest/sample.conf | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 7bce412bbdcc..76a5964595da 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -396,6 +396,13 @@ sub process_compare { return $ret; } +sub value_defined { + my ($val) = @_; + + return defined($variable{$2}) || + defined($opt{$2}); +} + sub process_if { my ($name, $value) = @_; @@ -409,13 +416,21 @@ sub process_if { return $ret; } + if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) { + if (defined $1) { + return !value_defined($2); + } else { + return value_defined($2); + } + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { return 1; } - die ("$name: $.: Undefined variable $val in if statement\n"); + die ("$name: $.: Undefined content $val in if statement\n"); return 1; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 0fd3ca30ad0c..7b49f07b6423 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -137,6 +137,23 @@ # ELSE # BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64 # +# The DEFINED keyword can be used by the IF statements too. +# It returns true if the given config variable or option has been defined +# or false otherwise. +# +# +# DEFAULTS IF DEFINED USE_CC +# CC := ${USE_CC} +# ELSE +# CC := gcc +# +# +# As well as NOT DEFINED. +# +# DEFAULTS IF NOT DEFINED MAKE_CMD +# MAKE_CMD := make ARCH=x86 +# +# # # INCLUDE file # -- cgit From ac6974c76e66c2f9b8b8a23b974c5f3d94302e81 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 4 Oct 2011 09:40:17 -0400 Subject: ktest: Sort make_min_config configs by dependecies The make_min_config test will turn off one config at a time and check if the config boots or not, and if it does, it will remove that config plus any config that depended on that config. ktest already looks if a config has a dependency and will try the dependency config first. But by sorting the configs and trying the config with the most configs dependent on it, we can shrink the minconfig faster. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 71 ++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 76a5964595da..2a9d04207174 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -2372,12 +2372,31 @@ sub patchcheck { } my %depends; +my %depcount; my $iflevel = 0; my @ifdeps; # prevent recursion my %read_kconfigs; +sub add_dep { + # $config depends on $dep + my ($config, $dep) = @_; + + if (defined($depends{$config})) { + $depends{$config} .= " " . $dep; + } else { + $depends{$config} = $dep; + } + + # record the number of configs depending on $dep + if (defined $depcount{$dep}) { + $depcount{$dep}++; + } else { + $depcount{$dep} = 1; + } +} + # taken from streamline_config.pl sub read_kconfig { my ($kconfig) = @_; @@ -2424,30 +2443,19 @@ sub read_kconfig { $config = $2; for (my $i = 0; $i < $iflevel; $i++) { - if ($i) { - $depends{$config} .= " " . $ifdeps[$i]; - } else { - $depends{$config} = $ifdeps[$i]; - } - $state = "DEP"; + add_dep $config, $ifdeps[$i]; } # collect the depends for the config } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { - if (defined($depends{$1})) { - $depends{$config} .= " " . $1; - } else { - $depends{$config} = $1; - } + add_dep $config, $1; # Get the configs that select this config - } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { - if (defined($depends{$1})) { - $depends{$1} .= " " . $config; - } else { - $depends{$1} = $config; - } + } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) { + + # selected by depends on config + add_dep $1, $config; # Check for if statements } elsif (/^if\s+(.*\S)\s*$/) { @@ -2559,11 +2567,18 @@ sub make_new_config { close OUT; } +sub chomp_config { + my ($config) = @_; + + $config =~ s/CONFIG_//; + + return $config; +} + sub get_depends { my ($dep) = @_; - my $kconfig = $dep; - $kconfig =~ s/CONFIG_//; + my $kconfig = chomp_config $dep; $dep = $depends{"$kconfig"}; @@ -2613,8 +2628,7 @@ sub test_this_config { return undef; } - my $kconfig = $config; - $kconfig =~ s/CONFIG_//; + my $kconfig = chomp_config $config; # Test dependencies first if (defined($depends{"$kconfig"})) { @@ -2704,6 +2718,14 @@ sub make_min_config { my @config_keys = keys %min_configs; + # All configs need a depcount + foreach my $config (@config_keys) { + my $kconfig = chomp_config $config; + if (!defined $depcount{$kconfig}) { + $depcount{$kconfig} = 0; + } + } + # Remove anything that was set by the make allnoconfig # we shouldn't need them as they get set for us anyway. foreach my $config (@config_keys) { @@ -2742,8 +2764,13 @@ sub make_min_config { # Now disable each config one by one and do a make oldconfig # till we find a config that changes our list. - # Put configs that did not modify the config at the end. my @test_configs = keys %min_configs; + + # Sort keys by who is most dependent on + @test_configs = sort { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} } + @test_configs ; + + # Put configs that did not modify the config at the end. my $reset = 1; for (my $i = 0; $i < $#test_configs; $i++) { if (!defined($nochange_config{$test_configs[0]})) { -- cgit From a9f84424be8d12e8a84b9eac112cd1152587d437 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 17 Oct 2011 11:06:29 -0400 Subject: ktest: Fix parsing of config section lines The order for some of the keywords on a section line (TEST_START or DEFAULTS) does not really matter. Simply need to remove the keyword from the line as we process it and evaluate the next keyword in the line. By removing the keywords as we find them, we do not need to keep track of where on the line they were found. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 49 ++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 2a9d04207174..d292c2d8dfe9 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -449,6 +449,7 @@ sub __read_config { my $num_tests_set = 0; my $skip = 0; my $rest; + my $line; my $test_case = 0; my $if = 0; my $if_set = 0; @@ -465,6 +466,7 @@ sub __read_config { my $type = $1; $rest = $2; + $line = $2; my $old_test_num; my $old_repeat; @@ -486,32 +488,28 @@ sub __read_config { $default = 1; } - if ($rest =~ /\s+SKIP\b(.*)/) { - $rest = $1; + # If SKIP is anywhere in the line, the command will be skipped + if ($rest =~ s/\s+SKIP\b//) { $skip = 1; } else { $test_case = 1; $skip = 0; } - if (!$skip) { - if ($type eq "TEST_START") { - if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) { - $repeat = $1; - $rest = $2; - $repeat_tests{"$test_num"} = $repeat; - } - } elsif ($rest =~ /\sOVERRIDE\b(.*)/) { - # DEFAULT only - $rest = $1; - $override = 1; - # Clear previous overrides - %overrides = (); + if ($rest =~ s/\sELSE\b//) { + if (!$if) { + die "$name: $.: ELSE found with out matching IF section\n$_"; + } + $if = 0; + + if ($if_set) { + $skip = 1; + } else { + $skip = 0; } } - if ($rest =~ /\sIF\s+(.*)/) { - $rest = ""; + if ($rest =~ s/\sIF\s+(.*)//) { if (process_if($name, $1)) { $if_set = 1; } else { @@ -520,9 +518,24 @@ sub __read_config { $if = 1; } else { $if = 0; + $if_set = 0; } - if ($rest !~ /^\s*$/) { + if (!$skip) { + if ($type eq "TEST_START") { + if ($rest =~ s/\s+ITERATE\s+(\d+)//) { + $repeat = $1; + $repeat_tests{"$test_num"} = $repeat; + } + } elsif ($rest =~ s/\sOVERRIDE\b//) { + # DEFAULT only + $override = 1; + # Clear previous overrides + %overrides = (); + } + } + + if (!$skip && $rest !~ /^\s*$/) { die "$name: $.: Gargbage found after $type\n$_"; } -- cgit From 8d735212e441af855afd28ccc402fcaf12999f8d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 17 Oct 2011 11:36:44 -0400 Subject: ktest: Add processing of complex conditionals The IF statements for DEFAULTS and TEST_START sections now handle complex statements (&&,||) Example: TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 53 +++++++++++++++++++++++++++++++++++++---- tools/testing/ktest/sample.conf | 10 ++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index d292c2d8dfe9..1bda07f6d673 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -304,7 +304,7 @@ sub get_ktest_configs { } sub process_variables { - my ($value) = @_; + my ($value, $remove_undef) = @_; my $retval = ""; # We want to check for '\', and it is just easier @@ -322,6 +322,10 @@ sub process_variables { $retval = "$retval$begin"; if (defined($variable{$var})) { $retval = "$retval$variable{$var}"; + } elsif (defined($remove_undef) && $remove_undef) { + # for if statements, any variable that is not defined, + # we simple convert to 0 + $retval = "${retval}0"; } else { # put back the origin piece. $retval = "$retval\$\{$var\}"; @@ -403,10 +407,40 @@ sub value_defined { defined($opt{$2}); } -sub process_if { - my ($name, $value) = @_; +my $d = 0; +sub process_expression { + my ($name, $val) = @_; + + my $c = $d++; + + while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) { + my $express = $1; + + if (process_expression($name, $express)) { + $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /; + } else { + $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /; + } + } + + $d--; + my $OR = "\\|\\|"; + my $AND = "\\&\\&"; - my $val = process_variables($value); + while ($val =~ s/^(.*?)($OR|$AND)//) { + my $express = $1; + my $op = $2; + + if (process_expression($name, $express)) { + if ($op eq "||") { + return 1; + } + } else { + if ($op eq "&&") { + return 0; + } + } + } if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) { my $ret = process_compare($1, $2, $3); @@ -431,7 +465,16 @@ sub process_if { } die ("$name: $.: Undefined content $val in if statement\n"); - return 1; +} + +sub process_if { + my ($name, $value) = @_; + + # Convert variables and replace undefined ones with 0 + my $val = process_variables($value, 1); + my $ret = process_expression $name, $val; + + return $ret; } sub __read_config { diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 7b49f07b6423..dbedfa196727 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -154,6 +154,16 @@ # MAKE_CMD := make ARCH=x86 # # +# And/or ops (&&,||) may also be used to make complex conditionals. +# +# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf +# +# Notice the use of paranthesis. Without any paranthesis the above would be +# processed the same as: +# +# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf) +# +# # # INCLUDE file # -- cgit From c54367f9d6be8e19c6e98ae7038438f0377ee138 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 20 Oct 2011 09:56:41 -0400 Subject: ktest: Do not opencode reboot in grub setting When setting the next kernel to boot to with grub, do not opencode the reboot operation. The normal reboot operation can be modified by config options (namely POWERCYCLE_AFTER_REBOOT). This needs to affect all reboots. Remove the opencoded reboot to make sure that any changes to the reboot code also affect all reboots. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 1bda07f6d673..d60c496fb514 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1150,7 +1150,8 @@ sub wait_for_input sub reboot_to { if ($reboot_type eq "grub") { - run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'"; + run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; + reboot; return; } -- cgit From 9f7424cc86adf55c3fccaa1160b6cf5c6cfc4c02 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Sat, 22 Oct 2011 08:58:19 -0400 Subject: ktest: Add another monitor flush before installing kernel On some tests that do multiple boots (patchcheck, bisect, etc), the build of the next kernel to run may finish before the stable kernel has finished booting. Then the install of the new kernel will fail when it tries to connect as the machine has not finished the boot process. Do one more monitor flush to make sure the machine is up and running before trying to connect to it again. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index d60c496fb514..652446dd9e79 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1391,6 +1391,11 @@ sub get_version { } sub start_monitor_and_boot { + # Make sure the stable kernel has finished booting + start_monitor; + wait_for_monitor 5; + end_monitor; + get_grub_index; get_version; install; -- cgit From 7bf5107347d94bb056c5a0cf78f09e499c3d8f48 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Sat, 22 Oct 2011 09:07:03 -0400 Subject: ktest: Add variable ${PWD} Adding the variable ${PWD} that equals `pwd` makes the config files much simpler. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 652446dd9e79..9d9ee321a3dc 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -136,6 +136,9 @@ my %force_config; # do not force reboots on config problems my $no_reboot = 1; +# default variables that can be used +chomp ($variable{"PWD"} = `pwd`); + $config_help{"MACHINE"} = << "EOF" The machine hostname that you will test. EOF -- cgit From c2bc11113c50449f23c40b724fe410fc2380a8e9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 27 Oct 2011 18:12:42 -0700 Subject: time: Improve documentation of timekeeeping_adjust() After getting a number of questions in private emails about the math around admittedly very complex timekeeping_adjust() and timekeeping_big_adjust(), I figure the code needs some better comments. Hopefully the explanations are clear enough and don't muddy the water any worse. Still needs documentation for ntp_error, but I couldn't recall exactly the full explanation behind the code that's there (although I do recall once working it out when Roman first proposed it). Given a bit more time I can probably work it out, but I don't want to hold back this documentation until then. Signed-off-by: John Stultz Cc: Chen Jie Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1319764362-32367-1-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar --- kernel/time/timekeeping.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2b021b0e8507..025e136f3881 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -802,14 +802,44 @@ static void timekeeping_adjust(s64 offset) s64 error, interval = timekeeper.cycle_interval; int adj; + /* + * The point of this is to check if the error is greater then half + * an interval. + * + * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs. + * + * Note we subtract one in the shift, so that error is really error*2. + * This "saves" dividing(shifting) intererval twice, but keeps the + * (error > interval) comparision as still measuring if error is + * larger then half an interval. + * + * Note: It does not "save" on aggrivation when reading the code. + */ error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1); if (error > interval) { + /* + * We now divide error by 4(via shift), which checks if + * the error is greater then twice the interval. + * If it is greater, we need a bigadjust, if its smaller, + * we can adjust by 1. + */ error >>= 2; + /* + * XXX - In update_wall_time, we round up to the next + * nanosecond, and store the amount rounded up into + * the error. This causes the likely below to be unlikely. + * + * The properfix is to avoid rounding up by using + * the high precision timekeeper.xtime_nsec instead of + * xtime.tv_nsec everywhere. Fixing this will take some + * time. + */ if (likely(error <= interval)) adj = 1; else adj = timekeeping_bigadjust(error, &interval, &offset); } else if (error < -interval) { + /* See comment above, this is just switched for the negative */ error >>= 2; if (likely(error >= -interval)) { adj = -1; @@ -817,9 +847,58 @@ static void timekeeping_adjust(s64 offset) offset = -offset; } else adj = timekeeping_bigadjust(error, &interval, &offset); - } else + } else /* No adjustment needed */ return; + /* + * So the following can be confusing. + * + * To keep things simple, lets assume adj == 1 for now. + * + * When adj != 1, remember that the interval and offset values + * have been appropriately scaled so the math is the same. + * + * The basic idea here is that we're increasing the multiplier + * by one, this causes the xtime_interval to be incremented by + * one cycle_interval. This is because: + * xtime_interval = cycle_interval * mult + * So if mult is being incremented by one: + * xtime_interval = cycle_interval * (mult + 1) + * Its the same as: + * xtime_interval = (cycle_interval * mult) + cycle_interval + * Which can be shortened to: + * xtime_interval += cycle_interval + * + * So offset stores the non-accumulated cycles. Thus the current + * time (in shifted nanoseconds) is: + * now = (offset * adj) + xtime_nsec + * Now, even though we're adjusting the clock frequency, we have + * to keep time consistent. In other words, we can't jump back + * in time, and we also want to avoid jumping forward in time. + * + * So given the same offset value, we need the time to be the same + * both before and after the freq adjustment. + * now = (offset * adj_1) + xtime_nsec_1 + * now = (offset * adj_2) + xtime_nsec_2 + * So: + * (offset * adj_1) + xtime_nsec_1 = + * (offset * adj_2) + xtime_nsec_2 + * And we know: + * adj_2 = adj_1 + 1 + * So: + * (offset * adj_1) + xtime_nsec_1 = + * (offset * (adj_1+1)) + xtime_nsec_2 + * (offset * adj_1) + xtime_nsec_1 = + * (offset * adj_1) + offset + xtime_nsec_2 + * Canceling the sides: + * xtime_nsec_1 = offset + xtime_nsec_2 + * Which gives us: + * xtime_nsec_2 = xtime_nsec_1 - offset + * Which simplfies to: + * xtime_nsec -= offset + * + * XXX - TODO: Doc ntp_error calculation. + */ timekeeper.mult += adj; timekeeper.xtime_interval += interval; timekeeper.xtime_nsec -= offset; -- cgit From 815e2bd7d609da9c7615ea28a3990064a394312f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 28 Oct 2011 07:01:40 -0400 Subject: ktest: Evaluate variables entered on the command line When ktest.pl is called without any arguments, or if the config file does not exist, ktest.pl will ask the user for some information. Some of these questions are code paths. Allowing the user to type ${PWD} for the current directory greatly simplifies these entries. Add variable processing to the entered values. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 9d9ee321a3dc..30e2befd6f2a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -250,6 +250,7 @@ sub read_yn { sub get_ktest_config { my ($config) = @_; + my $ans; return if (defined($opt{$config})); @@ -263,16 +264,17 @@ sub get_ktest_config { if (defined($default{$config})) { print "\[$default{$config}\] "; } - $entered_configs{$config} = ; - $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/; - if ($entered_configs{$config} =~ /^\s*$/) { + $ans = ; + $ans =~ s/^\s*(.*\S)\s*$/$1/; + if ($ans =~ /^\s*$/) { if ($default{$config}) { - $entered_configs{$config} = $default{$config}; + $ans = $default{$config}; } else { print "Your answer can not be blank\n"; next; } } + $entered_configs{$config} = process_variables($ans); last; } } -- cgit From f74974c763c872d65da4062a14f4e73c77a0b577 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 11 Oct 2011 17:27:51 +0200 Subject: drm/i915: disable temporal dithering on the internal panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i'm getting tempted to just disable temporal Approved. apparently it makes the screen look pulse-y which is worse than the disease. References: http://lists.freedesktop.org/archives/intel-gfx/2011-October/012545.html Tested-by: Олег Герман Reviewed-by: Adam Jackson Signed-off-by: Daniel Vetter Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 981b1f1c04d8..b75bd93cf59b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5671,7 +5671,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; if ((is_lvds && dev_priv->lvds_dither) || dither) { pipeconf |= PIPECONF_DITHER_EN; - pipeconf |= PIPECONF_DITHER_TYPE_ST1; + pipeconf |= PIPECONF_DITHER_TYPE_SP; } if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { intel_dp_set_m_n(crtc, mode, adjusted_mode); -- cgit From 80a2901d2a59946d098c4479d650d0c3c82c3d85 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 11 Oct 2011 10:59:05 +0200 Subject: drm/i915: only match on PCI_BASE_CLASS_DISPLAY ... not DISPLAY_VGA, because we ignore the VGA subclass with our class_mask. It confused me until Chris Wilson clued me up. Signed-off-by: Daniel Vetter Reviewed-by: Adam Jackson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 4c8d681c2151..548e04bade3c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -106,7 +106,7 @@ static struct drm_driver driver; extern int intel_agp_enabled; #define INTEL_VGA_DEVICE(id, info) { \ - .class = PCI_CLASS_DISPLAY_VGA << 8, \ + .class = PCI_BASE_CLASS_DISPLAY << 16, \ .class_mask = 0xff0000, \ .vendor = 0x8086, \ .device = id, \ -- cgit From 828204903945002be837d938401e242978b7b505 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Oct 2011 16:33:34 -0400 Subject: drm/i915: intel_choose_pipe_bpp_dither messages should be DRM_DEBUG_KMS Shouldn't hide these behind _DRIVER, they're all KMS-related. Signed-off-by: Adam Jackson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b75bd93cf59b..9fa342e89454 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4711,7 +4711,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, lvds_bpc = 6; if (lvds_bpc < display_bpc) { - DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc); + DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc); display_bpc = lvds_bpc; } continue; @@ -4722,7 +4722,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, unsigned int edp_bpc = dev_priv->edp.bpp / 3; if (edp_bpc < display_bpc) { - DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); display_bpc = edp_bpc; } continue; @@ -4737,7 +4737,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, /* Don't use an invalid EDID bpc value */ if (connector->display_info.bpc && connector->display_info.bpc < display_bpc) { - DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc); + DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc); display_bpc = connector->display_info.bpc; } } @@ -4748,10 +4748,10 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, */ if (intel_encoder->type == INTEL_OUTPUT_HDMI) { if (display_bpc > 8 && display_bpc < 12) { - DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n"); + DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n"); display_bpc = 12; } else { - DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n"); + DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n"); display_bpc = 8; } } @@ -4789,8 +4789,8 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, display_bpc = min(display_bpc, bpc); - DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n", - bpc, display_bpc); + DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n", + bpc, display_bpc); *pipe_bpp = display_bpc * 3; -- cgit From 3fca806cf343155d0bb0dfbdbc2e51ef47b65750 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Oct 2011 14:42:41 +0300 Subject: drm/i915: fix if statement (bogus semi-colon) The semi-colon is a typo here and it makes the if statement unconditional. Signed-off-by: Dan Carpenter Signed-off-by: Keith Packard --- drivers/char/agp/intel-gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 66cd0b8096ca..3a8d44886010 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1236,7 +1236,7 @@ static int i9xx_setup(void) intel_private.gtt_bus_addr = reg_addr + gtt_offset; } - if (needs_idle_maps()); + if (needs_idle_maps()) intel_private.base.do_idle_maps = 1; intel_i9xx_setup_flush(); -- cgit From c5e62bdd73da80e1017058c923336a5a150af9f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 28 Oct 2011 10:28:00 -0700 Subject: agp: iommu_gfx_mapped only available if CONFIG_INTEL_IOMMU is set Kernels with no iommu support cannot ever need the Ironlake work-around, so never enable it in that case. Might be better to completely remove the work-around from the kernel in this case? Signed-off-by: Keith Packard Reviewed-by: Ben Widawsky --- drivers/char/agp/intel-gtt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 3a8d44886010..c92424ca1a55 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1186,10 +1186,11 @@ static void gen6_cleanup(void) /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. */ -extern int intel_iommu_gfx_mapped; static inline int needs_idle_maps(void) { +#ifdef CONFIG_INTEL_IOMMU const unsigned short gpu_devid = intel_private.pcidev->device; + extern int intel_iommu_gfx_mapped; /* Query intel_iommu to see if we need the workaround. Presumably that * was loaded first. @@ -1198,7 +1199,7 @@ static inline int needs_idle_maps(void) gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && intel_iommu_gfx_mapped) return 1; - +#endif return 0; } -- cgit From f0eb824beee3f596b9799e667a6fdac3116e9f7d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 14 Oct 2011 15:31:59 +0200 Subject: gpio: pca953x: remove unneeded check for chip type We can assume our own device_id table is correct, so remove checking if the chip type is valid. (The check was bogus anyway: If it found an invalid entry, it returned with 0!) This is in preparation for further cleanups. Signed-off-by: Wolfram Sang Cc: Grant Likely Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c43b8ff626a7..45de6a4ac632 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -673,10 +673,8 @@ static int __devinit pca953x_probe(struct i2c_client *client, if (chip->chip_type == PCA953X_TYPE) device_pca953x_init(chip, invert); - else if (chip->chip_type == PCA957X_TYPE) - device_pca957x_init(chip, invert); else - goto out_failed; + device_pca957x_init(chip, invert); ret = pca953x_irq_setup(chip, id, irq_base); if (ret) -- cgit From 7ea2aa2046a15af1c048115e7c05f1ba1566899d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 14 Oct 2011 15:32:00 +0200 Subject: gpio: pca953x: propagate the errno from the chip_init functions Initializing the chips may return with an error, but this error gets dropped in probe(). Propagate this further to the driver core. Also, simplify returning the error in one of the init functions. Signed-off-by: Wolfram Sang Cc: Grant Likely Signed-off-by: Grant Likely --- drivers/gpio/gpio-pca953x.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 45de6a4ac632..a3fef0c94ba6 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -595,9 +595,6 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) /* set platform specific polarity inversion */ ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); - if (ret) - goto out; - return 0; out: return ret; } @@ -639,7 +636,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, struct pca953x_platform_data *pdata; struct pca953x_chip *chip; int irq_base=0, invert=0; - int ret = 0; + int ret; chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) @@ -672,9 +669,11 @@ static int __devinit pca953x_probe(struct i2c_client *client, pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK); if (chip->chip_type == PCA953X_TYPE) - device_pca953x_init(chip, invert); + ret = device_pca953x_init(chip, invert); else - device_pca957x_init(chip, invert); + ret = device_pca957x_init(chip, invert); + if (ret) + goto out_failed; ret = pca953x_irq_setup(chip, id, irq_base); if (ret) -- cgit From 0d52f54e2ef64c189dedc332e680b2eb4a34590a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 22 Oct 2011 00:43:38 +0200 Subject: PCI / ACPI: Make acpiphp ignore root bridges using PCIe native hotplug If the kernel has requested control of the PCIe native hotplug feature for a given root complex, the acpiphp driver should not try to handle that root complex and it should leave it to pciehp. Failing to do so causes problems to happen if acpiphp is loaded before pciehp on such systems. To address this issue make find_root_bridges() ignore PCIe root complexes with PCIe native hotplug enabled and make add_bridge() return error code if PCIe native hotplug is enabled for the given root port. This causes acpiphp to refuse to load if PCIe native hotplug is enabled for all complexes and to refuse binding to the root complexes with PCIe native hotplug is enabled. Acked-by: Kenji Kaneshige Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpiphp_glue.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 596172b4ae95..fce1c54a0c8d 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -459,8 +459,17 @@ static int add_bridge(acpi_handle handle) { acpi_status status; unsigned long long tmp; + struct acpi_pci_root *root; acpi_handle dummy_handle; + /* + * We shouldn't use this bridge if PCIe native hotplug control has been + * granted by the BIOS for it. + */ + root = acpi_pci_find_root(handle); + if (root && (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) + return -ENODEV; + /* if the bridge doesn't have _STA, we assume it is always there */ status = acpi_get_handle(handle, "_STA", &dummy_handle); if (ACPI_SUCCESS(status)) { @@ -1376,13 +1385,23 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, static acpi_status find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { + struct acpi_pci_root *root; int *count = (int *)context; - if (acpi_is_root_bridge(handle)) { - acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_bridge, NULL); - (*count)++; - } + if (!acpi_is_root_bridge(handle)) + return AE_OK; + + root = acpi_pci_find_root(handle); + if (!root) + return AE_OK; + + if (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) + return AE_OK; + + (*count)++; + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge, NULL); + return AE_OK ; } -- cgit From 466b3ddfbcf4f5ce402a77397630a0fa9ea9ce6b Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Sun, 30 Oct 2011 16:35:08 +0100 Subject: PCI: Fix compile errors with PCI_ATS and !PCI_IOV The ats and sroiv members of 'struct pci_dev' are required for the ATS code already, even without IOV support compiled in. So depend on ATS here. This is fine with PCI_IOV too because it selects PCI_ATS. Also the prototypes for ATS need to be available for PCI_ATS. Reported-by: Randy Dunlap Signed-off-by: Joerg Roedel Signed-off-by: Jesse Barnes --- include/linux/pci-ats.h | 6 +++--- include/linux/pci.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index e3d0b3890249..7ef68724f0f0 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -12,7 +12,7 @@ struct pci_ats { unsigned int is_enabled:1; /* Enable bit is set */ }; -#ifdef CONFIG_PCI_IOV +#ifdef CONFIG_PCI_ATS extern int pci_enable_ats(struct pci_dev *dev, int ps); extern void pci_disable_ats(struct pci_dev *dev); @@ -29,7 +29,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev) return dev->ats && dev->ats->is_enabled; } -#else /* CONFIG_PCI_IOV */ +#else /* CONFIG_PCI_ATS */ static inline int pci_enable_ats(struct pci_dev *dev, int ps) { @@ -50,7 +50,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev) return 0; } -#endif /* CONFIG_PCI_IOV */ +#endif /* CONFIG_PCI_ATS */ #ifdef CONFIG_PCI_PRI diff --git a/include/linux/pci.h b/include/linux/pci.h index 337df0d5d5f7..7cda65b5f798 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -338,7 +338,7 @@ struct pci_dev { struct list_head msi_list; #endif struct pci_vpd *vpd; -#ifdef CONFIG_PCI_IOV +#ifdef CONFIG_PCI_ATS union { struct pci_sriov *sriov; /* SR-IOV capability related */ struct pci_dev *physfn; /* the PF this VF is associated with */ -- cgit From c54420d3302d30999060e2669d0800b85e5b5a20 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Sun, 30 Oct 2011 16:35:07 +0100 Subject: PCI: Let PCI_PRI depend on PCI This avoids the PCI_PRI question in 'make config' when PCI is not selected. Reported-by: Geert Uytterhoeven Signed-off-by: Joerg Roedel Signed-off-by: Jesse Barnes --- drivers/pci/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index cec66064ee4b..8252fc3430bd 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -87,6 +87,7 @@ config PCI_IOV config PCI_PRI bool "PCI PRI support" + depends on PCI select PCI_ATS help PRI is the PCI Page Request Interface. It allows PCI devices that are -- cgit From 51ce185af0f71b65c23ed719f72d0241895a61da Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 1 Nov 2011 00:51:30 -0700 Subject: sparc: Hook up process_vm_{readv,writev} syscalls. Signed-off-by: David S. Miller --- arch/sparc/include/asm/unistd.h | 4 +++- arch/sparc/kernel/systbls_32.S | 2 +- arch/sparc/kernel/systbls_64.S | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 6260d5deeabc..c7cb0af0eb59 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -406,8 +406,10 @@ #define __NR_syncfs 335 #define __NR_sendmmsg 336 #define __NR_setns 337 +#define __NR_process_vm_readv 338 +#define __NR_process_vm_writev 339 -#define NR_syscalls 338 +#define NR_syscalls 340 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 09d8ec454450..63402f9e9f51 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -84,4 +84,4 @@ sys_call_table: /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime -/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns +/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index edbec45d4688..db86b1a0e9a9 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -85,7 +85,7 @@ sys_call_table32: /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime - .word sys_syncfs, compat_sys_sendmmsg, sys_setns + .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev #endif /* CONFIG_COMPAT */ @@ -162,4 +162,4 @@ sys_call_table: /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime - .word sys_syncfs, sys_sendmmsg, sys_setns + .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev -- cgit From 627f7675f0f530ea555d76543dc4e469d70a1532 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Oct 2011 11:30:10 -0700 Subject: drm/i915: Use mode_config.mutex in ironlake_panel_vdd_work Use of the struct_mutex is not correct for locking in mode setting paths. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fc1a0832af4f..7259034b33d1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -971,9 +971,9 @@ static void ironlake_panel_vdd_work(struct work_struct *__work) struct intel_dp, panel_vdd_work); struct drm_device *dev = intel_dp->base.base.dev; - mutex_lock(&dev->struct_mutex); + mutex_lock(&dev->mode_config.mutex); ironlake_panel_vdd_off_sync(intel_dp); - mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->mode_config.mutex); } static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) -- cgit From ff56b0bc84c01fb2c5d2ec6438becfe0f5f2f78f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 31 Oct 2011 23:16:21 -0700 Subject: drm/i915: Fix object refcount leak on mmappable size limit error path. I've been seeing memory leaks on my system in the form of large (300-400MB) GEM objects created by now-dead processes laying around clogging up memory. I usually notice when it gets to about 1.2GB of them. Hopefully this clears up the issue, but I just found this bug by inspection. Signed-off-by: Eric Anholt Cc: stable@kernel.org Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6651c36b6e8a..d18b07adcffa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1396,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file, if (obj->base.size > dev_priv->mm.gtt_mappable_end) { ret = -E2BIG; - goto unlock; + goto out; } if (obj->madv != I915_MADV_WILLNEED) { -- cgit From fb223c32b4d3ee593c8dce07e983680d06abe387 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 2 Nov 2011 09:15:16 +1100 Subject: crypto: user - Fix rwsem leak in crypto_user The list_empty case in crypto_alg_match() will return without calling up_read() on crypto_alg_sem. We could do the "goto out" routine, but the function will clearly do the right thing with that test simply removed. Signed-off-by: Jonathan Corbet Signed-off-by: Herbert Xu --- crypto/crypto_user.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 2abca780312d..0605a2bbba75 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -44,9 +44,6 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) down_read(&crypto_alg_sem); - if (list_empty(&crypto_alg_list)) - return NULL; - list_for_each_entry(q, &crypto_alg_list, cra_list) { int match = 0; -- cgit From 47a6770ac6cd0d28f14dd9e1b17705abe6f05e41 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 25 Oct 2011 09:35:19 -0700 Subject: msm: boards: Fix fallout from removal of machine_desc in fixup After 0744a3ee (ARM: platform fixups: remove mdesc argument to fixup function, 2010-12-20) the fixup functions introduced in 9e775ad (ARM: 7012/1: Set proper TEXT_OFFSET for newer MSMs, 2011-08-12) cause warnings like: arch/arm/mach-msm/board-msm8x60.c:85: warning: initialization from incompatible pointer type Fix them by removing the machine_desc argument from the fixup functions. Signed-off-by: Stephen Boyd Signed-off-by: David Brown --- arch/arm/mach-msm/board-msm7x30.c | 4 ++-- arch/arm/mach-msm/board-msm8960.c | 4 ++-- arch/arm/mach-msm/board-msm8x60.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 71de5062c71e..db81ed531031 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -42,8 +42,8 @@ extern struct sys_timer msm_timer; -static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tag, - char **cmdline, struct meminfo *mi) +static void __init msm7x30_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) { for (; tag->hdr.size; tag = tag_next(tag)) if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) { diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c index b04468e7d00e..6dc1cbd2a595 100644 --- a/arch/arm/mach-msm/board-msm8960.c +++ b/arch/arm/mach-msm/board-msm8960.c @@ -32,8 +32,8 @@ #include "devices.h" -static void __init msm8960_fixup(struct machine_desc *desc, struct tag *tag, - char **cmdline, struct meminfo *mi) +static void __init msm8960_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) { for (; tag->hdr.size; tag = tag_next(tag)) if (tag->hdr.tag == ATAG_MEM && diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index 106170fb1844..eed73e2609ed 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -30,8 +30,8 @@ #include #include -static void __init msm8x60_fixup(struct machine_desc *desc, struct tag *tag, - char **cmdline, struct meminfo *mi) +static void __init msm8x60_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) { for (; tag->hdr.size; tag = tag_next(tag)) if (tag->hdr.tag == ATAG_MEM && -- cgit From f43d623164022dcbf6750ef220b7a1133a1183eb Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Thu, 20 Oct 2011 23:52:14 -0400 Subject: usb, xhci: fix lockdep warning on endpoint timeout While debugging a usb3 problem, I stumbled upon this lockdep warning. Oct 18 21:41:17 dhcp47-74 kernel: ================================= Oct 18 21:41:17 dhcp47-74 kernel: [ INFO: inconsistent lock state ] Oct 18 21:41:17 dhcp47-74 kernel: 3.1.0-rc4nmi+ #456 Oct 18 21:41:17 dhcp47-74 kernel: --------------------------------- Oct 18 21:41:17 dhcp47-74 kernel: inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. Oct 18 21:41:17 dhcp47-74 kernel: swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: Oct 18 21:41:17 dhcp47-74 kernel: (&(&xhci->lock)->rlock){?.-...}, at: [] xhci_stop_endpoint_command_watchdog+0x30/0x340 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: {IN-HARDIRQ-W} state was registered at: Oct 18 21:41:17 dhcp47-74 kernel: [] __lock_acquire+0x781/0x1660 Oct 18 21:41:17 dhcp47-74 kernel: [] lock_acquire+0x97/0x170 Oct 18 21:41:17 dhcp47-74 kernel: [] _raw_spin_lock+0x46/0x80 Oct 18 21:41:17 dhcp47-74 kernel: [] xhci_irq+0x3a/0x1960 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] xhci_msi_irq+0x31/0x40 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] handle_irq_event_percpu+0x85/0x320 Oct 18 21:41:17 dhcp47-74 kernel: [] handle_irq_event+0x48/0x70 Oct 18 21:41:17 dhcp47-74 kernel: [] handle_edge_irq+0x6d/0x130 Oct 18 21:41:17 dhcp47-74 kernel: [] handle_irq+0x49/0xa0 Oct 18 21:41:17 dhcp47-74 kernel: [] do_IRQ+0x5d/0xe0 Oct 18 21:41:17 dhcp47-74 kernel: [] ret_from_intr+0x0/0x13 Oct 18 21:41:17 dhcp47-74 kernel: [] usb_set_device_state+0x8a/0x180 Oct 18 21:41:17 dhcp47-74 kernel: [] usb_add_hcd+0x2b8/0x730 Oct 18 21:41:17 dhcp47-74 kernel: [] xhci_pci_probe+0x9e/0xd4 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] local_pci_probe+0x5f/0xd0 Oct 18 21:41:17 dhcp47-74 kernel: [] pci_device_probe+0x119/0x120 Oct 18 21:41:17 dhcp47-74 kernel: [] driver_probe_device+0xa3/0x2c0 Oct 18 21:41:17 dhcp47-74 kernel: [] __driver_attach+0xab/0xb0 Oct 18 21:41:17 dhcp47-74 kernel: [] bus_for_each_dev+0x6c/0xa0 Oct 18 21:41:17 dhcp47-74 kernel: [] driver_attach+0x1e/0x20 Oct 18 21:41:17 dhcp47-74 kernel: [] bus_add_driver+0x1f8/0x2b0 Oct 18 21:41:17 dhcp47-74 kernel: [] driver_register+0x76/0x140 Oct 18 21:41:17 dhcp47-74 kernel: [] __pci_register_driver+0x66/0xe0 Oct 18 21:41:17 dhcp47-74 kernel: [] snd_timer_find+0x4a/0x70 [snd_timer] Oct 18 21:41:17 dhcp47-74 kernel: [] snd_timer_find+0xe/0x70 [snd_timer] Oct 18 21:41:17 dhcp47-74 kernel: [] do_one_initcall+0x43/0x180 Oct 18 21:41:17 dhcp47-74 kernel: [] sys_init_module+0x92/0x1f0 Oct 18 21:41:17 dhcp47-74 kernel: [] system_call_fastpath+0x16/0x1b Oct 18 21:41:17 dhcp47-74 kernel: irq event stamp: 631984 Oct 18 21:41:17 dhcp47-74 kernel: hardirqs last enabled at (631984): [] _raw_spin_unlock_irq+0x30/0x50 Oct 18 21:41:17 dhcp47-74 kernel: hardirqs last disabled at (631983): [] _raw_spin_lock_irq+0x19/0x90 Oct 18 21:41:17 dhcp47-74 kernel: softirqs last enabled at (631980): [] _local_bh_enable+0x13/0x20 Oct 18 21:41:17 dhcp47-74 kernel: softirqs last disabled at (631981): [] call_softirq+0x1c/0x30 Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: other info that might help us debug this: Oct 18 21:41:17 dhcp47-74 kernel: Possible unsafe locking scenario: Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: CPU0 Oct 18 21:41:17 dhcp47-74 kernel: ---- Oct 18 21:41:17 dhcp47-74 kernel: lock(&(&xhci->lock)->rlock); Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: lock(&(&xhci->lock)->rlock); Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: *** DEADLOCK *** Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: 1 lock held by swapper/0: Oct 18 21:41:17 dhcp47-74 kernel: #0: (&ep->stop_cmd_timer){+.-...}, at: [] run_timer_softirq+0x162/0x570 Oct 18 21:41:17 dhcp47-74 kernel: Oct 18 21:41:17 dhcp47-74 kernel: stack backtrace: Oct 18 21:41:17 dhcp47-74 kernel: Pid: 0, comm: swapper Tainted: G W 3.1.0-rc4nmi+ #456 Oct 18 21:41:17 dhcp47-74 kernel: Call Trace: Oct 18 21:41:17 dhcp47-74 kernel: [] print_usage_bug+0x227/0x270 Oct 18 21:41:17 dhcp47-74 kernel: [] mark_lock+0x346/0x410 Oct 18 21:41:17 dhcp47-74 kernel: [] __lock_acquire+0x61e/0x1660 Oct 18 21:41:17 dhcp47-74 kernel: [] ? mark_lock+0x213/0x410 Oct 18 21:41:17 dhcp47-74 kernel: [] lock_acquire+0x97/0x170 Oct 18 21:41:17 dhcp47-74 kernel: [] ? xhci_stop_endpoint_command_watchdog+0x30/0x340 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] _raw_spin_lock+0x46/0x80 Oct 18 21:41:17 dhcp47-74 kernel: [] ? xhci_stop_endpoint_command_watchdog+0x30/0x340 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] xhci_stop_endpoint_command_watchdog+0x30/0x340 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] ? run_timer_softirq+0x162/0x570 Oct 18 21:41:17 dhcp47-74 kernel: [] run_timer_softirq+0x20d/0x570 Oct 18 21:41:17 dhcp47-74 kernel: [] ? run_timer_softirq+0x162/0x570 Oct 18 21:41:17 dhcp47-74 kernel: [] ? xhci_queue_isoc_tx_prepare+0x8e0/0x8e0 [xhci_hcd] Oct 18 21:41:17 dhcp47-74 kernel: [] __do_softirq+0xf2/0x3f0 Oct 18 21:41:17 dhcp47-74 kernel: [] ? lapic_next_event+0x1d/0x30 Oct 18 21:41:17 dhcp47-74 kernel: [] ? clockevents_program_event+0x5e/0x90 Oct 18 21:41:17 dhcp47-74 kernel: [] call_softirq+0x1c/0x30 Oct 18 21:41:17 dhcp47-74 kernel: [] do_softirq+0x8d/0xc0 Oct 18 21:41:17 dhcp47-74 kernel: [] irq_exit+0xe5/0x100 Oct 18 21:41:17 dhcp47-74 kernel: [] smp_apic_timer_interrupt+0x6e/0x99 Oct 18 21:41:17 dhcp47-74 kernel: [] apic_timer_interrupt+0x70/0x80 Oct 18 21:41:17 dhcp47-74 kernel: [] ? trace_hardirqs_off+0xd/0x10 Oct 18 21:41:17 dhcp47-74 kernel: [] ? acpi_idle_enter_bm+0x227/0x25b Oct 18 21:41:17 dhcp47-74 kernel: [] ? acpi_idle_enter_bm+0x222/0x25b Oct 18 21:41:17 dhcp47-74 kernel: [] cpuidle_idle_call+0x103/0x290 Oct 18 21:41:17 dhcp47-74 kernel: [] cpu_idle+0xe5/0x160 Oct 18 21:41:17 dhcp47-74 kernel: [] rest_init+0xe0/0xf0 Oct 18 21:41:17 dhcp47-74 kernel: [] ? csum_partial_copy_generic+0x170/0x170 Oct 18 21:41:17 dhcp47-74 kernel: [] start_kernel+0x3fc/0x407 Oct 18 21:41:17 dhcp47-74 kernel: [] x86_64_start_reservations+0x131/0x135 Oct 18 21:41:17 dhcp47-74 kernel: [] x86_64_start_kernel+0xed/0xf4 Oct 18 21:41:17 dhcp47-74 kernel: xhci_hcd 0000:00:14.0: xHCI host not responding to stop endpoint command. Oct 18 21:41:17 dhcp47-74 kernel: xhci_hcd 0000:00:14.0: Assuming host is dying, halting host. Oct 18 21:41:17 dhcp47-74 kernel: xhci_hcd 0000:00:14.0: HC died; cleaning up Oct 18 21:41:17 dhcp47-74 kernel: usb 3-4: device descriptor read/8, error -110 Oct 18 21:41:17 dhcp47-74 kernel: usb 3-4: device descriptor read/8, error -22 Oct 18 21:41:17 dhcp47-74 kernel: hub 3-0:1.0: cannot disable port 4 (err = -19) Basically what is happening is in xhci_stop_endpoint_command_watchdog() the xhci->lock is grabbed with just spin_lock. What lockdep deduces is that if an interrupt occurred while in this function it would deadlock with xhci_irq because that function also grabs the xhci->lock. Fixing it is trivial by using spin_lock_irqsave instead. This should be queued to stable kernels as far back as 2.6.33. Signed-off-by: Don Zickus Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci-ring.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 940321b3ec68..9f1d4b15d818 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -816,23 +816,24 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) struct xhci_ring *ring; struct xhci_td *cur_td; int ret, i, j; + unsigned long flags; ep = (struct xhci_virt_ep *) arg; xhci = ep->xhci; - spin_lock(&xhci->lock); + spin_lock_irqsave(&xhci->lock, flags); ep->stop_cmds_pending--; if (xhci->xhc_state & XHCI_STATE_DYING) { xhci_dbg(xhci, "Stop EP timer ran, but another timer marked " "xHCI as DYING, exiting.\n"); - spin_unlock(&xhci->lock); + spin_unlock_irqrestore(&xhci->lock, flags); return; } if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) { xhci_dbg(xhci, "Stop EP timer ran, but no command pending, " "exiting.\n"); - spin_unlock(&xhci->lock); + spin_unlock_irqrestore(&xhci->lock, flags); return; } @@ -844,11 +845,11 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) xhci->xhc_state |= XHCI_STATE_DYING; /* Disable interrupts from the host controller and start halting it */ xhci_quiesce(xhci); - spin_unlock(&xhci->lock); + spin_unlock_irqrestore(&xhci->lock, flags); ret = xhci_halt(xhci); - spin_lock(&xhci->lock); + spin_lock_irqsave(&xhci->lock, flags); if (ret < 0) { /* This is bad; the host is not responding to commands and it's * not allowing itself to be halted. At least interrupts are @@ -896,7 +897,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) } } } - spin_unlock(&xhci->lock); + spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg(xhci, "Calling usb_hc_died()\n"); usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); xhci_dbg(xhci, "xHCI host controller is dead.\n"); -- cgit From 86f14df8ed1ecec5cefe7d002b4d297e298238c2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 Nov 2011 21:36:32 +0000 Subject: ASoC: Update git repository URL Remove the -2.6 from the name. Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index bbf42cd74e2a..63b58dd1561e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6001,7 +6001,7 @@ F: sound/ SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) M: Liam Girdwood M: Mark Brown -T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://alsa-project.org/main/index.php/ASoC S: Supported -- cgit From c75d720fca8a91ce99196d33adea383621027bf2 Mon Sep 17 00:00:00 2001 From: Edward Donovan Date: Tue, 1 Nov 2011 15:29:44 -0400 Subject: genirq: Fix irqfixup, irqpoll regression commit d05c65fff0 ("genirq: spurious: Run only one poller at a time") introduced a regression, leaving the boot options 'irqfixup' and 'irqpoll' non-functional. The patch placed tests in each function, to exit if the function is already running. The test in 'misrouted_irq' exited when it should have proceeded, effectively disabling 'misrouted_irq' and 'poll_spurious_irqs'. The check for an already running poller needs to be "!= 1" not "== 1" as "1" is the value when the first poller starts running. Signed-off-by: Edward Donovan Cc: maciej.rutecki@gmail.com Link: http://lkml.kernel.org/r/1320175784-6745-1-git-send-email-edward.donovan@numble.net Cc: stable@vger.kernel.org # >= 2.6.39 Signed-off-by: Thomas Gleixner --- kernel/irq/spurious.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index aa57d5da18c1..b5f4742693c0 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -115,7 +115,7 @@ static int misrouted_irq(int irq) struct irq_desc *desc; int i, ok = 0; - if (atomic_inc_return(&irq_poll_active) == 1) + if (atomic_inc_return(&irq_poll_active) != 1) goto out; irq_poll_cpu = smp_processor_id(); -- cgit From 616fdb5afb12b4d5bb9e36df40d039e86aaaefc2 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 5 Oct 2011 11:44:54 -0700 Subject: drm/i915: forcewake warning fixes in debugfs Some more unsafe debugfs access are fixed with this patch. I tested all reads, but didn't thoroughly test the writes. Cc: "Nicolas Kalkhof" Signed-off-by: Ben Widawsky Reviewed-by: Daniel Vetter Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 57 +++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8e95d66800b0..f2e02075d510 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -635,11 +635,16 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; + int ret; ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; if (ring->size == 0) return 0; + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + seq_printf(m, "Ring %s:\n", ring->name); seq_printf(m, " Head : %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR); seq_printf(m, " Tail : %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR); @@ -653,6 +658,8 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) seq_printf(m, " Control : %08x\n", I915_READ_CTL(ring)); seq_printf(m, " Start : %08x\n", I915_READ_START(ring)); + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -841,7 +848,16 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - u16 crstanddelay = I915_READ16(CRSTANDVID); + u16 crstanddelay; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + crstanddelay = I915_READ16(CRSTANDVID); + + mutex_unlock(&dev->struct_mutex); seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f)); @@ -939,7 +955,11 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; u32 delayfreq; - int i; + int ret, i; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; for (i = 0; i < 16; i++) { delayfreq = I915_READ(PXVFREQ_BASE + i * 4); @@ -947,6 +967,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused) (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT); } + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -961,13 +983,19 @@ static int i915_inttoext_table(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; u32 inttoext; - int i; + int ret, i; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; for (i = 1; i <= 32; i++) { inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4); seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext); } + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -976,9 +1004,19 @@ static int i915_drpc_info(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - u32 rgvmodectl = I915_READ(MEMMODECTL); - u32 rstdbyctl = I915_READ(RSTDBYCTL); - u16 crstandvid = I915_READ16(CRSTANDVID); + u32 rgvmodectl, rstdbyctl; + u16 crstandvid; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + rgvmodectl = I915_READ(MEMMODECTL); + rstdbyctl = I915_READ(RSTDBYCTL); + crstandvid = I915_READ16(CRSTANDVID); + + mutex_unlock(&dev->struct_mutex); seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? "yes" : "no"); @@ -1166,9 +1204,16 @@ static int i915_gfxec(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4)); + mutex_unlock(&dev->struct_mutex); + return 0; } -- cgit From 775d17b6ca4357048f36c22151335addfe15db4b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 9 Oct 2011 21:52:01 +0200 Subject: drm/i915: Ivybridge still has fences! So don't forget to restore them on resume and dump them into the error state. Cc: stable@kernel.org Signed-off-by: Daniel Vetter Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_suspend.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9ee2729fe5c6..b40004b55977 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -824,6 +824,7 @@ static void i915_gem_record_fences(struct drm_device *dev, /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index f8f602d76650..7886e4fb60e3 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); @@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); -- cgit From 4b9de737fad5bd8993e6070530802de22f32744d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 9 Oct 2011 21:52:02 +0200 Subject: drm/i915: add constants to size fence arrays and fields In preparation of to support 32 fences on Ivybdrigde. Signed-Off-by: Daniel Vetter Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.h | 15 ++++++++------- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 06a37f4fd74b..d2da91f90252 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -126,6 +126,9 @@ struct drm_i915_master_private { struct _drm_i915_sarea *sarea_priv; }; #define I915_FENCE_REG_NONE -1 +#define I915_MAX_NUM_FENCES 16 +/* 16 fences + sign bit for FENCE_REG_NONE */ +#define I915_MAX_NUM_FENCE_BITS 5 struct drm_i915_fence_reg { struct list_head lru_list; @@ -168,7 +171,7 @@ struct drm_i915_error_state { u32 instdone1; u32 seqno; u64 bbaddr; - u64 fence[16]; + u64 fence[I915_MAX_NUM_FENCES]; struct timeval time; struct drm_i915_error_object { int page_count; @@ -182,7 +185,7 @@ struct drm_i915_error_state { u32 gtt_offset; u32 read_domains; u32 write_domain; - s32 fence_reg:5; + s32 fence_reg:I915_MAX_NUM_FENCE_BITS; s32 pinned:2; u32 tiling:2; u32 dirty:1; @@ -375,7 +378,7 @@ typedef struct drm_i915_private { struct notifier_block lid_notifier; int crt_ddc_pin; - struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ + struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */ @@ -506,7 +509,7 @@ typedef struct drm_i915_private { u8 saveAR[21]; u8 saveDACMASK; u8 saveCR[37]; - uint64_t saveFENCE[16]; + uint64_t saveFENCE[I915_MAX_NUM_FENCES]; u32 saveCURACNTR; u32 saveCURAPOS; u32 saveCURABASE; @@ -777,10 +780,8 @@ struct drm_i915_gem_object { * Fence register bits (if any) for this object. Will be set * as needed when mapped into the GTT. * Protected by dev->struct_mutex. - * - * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE) */ - signed int fence_reg:5; + signed int fence_reg:I915_MAX_NUM_FENCE_BITS; /** * Advice: are the backing pages purgeable? diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d18b07adcffa..a83859767d48 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1745,7 +1745,7 @@ static void i915_gem_reset_fences(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int i; - for (i = 0; i < 16; i++) { + for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; struct drm_i915_gem_object *obj = reg->obj; @@ -3877,7 +3877,7 @@ i915_gem_load(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.gtt_list); for (i = 0; i < I915_NUM_RINGS; i++) init_ring_lists(&dev_priv->ring[i]); - for (i = 0; i < 16; i++) + for (i = 0; i < I915_MAX_NUM_FENCES; i++) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); -- cgit From a918feef334090692ea65e77a8b0cca5e682e666 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 2 Nov 2011 17:30:49 +0000 Subject: ARM: mxc: fix local timer interrupt handling As local timer interrupts are now handled as normal interrupts, remove the special case in the GIC handler. Cc: Shawn Guo Cc: Sascha Hauer Signed-off-by: Marc Zyngier Tested-and-Acked-by: Shawn Guo --- arch/arm/plat-mxc/gic.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/arch/arm/plat-mxc/gic.c b/arch/arm/plat-mxc/gic.c index b3b8eed263b8..12f8f8109010 100644 --- a/arch/arm/plat-mxc/gic.c +++ b/arch/arm/plat-mxc/gic.c @@ -28,21 +28,14 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) if (irqnr == 1023) break; - if (irqnr > 29 && irqnr < 1021) + if (irqnr > 15 && irqnr < 1021) handle_IRQ(irqnr, regs); #ifdef CONFIG_SMP - else if (irqnr < 16) { + else { writel_relaxed(irqstat, gic_cpu_base_addr + GIC_CPU_EOI); handle_IPI(irqnr, regs); } -#endif -#ifdef CONFIG_LOCAL_TIMERS - else if (irqnr == 29) { - writel_relaxed(irqstat, gic_cpu_base_addr + - GIC_CPU_EOI); - handle_local_timer(regs); - } #endif } while (1); } -- cgit From 98de0cbbe2e7157fd87d04386621be3eadd4d6ab Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 3 Nov 2011 17:31:26 +0800 Subject: ARM:i.MX: fix build error in tzic/avic.c arch/arm/plat-mxc/tzic.c:105: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'tzic_handle_irq' Signed-off-by: Jason Liu --- arch/arm/plat-mxc/avic.c | 1 + arch/arm/plat-mxc/tzic.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c index 8875fb415f68..55f15699a383 100644 --- a/arch/arm/plat-mxc/avic.c +++ b/arch/arm/plat-mxc/avic.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "irq-common.h" diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c index e993a184189a..a3c164c7ba82 100644 --- a/arch/arm/plat-mxc/tzic.c +++ b/arch/arm/plat-mxc/tzic.c @@ -17,6 +17,7 @@ #include #include +#include #include #include -- cgit From 188d7c6b0cfee134cc7fbc61d36223b1d7dfffab Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Thu, 3 Nov 2011 17:31:27 +0800 Subject: ARM:i.MX: fix build error in clock-mx51-mx53.c arch/arm/mach-mx5/clock-mx51-mx53.c: In function 'clk_get_freq_dt': arch/arm/mach-mx5/clock-mx51-mx53.c:1643: error: implicit declaration of function 'for_each_compatible_node' arch/arm/mach-mx5/clock-mx51-mx53.c:1643: error: expected ';' before '{' token Signed-off-by: Jason Liu --- arch/arm/mach-mx5/clock-mx51-mx53.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index 2aacf41c48e7..6312425c0056 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -1634,6 +1634,7 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, return 0; } +#ifdef CONFIG_OF static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc, unsigned long *ckih1, unsigned long *ckih2) { @@ -1671,3 +1672,4 @@ int __init mx53_clocks_init_dt(void) clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); return mx53_clocks_init(ckil, osc, ckih1, ckih2); } +#endif -- cgit From a9866a0975881ba5e819b0a02324ba683b5cdb81 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 21 Oct 2011 11:53:34 +0800 Subject: MAINTAINERS: add ARM/FREESCALE MXS entry As suggested by Pengutronix, they want to get Sascha relieved from the burden of maintaining MXS sub-architecture. Since I brought the most of MXS core code to mainline (with the great help from Pengutronix people, thanks!), I would like to step up for maintaining MXS. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ab7767001286..8fe3f0184990 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -804,6 +804,13 @@ S: Maintained T: git git://git.linaro.org/people/shawnguo/linux-2.6.git F: arch/arm/mach-imx/*imx6* +ARM/FREESCALE MXS ARM ARCHITECTURE +M: Shawn Guo +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +T: git git://git.linaro.org/people/shawnguo/linux-2.6.git +F: arch/arm/mach-mxs/ + ARM/GLOMATION GESBC9312SX MACHINE SUPPORT M: Lennert Buytenhek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- cgit From 680da876f44a644aee891e1d0df5a560cfa4720e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 3 Nov 2011 14:15:13 -0700 Subject: drm/i915: enable cacheable objects on Ivybridge IVB supports these bits as well. Signed-off-by: Jesse Barnes Reviewed-by: Daniel Vetter Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a83859767d48..ed0b68fdb970 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3613,7 +3613,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->base.read_domains = I915_GEM_DOMAIN_CPU; - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { /* On Gen6, we can have the GPU use the LLC (the CPU * cache) for about a 10% performance improvement * compared to uncached. Graphics requests other than -- cgit From 15394cad2747ea2d98fc88ccb464973e173cd2f8 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Fri, 4 Nov 2011 20:30:18 +0800 Subject: ARM: mxc: Remove test_for_ltirq The patch "ARM: gic: consolidate PPI handling" removes the usage of test_for_ltirq. After the merge of imx6q remove this there, too. Cc: Sascha Hauer Signed-off-by: Dirk Behme Acked-by: Shawn Guo Acked-by: Marc Zyngier --- arch/arm/plat-mxc/include/mach/entry-macro.S | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index 9fe0dfcf4e7e..ca5cf26a04b1 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S @@ -25,6 +25,3 @@ .macro test_for_ipi, irqnr, irqstat, base, tmp .endm - - .macro test_for_ltirq, irqnr, irqstat, base, tmp - .endm -- cgit From dfd3b596fbbfa48b8e7966ef996d587157554b69 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 4 Nov 2011 22:13:50 +0900 Subject: sh: Fix cached/uncaced address calculation in 29bit mode In the case of 29bit mode, CAC/UNCAC_ADDR does not return a right address. This revises this problem by using P1SEGADDR and P2SEGADDR in 29bit mode. Reported-by: Yutaro Ebihara Signed-off-by: Nobuhiro Iwamatsu Tested-by: Kuninori Morimoto Tested-by: Simon Horman Cc: stable@kernel.org Signed-off-by: Paul Mundt --- arch/sh/include/asm/page.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 0dca9a5c6be6..15d970328f71 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -151,8 +151,13 @@ typedef struct page *pgtable_t; #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_UNCACHED_MAPPING +#if defined(CONFIG_29BIT) +#define UNCAC_ADDR(addr) P2SEGADDR(addr) +#define CAC_ADDR(addr) P1SEGADDR(addr) +#else #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + uncached_start) #define CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET) +#endif #else #define UNCAC_ADDR(addr) ((addr)) #define CAC_ADDR(addr) ((addr)) -- cgit From 3af1f8a41feab47b232b0c3d3b2322426672480d Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Mon, 3 Oct 2011 15:16:47 +0100 Subject: serial: sh-sci: Fix up SH-2A SCIF support. This fixes up support for SH-2(A) SCIFs by introducing a new regtype. As expected, it's close to the SH-4A SCIF with fifodata, but still different enough to warrant its own type. Fixes up a number of FIFO overflows and similar for both SH7203/SH7264. Signed-off-by: Phil Edworthy Tested-by: Federico Fuga Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 16 ++++++++++++---- drivers/tty/serial/sh-sci.c | 19 +++++++++++++++++++ include/linux/serial_sci.h | 1 + 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index a43124e608c3..0bd744f9a3b7 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -176,10 +176,12 @@ static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups, static struct plat_sci_port scif0_platform_data = { .mapbase = 0xfffe8000, .flags = UPF_BOOT_AUTOCONF, - .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, + .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE | + SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 192, 192, 192, 192 }, + .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif0_device = { @@ -193,10 +195,12 @@ static struct platform_device scif0_device = { static struct plat_sci_port scif1_platform_data = { .mapbase = 0xfffe8800, .flags = UPF_BOOT_AUTOCONF, - .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, + .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE | + SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 196, 196, 196, 196 }, + .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif1_device = { @@ -210,10 +214,12 @@ static struct platform_device scif1_device = { static struct plat_sci_port scif2_platform_data = { .mapbase = 0xfffe9000, .flags = UPF_BOOT_AUTOCONF, - .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, + .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE | + SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 200, 200, 200, 200 }, + .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif2_device = { @@ -227,10 +233,12 @@ static struct platform_device scif2_device = { static struct plat_sci_port scif3_platform_data = { .mapbase = 0xfffe9800, .flags = UPF_BOOT_AUTOCONF, - .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, + .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE | + SCSCR_REIE, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, .irqs = { 204, 204, 204, 204 }, + .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE, }; static struct platform_device scif3_device = { diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 9871c57b348e..1b6ec568f32a 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -206,6 +206,25 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { [SCLSR] = sci_reg_invalid, }, + /* + * Common SH-2(A) SCIF definitions for ports with FIFO data + * count registers. + */ + [SCIx_SH2_SCIF_FIFODATA_REGTYPE] = { + [SCSMR] = { 0x00, 16 }, + [SCBRR] = { 0x04, 8 }, + [SCSCR] = { 0x08, 16 }, + [SCxTDR] = { 0x0c, 8 }, + [SCxSR] = { 0x10, 16 }, + [SCxRDR] = { 0x14, 8 }, + [SCFCR] = { 0x18, 16 }, + [SCFDR] = { 0x1c, 16 }, + [SCTFDR] = sci_reg_invalid, + [SCRFDR] = sci_reg_invalid, + [SCSPTR] = { 0x20, 16 }, + [SCLSR] = { 0x24, 16 }, + }, + /* * Common SH-3 SCIF definitions. */ diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 8bffe9ae2ca0..5f3939c67dd8 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -67,6 +67,7 @@ enum { SCIx_IRDA_REGTYPE, SCIx_SCIFA_REGTYPE, SCIx_SCIFB_REGTYPE, + SCIx_SH2_SCIF_FIFODATA_REGTYPE, SCIx_SH3_SCIF_REGTYPE, SCIx_SH4_SCIF_REGTYPE, SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE, -- cgit From 87121ca504fd1d963a66b3fb0c72054b0fd9a177 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 7 Oct 2011 16:31:46 +0200 Subject: oprofile: Fix crash when unloading module (hr timer mode) Oprofile may crash in a KVM guest while unlaoding modules. This happens if oprofile_arch_init() fails and oprofile switches to the hr timer mode as a fallback. In this case oprofile_arch_exit() is called, but it never was initialized properly which causes the crash. This patch fixes this. oprofile: using timer interrupt. BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] unregister_syscore_ops+0x41/0x58 PGD 41da3f067 PUD 41d80e067 PMD 0 Oops: 0002 [#1] PREEMPT SMP CPU 5 Modules linked in: oprofile(-) Pid: 2382, comm: modprobe Not tainted 3.1.0-rc7-00018-g709a39d #18 Advanced Micro Device Anaheim/Anaheim RIP: 0010:[] [] unregister_syscore_ops+0x41/0x58 RSP: 0018:ffff88041de1de98 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffffffffa00060e0 RCX: dead000000200200 RDX: 0000000000000000 RSI: dead000000100100 RDI: ffffffff8178c620 RBP: ffff88041de1dea8 R08: 0000000000000001 R09: 0000000000000082 R10: 0000000000000000 R11: ffff88041de1dde8 R12: 0000000000000080 R13: fffffffffffffff5 R14: 0000000000000001 R15: 0000000000610210 FS: 00007f9ae5bef700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000008 CR3: 000000041ca44000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process modprobe (pid: 2382, threadinfo ffff88041de1c000, task ffff88042db6d040) Stack: ffff88041de1deb8 ffffffffa0006770 ffff88041de1deb8 ffffffffa000251e ffff88041de1dec8 ffffffffa00022c2 ffff88041de1ded8 ffffffffa0004993 ffff88041de1df78 ffffffff81073115 656c69666f72706f 0000000000610200 Call Trace: [] op_nmi_exit+0x15/0x17 [oprofile] [] oprofile_arch_exit+0xe/0x10 [oprofile] [] oprofile_exit+0x13/0x15 [oprofile] [] sys_delete_module+0x1c3/0x22f [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Code: 20 c6 78 81 e8 c5 cc 23 00 48 8b 13 48 8b 43 08 48 be 00 01 10 00 00 00 ad de 48 b9 00 02 20 00 00 00 ad de 48 c7 c7 20 c6 78 81 89 42 08 48 89 10 48 89 33 48 89 4b 08 e8 a6 c0 23 00 5a 5b RIP [] unregister_syscore_ops+0x41/0x58 RSP CR2: 0000000000000008 ---[ end trace 06d4e95b6aa3b437 ]--- CC: stable@kernel.org # 2.6.37+ Signed-off-by: Robert Richter --- drivers/oprofile/oprof.c | 29 ++++++++++++++++++++++++----- drivers/oprofile/timer_int.c | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dccd8636095c..f8c752e408a6 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -239,26 +239,45 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val) return err; } +static int timer_mode; + static int __init oprofile_init(void) { int err; + /* always init architecture to setup backtrace support */ err = oprofile_arch_init(&oprofile_ops); - if (err < 0 || timer) { - printk(KERN_INFO "oprofile: using timer interrupt.\n"); + + timer_mode = err || timer; /* fall back to timer mode on errors */ + if (timer_mode) { + if (!err) + oprofile_arch_exit(); err = oprofile_timer_init(&oprofile_ops); if (err) return err; } - return oprofilefs_register(); + + err = oprofilefs_register(); + if (!err) + return 0; + + /* failed */ + if (timer_mode) + oprofile_timer_exit(); + else + oprofile_arch_exit(); + + return err; } static void __exit oprofile_exit(void) { - oprofile_timer_exit(); oprofilefs_unregister(); - oprofile_arch_exit(); + if (timer_mode) + oprofile_timer_exit(); + else + oprofile_arch_exit(); } diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 3ef44624f510..878fba126582 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -110,6 +110,7 @@ int oprofile_timer_init(struct oprofile_operations *ops) ops->start = oprofile_hrtimer_start; ops->stop = oprofile_hrtimer_stop; ops->cpu_type = "timer"; + printk(KERN_INFO "oprofile: using timer interrupt.\n"); return 0; } -- cgit From 97f7f8189fe54e3cfe324ef9ad35064f3d2d3bff Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 10 Oct 2011 16:21:10 +0200 Subject: oprofile, x86: Fix crash when unloading module (nmi timer mode) If oprofile uses the nmi timer interrupt there is a crash while unloading the module. The bug can be triggered with oprofile build as module and kernel parameter nolapic set. This patch fixes this. oprofile: using NMI timer interrupt. BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] unregister_syscore_ops+0x41/0x58 PGD 42dbca067 PUD 41da6a067 PMD 0 Oops: 0002 [#1] PREEMPT SMP CPU 5 Modules linked in: oprofile(-) [last unloaded: oprofile] Pid: 2518, comm: modprobe Not tainted 3.1.0-rc7-00019-gb2fb49d #19 Advanced Micro Device Anaheim/Anaheim RIP: 0010:[] [] unregister_syscore_ops+0x41/0x58 RSP: 0018:ffff88041ef71e98 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffffffffa0017100 RCX: dead000000200200 RDX: 0000000000000000 RSI: dead000000100100 RDI: ffffffff8178c620 RBP: ffff88041ef71ea8 R08: 0000000000000001 R09: 0000000000000082 R10: 0000000000000000 R11: ffff88041ef71de8 R12: 0000000000000080 R13: fffffffffffffff5 R14: 0000000000000001 R15: 0000000000610210 FS: 00007fc902f20700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000008 CR3: 000000041cdb6000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process modprobe (pid: 2518, threadinfo ffff88041ef70000, task ffff88041d348040) Stack: ffff88041ef71eb8 ffffffffa0017790 ffff88041ef71eb8 ffffffffa0013532 ffff88041ef71ec8 ffffffffa00132d6 ffff88041ef71ed8 ffffffffa00159b2 ffff88041ef71f78 ffffffff81073115 656c69666f72706f 0000000000610200 Call Trace: [] op_nmi_exit+0x15/0x17 [oprofile] [] oprofile_arch_exit+0xe/0x10 [oprofile] [] oprofile_exit+0x1e/0x20 [oprofile] [] sys_delete_module+0x1c3/0x22f [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Code: 20 c6 78 81 e8 c5 cc 23 00 48 8b 13 48 8b 43 08 48 be 00 01 10 00 00 00 ad de 48 b9 00 02 20 00 00 00 ad de 48 c7 c7 20 c6 78 81 89 42 08 48 89 10 48 89 33 48 89 4b 08 e8 a6 c0 23 00 5a 5b RIP [] unregister_syscore_ops+0x41/0x58 RSP CR2: 0000000000000008 ---[ end trace 43a541a52956b7b0 ]--- CC: stable@kernel.org # 2.6.37+ Signed-off-by: Robert Richter --- arch/x86/oprofile/init.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c index cdfe4c54deca..f148cf652678 100644 --- a/arch/x86/oprofile/init.c +++ b/arch/x86/oprofile/init.c @@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops); extern void op_nmi_exit(void); extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); +static int nmi_timer; int __init oprofile_arch_init(struct oprofile_operations *ops) { @@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) #ifdef CONFIG_X86_LOCAL_APIC ret = op_nmi_init(ops); #endif + nmi_timer = (ret != 0); #ifdef CONFIG_X86_IO_APIC - if (ret < 0) + if (nmi_timer) ret = op_nmi_timer_init(ops); #endif ops->backtrace = x86_backtrace; @@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) void oprofile_arch_exit(void) { #ifdef CONFIG_X86_LOCAL_APIC - op_nmi_exit(); + if (!nmi_timer) + op_nmi_exit(); #endif } -- cgit From dd2c0ca1b153b555c09fd8e08f6842e12cf8e87b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Sep 2011 18:51:13 -0700 Subject: sh: clkfwk: add clk_rate_mult_range_round() This provides a clk_rate_mult_range_round() helper for use by some of the CPG PLL ranged multipliers, following the same approach as used by the div ranges. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/sh/clk/core.c | 20 ++++++++++++++++++++ include/linux/sh_clk.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index dc8d022c07a1..352036b1f9a2 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -173,6 +173,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, return clk_rate_round_helper(&div_range_round); } +static long clk_rate_mult_range_iter(unsigned int pos, + struct clk_rate_round_data *rounder) +{ + return clk_get_rate(rounder->arg) * pos; +} + +long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, + unsigned int mult_max, unsigned long rate) +{ + struct clk_rate_round_data mult_range_round = { + .min = mult_min, + .max = mult_max, + .func = clk_rate_mult_range_iter, + .arg = clk_get_parent(clk), + .rate = rate, + }; + + return clk_rate_round_helper(&mult_range_round); +} + int clk_rate_table_find(struct clk *clk, struct cpufreq_frequency_table *freq_table, unsigned long rate) diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index 3ccf18648d0a..9237c299641c 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -94,6 +94,9 @@ int clk_rate_table_find(struct clk *clk, long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, unsigned int div_max, unsigned long rate); +long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, + unsigned int mult_max, unsigned long rate); + long clk_round_parent(struct clk *clk, unsigned long target, unsigned long *best_freq, unsigned long *parent_freq, unsigned int div_min, unsigned int div_max); -- cgit From d31c285b3a71cf9056e6a060de41f37780b0af86 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 3 Nov 2011 13:06:08 -0700 Subject: xhci: Set slot and ep0 flags for address command. Matt's AsMedia xHCI host controller was responding with a Context Error to an address device command after a configured device reset. Some sequence of events leads both the slot and endpoint zero add flags cleared to zero, which the AsMedia host doesn't like: [ 223.701839] xhci_hcd 0000:03:00.0: Slot ID 1 Input Context: [ 223.701841] xhci_hcd 0000:03:00.0: @ffff880137b25000 (virt) @ffffc000 (dma) 0x000000 - drop flags [ 223.701843] xhci_hcd 0000:03:00.0: @ffff880137b25004 (virt) @ffffc004 (dma) 0x000000 - add flags [ 223.701846] xhci_hcd 0000:03:00.0: @ffff880137b25008 (virt) @ffffc008 (dma) 0x000000 - rsvd2[0] [ 223.701848] xhci_hcd 0000:03:00.0: @ffff880137b2500c (virt) @ffffc00c (dma) 0x000000 - rsvd2[1] [ 223.701850] xhci_hcd 0000:03:00.0: @ffff880137b25010 (virt) @ffffc010 (dma) 0x000000 - rsvd2[2] [ 223.701852] xhci_hcd 0000:03:00.0: @ffff880137b25014 (virt) @ffffc014 (dma) 0x000000 - rsvd2[3] [ 223.701854] xhci_hcd 0000:03:00.0: @ffff880137b25018 (virt) @ffffc018 (dma) 0x000000 - rsvd2[4] [ 223.701857] xhci_hcd 0000:03:00.0: @ffff880137b2501c (virt) @ffffc01c (dma) 0x000000 - rsvd2[5] [ 223.701858] xhci_hcd 0000:03:00.0: Slot Context: [ 223.701860] xhci_hcd 0000:03:00.0: @ffff880137b25020 (virt) @ffffc020 (dma) 0x8400000 - dev_info [ 223.701862] xhci_hcd 0000:03:00.0: @ffff880137b25024 (virt) @ffffc024 (dma) 0x010000 - dev_info2 [ 223.701864] xhci_hcd 0000:03:00.0: @ffff880137b25028 (virt) @ffffc028 (dma) 0x000000 - tt_info [ 223.701866] xhci_hcd 0000:03:00.0: @ffff880137b2502c (virt) @ffffc02c (dma) 0x000000 - dev_state [ 223.701869] xhci_hcd 0000:03:00.0: @ffff880137b25030 (virt) @ffffc030 (dma) 0x000000 - rsvd[0] [ 223.701871] xhci_hcd 0000:03:00.0: @ffff880137b25034 (virt) @ffffc034 (dma) 0x000000 - rsvd[1] [ 223.701873] xhci_hcd 0000:03:00.0: @ffff880137b25038 (virt) @ffffc038 (dma) 0x000000 - rsvd[2] [ 223.701875] xhci_hcd 0000:03:00.0: @ffff880137b2503c (virt) @ffffc03c (dma) 0x000000 - rsvd[3] [ 223.701877] xhci_hcd 0000:03:00.0: Endpoint 00 Context: [ 223.701879] xhci_hcd 0000:03:00.0: @ffff880137b25040 (virt) @ffffc040 (dma) 0x000000 - ep_info [ 223.701881] xhci_hcd 0000:03:00.0: @ffff880137b25044 (virt) @ffffc044 (dma) 0x2000026 - ep_info2 [ 223.701883] xhci_hcd 0000:03:00.0: @ffff880137b25048 (virt) @ffffc048 (dma) 0xffffe8e0 - deq [ 223.701885] xhci_hcd 0000:03:00.0: @ffff880137b25050 (virt) @ffffc050 (dma) 0x000000 - tx_info [ 223.701887] xhci_hcd 0000:03:00.0: @ffff880137b25054 (virt) @ffffc054 (dma) 0x000000 - rsvd[0] [ 223.701889] xhci_hcd 0000:03:00.0: @ffff880137b25058 (virt) @ffffc058 (dma) 0x000000 - rsvd[1] [ 223.701892] xhci_hcd 0000:03:00.0: @ffff880137b2505c (virt) @ffffc05c (dma) 0x000000 - rsvd[2] ... [ 223.701927] xhci_hcd 0000:03:00.0: // Ding dong! [ 223.701992] xhci_hcd 0000:03:00.0: Setup ERROR: address device command for slot 1. The xHCI spec says that both flags must be set to one for the Address Device command. When the device is first enumerated, xhci_setup_addressable_virt_dev() does set those flags. However, when the device is addressed after it has been reset in the configured state, xhci_setup_addressable_virt_dev() is not called, and xhci_copy_ep0_dequeue_into_input_ctx() is called instead. That function relies on the flags being set up by previous commands, which apparently isn't a good assumption. Move the setting of the flags into the common parent function. This should be queued for stable kernels as old as 2.6.35, since that was the first introduction of xhci_copy_ep0_dequeue_into_input_ctx. Signed-off-by: Sarah Sharp Tested-by: Matt Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-mem.c | 5 ----- drivers/usb/host/xhci.c | 5 ++++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 42a22b8e6922..0e4b25fa3bcd 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -982,7 +982,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud struct xhci_virt_device *dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; - struct xhci_input_control_ctx *ctrl_ctx; u32 port_num; struct usb_device *top_dev; @@ -994,12 +993,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud return -EINVAL; } ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0); - ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx); slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); - /* 2) New slot context and endpoint 0 context are valid*/ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); - /* 3) Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route); switch (udev->speed) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1ff95a0df576..747c5ead922b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3504,6 +3504,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) /* Otherwise, update the control endpoint ring enqueue pointer. */ else xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); + ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); + ctrl_ctx->drop_flags = 0; + xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); @@ -3585,7 +3589,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK) + 1; /* Zero the input context control for later use */ - ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->add_flags = 0; ctrl_ctx->drop_flags = 0; -- cgit From 79c3dd8150fd5236d95766a9e662e3e932b462c9 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Thu, 3 Nov 2011 09:07:18 -0400 Subject: usb, xhci: Clear warm reset change event during init I noticed on my Panther Point system that I wasn't getting hotplug events for my usb3.0 disk on a usb3 port. I tracked it down to the fact that the system had the warm reset change bit still set. This seemed to block future events from being received, including a hotplug event. Clearing this bit during initialization allowed the hotplug event to be received and the disk to be recognized correctly. This patch should be backported to kernels as old as 2.6.39. Signed-off-by: Don Zickus Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/core/hub.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 96f05b29c9ad..79781461eec9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -813,6 +813,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) USB_PORT_FEAT_C_PORT_LINK_STATE); } + if ((portchange & USB_PORT_STAT_C_BH_RESET) && + hub_is_superspeed(hub->hdev)) { + need_debounce_delay = true; + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + } /* We can forget about a "removed" device when there's a * physical disconnect or the connect status changes. */ -- cgit From 1788ea6e3b2a58cf4fb00206e362d9caff8d86a7 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 4 Nov 2011 13:31:21 -0400 Subject: nfs: when attempting to open a directory, fall back on normal lookup (try #5) commit d953126 changed how nfs_atomic_lookup handles an -EISDIR return from an OPEN call. Prior to that patch, that caused the client to fall back to doing a normal lookup. When that patch went in, the code began returning that error to userspace. The d_revalidate codepath however never had the corresponding change, so it was still possible to end up with a NULL ctx->state pointer after that. That patch caused a regression. When we attempt to open a directory that does not have a cached dentry, that open now errors out with EISDIR. If you attempt the same open with a cached dentry, it will succeed. Fix this by reverting the change in nfs_atomic_lookup and allowing attempts to open directories to fall back to a normal lookup Also, add a NFSv4-specific f_ops->open routine that just returns -ENOTDIR. This should never be called if things are working properly, but if it ever is, then the dprintk may help in debugging. To facilitate this, a new file_operations field is also added to the nfs_rpc_ops struct. Cc: stable@kernel.org Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 2 +- fs/nfs/file.c | 32 ++++++++++++++++++++++++++++++++ fs/nfs/inode.c | 2 +- fs/nfs/nfs3proc.c | 1 + fs/nfs/nfs4proc.c | 1 + fs/nfs/proc.c | 1 + include/linux/nfs_fs.h | 3 +++ include/linux/nfs_xdr.h | 1 + 8 files changed, 41 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b238d95ac48c..ac2899098147 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1468,12 +1468,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry res = NULL; goto out; /* This turned out not to be a regular file */ + case -EISDIR: case -ENOTDIR: goto no_open; case -ELOOP: if (!(nd->intent.open.flags & O_NOFOLLOW)) goto no_open; - /* case -EISDIR: */ /* case -EINVAL: */ default: res = ERR_CAST(inode); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 0a1f8312b4dc..6d93e0754b5e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -886,3 +886,35 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) file->f_path.dentry->d_name.name, arg); return -EINVAL; } + +#ifdef CONFIG_NFS_V4 +static int +nfs4_file_open(struct inode *inode, struct file *filp) +{ + /* + * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to + * this point, then something is very wrong + */ + dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp); + return -ENOTDIR; +} + +const struct file_operations nfs4_file_operations = { + .llseek = nfs_file_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = nfs_file_read, + .aio_write = nfs_file_write, + .mmap = nfs_file_mmap, + .open = nfs4_file_open, + .flush = nfs_file_flush, + .release = nfs_file_release, + .fsync = nfs_file_fsync, + .lock = nfs_lock, + .flock = nfs_flock, + .splice_read = nfs_file_splice_read, + .splice_write = nfs_file_splice_write, + .check_flags = nfs_check_flags, + .setlease = nfs_setlease, +}; +#endif /* CONFIG_NFS_V4 */ diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c07a55aec838..50a15fa8cf98 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) */ inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops; if (S_ISREG(inode->i_mode)) { - inode->i_fop = &nfs_file_operations; + inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops; inode->i_data.a_ops = &nfs_file_aops; inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; } else if (S_ISDIR(inode->i_mode)) { diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 85f1690ca08c..d4bc9ed91748 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -853,6 +853,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = { .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs3_dir_inode_operations, .file_inode_ops = &nfs3_file_inode_operations, + .file_ops = &nfs_file_operations, .getroot = nfs3_proc_get_root, .getattr = nfs3_proc_getattr, .setattr = nfs3_proc_setattr, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b60fddf606f7..069cb8094d43 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6253,6 +6253,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .dentry_ops = &nfs4_dentry_operations, .dir_inode_ops = &nfs4_dir_inode_operations, .file_inode_ops = &nfs4_file_inode_operations, + .file_ops = &nfs4_file_operations, .getroot = nfs4_proc_get_root, .getattr = nfs4_proc_getattr, .setattr = nfs4_proc_setattr, diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index ac40b8535d7e..f48125da198a 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -710,6 +710,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = { .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs_dir_inode_operations, .file_inode_ops = &nfs_file_inode_operations, + .file_ops = &nfs_file_operations, .getroot = nfs_proc_get_root, .getattr = nfs_proc_getattr, .setattr = nfs_proc_setattr, diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index ab2c6343361a..92ecf5585fac 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -410,6 +410,9 @@ extern const struct inode_operations nfs_file_inode_operations; extern const struct inode_operations nfs3_file_inode_operations; #endif /* CONFIG_NFS_V3 */ extern const struct file_operations nfs_file_operations; +#ifdef CONFIG_NFS_V4 +extern const struct file_operations nfs4_file_operations; +#endif /* CONFIG_NFS_V4 */ extern const struct address_space_operations nfs_file_aops; extern const struct address_space_operations nfs_dir_aops; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index c74595ba7094..2a7c533be5dd 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1192,6 +1192,7 @@ struct nfs_rpc_ops { const struct dentry_operations *dentry_ops; const struct inode_operations *dir_inode_ops; const struct inode_operations *file_inode_ops; + const struct file_operations *file_ops; int (*getroot) (struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); -- cgit From 0486958f57a496212e3c1e3d9194deebba3dc3d4 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 4 Nov 2011 13:31:22 -0400 Subject: nfs: move nfs_file_operations declaration to bottom of file.c (try #2) ...a remove a set of forward declarations. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 59 +++++++++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 6d93e0754b5e..eca56d4b39c0 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -40,48 +40,8 @@ #define NFSDBG_FACILITY NFSDBG_FILE -static int nfs_file_open(struct inode *, struct file *); -static int nfs_file_release(struct inode *, struct file *); -static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); -static int nfs_file_mmap(struct file *, struct vm_area_struct *); -static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, - struct pipe_inode_info *pipe, - size_t count, unsigned int flags); -static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, - struct file *filp, loff_t *ppos, - size_t count, unsigned int flags); -static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -static int nfs_file_flush(struct file *, fl_owner_t id); -static int nfs_file_fsync(struct file *, loff_t, loff_t, int datasync); -static int nfs_check_flags(int flags); -static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); -static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); -static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); - static const struct vm_operations_struct nfs_file_vm_ops; -const struct file_operations nfs_file_operations = { - .llseek = nfs_file_llseek, - .read = do_sync_read, - .write = do_sync_write, - .aio_read = nfs_file_read, - .aio_write = nfs_file_write, - .mmap = nfs_file_mmap, - .open = nfs_file_open, - .flush = nfs_file_flush, - .release = nfs_file_release, - .fsync = nfs_file_fsync, - .lock = nfs_lock, - .flock = nfs_flock, - .splice_read = nfs_file_splice_read, - .splice_write = nfs_file_splice_write, - .check_flags = nfs_check_flags, - .setlease = nfs_setlease, -}; - const struct inode_operations nfs_file_inode_operations = { .permission = nfs_permission, .getattr = nfs_getattr, @@ -887,6 +847,25 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) return -EINVAL; } +const struct file_operations nfs_file_operations = { + .llseek = nfs_file_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = nfs_file_read, + .aio_write = nfs_file_write, + .mmap = nfs_file_mmap, + .open = nfs_file_open, + .flush = nfs_file_flush, + .release = nfs_file_release, + .fsync = nfs_file_fsync, + .lock = nfs_lock, + .flock = nfs_flock, + .splice_read = nfs_file_splice_read, + .splice_write = nfs_file_splice_write, + .check_flags = nfs_check_flags, + .setlease = nfs_setlease, +}; + #ifdef CONFIG_NFS_V4 static int nfs4_file_open(struct inode *inode, struct file *filp) -- cgit From 8eeea521d9d0fa6afd62df8c6e6566ee946117fa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Nov 2011 15:52:31 +0000 Subject: ASoC: Don't use wm8994->control_data in wm8994_readable_register() The field is no longer initialised so this will crash if running on wm8958. Reported-by: Thomas Abraham Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6b73efd26991..3d2c3d4711d0 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = { static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->control_data; + struct wm8994 *control = codec->control_data; switch (reg) { case WM8994_GPIO_1: -- cgit From 5a3ad6bd6ae0687cb0ecb424d74221920fbc7f38 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Nov 2011 15:53:48 +0000 Subject: ASoC: Don't use wm8994->control_data when requesting IRQs The field is no longer initialised so this will crash if running on wm8958. Reported-by: Thomas Abraham Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 3d2c3d4711d0..9cb16cc853b3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3180,9 +3180,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, wm8994_fifo_error, "FIFO error", codec); - wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN, + wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, wm8994_temp_warn, "Thermal warning", codec); - wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT, + wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, wm8994_temp_shut, "Thermal shutdown", codec); ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, -- cgit From 19940b3d55c87d8089a8cb0fa8e5a9918a3846bd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 19 Aug 2011 18:05:05 +0900 Subject: ASoC: Ensure we get an impedence reported for WM8958 jack detect Occasionally we may see an accessory reported before we have a stable impedance for the accessory. If this happens then reread the status in order to ensure that the handler can take the appropriate action for the status change. Signed-off-by: Mark Brown --- include/linux/mfd/wm8994/registers.h | 15 +++++++++++++++ sound/soc/codecs/wm8994.c | 37 +++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h index fae295048a8b..83a9caec0e43 100644 --- a/include/linux/mfd/wm8994/registers.h +++ b/include/linux/mfd/wm8994/registers.h @@ -1962,6 +1962,21 @@ #define WM8958_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ #define WM8958_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ +/* + * R210 (0xD2) - Mic Detect 3 + */ +#define WM8958_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */ +#define WM8958_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */ +#define WM8958_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */ +#define WM8958_MICD_VALID 0x0002 /* MICD_VALID */ +#define WM8958_MICD_VALID_MASK 0x0002 /* MICD_VALID */ +#define WM8958_MICD_VALID_SHIFT 1 /* MICD_VALID */ +#define WM8958_MICD_VALID_WIDTH 1 /* MICD_VALID */ +#define WM8958_MICD_STS 0x0001 /* MICD_STS */ +#define WM8958_MICD_STS_MASK 0x0001 /* MICD_STS */ +#define WM8958_MICD_STS_SHIFT 0 /* MICD_STS */ +#define WM8958_MICD_STS_WIDTH 1 /* MICD_STS */ + /* * R76 (0x4C) - Charge Pump (1) */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9cb16cc853b3..9c982e47eb99 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3030,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) { struct wm8994_priv *wm8994 = data; struct snd_soc_codec *codec = wm8994->codec; - int reg; + int reg, count; - reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); - if (reg < 0) { - dev_err(codec->dev, "Failed to read mic detect status: %d\n", - reg); - return IRQ_NONE; - } + /* We may occasionally read a detection without an impedence + * range being provided - if that happens loop again. + */ + count = 10; + do { + reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); + if (reg < 0) { + dev_err(codec->dev, + "Failed to read mic detect status: %d\n", + reg); + return IRQ_NONE; + } - if (!(reg & WM8958_MICD_VALID)) { - dev_dbg(codec->dev, "Mic detect data not valid\n"); - goto out; - } + if (!(reg & WM8958_MICD_VALID)) { + dev_dbg(codec->dev, "Mic detect data not valid\n"); + goto out; + } + + if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK)) + break; + + msleep(1); + } while (count--); + + if (count == 0) + dev_warn(codec->dev, "No impedence range reported for jack\n"); #ifndef CONFIG_SND_SOC_WM8994_MODULE trace_snd_soc_jack_irq(dev_name(codec->dev)); -- cgit From b42c909743595208f7987e331f0921b73af2ce25 Mon Sep 17 00:00:00 2001 From: Tomas Miljenović Date: Fri, 4 Nov 2011 23:59:49 -0700 Subject: Input: i8042 - add HP Pavilion dv4s to 'notimeout' and 'nomux' blacklists Touchpad input doesn't work with newer HP Pavilion dv4 laptops due to bad i8042 timeout data. Booting with i8042.notimeout and i8042.nomux successfully works around the problem. This patch adds the devices to the i8042 notimeout and nomux blacklists. Signed-off-by: Tomas Miljenovic Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index bb9f5d31f0d0..b4cfc6c8be89 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -431,6 +431,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), }, }, + { + /* Newer HP Pavilion dv4 models */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, { } }; @@ -560,6 +567,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), }, }, + { + /* Newer HP Pavilion dv4 models */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, { } }; -- cgit From 15a2015fbc692e1c97d7ce12d96e077f5ae7ea6d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sat, 5 Nov 2011 22:06:31 -0700 Subject: ceph: fix iput race when queueing inode work If we queue a work item that calls iput(), make sure we ihold() before attempting to queue work. Otherwise our queued work might miraculously run before we notice the queue_work() succeeded and call ihold(), allowing the inode to be destroyed. That is, instead of if (queue_work(...)) ihold(); we need to do ihold(); if (!queue_work(...)) iput(); Reported-by: Amon Ott Signed-off-by: Sage Weil --- fs/ceph/inode.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e392bfce84a3..116f36502f17 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1328,12 +1328,13 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) */ void ceph_queue_writeback(struct inode *inode) { + ihold(inode); if (queue_work(ceph_inode_to_client(inode)->wb_wq, &ceph_inode(inode)->i_wb_work)) { dout("ceph_queue_writeback %p\n", inode); - ihold(inode); } else { dout("ceph_queue_writeback %p failed\n", inode); + iput(inode); } } @@ -1353,12 +1354,13 @@ static void ceph_writeback_work(struct work_struct *work) */ void ceph_queue_invalidate(struct inode *inode) { + ihold(inode); if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq, &ceph_inode(inode)->i_pg_inv_work)) { dout("ceph_queue_invalidate %p\n", inode); - ihold(inode); } else { dout("ceph_queue_invalidate %p failed\n", inode); + iput(inode); } } @@ -1434,13 +1436,14 @@ void ceph_queue_vmtruncate(struct inode *inode) { struct ceph_inode_info *ci = ceph_inode(inode); + ihold(inode); if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq, &ci->i_vmtruncate_work)) { dout("ceph_queue_vmtruncate %p\n", inode); - ihold(inode); } else { dout("ceph_queue_vmtruncate %p failed, pending=%d\n", inode, ci->i_truncate_pending); + iput(inode); } } -- cgit From 241fa6e42f5462a82f00ddf5169628a8c3976548 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 11 Oct 2011 11:54:26 -0300 Subject: [media] uvcvideo: GET_RES should only be checked for BITMAP type menu controls Currently it is also being checked for non BITMAP type menu controls, breaking the logitech LED control menu added by uvcdynctrl, as well as potentially breaking the powerline frequency menu. Signed-off-by: Hans de Goede Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 10c2364f3e8a..254d32688843 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1016,7 +1016,8 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, menu_info = &mapping->menu_info[query_menu->index]; - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { + if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && + (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { s32 bitmap; if (!ctrl->cached) { @@ -1225,7 +1226,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, /* Valid menu indices are reported by the GET_RES request for * UVC controls that support it. */ - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { + if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && + (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { if (!ctrl->cached) { ret = uvc_ctrl_populate_cache(chain, ctrl); if (ret < 0) -- cgit From a9380ba11fc384a52bcee0884ca6dd069deb6b1b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 23:20:41 -0300 Subject: [media] mxl111sf: fix return value of mxl111sf_idac_config mxl111sf_idac_config was incorrectly returning val instead of ret Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/mxl111sf-phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c index 91dc1fc2825b..ae8c2f839fcf 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c @@ -332,7 +332,7 @@ int mxl111sf_idac_config(struct mxl111sf_state *state, ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val); - return val; + return ret; } /* -- cgit From 2f4133de28edafcaac3ce6b57faf8f40ed2ff1b9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 23:29:17 -0300 Subject: [media] mxl111sf: check for errors after mxl111sf_write_reg in mxl111sf_idac_config Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/mxl111sf-phy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c index ae8c2f839fcf..09787be576ac 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c @@ -328,9 +328,11 @@ int mxl111sf_idac_config(struct mxl111sf_state *state, /* set hysteresis value reg: 0x0B<5:0> */ ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG, (hysteresis_value & 0x3F)); + mxl_fail(ret); } ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val); + mxl_fail(ret); return ret; } -- cgit From cd834fa693160914029fee128f52e87a79d3e480 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 23:31:04 -0300 Subject: [media] mxl111sf: remove pointless if condition in mxl111sf_config_spi Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/mxl111sf-phy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c index 09787be576ac..b741b3a7a325 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c @@ -296,8 +296,7 @@ int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff) goto fail; ret = mxl111sf_write_reg(state, 0x00, 0x00); - if (mxl_fail(ret)) - goto fail; + mxl_fail(ret); fail: return ret; } -- cgit From e836a1c078e230dd5a94bb086b186c2be3ec6a84 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 23:46:46 -0300 Subject: [media] mxl111sf: fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix build warning: variable ‘ret’ set but not used in function ‘mxl111sf_i2c_readagain’ Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/mxl111sf-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c index 2e8c288258a9..34434557ef65 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c @@ -398,7 +398,6 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state, u8 i2c_r_data[24]; u8 i = 0; u8 fifo_status = 0; - int ret; int status = 0; mxl_i2c("read %d bytes", count); @@ -418,7 +417,7 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state, i2c_w_data[4+(i*3)] = 0x00; } - ret = mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data); + mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data); /* Check for I2C NACK status */ if (mxl111sf_i2c_check_status(state) == 1) { -- cgit From eb513689c97e3e73bb9b4459d490a8e894b4a546 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 7 Nov 2011 10:47:42 -0500 Subject: ext4: ignore journalled data options on remount if fs has no journal This avoids a confusing failure in the init scripts when the /etc/fstab has data=writeback or data=journal but the file system does not have a journal. So check for this case explicitly, and warn the user that we are ignoring the (pointless, since they have no journal) data=* mount option. Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9953d80145ad..0435013dbd46 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1683,7 +1683,9 @@ static int parse_options(char *options, struct super_block *sb, data_opt = EXT4_MOUNT_WRITEBACK_DATA; datacheck: if (is_remount) { - if (test_opt(sb, DATA_FLAGS) != data_opt) { + if (!sbi->s_journal) + ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option"); + else if (test_opt(sb, DATA_FLAGS) != data_opt) { ext4_msg(sb, KERN_ERR, "Cannot change data mode on remount"); return 0; -- cgit From 2397256d6218e7bf5147a3b01dcc6aec20fd3916 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 7 Nov 2011 10:50:09 -0500 Subject: ext4: Remove kernel_lock annotations The BKL is gone, these annotations are useless. Signed-off-by: Richard Weinberger Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0435013dbd46..3858767ec672 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3101,8 +3101,6 @@ static void ext4_destroy_lazyinit_thread(void) } static int ext4_fill_super(struct super_block *sb, void *data, int silent) - __releases(kernel_lock) - __acquires(kernel_lock) { char *orig_data = kstrdup(data, GFP_KERNEL); struct buffer_head *bh; -- cgit From 3c1fcb2c24519febd7ca9cf292fa5bdf513b601f Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 7 Nov 2011 11:01:13 -0500 Subject: ext4: add blk_finish_plug in error case of writepages. blk_finish_plug is needed in error case of writepages. Signed-off-by: Namjae Jeon Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cc5a6da030a1..18b262bb6a4a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2270,6 +2270,7 @@ retry: ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: " "%ld pages, ino %lu; err %d", __func__, wbc->nr_to_write, inode->i_ino, ret); + blk_finish_plug(&plug); goto out_writepages; } -- cgit From fdbd3ce9efb3a045266f2f6b2f1b6047882ff092 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 7 Nov 2011 07:53:23 -0800 Subject: PCI: pciehp: Retrieve link speed after link is trained During hot plug, board_added will call pciehp_power_on_slot(). But link speed is updated in pciehp_power_on_slot(). We should not update link speed there, because that is too early. So move the link speed update to pciehp_check_link_status() after making sure the link has been trained. -v2: fix compile warning that Kenji found. Signed-off-by: Yinghai Lu Reviewed-by: Kenji Kaneshige Tested-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 96dc4734e4af..6692832c9c81 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -294,6 +294,8 @@ int pciehp_check_link_status(struct controller *ctrl) return retval; } + pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); + return retval; } @@ -484,7 +486,6 @@ int pciehp_power_on_slot(struct slot * slot) u16 slot_cmd; u16 cmd_mask; u16 slot_status; - u16 lnk_status; int retval = 0; /* Clear sticky power-fault bit from previous power failures */ @@ -516,14 +517,6 @@ int pciehp_power_on_slot(struct slot * slot) ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); - retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); - if (retval) { - ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n", - __func__); - return retval; - } - pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); - return retval; } -- cgit From 694718d8ad2f0b11d7376f8aa32b1befff6e5966 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 17 Oct 2011 16:59:25 +0200 Subject: b43: fill ctl1 word on all newer PHYs, fix PHY errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes PHY transmission errors reported on some LP-PHY and HT-PHY cards. For LP-PHY they were quite rare and not really noticable. On HT-PHY they were critical, OFDM rates were not available at all. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 58ea0e5fabfd..b62d4a15c534 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -175,6 +175,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, } } +/* TODO: verify if needed for SSLPN or LCN */ static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate) { const struct b43_phy *phy = &dev->phy; @@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev, unsigned int plcp_fragment_len; u32 mac_ctl = 0; u16 phy_ctl = 0; + bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP || + phy->type == B43_PHYTYPE_N || + phy->type == B43_PHYTYPE_HT); u8 extra_ft = 0; struct ieee80211_rate *txrate; struct ieee80211_tx_rate *rates; @@ -531,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, extra_ft |= B43_TXH_EFT_RTSFB_CCK; if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS && - phy->type == B43_PHYTYPE_N) { + fill_phy_ctl1) { txhdr->phy_ctl1_rts = cpu_to_le16( b43_generate_tx_phy_ctl1(dev, rts_rate)); txhdr->phy_ctl1_rts_fb = cpu_to_le16( @@ -552,7 +556,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, break; } - if (phy->type == B43_PHYTYPE_N) { + if (fill_phy_ctl1) { txhdr->phy_ctl1 = cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate)); txhdr->phy_ctl1_fb = -- cgit From 73d51f38c736ae286372e90056a7f31519f555ac Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 17 Oct 2011 17:15:44 +0200 Subject: b43: HT-PHY: report signal to mac80211 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 7 +++++++ drivers/net/wireless/b43/xmit.h | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index b62d4a15c534..5f77cbe0b6aa 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -740,7 +740,14 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* Link quality statistics */ switch (chanstat & B43_RX_CHAN_PHYTYPE) { + case B43_PHYTYPE_HT: + /* TODO: is max the right choice? */ + status.signal = max_t(__s8, + max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1), + rxhdr->phy_ht_power2); + break; case B43_PHYTYPE_N: + /* Broadcom has code for min and avg, but always uses max */ if (rxhdr->power0 == 16 || rxhdr->power0 == 32) status.signal = max(rxhdr->power1, rxhdr->power2); else diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 16c514d54afa..98d90747836a 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -249,6 +249,12 @@ struct b43_rxhdr_fw4 { } __packed; } __packed; union { + /* HT-PHY */ + struct { + PAD_BYTES(1); + __s8 phy_ht_power0; + } __packed; + /* RSSI for N-PHYs */ struct { __s8 power2; @@ -257,7 +263,15 @@ struct b43_rxhdr_fw4 { __le16 phy_status2; /* PHY RX Status 2 */ } __packed; - __le16 phy_status3; /* PHY RX Status 3 */ + union { + /* HT-PHY */ + struct { + __s8 phy_ht_power1; + __s8 phy_ht_power2; + } __packed; + + __le16 phy_status3; /* PHY RX Status 3 */ + } __packed; union { /* Tested with 598.314, 644.1001 and 666.2 */ struct { -- cgit From ae8e46723f803057daff392bdc93332be2f0ec98 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Sat, 29 Oct 2011 11:30:15 +0200 Subject: brcm80211: smac: eliminate a null pointer dereference in dma.c Though it's unlikely, di may be null, so we can't dereference di->dma.dmactrlflags until we've checked it. Move this de-reference after the check, and adjust the error message to not require de-referencing di. This is based upon Julia's original patch: <1319846297-2985-2-git-send-email-julia@diku.dk> Reported-by: Julia Lawall Acked-by: Arend van Spriel Signed-off-by: Julian Calaby Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index b56a30297c26..6ebec8f42846 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -358,13 +358,14 @@ static uint nrxdactive(struct dma_info *di, uint h, uint t) static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) { - uint dmactrlflags = di->dma.dmactrlflags; + uint dmactrlflags; if (di == NULL) { - DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name)); + DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n")); return 0; } + dmactrlflags = di->dma.dmactrlflags; dmactrlflags &= ~mask; dmactrlflags |= flags; -- cgit From 3432f9233704a66e6067944339a311744243707d Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 30 Oct 2011 15:41:59 +0200 Subject: mac80211: use min rate as basic rate for buggy APs Some buggy APs (and even P2P_GO) don't advertise their basic rates in the association response. In such case, use the min supported rate as the basic rate. Reported-by: Pontus Fuchs Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 17258feaab9b..d3b408cda08d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1485,6 +1485,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, int i, j, err; bool have_higher_than_11mbit = false; u16 ap_ht_cap_flags; + int min_rate = INT_MAX, min_rate_index = -1; /* AssocResp and ReassocResp have identical structure */ @@ -1551,6 +1552,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, rates |= BIT(j); if (is_basic) basic_rates |= BIT(j); + if (rate < min_rate) { + min_rate = rate; + min_rate_index = j; + } break; } } @@ -1568,11 +1573,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, rates |= BIT(j); if (is_basic) basic_rates |= BIT(j); + if (rate < min_rate) { + min_rate = rate; + min_rate_index = j; + } break; } } } + /* + * some buggy APs don't advertise basic_rates. use the lowest + * supported rate instead. + */ + if (unlikely(!basic_rates) && min_rate_index >= 0) { + printk(KERN_DEBUG "%s: No basic rates in AssocResp. " + "Using min supported rate instead.\n", sdata->name); + basic_rates = BIT(min_rate_index); + } + sta->sta.supp_rates[wk->chan->band] = rates; sdata->vif.bss_conf.basic_rates = basic_rates; -- cgit From 6c7394197af90f6a332180e33f5d025d3037d883 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 Nov 2011 09:27:01 +0100 Subject: nl80211: fix HT capability attribute validation Since the NL80211_ATTR_HT_CAPABILITY attribute is used as a struct, it needs a minimum, not maximum length. Enforce that properly. Not doing so could potentially lead to reading after the buffer. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 48260c2d092a..b587857a9d7d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -132,8 +132,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG }, - [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, - .len = NL80211_HT_CAPABILITY_LEN }, + [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN }, [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 }, [NL80211_ATTR_IE] = { .type = NLA_BINARY, -- cgit From 133a3ff2c934223a8143bfa52401bba962a97165 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 Nov 2011 14:50:13 +0100 Subject: cfg80211: allow setting TXQ parameters only in AP mode In other modes the parameters should not be set. Right now, mac80211 will set them, even if the user asked for setting them on VLANs which the driver doesn't know about, causing all kinds of trouble. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b587857a9d7d..b3a476fe8272 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1252,6 +1252,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { + result = -EINVAL; + goto bad_res; + } + nla_for_each_nested(nl_txq_params, info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], rem_txq_params) { -- cgit From 3b6ef6334febb05d3050a96546e635f038dbcb15 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Nov 2011 11:01:46 +0100 Subject: cfg80211: fix cmp_ies When comparing two items by IE, the sort order wasn't stable, which could lead to issues in the rbtree. Make it stable by making a missing IE sort before a present IE. Also sort by length first if it differs and then by contents. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/scan.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 0fb142410404..dc23b31594e0 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -259,17 +259,20 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) { const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); - int r; + /* equal if both missing */ if (!ie1 && !ie2) return 0; - if (!ie1 || !ie2) + /* sort missing IE before (left of) present IE */ + if (!ie1) return -1; + if (!ie2) + return 1; - r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); - if (r == 0 && ie1[1] != ie2[1]) + /* sort by length first, then by contents */ + if (ie1[1] != ie2[1]) return ie2[1] - ie1[1]; - return r; + return memcmp(ie1 + 2, ie2 + 2, ie1[1]); } static bool is_bss(struct cfg80211_bss *a, -- cgit From db652e4b36e5f1e5f49a4a49caf3aa365fe851c4 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 6 Nov 2011 22:58:31 +0100 Subject: net, wireless, mwifiex: Fix mem leak in mwifiex_update_curr_bss_params() If kmemdup() fails we leak the memory allocated to bss_desc. This patch fixes the leak. I also removed the pointless default assignment of 'NULL' to 'bss_desc' while I was there anyway. Signed-off-by: Jesper Juhl Reviewed-by: Srivatsa S. Bhat Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index dae8dbb24a03..8a3f9598ad33 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1469,7 +1469,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, s32 rssi, const u8 *ie_buf, size_t ie_len, u16 beacon_period, u16 cap_info_bitmap, u8 band) { - struct mwifiex_bssdescriptor *bss_desc = NULL; + struct mwifiex_bssdescriptor *bss_desc; int ret; unsigned long flags; u8 *beacon_ie; @@ -1484,6 +1484,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL); if (!beacon_ie) { + kfree(bss_desc); dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); return -ENOMEM; } -- cgit From 24b9c373ab787ccacfa2c46736153708796f5cd6 Mon Sep 17 00:00:00 2001 From: "Janusz.Dziedzic@tieto.com" Date: Mon, 7 Nov 2011 09:47:47 +0200 Subject: mac80211: uAPSD - fix IEEE80211_FCTL_MOREDATA bit setting Set IEEE80211_FCTL_MOREDATA bit also in case we have buffered frames (more than one) only for one AC. Signed-off-by: Janusz Dziedzic Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ce962d2c8782..8eaa746ec7a2 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1354,12 +1354,12 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, * Use MoreData flag to indicate whether there are * more buffered frames for this STA */ - if (!more_data) - hdr->frame_control &= - cpu_to_le16(~IEEE80211_FCTL_MOREDATA); - else + if (more_data || !skb_queue_empty(&frames)) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); + else + hdr->frame_control &= + cpu_to_le16(~IEEE80211_FCTL_MOREDATA); if (ieee80211_is_data_qos(hdr->frame_control) || ieee80211_is_qos_nullfunc(hdr->frame_control)) -- cgit From 4dff523a913197e3314c7b0d08734ab037709093 Mon Sep 17 00:00:00 2001 From: Arek Lichwa Date: Wed, 26 Oct 2011 11:23:22 +0200 Subject: Bluetooth: Revert: Fix L2CAP connection establishment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 330605423ca6eafafb8dcc27502bce1c585d1b06. The commit introduces regression when two 2.1 devices attempt establish rfcomm channel. Such connection is refused since there's a security block issue on l2cap. It means the link is unencrypted. 2011-09-16 18:08:46.567616 < ACL data: handle 1 flags 0x00 dlen 24 0000: 14 00 40 00 06 00 02 00 0f 35 03 19 12 00 ff ff ..@......5....˙˙ 0010: 35 05 0a 00 00 ff ff 00 5....˙˙. 2011-09-16 18:08:46.572377 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 1 packets 1 2011-09-16 18:08:46.577931 > ACL data: handle 1 flags 0x02 dlen 88 L2CAP(d): cid 0x0040 len 84 [psm 0] 0000: 07 00 02 00 4f 00 4c 35 4a 35 48 09 00 00 0a 00 ....O.L5J5H..... 0010: 01 00 00 09 00 01 35 03 19 12 00 09 00 05 35 03 ......5.......5. 0020: 19 10 02 09 00 09 35 08 35 06 19 12 00 09 01 02 ......5.5....... 0030: 09 02 00 09 01 02 09 02 01 09 00 0a 09 02 02 09 ................ 0040: 00 00 09 02 03 09 00 00 09 02 04 28 01 09 02 05 ...........(.... 0050: 09 00 02 00 .... 2011-09-16 18:08:46.626057 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 1 2011-09-16 18:08:46.627614 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 2011-09-16 18:08:46.627675 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:00:F2:6A:29:69 2011-09-16 18:08:46.634999 < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 bdaddr 00:00:F2:6A:29:69 key 58CD393179FC902E5E8F512A855EE532 2011-09-16 18:08:46.683278 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 status 0x00 bdaddr 00:00:F2:6A:29:69 2011-09-16 18:08:46.764729 > HCI Event: Auth Complete (0x06) plen 3 status 0x00 handle 1 2011-09-16 18:08:46.764821 < ACL data: handle 1 flags 0x00 dlen 12 0000: 08 00 01 00 02 05 04 00 03 00 41 00 ..........A. 2011-09-16 18:08:46.764851 > HCI Event: Command Status (0x0f) plen 4 Unknown (0x00|0x0000) status 0x00 ncmd 2 2011-09-16 18:08:46.768117 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 1 packets 1 2011-09-16 18:08:46.770894 > ACL data: handle 1 flags 0x02 dlen 16 L2CAP(s): Connect rsp: dcid 0x0000 scid 0x0041 result 3 status 0 Connection refused - security block 2011-09-16 18:08:49.000691 < ACL data: handle 1 flags 0x00 dlen 12 0000: 08 00 01 00 06 06 04 00 40 00 40 00 ........@.@. 2011-09-16 18:08:49.015675 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 1 packets 1 2011-09-16 18:08:49.016927 > ACL data: handle 1 flags 0x02 dlen 12 L2CAP(s): Disconn rsp: dcid 0x0040 scid 0x0040 2011-09-16 18:08:51.009480 < HCI Command: Disconnect (0x01|0x0006) plen 3 handle 1 reason 0x13 Reason: Remote User Terminated Connection 2011-09-16 18:08:51.011525 > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) status 0x00 ncmd 1 2011-09-16 18:08:51.123494 > HCI Event: Disconn Complete (0x05) plen 4 status 0x00 handle 1 reason 0x16 Reason: Connection Terminated by Local Host Signed-off-by: Arek Lichwa Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c1c597e3e198..e0af7237cd92 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -673,7 +673,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: - if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) + if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) -- cgit From abf015f04614a3a7da43d35b55edc90189af4e6a Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2011 19:04:36 +0000 Subject: Revert "ARM: 7098/1: kdump: copy kernel relocation code at the kexec prepare stage" This reverts commit 2b034922af2caa19df86f0c502e76cb6f6e910f9. Will Deacon reports: This is causing kexec to fail. The symptoms are that the .init.text section is not loaded as part of the new kernel image, so when we try to do the SMP/UP fixups we hit a whole sea of poison left there by the previous kernel. So my guess is that machine_kexec_prepare *is* too early for preparing the reboot_code_buffer and, unless anybody has a good reason not to, I'd like to revert the patch causing these problems. Reported-by: Will Deacon --- arch/arm/kernel/machine_kexec.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index c1b4463dcc83..e59bbd496c39 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -32,24 +32,6 @@ static atomic_t waiting_for_crash_ipi; int machine_kexec_prepare(struct kimage *image) { - unsigned long page_list; - void *reboot_code_buffer; - page_list = image->head & PAGE_MASK; - - reboot_code_buffer = page_address(image->control_code_page); - - /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; - - /* copy our kernel relocation code to the control code page */ - memcpy(reboot_code_buffer, - relocate_new_kernel, relocate_new_kernel_size); - - flush_icache_range((unsigned long) reboot_code_buffer, - (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); return 0; } @@ -100,14 +82,31 @@ void (*kexec_reinit)(void); void machine_kexec(struct kimage *image) { + unsigned long page_list; unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; + + page_list = image->head & PAGE_MASK; + /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); + /* Prepare parameters for reboot_code_buffer*/ + kexec_start_address = image->start; + kexec_indirection_page = page_list; + kexec_mach_type = machine_arch_type; + kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + + /* copy our kernel relocation code to the control code page */ + memcpy(reboot_code_buffer, + relocate_new_kernel, relocate_new_kernel_size); + + + flush_icache_range((unsigned long) reboot_code_buffer, + (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) -- cgit From f3f668b0ef4399b67e60e4c10a30099d630a6206 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 7 Nov 2011 17:19:04 -0200 Subject: Bluetooth: Use miliseconds for L2CAP channel timeouts Timers set by __set_chan_timer() should use miliseconds instead of jiffies. Commit 942ecc9c4643db5ce071562e0a23f99464d6b461 updated l2cap_set_timer() so it expects timeout to be specified in msecs instead of jiffies. This makes timeouts unreliable when CONFIG_HZ is not set to 1000. Signed-off-by: Andrzej Kaczmarek Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/l2cap.h | 7 +++++-- net/bluetooth/l2cap_core.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index ab90ae0970a6..6cc18f371675 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -39,8 +39,11 @@ #define L2CAP_DEFAULT_ACK_TO 200 #define L2CAP_LE_DEFAULT_MTU 23 -#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ -#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ +#define L2CAP_DISC_TIMEOUT (100) +#define L2CAP_DISC_REJ_TIMEOUT (5000) /* 5 seconds */ +#define L2CAP_ENC_TIMEOUT (5000) /* 5 seconds */ +#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ +#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ /* L2CAP socket address */ struct sockaddr_l2 { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8cd12917733b..5ea94a1eecf2 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -251,7 +251,7 @@ static void l2cap_chan_timeout(unsigned long arg) if (sock_owned_by_user(sk)) { /* sk is owned by user. Try again later */ - __set_chan_timer(chan, HZ / 5); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); bh_unlock_sock(sk); chan_put(chan); return; @@ -2488,7 +2488,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd if (sock_owned_by_user(sk)) { l2cap_state_change(chan, BT_DISCONN); __clear_chan_timer(chan); - __set_chan_timer(chan, HZ / 5); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); break; } @@ -2661,7 +2661,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr default: sk->sk_err = ECONNRESET; - __set_chan_timer(chan, HZ * 5); + __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -2718,7 +2718,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd if (sock_owned_by_user(sk)) { l2cap_state_change(chan, BT_DISCONN); __clear_chan_timer(chan); - __set_chan_timer(chan, HZ / 5); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); bh_unlock_sock(sk); return 0; } @@ -2752,7 +2752,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd if (sock_owned_by_user(sk)) { l2cap_state_change(chan,BT_DISCONN); __clear_chan_timer(chan); - __set_chan_timer(chan, HZ / 5); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); bh_unlock_sock(sk); return 0; } @@ -3998,7 +3998,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) if (encrypt == 0x00) { if (chan->sec_level == BT_SECURITY_MEDIUM) { __clear_chan_timer(chan); - __set_chan_timer(chan, HZ * 5); + __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); } else if (chan->sec_level == BT_SECURITY_HIGH) l2cap_chan_close(chan, ECONNREFUSED); } else { @@ -4066,7 +4066,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) L2CAP_CONN_REQ, sizeof(req), &req); } else { __clear_chan_timer(chan); - __set_chan_timer(chan, HZ / 10); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); } } else if (chan->state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -4086,7 +4086,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) } } else { l2cap_state_change(chan, BT_DISCONN); - __set_chan_timer(chan, HZ / 10); + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); res = L2CAP_CR_SEC_BLOCK; stat = L2CAP_CS_NO_INFO; } -- cgit From 45ea6095c8f0d6caad5658306416a5d254f1205e Mon Sep 17 00:00:00 2001 From: "slyich@gmail.com" Date: Mon, 7 Nov 2011 16:08:01 -0500 Subject: btrfs: fix double-free 'tree_root' in 'btrfs_mount()' On error path 'tree_root' is treed in 'free_fs_info()'. No need to free it explicitely. Noticed by SLUB in debug mode: Complete reproducer under usermode linux (discovered on real machine): bdev=/dev/ubda btr_root=/btr /mkfs.btrfs $bdev mount $bdev $btr_root mkdir $btr_root/subvols/ cd $btr_root/subvols/ /btrfs su cr foo /btrfs su cr bar mount $bdev -osubvol=subvols/foo $btr_root/subvols/bar umount $btr_root/subvols/bar which gives device fsid 4d55aa28-45b1-474b-b4ec-da912322195e devid 1 transid 7 /dev/ubda ============================================================================= BUG kmalloc-2048: Object already free ----------------------------------------------------------------------------- INFO: Allocated in btrfs_mount+0x389/0x7f0 age=0 cpu=0 pid=277 INFO: Freed in btrfs_mount+0x51c/0x7f0 age=0 cpu=0 pid=277 INFO: Slab 0x0000000062886200 objects=15 used=9 fp=0x0000000070b4d2d0 flags=0x4081 INFO: Object 0x0000000070b4d2d0 @offset=21200 fp=0x0000000070b4a968 ... Call Trace: 70b31948: [<6008c522>] print_trailer+0xe2/0x130 70b31978: [<6008c5aa>] object_err+0x3a/0x50 70b319a8: [<6008e242>] free_debug_processing+0x142/0x2a0 70b319e0: [<600ebf6f>] btrfs_mount+0x55f/0x7f0 70b319f8: [<6008e5c1>] __slab_free+0x221/0x2d0 Signed-off-by: Sergei Trofimovich Cc: Arne Jansen Cc: Chris Mason Cc: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/super.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 57080dffdfc6..dcd5aef6b614 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -933,8 +933,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, * then open_ctree will properly initialize everything later. */ fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); + if (!fs_info) { + error = -ENOMEM; + goto error_close_devices; + } tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); - if (!fs_info || !tree_root) { + if (!tree_root) { error = -ENOMEM; goto error_close_devices; } @@ -964,7 +968,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, btrfs_close_devices(fs_devices); free_fs_info(fs_info); - kfree(tree_root); } else { char b[BDEVNAME_SIZE]; @@ -992,7 +995,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, error_close_devices: btrfs_close_devices(fs_devices); free_fs_info(fs_info); - kfree(tree_root); return ERR_PTR(error); } -- cgit From a6f498a891c730327645a7afa10c5ae977de6fd8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 7 Nov 2011 15:50:32 -0500 Subject: NFS: Fix a regression in the referral code Fix a regression that was introduced by commit 0c2e53f11a6dae9e3af5f50f5ad0382e7c3e0cfa (NFS: Remove the unused "lookupfh()" version of nfs4_proc_lookup()). In the case where the lookup gets an NFS4ERR_MOVED, we want to return the result of nfs4_get_referral(). Instead, that value is getting clobbered by the call to nfs4_handle_exception()... Reported-by: Tigran Mkrtchyan Tested-by: Tigran Mkrtchyan Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 069cb8094d43..be2bbac13817 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2464,8 +2464,7 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst case -NFS4ERR_BADNAME: return -ENOENT; case -NFS4ERR_MOVED: - err = nfs4_get_referral(dir, name, fattr, fhandle); - break; + return nfs4_get_referral(dir, name, fattr, fhandle); case -NFS4ERR_WRONGSEC: nfs_fixup_secinfo_attributes(fattr, fhandle); } -- cgit From a6f05b97d1ba87326bd96f3da9fef994830d6994 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 6 Nov 2011 21:54:12 +0100 Subject: PM / QoS: Set cpu_dma_pm_qos->name Since commit 4a31a334, the name of this misc device is not initialized, which leads to a funny device named /dev/(null) being created and /proc/misc containing an entry with just a number but no name. The latter leads to complaints by cryptsetup, which caused me to investigate this matter. Signed-off-by: Dominik Brodowski Signed-off-by: Rafael J. Wysocki --- kernel/power/qos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 56db75147186..995e3bd3417b 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -70,6 +70,7 @@ static struct pm_qos_constraints cpu_dma_constraints = { }; static struct pm_qos_object cpu_dma_pm_qos = { .constraints = &cpu_dma_constraints, + .name = "cpu_dma_latency", }; static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); -- cgit From 5f11161675be1351cadb96c83850e20bf5bcdc48 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 6 Nov 2011 22:00:20 +0100 Subject: Documentation: Fix typo in freezer-subsystem.txt Fix a typo in Documentation/cgroups/freezer-subsystem.txt. Signed-off-by: Rafael J. Wysocki Reviewed-by: Srivatsa S. Bhat Acked-by: Randy Dunlap --- Documentation/cgroups/freezer-subsystem.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt index c21d77742a07..7e62de1e59ff 100644 --- a/Documentation/cgroups/freezer-subsystem.txt +++ b/Documentation/cgroups/freezer-subsystem.txt @@ -33,9 +33,9 @@ demonstrate this problem using nested bash shells: From a second, unrelated bash shell: $ kill -SIGSTOP 16690 - $ kill -SIGCONT 16990 + $ kill -SIGCONT 16690 - + This happens because bash can observe both signals and choose how it responds to them. -- cgit From 1a51cfdc4516a6e1f2c1f8a579630a027c30331a Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 7 Nov 2011 23:54:53 +0100 Subject: PM / devfreq: fix private_data The "private_date" field in struct devfreq_dev_status almost certainly wants to be "private_data"; since there are no in-tree users of this functionality, now seems like an easy time to make the fix. Signed-off-by: Jonathan Corbet Signed-off-by: Rafael J. Wysocki --- include/linux/devfreq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index afb94583960c..98ce8124b1cc 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -41,7 +41,7 @@ struct devfreq_dev_status { unsigned long total_time; unsigned long busy_time; unsigned long current_frequency; - void *private_date; + void *private_data; }; /** -- cgit From 5698eb4eda657fd4a74612a65cd5d583f35a5bdb Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 7 Nov 2011 15:58:40 -0800 Subject: ARM: OMAP3: CPUidle: include The CPUidle use THIS_MODULE, so needs Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/cpuidle34xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 4bf6e6e8b100..2e0fa5a4aaeb 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -24,6 +24,7 @@ #include #include +#include #include #include -- cgit From 4e549d6d4a32d1a610ad081841d575f64087744a Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 6 Nov 2011 12:57:31 +0100 Subject: MTD: MAPS: bcm963xx-flash.c: explicitly include module.h module.h was previously implicitly included through mtd/mtd.h. Fixes the following build failure after the module.h cleanup: CC drivers/mtd/maps/bcm963xx-flash.o drivers/mtd/maps/bcm963xx-flash.c: In function 'bcm963xx_probe': drivers/mtd/maps/bcm963xx-flash.c:208:29: error: 'THIS_MODULE' undeclared (first use in this function) [...] drivers/mtd/maps/bcm963xx-flash.c:276:1: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' drivers/mtd/maps/bcm963xx-flash.c:276:15: warning: function declaration isn't a prototype make[7]: *** [drivers/mtd/maps/bcm963xx-flash.o] Error 1 Signed-off-by: Jonas Gorski Signed-off-by: Paul Gortmaker --- drivers/mtd/maps/bcm963xx-flash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c index 608967fe74c6..736ca10ca9f1 100644 --- a/drivers/mtd/maps/bcm963xx-flash.c +++ b/drivers/mtd/maps/bcm963xx-flash.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include -- cgit From 8f7346bdea64f2e3d02b0bcaf456e391c4cba134 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 6 Nov 2011 21:16:51 +0800 Subject: hwspinlock/u8500: include linux/module.h Include module.h to fix below build error: CC drivers/hwspinlock/u8500_hsem.o drivers/hwspinlock/u8500_hsem.c:177: error: 'THIS_MODULE' undeclared here (not in a function) [...] drivers/hwspinlock/u8500_hsem.c:196: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' drivers/hwspinlock/u8500_hsem.c:196: warning: function declaration isn't a prototype make[2]: *** [drivers/hwspinlock/u8500_hsem.o] Error 1 make[1]: *** [drivers/hwspinlock] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Paul Gortmaker --- drivers/hwspinlock/u8500_hsem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c index 143461a95ae4..0156af510032 100644 --- a/drivers/hwspinlock/u8500_hsem.c +++ b/drivers/hwspinlock/u8500_hsem.c @@ -21,6 +21,7 @@ * General Public License for more details. */ +#include #include #include #include -- cgit From 3b8ce3aed986090d9249629f97c53b4dfb8c9783 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 7 Nov 2011 11:17:04 -0500 Subject: mfd: fix build failures in recently added ab5500 code These files had implicit dependencies on modular support which now show up as build failures with the module cleanup work merged to mainline. Reported-by: Axel Lin Signed-off-by: Paul Gortmaker --- drivers/mfd/ab5500-core.c | 1 + drivers/mfd/ab5500-debugfs.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c index 4175544b491b..ec10629a0b0b 100644 --- a/drivers/mfd/ab5500-core.c +++ b/drivers/mfd/ab5500-core.c @@ -13,6 +13,7 @@ * TODO: Event handling with irq_chip. Waiting for PRCMU fw support. */ +#include #include #include #include diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c index 6be1fe6b5f9a..43c0ebb81956 100644 --- a/drivers/mfd/ab5500-debugfs.c +++ b/drivers/mfd/ab5500-debugfs.c @@ -4,6 +4,7 @@ * Debugfs support for the AB5500 MFD driver */ +#include #include #include #include -- cgit From 406478dc911e16677fbd9c84d1d50cdffbc031ab Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 7 Nov 2011 16:07:04 -0800 Subject: drm/i915: Turn on a required 3D clock gating bit on Sandybridge. Fixes rendering failures in Unigine Tropics and Sanctuary and the mesa "fire" demo. Signed-off-by: Eric Anholt Cc: stable@kernel.org Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5a09416e611f..b807275ea739 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3444,6 +3444,9 @@ #define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_NUM_RESERVED_ENTRIES 20 +#define GEN6_UCGCTL2 0x9404 +# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) + #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) #define GEN6_FREQUENCY(x) ((x)<<25) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9fa342e89454..2b2a7645cd0c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8148,6 +8148,15 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after + * some amount of runtime in the Mesa "fire" demo, and Unigine + * Sanctuary and Tropics, and apparently anything else with + * alpha test or pixel discard. + */ + I915_WRITE(GEN6_UCGCTL2, GEN6_RCPBUNIT_CLOCK_GATE_DISABLE); + /* * According to the spec the following bits should be * set in order to enable memory self-refresh and fbc: -- cgit From 9ca1d10d748e56964de95e3ed80211b192f56cf4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 7 Nov 2011 16:07:05 -0800 Subject: drm/i915: Turn on another required clock gating bit on gen6. Unlike the previous one, I don't have known testcases it fixes. I'd rather not go through the same debug cycle on whatever testcases those might be. Signed-off-by: Eric Anholt Cc: stable@kernel.org Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b807275ea739..a34e86630f26 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3446,6 +3446,7 @@ #define GEN6_UCGCTL2 0x9404 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) +# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2b2a7645cd0c..591eb0ed3110 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8154,8 +8154,13 @@ static void gen6_init_clock_gating(struct drm_device *dev) * some amount of runtime in the Mesa "fire" demo, and Unigine * Sanctuary and Tropics, and apparently anything else with * alpha test or pixel discard. + * + * According to the spec, bit 11 (RCCUNIT) must also be set, + * but we didn't debug actual testcases to find it out. */ - I915_WRITE(GEN6_UCGCTL2, GEN6_RCPBUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN6_UCGCTL2, + GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | + GEN6_RCCUNIT_CLOCK_GATE_DISABLE); /* * According to the spec the following bits should be -- cgit From ad61d64e263228a418fe25809a23d5107cf778a0 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2011 13:36:56 +0000 Subject: powerpc/kvm: Fix build with older toolchains Fix KVM build for older toolchains (found with .powerpc64-unknown-linux-gnu-gcc (crosstool-NG-1.8.1) 4.3.2): AS arch/powerpc/kvm/book3s_hv_rmhandlers.o arch/powerpc/kvm/book3s_hv_rmhandlers.S: Assembler messages: arch/powerpc/kvm/book3s_hv_rmhandlers.S:1388: Error: Unrecognized opcode: `popcntw' make[1]: *** [arch/powerpc/kvm/book3s_hv_rmhandlers.o] Error 1 make: *** [_module_arch/powerpc/kvm] Error 2 Signed-off-by: Nishanth Aravamudan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index f422231d9235..44d8829334ab 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -1263,7 +1263,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) addi r6,r5,VCORE_NAPPING_THREADS 31: lwarx r4,0,r6 or r4,r4,r0 - popcntw r7,r4 + PPC_POPCNTW(r7,r4) cmpw r7,r8 bge 2f stwcx. r4,0,r6 -- cgit From 88cf11b4cca8ee0044d0a10ce100d8c0012b2c5e Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 7 Nov 2011 14:49:13 +0000 Subject: powerpc: Add KVM as module to defconfigs Add HV mode KVM to Book3 server 64bit defconfigs as a module. Doesn't add much to the size: text data bss dec hex filename 8244109 4686767 994000 13924876 d47a0c vmlinux.vanilla 8256092 4691607 994128 13941827 d4bc43 vmlinux.kvm This should enable more testing of this configuration. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/configs/ppc64_defconfig | 4 ++++ arch/powerpc/configs/pseries_defconfig | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 84a685a505fe..535711fcb13c 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -485,3 +485,7 @@ CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_BOOK3S_64=m +CONFIG_KVM_BOOK3S_64_HV=y +CONFIG_VHOST_NET=m diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 96a58b709705..a72f2415a647 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -362,3 +362,7 @@ CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +CONFIG_VIRTUALIZATION=y +CONFIG_KVM_BOOK3S_64=m +CONFIG_KVM_BOOK3S_64_HV=y +CONFIG_VHOST_NET=m -- cgit From c40dd2f76644016ca7677545fc846ec2470d70a1 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 2 Nov 2011 14:56:12 +0000 Subject: powerpc: Add System RAM to /proc/iomem We've resisted adding System RAM to /proc/iomem because it is the wrong place for it. Unfortunately we continue to find tools that rely on this behaviour so give up and add it in. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/mem.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 16da595ff402..2dd6bdd31fe1 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -555,3 +556,32 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, book3e_hugetlb_preload(vma->vm_mm, address, *ptep); #endif } + +/* + * System memory should not be in /proc/iomem but various tools expect it + * (eg kdump). + */ +static int add_system_ram_resources(void) +{ + struct memblock_region *reg; + + for_each_memblock(memory, reg) { + struct resource *res; + unsigned long base = reg->base; + unsigned long size = reg->size; + + res = kzalloc(sizeof(struct resource), GFP_KERNEL); + WARN_ON(!res); + + if (res) { + res->name = "System RAM"; + res->start = base; + res->end = base + size - 1; + res->flags = IORESOURCE_MEM; + WARN_ON(request_resource(&iomem_resource, res) < 0); + } + } + + return 0; +} +subsys_initcall(add_system_ram_resources); -- cgit From 1c8ee73395af762726e9eb628636d3b763618c60 Mon Sep 17 00:00:00 2001 From: Dipankar Sarma Date: Fri, 28 Oct 2011 04:25:32 +0000 Subject: powerpc/numa: NUMA topology support for PowerNV This patch adds support for numa topology on powernv platforms running OPAL formware. It checks for the type of platform at run time and sets the affinity form correctly so that NUMA topology can be discovered correctly. Signed-off-by: Dipankar Sarma Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/numa.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index c7dd4dec4df8..b22a83a91cb8 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -315,7 +315,10 @@ static int __init find_min_common_depth(void) struct device_node *root; const char *vec5; - root = of_find_node_by_path("/rtas"); + if (firmware_has_feature(FW_FEATURE_OPAL)) + root = of_find_node_by_path("/ibm,opal"); + else + root = of_find_node_by_path("/rtas"); if (!root) root = of_find_node_by_path("/"); @@ -344,12 +347,19 @@ static int __init find_min_common_depth(void) #define VEC5_AFFINITY_BYTE 5 #define VEC5_AFFINITY 0x80 - chosen = of_find_node_by_path("/chosen"); - if (chosen) { - vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL); - if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) { - dbg("Using form 1 affinity\n"); - form1_affinity = 1; + + if (firmware_has_feature(FW_FEATURE_OPAL)) + form1_affinity = 1; + else { + chosen = of_find_node_by_path("/chosen"); + if (chosen) { + vec5 = of_get_property(chosen, + "ibm,architecture-vec-5", NULL); + if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & + VEC5_AFFINITY)) { + dbg("Using form 1 affinity\n"); + form1_affinity = 1; + } } } -- cgit From a3a9f3b47d12b5f6dfc9c7ed9d7b193d77812195 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Fri, 21 Oct 2011 23:56:27 +0000 Subject: powerpc/irq: Remove IRQF_DISABLED Since commit [e58aa3d2: genirq: Run irq handlers with interrupts disabled], We run all interrupt handlers with interrupts disabled and we even check and yell when an interrupt handler returns with interrupts enabled (see commit [b738a50a: genirq: Warn when handler enables interrupts]). So now this flag is a NOOP and can be removed. Signed-off-by: Yong Zhang Acked-by: Arnd Bergmann Acked-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/floppy.h | 4 ++-- arch/powerpc/include/asm/xics.h | 4 ++-- arch/powerpc/kernel/smp.c | 2 +- arch/powerpc/platforms/cell/beat.c | 2 +- arch/powerpc/platforms/cell/celleb_scc_pciex.c | 2 +- arch/powerpc/platforms/cell/iommu.c | 3 +-- arch/powerpc/platforms/cell/pmu.c | 2 +- arch/powerpc/platforms/cell/spu_base.c | 9 +++------ arch/powerpc/platforms/powermac/pic.c | 1 - arch/powerpc/platforms/powermac/smp.c | 4 ++-- arch/powerpc/platforms/ps3/device-init.c | 2 +- arch/powerpc/sysdev/mpic.c | 2 -- arch/powerpc/sysdev/ppc4xx_soc.c | 2 +- arch/powerpc/sysdev/xics/xics-common.c | 5 ++--- 14 files changed, 18 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/include/asm/floppy.h b/arch/powerpc/include/asm/floppy.h index 24bd34c57e9d..936a904ae78c 100644 --- a/arch/powerpc/include/asm/floppy.h +++ b/arch/powerpc/include/asm/floppy.h @@ -108,10 +108,10 @@ static int fd_request_irq(void) { if (can_use_virtual_dma) return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + 0, "floppy", NULL); else return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + 0, "floppy", NULL); } static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h index bd6c401c0ee5..c48de98ba94e 100644 --- a/arch/powerpc/include/asm/xics.h +++ b/arch/powerpc/include/asm/xics.h @@ -15,8 +15,8 @@ #define DEFAULT_PRIORITY 5 /* - * Mark IPIs as higher priority so we can take them inside interrupts that - * arent marked IRQF_DISABLED + * Mark IPIs as higher priority so we can take them inside interrupts + * FIXME: still true now? */ #define IPI_PRIORITY 4 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 25ddbfc7dd36..6df70907d60a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -187,7 +187,7 @@ int smp_request_message_ipi(int virq, int msg) return 1; } #endif - err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU, + err = request_irq(virq, smp_ipi_action[msg], IRQF_PERCPU, smp_ipi_name[msg], 0); WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n", virq, smp_ipi_name[msg], err); diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c index 232fc384e855..852592b2b712 100644 --- a/arch/powerpc/platforms/cell/beat.c +++ b/arch/powerpc/platforms/cell/beat.c @@ -230,7 +230,7 @@ static int __init beat_register_event(void) } ev->virq = virq; - rc = request_irq(virq, ev->handler, IRQF_DISABLED, + rc = request_irq(virq, ev->handler, 0, ev->typecode, NULL); if (rc != 0) { printk(KERN_ERR "Beat: failed to request virtual IRQ" diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c index ae790ac4a589..14be2bd358b8 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c +++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c @@ -514,7 +514,7 @@ static __init int celleb_setup_pciex(struct device_node *node, virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (request_irq(virq, pciex_handle_internal_irq, - IRQF_DISABLED, "pciex", (void *)phb)) { + 0, "pciex", (void *)phb)) { pr_err("PCIEXC:Failed to request irq\n"); goto error; } diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index fc46fcac3921..592c3d51b817 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -412,8 +412,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu) IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT)); BUG_ON(virq == NO_IRQ); - ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED, - iommu->name, iommu); + ret = request_irq(virq, ioc_interrupt, 0, iommu->name, iommu); BUG_ON(ret); /* set the IOC segment table origin register (and turn on the iommu) */ diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index 1acf36010423..59c1a1694104 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -392,7 +392,7 @@ static int __init cbe_init_pm_irq(void) } rc = request_irq(irq, cbe_pm_irq, - IRQF_DISABLED, "cbe-pmu-0", NULL); + 0, "cbe-pmu-0", NULL); if (rc) { printk("ERROR: Request for irq on node %d failed\n", node); diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 3675da73623f..e94d3ecdd8bb 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -442,8 +442,7 @@ static int spu_request_irqs(struct spu *spu) snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number); ret = request_irq(spu->irqs[0], spu_irq_class_0, - IRQF_DISABLED, - spu->irq_c0, spu); + 0, spu->irq_c0, spu); if (ret) goto bail0; } @@ -451,8 +450,7 @@ static int spu_request_irqs(struct spu *spu) snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number); ret = request_irq(spu->irqs[1], spu_irq_class_1, - IRQF_DISABLED, - spu->irq_c1, spu); + 0, spu->irq_c1, spu); if (ret) goto bail1; } @@ -460,8 +458,7 @@ static int spu_request_irqs(struct spu *spu) snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number); ret = request_irq(spu->irqs[2], spu_irq_class_2, - IRQF_DISABLED, - spu->irq_c2, spu); + 0, spu->irq_c2, spu); if (ret) goto bail2; } diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index cb40e921a565..901bfbddc3dd 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -272,7 +272,6 @@ static struct irqaction xmon_action = { static struct irqaction gatwick_cascade_action = { .handler = gatwick_action, - .flags = IRQF_DISABLED, .name = "cascade", }; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 9a521dc8e485..9b6a820bdd7d 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -200,7 +200,7 @@ static int psurge_secondary_ipi_init(void) if (psurge_secondary_virq) rc = request_irq(psurge_secondary_virq, psurge_ipi_intr, - IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL); + IRQF_PERCPU, "IPI", NULL); if (rc) pr_err("Failed to setup secondary cpu IPI\n"); @@ -408,7 +408,7 @@ static int __init smp_psurge_kick_cpu(int nr) static struct irqaction psurge_irqaction = { .handler = psurge_ipi_intr, - .flags = IRQF_DISABLED|IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "primary IPI", }; diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index 6c4b5837fc8a..3f175e8aedb4 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c @@ -825,7 +825,7 @@ static int ps3_probe_thread(void *data) spin_lock_init(&dev.lock); - res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED, + res = request_irq(irq, ps3_notification_interrupt, 0, "ps3_notification", &dev); if (res) { pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__, diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 0842c6f8a3e6..8c7e8528e7c4 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data *d) * IPIs are marked IRQ_PER_CPU. This has the side effect of * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from * applying to them. We EOI them late to avoid re-entering. - * We mark IPI's with IRQF_DISABLED as they must run with - * irqs disabled. */ mpic_eoi(mpic); } diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c index d3d6ce3c33b4..0debcc31ad70 100644 --- a/arch/powerpc/sysdev/ppc4xx_soc.c +++ b/arch/powerpc/sysdev/ppc4xx_soc.c @@ -115,7 +115,7 @@ static int __init ppc4xx_l2c_probe(void) } /* Install error handler */ - if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) { + if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) { printk(KERN_ERR "Cannot install L2C error handler" ", cache is not enabled\n"); of_node_put(np); diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 3d93a8ded0f8..63762c672a03 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -134,11 +134,10 @@ static void xics_request_ipi(void) BUG_ON(ipi == NO_IRQ); /* - * IPIs are marked IRQF_DISABLED as they must run with irqs - * disabled, and PERCPU. The handler was set in map. + * IPIs are marked IRQF_PERCPU. The handler was set in map. */ BUG_ON(request_irq(ipi, icp_ops->ipi_action, - IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL)); + IRQF_PERCPU, "IPI", NULL)); } int __init xics_smp_probe(void) -- cgit From 6ea741a13690da9dbbac76175db8e313b0c4b817 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Fri, 21 Oct 2011 23:56:53 +0000 Subject: powerpc/ps3: irq: Remove IRQF_DISABLED Since commit [e58aa3d2: genirq: Run irq handlers with interrupts disabled], We run all interrupt handlers with interrupts disabled and we even check and yell when an interrupt handler returns with interrupts enabled (see commit [b738a50a: genirq: Warn when handler enables interrupts]). So now this flag is a NOOP and can be removed. Signed-off-by: Yong Zhang Acked-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- drivers/ps3/ps3-vuart.c | 2 +- drivers/ps3/ps3stor_lib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ps3/ps3-vuart.c b/drivers/ps3/ps3-vuart.c index d9fb729535a1..fb7300837fee 100644 --- a/drivers/ps3/ps3-vuart.c +++ b/drivers/ps3/ps3-vuart.c @@ -952,7 +952,7 @@ static int ps3_vuart_bus_interrupt_get(void) } result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, - IRQF_DISABLED, "vuart", &vuart_bus_priv); + 0, "vuart", &vuart_bus_priv); if (result) { pr_debug("%s:%d: request_irq failed (%d)\n", diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c index cc328dec946b..8c3f5adf1bc6 100644 --- a/drivers/ps3/ps3stor_lib.c +++ b/drivers/ps3/ps3stor_lib.c @@ -167,7 +167,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler) goto fail_close_device; } - error = request_irq(dev->irq, handler, IRQF_DISABLED, + error = request_irq(dev->irq, handler, 0, dev->sbd.core.driver->name, dev); if (error) { dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n", -- cgit From 5233e26ebb90242e3691c185ddda02dc83649e7d Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 12 Oct 2011 08:39:15 +0000 Subject: powerpc/ps3: Fix PS3 repository build warnings Fix uninitialized variable warnings in build of repository.c Signed-off-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/ps3/repository.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index 5e304c292f68..ca40f6afd35d 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c @@ -184,7 +184,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index, enum ps3_bus_type *bus_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -199,7 +199,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index, unsigned int *num_dev) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -239,7 +239,7 @@ int ps3_repository_read_dev_type(unsigned int bus_index, unsigned int dev_index, enum ps3_dev_type *dev_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -256,8 +256,8 @@ int ps3_repository_read_dev_intr(unsigned int bus_index, enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id) { int result; - u64 v1; - u64 v2; + u64 v1 = 0; + u64 v2 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -275,7 +275,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index, enum ps3_reg_type *reg_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -615,7 +615,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, unsigned int dev_index, unsigned int *num_regions) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -631,7 +631,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, unsigned int *region_id) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -786,7 +786,7 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -805,7 +805,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -827,8 +827,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index, enum ps3_spu_resource_type *resource_type, unsigned int *resource_id) { int result; - u64 v1; - u64 v2; + u64 v1 = 0; + u64 v2 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -854,7 +854,7 @@ static int ps3_repository_read_boot_dat_address(u64 *address) int ps3_repository_read_boot_dat_size(unsigned int *size) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -869,7 +869,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) int ps3_repository_read_vuart_av_port(unsigned int *port) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -884,7 +884,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port) int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -919,7 +919,7 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) int ps3_repository_read_num_be(unsigned int *num_be) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("ben", 0), -- cgit From 9fce85f7ff94f1a877c15ad3d6ffbaed4b5cd1a6 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 12 Oct 2011 08:42:13 +0000 Subject: powerpc/ps3: Fix lv1_gpu_attribute hcall The lv1_gpu_attribute hcall takes three, not five input arguments. Adjust the lv1 hcall table and all calls. Signed-off-by: Geoff Levand CC: Takashi Iwai Acked-by: Takashi Iwai Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/lv1call.h | 2 +- sound/ppc/snd_ps3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/lv1call.h b/arch/powerpc/include/asm/lv1call.h index 9cd5fc828a37..f77c708c67a0 100644 --- a/arch/powerpc/include/asm/lv1call.h +++ b/arch/powerpc/include/asm/lv1call.h @@ -316,7 +316,7 @@ LV1_CALL(gpu_context_free, 1, 0, 218 ) LV1_CALL(gpu_context_iomap, 5, 0, 221 ) LV1_CALL(gpu_context_attribute, 6, 0, 225 ) LV1_CALL(gpu_context_intr, 1, 1, 227 ) -LV1_CALL(gpu_attribute, 5, 0, 228 ) +LV1_CALL(gpu_attribute, 3, 0, 228 ) LV1_CALL(get_rtc, 0, 2, 232 ) LV1_CALL(set_ppe_periodic_tracer_frequency, 1, 0, 240 ) LV1_CALL(start_ppe_periodic_tracer, 5, 0, 241 ) diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index a3ce1b22620d..1aa52eff526a 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -876,7 +876,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) (0x0fUL << 12) | (PS3_AUDIO_IOID); - ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0); + ret = lv1_gpu_attribute(0x100, 0x007, val); if (ret) pr_info("%s: gpu_attribute failed %d\n", __func__, ret); -- cgit From 5ccf55dd8177295813b68780f0a3c85e47306be1 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 13 Sep 2011 04:15:31 +0000 Subject: powerpc/kvm: Fix build failure with HV KVM and CBE When running with HV KVM and CBE config options enabled, I get build failures like the following: arch/powerpc/kernel/head_64.o: In function `cbe_system_error_hv': (.text+0x1228): undefined reference to `do_kvm_0x1202' arch/powerpc/kernel/head_64.o: In function `cbe_maintenance_hv': (.text+0x1628): undefined reference to `do_kvm_0x1602' arch/powerpc/kernel/head_64.o: In function `cbe_thermal_hv': (.text+0x1828): undefined reference to `do_kvm_0x1802' This is because we jump to a KVM handler when HV is enabled, but we only generate the handler with PR KVM mode. Signed-off-by: Alexander Graf Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/exceptions-64s.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index a54d92fec612..cf9c69b9189c 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -267,7 +267,7 @@ vsx_unavailable_pSeries_1: #ifdef CONFIG_CBE_RAS STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error) - KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202) + KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202) #endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint) @@ -275,7 +275,7 @@ vsx_unavailable_pSeries_1: #ifdef CONFIG_CBE_RAS STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance) - KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602) + KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602) #endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist) @@ -283,7 +283,7 @@ vsx_unavailable_pSeries_1: #ifdef CONFIG_CBE_RAS STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal) - KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802) + KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802) #endif /* CONFIG_CBE_RAS */ . = 0x3000 -- cgit From 9a3f530f39f4490eaa18b02719fb74ce5f4d2d86 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2011 16:22:01 +1100 Subject: md/raid5: abort any pending parity operations when array fails. When the number of failed devices exceeds the allowed number we must abort any active parity operations (checks or updates) as they are no longer meaningful, and can lead to a BUG_ON in handle_parity_checks6. This bug was introduce by commit 6c0069c0ae9659e3a91b68eaed06a5c6c37f45c8 in 2.6.29. Reported-by: Manish Katiyar Tested-by: Manish Katiyar Acked-by: Dan Williams Signed-off-by: NeilBrown Cc: stable@kernel.org --- drivers/md/raid5.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 472aedfb07cf..318bdae9b56c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3159,10 +3159,14 @@ static void handle_stripe(struct stripe_head *sh) /* check if the array has lost more than max_degraded devices and, * if so, some requests might need to be failed. */ - if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written) - handle_failed_stripe(conf, sh, &s, disks, &s.return_bi); - if (s.failed > conf->max_degraded && s.syncing) - handle_failed_sync(conf, sh, &s); + if (s.failed > conf->max_degraded) { + sh->check_state = 0; + sh->reconstruct_state = 0; + if (s.to_read+s.to_write+s.written) + handle_failed_stripe(conf, sh, &s, disks, &s.return_bi); + if (s.syncing) + handle_failed_sync(conf, sh, &s); + } /* * might be able to return some write requests if the parity blocks -- cgit From 257a4b42af7586fab4eaec7f04e6896b86551843 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Nov 2011 16:22:06 +1100 Subject: md/raid5: STRIPE_ACTIVE has lock semantics, add barriers All updates that occur under STRIPE_ACTIVE should be globally visible when STRIPE_ACTIVE clears. test_and_set_bit() implies a barrier, but clear_bit() does not. This is suitable for 3.1-stable. Signed-off-by: Dan Williams Signed-off-by: NeilBrown Cc: stable@kernel.org --- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 318bdae9b56c..297e26092178 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3110,7 +3110,7 @@ static void handle_stripe(struct stripe_head *sh) struct r5dev *pdev, *qdev; clear_bit(STRIPE_HANDLE, &sh->state); - if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) { + if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) { /* already being handled, ensure it gets handled * again when current action finishes */ set_bit(STRIPE_HANDLE, &sh->state); @@ -3375,7 +3375,7 @@ finish: return_io(s.return_bi); - clear_bit(STRIPE_ACTIVE, &sh->state); + clear_bit_unlock(STRIPE_ACTIVE, &sh->state); } static void raid5_activate_delayed(struct r5conf *conf) -- cgit From 5a9a51799b23142d2fc3ef94894d3b5ac00d05a5 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Mon, 7 Nov 2011 20:33:25 +0400 Subject: ALSA: intel8x0: Improve comments for VM optimization The recently merged 228cf79376f1 looks a bit hackish while it is not. The change was quite simple. In a virtualized environment the patch unhacks old kludge introduced for old broken AC97 hardware. This patch adds proper comment to "unkludge" code. Signed-off-by: Denis V. Lunev Signed-off-by: Konstantin Ozerkov Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 29e312597f20..c3b9bd0e188e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1077,6 +1077,13 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs } if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) continue; + + /* IO read operation is very expensive inside virtual machine + * as it is emulated. The probability that subsequent PICB read + * will return different result is high enough to loop till + * timeout here. + * Same CIV is strict enough condition to be sure that PICB + * is valid inside VM on emulated card. */ if (chip->inside_vm) break; if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) -- cgit From dccc1810f41b42773a2e359907f05a7fd10910bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Nov 2011 07:52:19 +0100 Subject: ALSA: hda - Mute unused capture sources for Realtek codecs When a Realtek codec has a matrix-style capture-source selection, we need to scan all connections instead of only imux items. Otherwise some input might be kept unmuted. Although the corresponding input must be dead so there should be no input from it, it's still safer to mute the route completely. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a24e068a021b..308bb575bc06 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -284,7 +284,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, struct alc_spec *spec = codec->spec; const struct hda_input_mux *imux; unsigned int mux_idx; - int i, type; + int i, type, num_conns; hda_nid_t nid; mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; @@ -307,16 +307,17 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; /* no selection? */ - if (snd_hda_get_conn_list(codec, nid, NULL) <= 1) + num_conns = snd_hda_get_conn_list(codec, nid, NULL); + if (num_conns <= 1) return 1; type = get_wcaps_type(get_wcaps(codec, nid)); if (type == AC_WID_AUD_MIX) { /* Matrix-mixer style (e.g. ALC882) */ - for (i = 0; i < imux->num_items; i++) { - unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, - imux->items[i].index, + int active = imux->items[idx].index; + for (i = 0; i < num_conns; i++) { + unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE; + snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i, HDA_AMP_MUTE, v); } } else { -- cgit From 816af3bb5022c1468b3d826c645ddc2cac45bc97 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 3 Nov 2011 14:45:48 +0800 Subject: hwspinlock: Don't return a value in __hwspin_unlock Fix below build warning: CC arch/arm/mach-omap2/hwspinlock.o In file included from arch/arm/mach-omap2/hwspinlock.c:22: include/linux/hwspinlock.h: In function '__hwspin_unlock': include/linux/hwspinlock.h:121: warning: 'return' with a value, in function returning void Signed-off-by: Axel Lin Signed-off-by: Ohad Ben-Cohen --- include/linux/hwspinlock.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h index 08a2fee40659..aad6bd4b3efd 100644 --- a/include/linux/hwspinlock.h +++ b/include/linux/hwspinlock.h @@ -118,7 +118,6 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) static inline void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags) { - return 0; } static inline int hwspin_lock_get_id(struct hwspinlock *hwlock) -- cgit From fdcb23634c9b6649bb02c681033d4973491b0e35 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 6 Nov 2011 21:14:16 +0800 Subject: hwspinlock/u8500: fix build error due to undefined label Fix below build error: CC drivers/hwspinlock/u8500_hsem.o drivers/hwspinlock/u8500_hsem.c: In function 'u8500_hsem_probe': drivers/hwspinlock/u8500_hsem.c:113: error: label 'free_state' used but not defined Signed-off-by: Axel Lin Signed-off-by: Ohad Ben-Cohen --- drivers/hwspinlock/u8500_hsem.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c index 143461a95ae4..a120f14814f9 100644 --- a/drivers/hwspinlock/u8500_hsem.c +++ b/drivers/hwspinlock/u8500_hsem.c @@ -108,10 +108,8 @@ static int __devinit u8500_hsem_probe(struct platform_device *pdev) return -ENODEV; io_base = ioremap(res->start, resource_size(res)); - if (!io_base) { - ret = -ENOMEM; - goto free_state; - } + if (!io_base) + return -ENOMEM; /* make sure protocol 1 is selected */ val = readl(io_base + HSEM_CTRL_REG); -- cgit From 1258ea596fe0422272525d9ec8a25b703de4623f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:09 -0700 Subject: ARM: OMAP2xxx: HWMOD: Fix DSS reset DSS needs all DSS clocks to be enabled to be able to finish reset properly. Before v3.1-rc1 the omapdss driver was managing clocks and resets correctly. However, when omapdss started using runtime PM at v3.1-rc1, the responsibility for the reset moved to HWMOD framework. HWMOD framework does not currently enable all the DSS clocks when resetting the DSS hardware. This hasn't caused any problems so far, but we may just have been lucky. This patch sets HWMOD_CONTROL_OPT_CLKS_IN_RESET for dss_core in OMAP2xxx HWMOD data, fixing the issue. Signed-off-by: Tomi Valkeinen [paul@pwsan.com: merged duplicate .flags fields] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 6 +++++- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 6d7206213525..5160e3509d5d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -875,6 +875,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { + /* + * The DSS HW needs all DSS clocks enabled during reset. The dss_core + * driver does not use these clocks. + */ { .role = "tv_clk", .clk = "dss_54m_fck" }, { .role = "sys_clk", .clk = "dss2_fck" }, }; @@ -899,7 +903,7 @@ static struct omap_hwmod omap2420_dss_core_hwmod = { .slaves_cnt = ARRAY_SIZE(omap2420_dss_slaves), .masters = omap2420_dss_masters, .masters_cnt = ARRAY_SIZE(omap2420_dss_masters), - .flags = HWMOD_NO_IDLEST, + .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET, }; /* l4_core -> dss_dispc */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index a2580d01c3ff..d02a44ea7f9b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -942,6 +942,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { + /* + * The DSS HW needs all DSS clocks enabled during reset. The dss_core + * driver does not use these clocks. + */ { .role = "tv_clk", .clk = "dss_54m_fck" }, { .role = "sys_clk", .clk = "dss2_fck" }, }; @@ -966,7 +970,7 @@ static struct omap_hwmod omap2430_dss_core_hwmod = { .slaves_cnt = ARRAY_SIZE(omap2430_dss_slaves), .masters = omap2430_dss_masters, .masters_cnt = ARRAY_SIZE(omap2430_dss_masters), - .flags = HWMOD_NO_IDLEST, + .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET, }; /* l4_core -> dss_dispc */ -- cgit From b8ac10d8b75843c9ddd6aadf70a0cdf8aa783659 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:09 -0700 Subject: ARM: OMAP2xxx: HWMOD: fix DSS clock data The OMAP2xxx HWMOD data currently contains two errors with DSS clocks: - dss_rfbi is missing ick opt-clock, which is needed for RFBI to calculate timings - dss_venc's interface and main clocks are wrong, causing VENC to fail to start These problems were temporarily fixed with a DSS patch 9ede365aa6f74428a1f69c21ca1cf21213167576 ("HACK: OMAP: DSS2: clk hack for OMAP2/3"), which can be reverted after this patch (and the similar patches for other OMAPs). Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 10 ++++++++-- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 5160e3509d5d..74037a5807af 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -965,6 +965,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = { &omap2420_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { + { .role = "ick", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap2420_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap2_rfbi_hwmod_class, @@ -976,6 +980,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = dss_rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), .slaves = omap2420_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves), .flags = HWMOD_NO_IDLEST, @@ -985,7 +991,7 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = { static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = { .master = &omap2420_l4_core_hwmod, .slave = &omap2420_dss_venc_hwmod, - .clk = "dss_54m_fck", + .clk = "dss_ick", .addr = omap2_dss_venc_addrs, .fw = { .omap2 = { @@ -1005,7 +1011,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = { static struct omap_hwmod omap2420_dss_venc_hwmod = { .name = "dss_venc", .class = &omap2_venc_hwmod_class, - .main_clk = "dss1_fck", + .main_clk = "dss_54m_fck", .prcm = { .omap2 = { .prcm_reg_id = 1, diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index d02a44ea7f9b..6f0365388dfc 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1020,6 +1020,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = { &omap2430_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { + { .role = "ick", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap2430_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap2_rfbi_hwmod_class, @@ -1031,6 +1035,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = dss_rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), .slaves = omap2430_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves), .flags = HWMOD_NO_IDLEST, @@ -1040,7 +1046,7 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = { static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = { .master = &omap2430_l4_core_hwmod, .slave = &omap2430_dss_venc_hwmod, - .clk = "dss_54m_fck", + .clk = "dss_ick", .addr = omap2_dss_venc_addrs, .flags = OCPIF_SWSUP_IDLE, .user = OCP_USER_MPU | OCP_USER_SDMA, @@ -1054,7 +1060,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = { static struct omap_hwmod omap2430_dss_venc_hwmod = { .name = "dss_venc", .class = &omap2_venc_hwmod_class, - .main_clk = "dss1_fck", + .main_clk = "dss_54m_fck", .prcm = { .omap2 = { .prcm_reg_id = 1, -- cgit From 8c3105ca1a42783b13930fbd375484ec8c72e608 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:10 -0700 Subject: ARM: OMAP3: HWMOD: Fix DSS reset DSS needs all DSS clocks to be enabled to be able to finish reset properly. Before v3.1-rc1 the omapdss driver was managing clocks and resets correctly. However, when omapdss started using runtime PM at v3.1-rc1, the responsibility for the reset moved to HWMOD framework. HWMOD framework does not currently enable all the DSS clocks when resetting the DSS hardware. This hasn't caused any problems so far, but we may just have been lucky. dss_core's opt-clocks is also missing dss_96m_fck, which is a DSS clock present only on OMAP3430, and thus required on OMAP3430 to finish the reset. This patch sets HWMOD_CONTROL_OPT_CLKS_IN_RESET and adds the dss_96m_fck opt-clock for dss_core in OMAP3 HWMOD data, fixing the issue. Signed-off-by: Tomi Valkeinen [paul@pwsan.com: merged duplicate .flags fields] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index bc9035ec87fc..45ccd4f07cff 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1369,9 +1369,14 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "tv_clk", .clk = "dss_tv_fck" }, - { .role = "video_clk", .clk = "dss_96m_fck" }, + /* + * The DSS HW needs all DSS clocks enabled during reset. The dss_core + * driver does not use these clocks. + */ { .role = "sys_clk", .clk = "dss2_alwon_fck" }, + { .role = "tv_clk", .clk = "dss_tv_fck" }, + /* required only on OMAP3430 */ + { .role = "tv_dac_clk", .clk = "dss_96m_fck" }, }; static struct omap_hwmod omap3430es1_dss_core_hwmod = { @@ -1394,11 +1399,12 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = { .slaves_cnt = ARRAY_SIZE(omap3430es1_dss_slaves), .masters = omap3xxx_dss_masters, .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters), - .flags = HWMOD_NO_IDLEST, + .flags = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET, }; static struct omap_hwmod omap3xxx_dss_core_hwmod = { .name = "dss_core", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .class = &omap2_dss_hwmod_class, .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ .sdma_reqs = omap3xxx_dss_sdma_chs, -- cgit From 6c3d7e34d68ffae888d33bf364f447e0b415591f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:10 -0700 Subject: ARM: OMAP3: HWMOD: fix DSS clock data The OMAP3 HWMOD data currently contains these errors with DSS clocks: - dss_rfbi is missing ick opt-clock, which is needed for RFBI to calculate timings - dss_dsi is missing ick and sys_clk - dss_venc is missing dss_96m_fck opt-clock, which is required on OMAP3430 - dss_venc's interface and main clocks are wrong, causing VENC to fail to start These problems were temporarily fixed with a DSS patch 9ede365aa6f74428a1f69c21ca1cf21213167576 ("HACK: OMAP: DSS2: clk hack for OMAP2/3"), which can be reverted after this patch (and the similar patches for other OMAPs). Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 45ccd4f07cff..4aaf0caaf3cc 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1492,6 +1492,7 @@ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = { static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap3xxx_dss_dsi1_hwmod, + .clk = "dss_ick", .addr = omap3xxx_dss_dsi1_addrs, .fw = { .omap2 = { @@ -1508,6 +1509,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = { &omap3xxx_l4_core__dss_dsi1, }; +static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = { + { .role = "sys_clk", .clk = "dss2_alwon_fck" }, +}; + static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .name = "dss_dsi1", .class = &omap3xxx_dsi_hwmod_class, @@ -1520,6 +1525,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = dss_dsi1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_opt_clks), .slaves = omap3xxx_dss_dsi1_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves), .flags = HWMOD_NO_IDLEST, @@ -1546,6 +1553,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = { &omap3xxx_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { + { .role = "ick", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap2_rfbi_hwmod_class, @@ -1557,6 +1568,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = dss_rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), .slaves = omap3xxx_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves), .flags = HWMOD_NO_IDLEST, @@ -1566,7 +1579,7 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap3xxx_dss_venc_hwmod, - .clk = "dss_tv_fck", + .clk = "dss_ick", .addr = omap2_dss_venc_addrs, .fw = { .omap2 = { @@ -1584,10 +1597,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = { &omap3xxx_l4_core__dss_venc, }; +static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = { + /* required only on OMAP3430 */ + { .role = "tv_dac_clk", .clk = "dss_96m_fck" }, +}; + static struct omap_hwmod omap3xxx_dss_venc_hwmod = { .name = "dss_venc", .class = &omap2_venc_hwmod_class, - .main_clk = "dss1_alwon_fck", + .main_clk = "dss_tv_fck", .prcm = { .omap2 = { .prcm_reg_id = 1, @@ -1595,6 +1613,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = dss_venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks), .slaves = omap3xxx_dss_venc_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves), .flags = HWMOD_NO_IDLEST, -- cgit From 4247878efca76143aa015ed1142652056052abb8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:11 -0700 Subject: ARM: OMAP4: HWMOD: remove extra clocks Remove the dss_dss_clk from dss_core's opt-clocks. dss_dss_clk already defined as the dss main_clk, and thus is not needed as an opt-clock. Remove opt-clocks for dss_dispc, as dispc only uses the main_clk. Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 7695e5d43316..3b9f2d9f1471 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1240,7 +1240,6 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = { static struct omap_hwmod_opt_clk dss_opt_clks[] = { { .role = "sys_clk", .clk = "dss_sys_clk" }, { .role = "tv_clk", .clk = "dss_tv_clk" }, - { .role = "dss_clk", .clk = "dss_dss_clk" }, { .role = "video_clk", .clk = "dss_48mhz_clk" }, }; @@ -1340,12 +1339,6 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = { &omap44xx_l4_per__dss_dispc, }; -static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, - { .role = "tv_clk", .clk = "dss_tv_clk" }, - { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, -}; - static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap44xx_dispc_hwmod_class, @@ -1359,8 +1352,6 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET, }, }, - .opt_clks = dss_dispc_opt_clks, - .opt_clks_cnt = ARRAY_SIZE(dss_dispc_opt_clks), .slaves = omap44xx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves), }; -- cgit From 37ad085527860397438f27c81a2cb13272378458 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:11 -0700 Subject: ARM: OMAP4: HWMOD: Add HWMOD_CONTROL_OPT_CLKS_IN_RESET for dss_core DSS needs all DSS clocks to be enabled to be able to finish reset properly. Before v3.1-rc1 the omapdss driver was managing clocks and resets correctly. However, when omapdss started using runtime PM at v3.1-rc1, the responsibility for the reset moved to HWMOD framework. HWMOD framework does not currently enable all the DSS clocks when resetting the DSS hardware. This causes the HWMOD frameworks boot-time reset to fail, possibly leaving the DSS hardware in undefined state. This patch sets HWMOD_CONTROL_OPT_CLKS_IN_RESET for dss_core. The flag is actually not used on OMAP4, because dss_core hardware does not have soft-reset functionality and thus the HWMOD framework never resets nor waits for the reset to finish. However, while the flag is not strictly needed currently, I think it represents the HW correctly: all the DSS clocks should be enabled after power-on to allow DSS hardware to finish its reset. A custom reset function will be added in the following patches which manages this correctly for OMAP4. Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 3b9f2d9f1471..b82720abf210 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1245,6 +1245,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = { static struct omap_hwmod omap44xx_dss_hwmod = { .name = "dss_core", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .class = &omap44xx_dss_hwmod_class, .clkdm_name = "l3_dss_clkdm", .main_clk = "dss_dss_clk", -- cgit From 4d0698d98f501b86d3bef38c46a54a702e0469a0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:12 -0700 Subject: ARM: OMAP4: HWMOD: fix DSS clock data The OMAP4 HWMOD data currently contains errors with DSS clocks: dss_hdmi and dss_venc have their main_clks wrong. The clocks should be dss_48mhz_clk and dss_tv_clk, respectively. These problems were temporarily fixed with the DSS patches 9ede365aa6f74428a1f69c21ca1cf21213167576 ("HACK: OMAP: DSS2: clk hack for OMAP2/3"), and df5d3ed23cf73ee0763a8963003bda9b69d9620f ("OMAP: DSS2: HDMI: fix hdmi clock name"), which can be reverted after this patch. Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index b82720abf210..cadf0bb2d3b7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1240,7 +1240,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = { static struct omap_hwmod_opt_clk dss_opt_clks[] = { { .role = "sys_clk", .clk = "dss_sys_clk" }, { .role = "tv_clk", .clk = "dss_tv_clk" }, - { .role = "video_clk", .clk = "dss_48mhz_clk" }, + { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, }; static struct omap_hwmod omap44xx_dss_hwmod = { @@ -1616,7 +1616,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { .clkdm_name = "l3_dss_clkdm", .mpu_irqs = omap44xx_dss_hdmi_irqs, .sdma_reqs = omap44xx_dss_hdmi_sdma_reqs, - .main_clk = "dss_dss_clk", + .main_clk = "dss_48mhz_clk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, @@ -1777,7 +1777,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = { .name = "dss_venc", .class = &omap44xx_venc_hwmod_class, .clkdm_name = "l3_dss_clkdm", - .main_clk = "dss_dss_clk", + .main_clk = "dss_tv_clk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET, -- cgit From 3ce32676bb355420ceeda57b73dd84df0ff5ad6f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:12 -0700 Subject: ARM: OMAP2/3: HWMOD: Add SYSS_HAS_RESET_STATUS for dss OMAP2/3 dss_core has a reset status flag in sysstatus register. Add SYSS_HAS_RESET_STATUS flag to HWMOD data so it can be used. Signed-off-by: Tomi Valkeinen Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c index c451729d289a..d78c1324ae59 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c @@ -43,7 +43,8 @@ static struct omap_hwmod_class_sysconfig omap2_dss_sysc = { .rev_offs = 0x0000, .sysc_offs = 0x0010, .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .sysc_fields = &omap_hwmod_sysc_type1, }; -- cgit From 13662dc5b177d68885695ef513dd4ae0e4d2a099 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 03:16:13 -0700 Subject: ARM: OMAP: HWMOD: Unify DSS resets for OMAPs This patch adds a custom DSS reset function used on OMAPs from OMAP2 forward. The function doesn't actually do a reset, it only waits for the reset to complete. The reason for this is that on OMAP4 there is no possibility to do a SW reset, and on OMAP2/3 doing a SW reset for dss_core resets all the other DSS modules also, thus breaking the HWMOD model where every DSS module is handled independently. This fixes the problem with DSS reset on OMAP4, caused by the fact that because there's no SW reset for dss_core on OMAP4, the HWMOD framework doesn't try to reset dss_core and thus the DSS clocks were never enabled at the same time. This causes causes the HWMOD reset to fail for dss_dispc and dss_rfbi. The common reset function will also allow us to fix another problem in the future: before doing a reset we need to disable DSS outputs, which are in some cases enabled by the bootloader, as otherwise DSS HW seems to get more or less stuck, requiring a power reset to recover. Signed-off-by: Tomi Valkeinen [paul@pwsan.com: modified to build arch/arm/mach-omap2/display.o unconditionally to avoid an error when !CONFIG_OMAP2_DSS] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 5 +--- arch/arm/mach-omap2/display.c | 35 ++++++++++++++++++++++ .../mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c | 2 ++ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 ++ arch/arm/plat-omap/include/plat/common.h | 3 ++ include/video/omapdss.h | 7 ----- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 69ab1c069134..b009f17dee56 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \ - common.o gpio.o dma.o wd_timer.o + common.o gpio.o dma.o wd_timer.o display.o omap-2-3-common = irq.o sdrc.o hwmod-common = omap_hwmod.o \ @@ -264,7 +264,4 @@ smsc911x-$(CONFIG_SMSC911X) := gpmc-smsc911x.o obj-y += $(smsc911x-m) $(smsc911x-y) obj-$(CONFIG_ARCH_OMAP4) += hwspinlock.o -disp-$(CONFIG_OMAP2_DSS) := display.o -obj-y += $(disp-m) $(disp-y) - obj-y += common-board-devices.o twl-common.o diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index adb2756e242f..941b5459707f 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "control.h" @@ -172,3 +173,37 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) return r; } + +#define MAX_MODULE_SOFTRESET_WAIT 10000 +int omap_dss_reset(struct omap_hwmod *oh) +{ + struct omap_hwmod_opt_clk *oc; + int c = 0; + int i, r; + + if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) { + pr_err("dss_core: hwmod data doesn't contain reset data\n"); + return -EINVAL; + } + + for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) + if (oc->_clk) + clk_enable(oc->_clk); + + omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs) + & SYSS_RESETDONE_MASK), + MAX_MODULE_SOFTRESET_WAIT, c); + + if (c == MAX_MODULE_SOFTRESET_WAIT) + pr_warning("dss_core: waiting for reset to finish failed\n"); + else + pr_debug("dss_core: softreset done\n"); + + for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) + if (oc->_clk) + clk_disable(oc->_clk); + + r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0; + + return r; +} diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c index d78c1324ae59..c11273da5dcc 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -51,6 +52,7 @@ static struct omap_hwmod_class_sysconfig omap2_dss_sysc = { struct omap_hwmod_class omap2_dss_hwmod_class = { .name = "dss", .sysc = &omap2_dss_sysc, + .reset = omap_dss_reset, }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index cadf0bb2d3b7..3b04d63316f5 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "omap_hwmod_common_data.h" @@ -1187,6 +1188,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = { static struct omap_hwmod_class omap44xx_dss_hwmod_class = { .name = "dss", .sysc = &omap44xx_dss_sysc, + .reset = omap_dss_reset, }; /* dss */ diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index c50df4814f6f..3ff3e36580f2 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -30,6 +30,7 @@ #include #include +#include struct sys_timer; @@ -55,6 +56,8 @@ void am35xx_init_early(void); void ti816x_init_early(void); void omap4430_init_early(void); +extern int omap_dss_reset(struct omap_hwmod *); + void omap_sram_init(void); /* diff --git a/include/video/omapdss.h b/include/video/omapdss.h index b66ebb2032c6..378c7ed6760b 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -307,15 +307,8 @@ struct omap_dss_board_info { void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); }; -#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) /* Init with the board info */ extern int omap_display_init(struct omap_dss_board_info *board_data); -#else -static inline int omap_display_init(struct omap_dss_board_info *board_data) -{ - return 0; -} -#endif struct omap_display_platform_data { struct omap_dss_board_info *board_data; -- cgit From b923d40dd4211c4ef7d4efa2bd81b7ca1d8744c1 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 6 Oct 2011 18:04:08 -0600 Subject: ARM: OMAP2PLUS: DSS: Ensure DSS works correctly if display is enabled in bootloader Resetting DISPC when a DISPC output is enabled causes the DSS to go into an inconsistent state. Thus if the bootloader has enabled a display, the hwmod code cannot reset the DISPC module just like that, but the outputs need to be disabled first. Add function dispc_disable_outputs() which disables all active overlay manager and ensure all frame transfers are completed. Modify omap_dss_reset() to call this function and clear DSS_CONTROL, DSS_SDI_CONTROL and DSS_PLL_CONTROL so that DSS is in a clean state when the DSS2 driver starts. This resolves the hang issue(caused by a L3 error during boot) seen on the beagle board C3, which has a factory bootloader that enables display. The issue is resolved with this patch. Thanks to Tomi and Sricharan for some additional testing. Acked-by: Tomi Valkeinen Tested-by: R, Sricharan Signed-off-by: Archit Taneja [paul@pwsan.com: restructured code, removed omap_{read,write}l(), removed cpu_is_omap*() calls and converted to dev_attr] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/display.c | 124 +++++++++++++++++++++++++++ arch/arm/mach-omap2/display.h | 29 +++++++ arch/arm/mach-omap2/omap_hwmod_2420_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_2430_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 1 + arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 6 ++ arch/arm/mach-omap2/omap_hwmod_common_data.c | 4 + arch/arm/mach-omap2/omap_hwmod_common_data.h | 4 + 8 files changed, 170 insertions(+) create mode 100644 arch/arm/mach-omap2/display.h diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 941b5459707f..dce9905d64bb 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -30,6 +30,32 @@ #include #include "control.h" +#include "display.h" + +#define DISPC_CONTROL 0x0040 +#define DISPC_CONTROL2 0x0238 +#define DISPC_IRQSTATUS 0x0018 + +#define DSS_SYSCONFIG 0x10 +#define DSS_SYSSTATUS 0x14 +#define DSS_CONTROL 0x40 +#define DSS_SDI_CONTROL 0x44 +#define DSS_PLL_CONTROL 0x48 + +#define LCD_EN_MASK (0x1 << 0) +#define DIGIT_EN_MASK (0x1 << 1) + +#define FRAMEDONE_IRQ_SHIFT 0 +#define EVSYNC_EVEN_IRQ_SHIFT 2 +#define EVSYNC_ODD_IRQ_SHIFT 3 +#define FRAMEDONE2_IRQ_SHIFT 22 +#define FRAMEDONETV_IRQ_SHIFT 24 + +/* + * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC + * reset before deciding that something has gone wrong + */ +#define FRAMEDONE_IRQ_TIMEOUT 100 static struct platform_device omap_display_device = { .name = "omapdss", @@ -174,6 +200,90 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) return r; } +static void dispc_disable_outputs(void) +{ + u32 v, irq_mask = 0; + bool lcd_en, digit_en, lcd2_en = false; + int i; + struct omap_dss_dispc_dev_attr *da; + struct omap_hwmod *oh; + + oh = omap_hwmod_lookup("dss_dispc"); + if (!oh) { + WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n"); + return; + } + + if (!oh->dev_attr) { + pr_err("display: could not disable outputs during reset due to missing dev_attr\n"); + return; + } + + da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr; + + /* store value of LCDENABLE and DIGITENABLE bits */ + v = omap_hwmod_read(oh, DISPC_CONTROL); + lcd_en = v & LCD_EN_MASK; + digit_en = v & DIGIT_EN_MASK; + + /* store value of LCDENABLE for LCD2 */ + if (da->manager_count > 2) { + v = omap_hwmod_read(oh, DISPC_CONTROL2); + lcd2_en = v & LCD_EN_MASK; + } + + if (!(lcd_en | digit_en | lcd2_en)) + return; /* no managers currently enabled */ + + /* + * If any manager was enabled, we need to disable it before + * DSS clocks are disabled or DISPC module is reset + */ + if (lcd_en) + irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT; + + if (digit_en) { + if (da->has_framedonetv_irq) { + irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT; + } else { + irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT | + 1 << EVSYNC_ODD_IRQ_SHIFT; + } + } + + if (lcd2_en) + irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT; + + /* + * clear any previous FRAMEDONE, FRAMEDONETV, + * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts + */ + omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS); + + /* disable LCD and TV managers */ + v = omap_hwmod_read(oh, DISPC_CONTROL); + v &= ~(LCD_EN_MASK | DIGIT_EN_MASK); + omap_hwmod_write(v, oh, DISPC_CONTROL); + + /* disable LCD2 manager */ + if (da->manager_count > 2) { + v = omap_hwmod_read(oh, DISPC_CONTROL2); + v &= ~LCD_EN_MASK; + omap_hwmod_write(v, oh, DISPC_CONTROL2); + } + + i = 0; + while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) != + irq_mask) { + i++; + if (i > FRAMEDONE_IRQ_TIMEOUT) { + pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n"); + break; + } + mdelay(1); + } +} + #define MAX_MODULE_SOFTRESET_WAIT 10000 int omap_dss_reset(struct omap_hwmod *oh) { @@ -190,6 +300,20 @@ int omap_dss_reset(struct omap_hwmod *oh) if (oc->_clk) clk_enable(oc->_clk); + dispc_disable_outputs(); + + /* clear SDI registers */ + if (cpu_is_omap3430()) { + omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL); + omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL); + } + + /* + * clear DSS_CONTROL register to switch DSS clock sources to + * PRCM clock, if any + */ + omap_hwmod_write(0x0, oh, DSS_CONTROL); + omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs) & SYSS_RESETDONE_MASK), MAX_MODULE_SOFTRESET_WAIT, c); diff --git a/arch/arm/mach-omap2/display.h b/arch/arm/mach-omap2/display.h new file mode 100644 index 000000000000..b871b017b352 --- /dev/null +++ b/arch/arm/mach-omap2/display.h @@ -0,0 +1,29 @@ +/* + * display.h - OMAP2+ integration-specific DSS header + * + * Copyright (C) 2011 Texas Instruments, 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. + * + * 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, see . + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H +#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H + +#include + +struct omap_dss_dispc_dev_attr { + u8 manager_count; + bool has_framedonetv_irq; +}; + +#endif diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 74037a5807af..a5409ce3f323 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -943,6 +943,7 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = { .slaves = omap2420_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves), .flags = HWMOD_NO_IDLEST, + .dev_attr = &omap2_3_dss_dispc_dev_attr }; /* l4_core -> dss_rfbi */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 6f0365388dfc..c4f56cb60d7d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1004,6 +1004,7 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = { .slaves = omap2430_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves), .flags = HWMOD_NO_IDLEST, + .dev_attr = &omap2_3_dss_dispc_dev_attr }; /* l4_core -> dss_rfbi */ diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 4aaf0caaf3cc..7f8915ad5099 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1462,6 +1462,7 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .slaves = omap3xxx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves), .flags = HWMOD_NO_IDLEST, + .dev_attr = &omap2_3_dss_dispc_dev_attr }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 3b04d63316f5..daaf165af696 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1327,6 +1327,11 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = { { } }; +static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = { + .manager_count = 3, + .has_framedonetv_irq = 1 +}; + /* l4_per -> dss_dispc */ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = { .master = &omap44xx_l4_per_hwmod, @@ -1357,6 +1362,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = { }, .slaves = omap44xx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves), + .dev_attr = &omap44xx_dss_dispc_dev_attr }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c index de832ebc93a9..51e5418899fb 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c @@ -49,3 +49,7 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = { .srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT, }; +struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = { + .manager_count = 2, + .has_framedonetv_irq = 0 +}; diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h index 39a7c37f4587..ad5d8f04c0b8 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h @@ -16,6 +16,8 @@ #include +#include "display.h" + /* Common address space across OMAP2xxx */ extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[]; extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[]; @@ -111,4 +113,6 @@ extern struct omap_hwmod_class omap2xxx_dma_hwmod_class; extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class; extern struct omap_hwmod_class omap2xxx_mcspi_class; +extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr; + #endif -- cgit From 35b09c9bf619c4fc6040c52dcea6bd5bd6af7679 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Oct 2011 14:42:41 +0300 Subject: drm/i915: fix if statement (bogus semi-colon) The semi-colon is a typo here and it makes the if statement unconditional. Signed-off-by: Dan Carpenter Signed-off-by: Keith Packard --- drivers/char/agp/intel-gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 66cd0b8096ca..3a8d44886010 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1236,7 +1236,7 @@ static int i9xx_setup(void) intel_private.gtt_bus_addr = reg_addr + gtt_offset; } - if (needs_idle_maps()); + if (needs_idle_maps()) intel_private.base.do_idle_maps = 1; intel_i9xx_setup_flush(); -- cgit From a08185a3eb658854b29c05bcbfac0f85038ffe9f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 28 Oct 2011 10:28:00 -0700 Subject: agp: iommu_gfx_mapped only available if CONFIG_INTEL_IOMMU is set Kernels with no iommu support cannot ever need the Ironlake work-around, so never enable it in that case. Might be better to completely remove the work-around from the kernel in this case? Signed-off-by: Keith Packard Reviewed-by: Ben Widawsky --- drivers/char/agp/intel-gtt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 3a8d44886010..c92424ca1a55 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1186,10 +1186,11 @@ static void gen6_cleanup(void) /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. */ -extern int intel_iommu_gfx_mapped; static inline int needs_idle_maps(void) { +#ifdef CONFIG_INTEL_IOMMU const unsigned short gpu_devid = intel_private.pcidev->device; + extern int intel_iommu_gfx_mapped; /* Query intel_iommu to see if we need the workaround. Presumably that * was loaded first. @@ -1198,7 +1199,7 @@ static inline int needs_idle_maps(void) gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && intel_iommu_gfx_mapped) return 1; - +#endif return 0; } -- cgit From 14660ccd599dc7bd6ecef17408bd76dc853f9b77 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 31 Oct 2011 23:16:21 -0700 Subject: drm/i915: Fix object refcount leak on mmappable size limit error path. I've been seeing memory leaks on my system in the form of large (300-400MB) GEM objects created by now-dead processes laying around clogging up memory. I usually notice when it gets to about 1.2GB of them. Hopefully this clears up the issue, but I just found this bug by inspection. Signed-off-by: Eric Anholt Cc: stable@kernel.org Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6651c36b6e8a..d18b07adcffa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1396,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file, if (obj->base.size > dev_priv->mm.gtt_mappable_end) { ret = -E2BIG; - goto unlock; + goto out; } if (obj->madv != I915_MADV_WILLNEED) { -- cgit From 2c2dd6ac738d8a22def46e073fb7383cac8fa180 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 12 Oct 2011 13:09:53 -0300 Subject: [media] media: vb2: add a check for uninitialized buffer __buffer_in_use() might be called for empty/uninitialized buffer in the following scenario: REQBUF(n, USER_PTR), QUERYBUF(). This patch fixes kernel ops in such case. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 979e544388cb..9bb92145ad5a 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -296,14 +296,14 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) { unsigned int plane; for (plane = 0; plane < vb->num_planes; ++plane) { + void *mem_priv = vb->planes[plane].mem_priv; /* * If num_users() has not been provided, call_memop * will return 0, apparently nobody cares about this * case anyway. If num_users() returns more than 1, * we are not the only user of the plane's memory. */ - if (call_memop(q, plane, num_users, - vb->planes[plane].mem_priv) > 1) + if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1) return true; } return false; -- cgit From 4907602f85d454c127d20ac943ead13e2919898d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 13 Oct 2011 07:07:24 -0300 Subject: [media] media: vb2: set buffer length correctly for all buffer types v4l2_planes[plane].length field was not initialized for userptr buffers. This patch fixes this issue. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 9bb92145ad5a..e7c52ff3c761 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -131,6 +131,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n) continue; for (plane = 0; plane < vb->num_planes; ++plane) { + vb->v4l2_planes[plane].length = q->plane_sizes[plane]; vb->v4l2_planes[plane].m.mem_offset = off; dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n", -- cgit From bd50d999d4d4f311fda9b777d1e567433cc0f142 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 25 Oct 2011 03:07:59 -0300 Subject: [media] media: vb2: reset queued list on REQBUFS(0) call Queued list was not reset on REQBUFS(0) call. This caused to enqueue a freed buffer to the driver. Reported-by: Angela Wan Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index e7c52ff3c761..95a3f5e82aef 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -265,6 +265,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers) q->num_buffers -= buffers; if (!q->num_buffers) q->memory = 0; + INIT_LIST_HEAD(&q->queued_list); } /** -- cgit From 43defb118247b9c72d53328aa366bdb154d5ee98 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Thu, 6 Oct 2011 11:34:05 -0300 Subject: [media] v4l: s5p-mfc: fix reported capabilities MFC uses the multi-plane API, but it reported single-plane when querying capabilities. Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park Signed-off-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-mfc/s5p_mfc_dec.c | 4 ++-- drivers/media/video/s5p-mfc/s5p_mfc_enc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c index 725634d9736d..844a4d7797bc 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c @@ -220,8 +220,8 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; return 0; } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c index ecef127dbc66..1e8cdb77d4b8 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c @@ -785,8 +785,8 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE - | V4L2_CAP_VIDEO_OUTPUT + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE + | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; return 0; } -- cgit From 60659dd49509f255ad9748411cd4eb3c74a8d8a9 Mon Sep 17 00:00:00 2001 From: Jeongtae Park Date: Fri, 14 Oct 2011 00:03:23 -0300 Subject: [media] MAINTAINERS: add a maintainer for s5p-mfc driver Add a maintainer for s5p-mfc driver. Signed-off-by: Jeongtae Park Acked-by: Marek Szyprowski Acked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5e587fcaf4dc..e839b95b2723 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1088,6 +1088,7 @@ F: drivers/media/video/s5p-fimc/ ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT M: Kyungmin Park M: Kamil Debski +M: Jeongtae Park L: linux-arm-kernel@lists.infradead.org L: linux-media@vger.kernel.org S: Maintained -- cgit From b36b505965e374b284166c2e6b9c1d369d663ea9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 24 Oct 2011 05:03:27 -0300 Subject: [media] v4l2-event: Deny subscribing with a type of V4L2_EVENT_ALL Signed-off-by: Hans de Goede Acked-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 53b190cf225e..9f56f18d509f 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -215,6 +215,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, unsigned long flags; unsigned i; + if (sub->type == V4L2_EVENT_ALL) + return -EINVAL; + if (elems < 1) elems = 1; if (sub->type == V4L2_EVENT_CTRL) { -- cgit From 78c87e863bb3350426fecd14912fd0a546c58ec0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 26 Oct 2011 05:40:27 -0300 Subject: [media] v4l2-event: Remove pending events from fh event queue when unsubscribing The kev pointers inside the pending events queue (the available queue) of the fh point to data inside the sev, unsubscribing frees the sev, thus making these pointers point to freed memory! This patch fixes these dangling pointers in the available queue by removing all matching pending events on unsubscription. Signed-off-by: Hans de Goede Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-event.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 9f56f18d509f..4d01f17497f6 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -285,6 +285,7 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, { struct v4l2_subscribed_event *sev; unsigned long flags; + int i; if (sub->type == V4L2_EVENT_ALL) { v4l2_event_unsubscribe_all(fh); @@ -295,6 +296,11 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, sev = v4l2_event_subscribed(fh, sub->type, sub->id); if (sev != NULL) { + /* Remove any pending events for this subscription */ + for (i = 0; i < sev->in_use; i++) { + list_del(&sev->events[sev_pos(sev, i)].list); + fh->navailable--; + } list_del(&sev->list); sev->fh = NULL; } -- cgit From e3e72f39b68ec2563d8ef22f9704a66b7f71b638 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 26 Oct 2011 05:52:47 -0300 Subject: [media] v4l2-event: Don't set sev->fh to NULL on unsubscribe Setting sev->fh to NULL causes problems for the del op added in the next patch of this series, since this op needs a way to get to its own data structures, and typically this will be done by using container_of on an embedded v4l2_fh struct. The reason the original code is setting sev->fh to NULL is to signal to users of the event framework that the unsubscription has happened, but since their is no shared lock between the event framework and users of it, this is inherently racy, and it also turns out to be unnecessary as long as both the event framework and the user of the framework do their own locking properly and the user guarantees that it holds no references to the subcribed_event structure after its del operation has been called. This is best explained by looking at the only code currently checking for sev->fh being set to NULL on unsubscribe, which is the v4l2-ctrls.c send_event function. Here is the relevant code from v4l2-ctrls: send_event(): if (sev->fh && (sev->fh != fh || (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))) v4l2_event_queue_fh(sev->fh, &ev); Now lets say that v4l2_event_unsubscribe and v4l2-ctrls: send_event() race on the same sev, then the following could happens: 1) send_event checks sev->fh, finds it is not NULL 2) v4l2_event_unsubscribe sets sev->fh NULL 3) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks as the thread calling send_event holds the ctrl_lock 4) send_event calls v4l2_event_queue_fh(sev->fh, &ev) which not is equivalent to calling: v4l2_event_queue_fh(NULL, &ev) 5) oops, NULL pointer deref. Now again without setting sev->fh to NULL in v4l2_event_unsubscribe and without the (now senseless since always true) sev->fh != NULL check in 1) send_event is about to call v4l2_event_queue_fh(sev->fh, &ev) 2) v4l2_event_unsubscribe removes sev->list from the fh->subscribed list 3) send_event calls v4l2_event_queue_fh(sev->fh, &ev) 4) v4l2_event_queue_fh blocks on the fh_lock spinlock 5) v4l2_event_unsubscribe unlocks the fh_lock spinlock 6) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks as the thread calling send_event holds the ctrl_lock 8) v4l2_event_queue_fh takes the fh_lock 7) v4l2_event_queue_fh calls v4l2_event_subscribed, does not find it since sev->list has been removed from fh->subscribed already -> does nothing 9) v4l2_event_queue_fh releases the fh_lock 10) the caller of send_event releases the ctrl lock (mutex) 11) v4l2_ctrls del_event takes the ctrl lock 12) v4l2_ctrls del_event removes sev->node from the ev_subs list 13) v4l2_ctrls del_event releases the ctrl lock 14) v4l2_event_unsubscribe frees the sev, to which no references are being held anymore Signed-off-by: Hans de Goede Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ctrls.c | 4 ++-- drivers/media/video/v4l2-event.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 5552f8137571..c58c91bbcfbd 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -820,8 +820,8 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) fill_event(&ev, ctrl, changes); list_for_each_entry(sev, &ctrl->ev_subs, node) - if (sev->fh && (sev->fh != fh || - (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))) + if (sev->fh != fh || + (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)) v4l2_event_queue_fh(sev->fh, &ev); } diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 4d01f17497f6..3d93251f292e 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -302,7 +302,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, fh->navailable--; } list_del(&sev->list); - sev->fh = NULL; } spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); -- cgit From 1249a3a82d08d73ece65ae79e0553cd0f3407a15 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 31 Oct 2011 11:16:44 -0300 Subject: [media] v4l2-ctrl: Send change events to all fh for auto cluster slave controls Otherwise the fh changing the master control won't get the inactive state change event for the slave controls. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ctrls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index c58c91bbcfbd..2ece7093b513 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -946,6 +946,7 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, if (ctrl->cluster[0]->has_volatiles) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; } + fh = NULL; } if (changed || update_inactive) { /* If a control was changed that was not one of the controls -- cgit From 617d1017545c27a56229483cc1d689eff6c38561 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Sat, 29 Oct 2011 15:45:56 +0200 Subject: MIPS: Yosemite, Emma: Fix off-by-two in arcs_cmdline buffer size check Cause is a misplaced bracket. The code strlen(buf+1) will be two bytes less than strlen(buf)+1 The +1 is in this code to reserve space for an additional space character. [ralf@linux-mips.org: Thomas' original patch fixed the issue only for Yosemite but the same bug exists also in Emma.] Signed-off-by: Thomas Jarosch Patchwork: https://patchwork.linux-mips.org/patch/2861/ Signed-off-by: Ralf Baechle --- arch/mips/emma/common/prom.c | 2 +- arch/mips/pmc-sierra/yosemite/prom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/emma/common/prom.c b/arch/mips/emma/common/prom.c index 708f08761406..cae42259d6da 100644 --- a/arch/mips/emma/common/prom.c +++ b/arch/mips/emma/common/prom.c @@ -50,7 +50,7 @@ void __init prom_init(void) /* arg[0] is "g", the rest is boot parameters */ for (i = 1; i < argc; i++) { - if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >= sizeof(arcs_cmdline)) break; strcat(arcs_cmdline, arg[i]); diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c index cf4c868715ac..dcc926e06fce 100644 --- a/arch/mips/pmc-sierra/yosemite/prom.c +++ b/arch/mips/pmc-sierra/yosemite/prom.c @@ -102,7 +102,7 @@ void __init prom_init(void) /* Get the boot parameters */ for (i = 1; i < argc; i++) { - if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >= + if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >= sizeof(arcs_cmdline)) break; -- cgit From 798580815126c899616146f286d5cc259abb5e16 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 4 Nov 2011 10:45:57 +0000 Subject: MIPS: NXP: Remove unused source files. The NXP code was moved for 2.6.36 but two files survived unused in the old location. Signed-off-by: Ralf Baechle --- arch/mips/nxp/pnx8550/common/pci.c | 134 -------------------------------- arch/mips/nxp/pnx8550/common/setup.c | 143 ----------------------------------- 2 files changed, 277 deletions(-) delete mode 100644 arch/mips/nxp/pnx8550/common/pci.c delete mode 100644 arch/mips/nxp/pnx8550/common/setup.c diff --git a/arch/mips/nxp/pnx8550/common/pci.c b/arch/mips/nxp/pnx8550/common/pci.c deleted file mode 100644 index 98e86ddb86cc..000000000000 --- a/arch/mips/nxp/pnx8550/common/pci.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * - * Author: source@mvista.com - * - * This program is free software; you can distribute 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 it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ -#include -#include -#include -#include - -#include -#include -#include - -static struct resource pci_io_resource = { - .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */ - .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE, - .name = "pci IO space", - .flags = IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - .start = PNX8550_PCIMEM, - .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1, - .name = "pci memory space", - .flags = IORESOURCE_MEM -}; - -extern struct pci_ops pnx8550_pci_ops; - -static struct pci_controller pnx8550_controller = { - .pci_ops = &pnx8550_pci_ops, - .io_map_base = PNX8550_PORT_BASE, - .io_resource = &pci_io_resource, - .mem_resource = &pci_mem_resource, -}; - -/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ -static inline unsigned long get_system_mem_size(void) -{ - /* Read IP2031_RANK0_ADDR_LO */ - unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); - /* Read IP2031_RANK1_ADDR_HI */ - unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); - - return dram_r1_hi - dram_r0_lo + 1; -} - -static int __init pnx8550_pci_setup(void) -{ - int pci_mem_code; - int mem_size = get_system_mem_size() >> 20; - - /* Clear the Global 2 Register, PCI Inta Output Enable Registers - Bit 1:Enable DAC Powerdown - -> 0:DACs are enabled and are working normally - 1:DACs are powerdown - Bit 0:Enable of PCI inta output - -> 0 = Disable PCI inta output - 1 = Enable PCI inta output - */ - PNX8550_GLB2_ENAB_INTA_O = 0; - - /* Calc the PCI mem size code */ - if (mem_size >= 128) - pci_mem_code = SIZE_128M; - else if (mem_size >= 64) - pci_mem_code = SIZE_64M; - else if (mem_size >= 32) - pci_mem_code = SIZE_32M; - else - pci_mem_code = SIZE_16M; - - /* Set PCI_XIO registers */ - outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO); - outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI); - outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO); - outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI); - - /* Send memory transaction via PCI_BASE2 */ - outl(0x00000001, PCI_BASE | PCI_IO); - - /* Unlock the setup register */ - outl(0xca, PCI_BASE | PCI_UNLOCKREG); - - /* - * BAR0 of PNX8550 (pci base 10) must be zero in order for ide - * to work, and in order for bus_to_baddr to work without any - * hacks. - */ - outl(0x00000000, PCI_BASE | PCI_BASE10); - - /* - *These two bars are set by default or the boot code. - * However, it's safer to set them here so we're not boot - * code dependent. - */ - outl(0x1be00000, PCI_BASE | PCI_BASE14); /* PNX MMIO */ - outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18); /* XIO */ - - outl(PCI_EN_TA | - PCI_EN_PCI2MMI | - PCI_EN_XIO | - PCI_SETUP_BASE18_SIZE(SIZE_32M) | - PCI_SETUP_BASE18_EN | - PCI_SETUP_BASE14_EN | - PCI_SETUP_BASE10_PREF | - PCI_SETUP_BASE10_SIZE(pci_mem_code) | - PCI_SETUP_CFGMANAGE_EN | - PCI_SETUP_PCIARB_EN, - PCI_BASE | - PCI_SETUP); /* PCI_SETUP */ - outl(0x00000000, PCI_BASE | PCI_CTRL); /* PCI_CONTROL */ - - register_pci_controller(&pnx8550_controller); - - return 0; -} - -arch_initcall(pnx8550_pci_setup); diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c deleted file mode 100644 index 71adac323323..000000000000 --- a/arch/mips/nxp/pnx8550/common/setup.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * 2.6 port, Embedded Alley Solutions, Inc - * - * Based on Per Hallsmark, per.hallsmark@mvista.com - * - * This program is free software; you can distribute 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 it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -extern void __init board_setup(void); -extern void pnx8550_machine_restart(char *); -extern void pnx8550_machine_halt(void); -extern void pnx8550_machine_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; -extern char *prom_getcmdline(void); - -struct resource standard_io_resources[] = { - { - .start = 0x00, - .end = 0x1f, - .name = "dma1", - .flags = IORESOURCE_BUSY - }, { - .start = 0x40, - .end = 0x5f, - .name = "timer", - .flags = IORESOURCE_BUSY - }, { - .start = 0x80, - .end = 0x8f, - .name = "dma page reg", - .flags = IORESOURCE_BUSY - }, { - .start = 0xc0, - .end = 0xdf, - .name = "dma2", - .flags = IORESOURCE_BUSY - }, -}; - -#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources) - -extern struct resource pci_io_resource; -extern struct resource pci_mem_resource; - -/* Return the total size of DRAM-memory, (RANK0 + RANK1) */ -unsigned long get_system_mem_size(void) -{ - /* Read IP2031_RANK0_ADDR_LO */ - unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010); - /* Read IP2031_RANK1_ADDR_HI */ - unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018); - - return dram_r1_hi - dram_r0_lo + 1; -} - -int pnx8550_console_port = -1; - -void __init plat_mem_setup(void) -{ - int i; - char* argptr; - - board_setup(); /* board specific setup */ - - _machine_restart = pnx8550_machine_restart; - _machine_halt = pnx8550_machine_halt; - pm_power_off = pnx8550_machine_power_off; - - /* Clear the Global 2 Register, PCI Inta Output Enable Registers - Bit 1:Enable DAC Powerdown - -> 0:DACs are enabled and are working normally - 1:DACs are powerdown - Bit 0:Enable of PCI inta output - -> 0 = Disable PCI inta output - 1 = Enable PCI inta output - */ - PNX8550_GLB2_ENAB_INTA_O = 0; - - /* IO/MEM resources. */ - set_io_port_base(PNX8550_PORT_BASE); - ioport_resource.start = 0; - ioport_resource.end = ~0; - iomem_resource.start = 0; - iomem_resource.end = ~0; - - /* Request I/O space for devices on this board */ - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources + i); - - /* Place the Mode Control bit for GPIO pin 16 in primary function */ - /* Pin 16 is used by UART1, UA1_TX */ - outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) | - (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT), - PNX8550_GPIO_MC1); - - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=ttyS")) != NULL) { - argptr += strlen("console=ttyS"); - pnx8550_console_port = *argptr == '0' ? 0 : 1; - - /* We must initialize the UART (console) before early printk */ - /* Set LCR to 8-bit and BAUD to 38400 (no 5) */ - ip3106_lcr(UART_BASE, pnx8550_console_port) = - PNX8XXX_UART_LCR_8BIT; - ip3106_baud(UART_BASE, pnx8550_console_port) = 5; - } -} -- cgit From df55a66addf87bc21ef5678bea238f2c1b2db48a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 4 Nov 2011 11:17:46 +0100 Subject: MIPS: BCM47xx: fix build with GENERIC_GPIO configuration Since eb9ae7f2 (gpio: fix build error in include/asm-generic/gpio.h) the generic version of gpio.h calls __gpio_{set,get}_value which we do not define. Get rid of asm-generic/gpio.h and define the missing stubs directly for BCM47xx to build. Reported-by: Ralf Baechle To: linux-mips@linux-mips.org CC: Hauke Mehrtens Signed-off-by: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/2885/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-bcm47xx/gpio.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h index 76961cabeedf..2ef17e8df403 100644 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h @@ -36,6 +36,8 @@ static inline int gpio_get_value(unsigned gpio) return -EINVAL; } +#define gpio_get_value_cansleep gpio_get_value + static inline void gpio_set_value(unsigned gpio, int value) { switch (bcm47xx_bus_type) { @@ -54,6 +56,19 @@ static inline void gpio_set_value(unsigned gpio, int value) } } +#define gpio_set_value_cansleep gpio_set_value + +static inline int gpio_cansleep(unsigned gpio) +{ + return 0; +} + +static inline int gpio_is_valid(unsigned gpio) +{ + return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES); +} + + static inline int gpio_direction_input(unsigned gpio) { switch (bcm47xx_bus_type) { @@ -137,7 +152,4 @@ static inline int gpio_polarity(unsigned gpio, int value) } -/* cansleep wrappers */ -#include - #endif /* __BCM47XX_GPIO_H */ -- cgit From e63fb7a9dae820b3ff6754f794fd713f83e32fff Mon Sep 17 00:00:00 2001 From: Venkat Subbiah Date: Mon, 3 Oct 2011 13:31:10 -0700 Subject: MIPS: Octeon: Mark SMP-IPI interrupt as IRQF_NO_THREAD This is to exclude it from force threading to allow RT patch set to work. And while on this line * Remove IRQF_DISABLED as as this flag is NOOP * Add IRQF_PERCPU as this is a per cpu interrupt. Signed-off-by: Venkat Subbiah Acked-by: David Daney To: linux-mips@linux-mips.org To: linux-rt-users@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/2817/ Acked-by: Thomas Gleixner Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/smp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 8b606423bbd7..efcfff4d4627 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -207,8 +207,9 @@ void octeon_prepare_cpus(unsigned int max_cpus) * the other bits alone. */ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff); - if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED, - "SMP-IPI", mailbox_interrupt)) { + if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI", + mailbox_interrupt)) { panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n"); } } -- cgit From e94e05eae9a56e4fad93f18a63ae90e7ff02b576 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 8 Nov 2011 21:57:59 +0800 Subject: arm/mxs: fix mmc device adding for mach-mx28evk The merge commit "526b264 Merge branch 'imx/cleanup' into imx/devel" left a duplicated mx28_add_mxs_mmc() call, which causes the problem below during boot. kobject_add_internal failed for mxs-mmc.1 with -EEXIST, don't try to register things with the same name in the same directory. The patch removes this leftover and also change mmc0 adding to align with mmc1. Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/mach-mx28evk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c index ac2316d53d3c..064ec5abaa55 100644 --- a/arch/arm/mach-mxs/mach-mx28evk.c +++ b/arch/arm/mach-mxs/mach-mx28evk.c @@ -471,7 +471,8 @@ static void __init mx28evk_init(void) "mmc0-slot-power"); if (ret) pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret); - mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]); + else + mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]); ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW, "mmc1-slot-power"); @@ -480,7 +481,6 @@ static void __init mx28evk_init(void) else mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]); - mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]); mx28_add_rtc_stmp3xxx(); gpio_led_register_device(0, &mx28evk_led_data); -- cgit From d13431ca3eb2a2c14314f04813cdc11cd869f150 Mon Sep 17 00:00:00 2001 From: Wen-chien Jesse Sung Date: Tue, 8 Nov 2011 14:30:22 +0800 Subject: Bluetooth: Add support for Broadcom BCM20702A0 Since this device declares itself as vendor specific, must add a new entry to device ID table to support it. usb-device output of this device: T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=413c ProdID=8197 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=D0DF9AA9C9F1 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Wen-chien Jesse Sung Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f9b726091ad0..fe4ebc375b3d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -100,6 +100,9 @@ static struct usb_device_id btusb_table[] = { /* Canyon CN-BTU1 with HID interfaces */ { USB_DEVICE(0x0c10, 0x0000) }, + /* Broadcom BCM20702A0 */ + { USB_DEVICE(0x413c, 0x8197) }, + { } /* Terminating entry */ }; -- cgit From 66f5ddf30a59f811818656cb2833c80da0340cfa Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Thu, 3 Nov 2011 11:46:47 -0700 Subject: x86/mce: Make mce_chrdev_ops 'static const' Arjan would like to make struct file_operations const, but mce-inject directly writes to the mce_chrdev_ops to install its write handler. In an ideal world mce-inject would have its own character device, but we have a sizable legacy of test scripts that hardwire "/dev/mcelog", so it would be painful to switch to a separate device now. Instead, this patch switches to a stub function in the mce code, with a registration helper that mce-inject can call when it is loaded. Note that this would also allow for a sane process to allow mce-inject to be unloaded again (with an unregister function, and appropriate module_{get,put}() calls), but that is left for potential future patches. Reported-by: Arjan van de Ven Signed-off-by: Tony Luck Link: http://lkml.kernel.org/r/4eb2e1971326651a3b@agluck-desktop.sc.intel.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mce.h | 5 ++++- arch/x86/kernel/cpu/mcheck/mce-inject.c | 2 +- arch/x86/kernel/cpu/mcheck/mce.c | 25 ++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index c9321f34e55b..0e8ae57d3656 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -201,7 +201,10 @@ int mce_notify_irq(void); void mce_notify_process(void); DECLARE_PER_CPU(struct mce, injectm); -extern struct file_operations mce_chrdev_ops; + +extern void register_mce_write_callback(ssize_t (*)(struct file *filp, + const char __user *ubuf, + size_t usize, loff_t *off)); /* * Exception handler diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 6199232161cf..319882ef848d 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -208,7 +208,7 @@ static int inject_init(void) if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) return -ENOMEM; printk(KERN_INFO "Machine check injector initialized\n"); - mce_chrdev_ops.write = mce_write; + register_mce_write_callback(mce_write); register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify"); return 0; diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 362056aefeb4..2af127d4c3d1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1634,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd, } } -/* Modified in mce-inject.c, so not static or const */ -struct file_operations mce_chrdev_ops = { +static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf, + size_t usize, loff_t *off); + +void register_mce_write_callback(ssize_t (*fn)(struct file *filp, + const char __user *ubuf, + size_t usize, loff_t *off)) +{ + mce_write = fn; +} +EXPORT_SYMBOL_GPL(register_mce_write_callback); + +ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, + size_t usize, loff_t *off) +{ + if (mce_write) + return mce_write(filp, ubuf, usize, off); + else + return -EINVAL; +} + +static const struct file_operations mce_chrdev_ops = { .open = mce_chrdev_open, .release = mce_chrdev_release, .read = mce_chrdev_read, + .write = mce_chrdev_write, .poll = mce_chrdev_poll, .unlocked_ioctl = mce_chrdev_ioctl, .llseek = no_llseek, }; -EXPORT_SYMBOL_GPL(mce_chrdev_ops); static struct miscdevice mce_chrdev_device = { MISC_MCELOG_MINOR, -- cgit From f1e10354fc2a12773e5e8efcf841380aa57d4aa5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 5 Nov 2011 14:47:19 +0800 Subject: ASoC: wm9081: Fix reading wrong register for setting VMID 2*240k VMID Divider Enable and Select is controlled by BIT[2:1] of WM9081_VMID_CONTROL register (04h). Current code reads wrong register (WM9081_BIAS_CONTROL_1) for setting VMID 2*240k. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 3cd35a02c28c..fe6561885f39 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -818,7 +818,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, } /* VMID 2*240k */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = snd_soc_read(codec, WM9081_VMID_CONTROL); reg &= ~WM9081_VMID_SEL_MASK; reg |= 0x04; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); -- cgit From adf463626ad8e0a2cdbe17d8bb64c1d9d0ac160d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 5 Nov 2011 14:49:21 +0800 Subject: ASoC: wm9081: Don't write WM9081_BIAS_ENA bit to WM9081_VMID_CONTROL register WM9081_BIAS_ENA is the bit[1] of WM9081_BIAS_CONTROL_1 register (05h). Current code incorrectly write it to WM9081_VMID_CONTROL(04h) register. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index fe6561885f39..4a398c3bfe84 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -807,7 +807,6 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, mdelay(100); /* Normal bias enable & soft start off */ - reg |= WM9081_BIAS_ENA; reg &= ~WM9081_VMID_RAMP; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); @@ -830,14 +829,15 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - /* Startup bias source */ + /* Startup bias source and disable bias */ reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); reg |= WM9081_BIAS_SRC; + reg &= ~WM9081_BIAS_ENA; snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); - /* Disable VMID and biases with soft ramping */ + /* Disable VMID with soft ramping */ reg = snd_soc_read(codec, WM9081_VMID_CONTROL); - reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA); + reg &= ~WM9081_VMID_SEL_MASK; reg |= WM9081_VMID_RAMP; snd_soc_write(codec, WM9081_VMID_CONTROL, reg); -- cgit From 08f2e6312c67fed80df9342e06ad36daf11eb80b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 8 Nov 2011 18:29:15 +0800 Subject: iommu: omap: Fix compile failure Fix compile failure in drivers/iommu/omap-iommu-debug.c because of missing module.h include. Signed-off-by: Ming Lei Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu-debug.c | 1 + drivers/iommu/omap-iovmm.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 9c192e79f806..288da5c1499d 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c index e8fdb8830f69..46be456fcc00 100644 --- a/drivers/iommu/omap-iovmm.c +++ b/drivers/iommu/omap-iovmm.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include -- cgit From b52a360b2aa1c59ba9970fb0f52bbb093fcc7a24 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Mon, 7 Nov 2011 16:10:24 +0000 Subject: xfs: Fix possible memory corruption in xfs_readlink Fixes a possible memory corruption when the link is larger than MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the S_ISLNK assert, since the inode mode is checked previously in xfs_readlink_by_handle() and via VFS. Updated to address concerns raised by Ben Hutchings about the loose attention paid to 32- vs 64-bit values, and the lack of handling a potentially negative pathlen value: - Changed type of "pathlen" to be xfs_fsize_t, to match that of ip->i_d.di_size - Added checking for a negative pathlen to the too-long pathlen test, and generalized the message that gets reported in that case to reflect the change As a result, if a negative pathlen were encountered, this function would return EFSCORRUPTED (and would fail an assertion for a debug build)--just as would a too-long pathlen. Signed-off-by: Alex Elder Signed-off-by: Carlos Maiolino Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_vnodeops.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 4ecf2a549060..ce9268a2f56b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -112,7 +112,7 @@ xfs_readlink( char *link) { xfs_mount_t *mp = ip->i_mount; - int pathlen; + xfs_fsize_t pathlen; int error = 0; trace_xfs_readlink(ip); @@ -122,13 +122,19 @@ xfs_readlink( xfs_ilock(ip, XFS_ILOCK_SHARED); - ASSERT(S_ISLNK(ip->i_d.di_mode)); - ASSERT(ip->i_d.di_size <= MAXPATHLEN); - pathlen = ip->i_d.di_size; if (!pathlen) goto out; + if (pathlen < 0 || pathlen > MAXPATHLEN) { + xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)", + __func__, (unsigned long long) ip->i_ino, + (long long) pathlen); + ASSERT(0); + return XFS_ERROR(EFSCORRUPTED); + } + + if (ip->i_df.if_flags & XFS_IFINLINE) { memcpy(link, ip->i_df.if_u1.if_data, pathlen); link[pathlen] = '\0'; -- cgit From 272e42b215c52d32e06bf035c1f6b70baa6716bd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Oct 2011 09:54:24 +0000 Subject: xfs: constify xfs_item_ops The log item ops aren't nessecarily the biggest exploit vector, but marking them const is easy enough. Also remove the unused xfs_item_ops_t typedef while we're at it. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Alex Elder --- fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_dquot_item.c | 6 +++--- fs/xfs/xfs_extfree_item.c | 4 ++-- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_log.h | 2 +- fs/xfs/xfs_trans.h | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 1a3513881bce..eac97ef81e2a 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -656,7 +656,7 @@ xfs_buf_item_committing( /* * This is the ops vector shared by all buf log items. */ -static struct xfs_item_ops xfs_buf_item_ops = { +static const struct xfs_item_ops xfs_buf_item_ops = { .iop_size = xfs_buf_item_size, .iop_format = xfs_buf_item_format, .iop_pin = xfs_buf_item_pin, diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c index bb3f71d236d2..0dee0b71029d 100644 --- a/fs/xfs/xfs_dquot_item.c +++ b/fs/xfs/xfs_dquot_item.c @@ -295,7 +295,7 @@ xfs_qm_dquot_logitem_committing( /* * This is the ops vector for dquots */ -static struct xfs_item_ops xfs_dquot_item_ops = { +static const struct xfs_item_ops xfs_dquot_item_ops = { .iop_size = xfs_qm_dquot_logitem_size, .iop_format = xfs_qm_dquot_logitem_format, .iop_pin = xfs_qm_dquot_logitem_pin, @@ -483,7 +483,7 @@ xfs_qm_qoff_logitem_committing( { } -static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { +static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { .iop_size = xfs_qm_qoff_logitem_size, .iop_format = xfs_qm_qoff_logitem_format, .iop_pin = xfs_qm_qoff_logitem_pin, @@ -498,7 +498,7 @@ static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { /* * This is the ops vector shared by all quotaoff-start log items. */ -static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { +static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = { .iop_size = xfs_qm_qoff_logitem_size, .iop_format = xfs_qm_qoff_logitem_format, .iop_pin = xfs_qm_qoff_logitem_pin, diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index d22e62623437..35c2aff38b20 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -217,7 +217,7 @@ xfs_efi_item_committing( /* * This is the ops vector shared by all efi log items. */ -static struct xfs_item_ops xfs_efi_item_ops = { +static const struct xfs_item_ops xfs_efi_item_ops = { .iop_size = xfs_efi_item_size, .iop_format = xfs_efi_item_format, .iop_pin = xfs_efi_item_pin, @@ -477,7 +477,7 @@ xfs_efd_item_committing( /* * This is the ops vector shared by all efd log items. */ -static struct xfs_item_ops xfs_efd_item_ops = { +static const struct xfs_item_ops xfs_efd_item_ops = { .iop_size = xfs_efd_item_size, .iop_format = xfs_efd_item_format, .iop_pin = xfs_efd_item_pin, diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index b7cf21ba240f..abaafdbb3e65 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -795,7 +795,7 @@ xfs_inode_item_committing( /* * This is the ops vector shared by all buf log items. */ -static struct xfs_item_ops xfs_inode_item_ops = { +static const struct xfs_item_ops xfs_inode_item_ops = { .iop_size = xfs_inode_item_size, .iop_format = xfs_inode_item_format, .iop_pin = xfs_inode_item_pin, diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 2758a6277c52..a14cd89fe465 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -626,7 +626,7 @@ xfs_log_item_init( struct xfs_mount *mp, struct xfs_log_item *item, int type, - struct xfs_item_ops *ops) + const struct xfs_item_ops *ops) { item->li_mountp = mp; item->li_ailp = mp->m_ail; diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 78c9039994af..3f7bf451c034 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -137,7 +137,7 @@ struct xfs_trans; void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, int type, - struct xfs_item_ops *ops); + const struct xfs_item_ops *ops); xfs_lsn_t xfs_log_done(struct xfs_mount *mp, struct xlog_ticket *ticket, diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 603f3eb52041..3ae713c0abd9 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -326,7 +326,7 @@ typedef struct xfs_log_item { struct xfs_log_item *); /* buffer item iodone */ /* callback func */ - struct xfs_item_ops *li_ops; /* function list */ + const struct xfs_item_ops *li_ops; /* function list */ /* delayed logging */ struct list_head li_cil; /* CIL pointers */ @@ -341,7 +341,7 @@ typedef struct xfs_log_item { { XFS_LI_IN_AIL, "IN_AIL" }, \ { XFS_LI_ABORTED, "ABORTED" } -typedef struct xfs_item_ops { +struct xfs_item_ops { uint (*iop_size)(xfs_log_item_t *); void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); void (*iop_pin)(xfs_log_item_t *); @@ -352,7 +352,7 @@ typedef struct xfs_item_ops { void (*iop_push)(xfs_log_item_t *); bool (*iop_pushbuf)(xfs_log_item_t *); void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t); -} xfs_item_ops_t; +}; #define IOP_SIZE(ip) (*(ip)->li_ops->iop_size)(ip) #define IOP_FORMAT(ip,vp) (*(ip)->li_ops->iop_format)(ip, vp) -- cgit From 810627d9a6d0e8820c798001875bc4e1b7754ebf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2011 08:56:15 +0000 Subject: xfs: fix force shutdown handling in xfs_end_io Ensure ioend->io_error gets propagated back to e.g. AIO completions. Signed-off-by: Christoph Hellwig Reviewed-by: Alex Elder --- fs/xfs/xfs_aops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 33b13310ee0c..574d4ee9b625 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -189,7 +189,7 @@ xfs_end_io( int error = 0; if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { - error = -EIO; + ioend->io_error = -EIO; goto done; } if (ioend->io_error) -- cgit From dcaaf9f2c16b56f8bb316881fcd3f15c18fc71e7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Nov 2011 17:50:27 +0100 Subject: ALSA: usb-audio - Fix the missing volume quirks at delayed init In the recent usb-audio driver, the initialization of volume ranges may be delayed when the device doesn't respond well at the probing time. But the volume quirks for certain devices are applied only in mixer_ctl_feature_info() thus only at the very first probe and will be missing when the volume range is initialized later. This patch moves the volume quirk code to be always called from the volume-range extraction (get_min_max()), so that the quirks are properly applied in the later init time. Reported-and-tested-by: Alexey Fisher Cc: Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 109 +++++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 60f65ace7474..c5444e00f0c6 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -765,10 +765,60 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) * interface to ALSA control for feature/mixer units */ +/* volume control quirks */ +static void volume_control_quirks(struct usb_mixer_elem_info *cval, + struct snd_kcontrol *kctl) +{ + switch (cval->mixer->chip->usb_id) { + case USB_ID(0x0471, 0x0101): + case USB_ID(0x0471, 0x0104): + case USB_ID(0x0471, 0x0105): + case USB_ID(0x0672, 0x1041): + /* quirk for UDA1321/N101. + * note that detection between firmware 2.1.1.7 (N101) + * and later 2.1.1.21 is not very clear from datasheets. + * I hope that the min value is -15360 for newer firmware --jk + */ + if (!strcmp(kctl->id.name, "PCM Playback Volume") && + cval->min == -15616) { + snd_printk(KERN_INFO + "set volume quirk for UDA1321/N101 chip\n"); + cval->max = -256; + } + break; + + case USB_ID(0x046d, 0x09a4): + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + snd_printk(KERN_INFO + "set volume quirk for QuickCam E3500\n"); + cval->min = 6080; + cval->max = 8768; + cval->res = 192; + } + break; + + case USB_ID(0x046d, 0x0808): + case USB_ID(0x046d, 0x0809): + case USB_ID(0x046d, 0x0991): + /* Most audio usb devices lie about volume resolution. + * Most Logitech webcams have res = 384. + * Proboly there is some logitech magic behind this number --fishor + */ + if (!strcmp(kctl->id.name, "Mic Capture Volume")) { + snd_printk(KERN_INFO + "set resolution quirk: cval->res = 384\n"); + cval->res = 384; + } + break; + + } +} + /* * retrieve the minimum and maximum values for the specified control */ -static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) +static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, + int default_min, struct snd_kcontrol *kctl) { /* for failsafe */ cval->min = default_min; @@ -844,6 +894,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) cval->initialized = 1; } + if (kctl) + volume_control_quirks(cval, kctl); + /* USB descriptions contain the dB scale in 1/256 dB unit * while ALSA TLV contains in 1/100 dB unit */ @@ -864,6 +917,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) return 0; } +#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) /* get a feature/mixer unit info */ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -882,7 +936,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ uinfo->value.integer.max = 1; } else { if (!cval->initialized) { - get_min_max(cval, 0); + get_min_max_with_quirks(cval, 0, kcontrol); if (cval->initialized && cval->dBmin >= cval->dBmax) { kcontrol->vd[0].access &= ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | @@ -1045,9 +1099,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, cval->ch_readonly = readonly_mask; } - /* get min/max values */ - get_min_max(cval, 0); - /* if all channels in the mask are marked read-only, make the control * read-only. set_cur_mix_value() will check the mask again and won't * issue write commands to read-only channels. */ @@ -1069,6 +1120,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); + /* get min/max values */ + get_min_max_with_quirks(cval, 0, kctl); + switch (control) { case UAC_FU_MUTE: case UAC_FU_VOLUME: @@ -1118,51 +1172,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, break; } - /* volume control quirks */ - switch (state->chip->usb_id) { - case USB_ID(0x0471, 0x0101): - case USB_ID(0x0471, 0x0104): - case USB_ID(0x0471, 0x0105): - case USB_ID(0x0672, 0x1041): - /* quirk for UDA1321/N101. - * note that detection between firmware 2.1.1.7 (N101) - * and later 2.1.1.21 is not very clear from datasheets. - * I hope that the min value is -15360 for newer firmware --jk - */ - if (!strcmp(kctl->id.name, "PCM Playback Volume") && - cval->min == -15616) { - snd_printk(KERN_INFO - "set volume quirk for UDA1321/N101 chip\n"); - cval->max = -256; - } - break; - - case USB_ID(0x046d, 0x09a4): - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO - "set volume quirk for QuickCam E3500\n"); - cval->min = 6080; - cval->max = 8768; - cval->res = 192; - } - break; - - case USB_ID(0x046d, 0x0808): - case USB_ID(0x046d, 0x0809): - case USB_ID(0x046d, 0x0991): - /* Most audio usb devices lie about volume resolution. - * Most Logitech webcams have res = 384. - * Proboly there is some logitech magic behind this number --fishor - */ - if (!strcmp(kctl->id.name, "Mic Capture Volume")) { - snd_printk(KERN_INFO - "set resolution quirk: cval->res = 384\n"); - cval->res = 384; - } - break; - - } - range = (cval->max - cval->min) / cval->res; /* Are there devices with volume range more than 255? I use a bit more * to be sure. 384 is a resolution magic number found on Logitech -- cgit From eca55f4d9c1d918c2aa95fb8a73a34e2ba8a1b11 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 8 Nov 2011 13:07:36 +0000 Subject: ARM: msm: fix compilation flags for MSM_SCM CONFIG_MSM_SCM uses the smc instruction, which with some toolchains requires a ".arch_extension" directive. Cc: David Brown Signed-off-by: Marc Zyngier Signed-off-by: David Brown --- arch/arm/mach-msm/Makefile | 2 ++ arch/arm/mach-msm/scm.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 4285dfd80b6f..4ad3969b9881 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -15,6 +15,8 @@ obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) + obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c index 232f97a04504..bafabb502580 100644 --- a/arch/arm/mach-msm/scm.c +++ b/arch/arm/mach-msm/scm.c @@ -180,6 +180,9 @@ static u32 smc(u32 cmd_addr) __asmeq("%1", "r0") __asmeq("%2", "r1") __asmeq("%3", "r2") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif "smc #0 @ switch to secure world\n" : "=r" (r0) : "r" (r0), "r" (r1), "r" (r2) -- cgit From 10953db8e1a278742ef7e64a3d1491802bcfa98b Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 7 Nov 2011 20:44:37 +0000 Subject: r8169: increase the delay parameter of pm_schedule_suspend The link down would occur when reseting PHY. And it would take about 2 ~ 5 seconds from link down to link up. If the delay of pm_schedule_suspend is not long enough, the device would enter runtime_suspend before link up. After link up, the device would wake up and reset PHY again. Then, you would find the driver keep in a loop of runtime_suspend and rumtime_resume. Signed-off-by: Hayes Wang Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 92b45f08858f..6f06aa10f0d7 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1292,7 +1292,7 @@ static void __rtl8169_check_link_status(struct net_device *dev, netif_carrier_off(dev); netif_info(tp, ifdown, dev, "link down\n"); if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 100); + pm_schedule_suspend(&tp->pci_dev->dev, 5000); } spin_unlock_irqrestore(&tp->lock, flags); } -- cgit From c457338d7acd3823e765b684a62294cfda9d2f55 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Tue, 8 Nov 2011 04:41:42 +0000 Subject: ipv6: drop packets when source address is multicast RFC 4291 Section 2.7 says Multicast addresses must not be used as source addresses in IPv6 packets - drop them on input so we don't process the packet further. Signed-off-by: Brian Haley Reported-and-Tested-by: Kumar Sanghvi Signed-off-by: David S. Miller --- net/ipv6/ip6_input.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 027c7ff6f1e5..a46c64eb0a66 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -111,6 +111,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ipv6_addr_loopback(&hdr->daddr)) goto err; + /* + * RFC4291 2.7 + * Multicast addresses must not be used as source addresses in IPv6 + * packets or appear in any Routing header. + */ + if (ipv6_addr_is_multicast(&hdr->saddr)) + goto err; + skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); -- cgit From ea1649dea95fb270af94f75e842402c4cfbfc15f Mon Sep 17 00:00:00 2001 From: Nico Erfurth Date: Tue, 8 Nov 2011 07:30:40 +0000 Subject: Fix incorrect usage of NET_IP_ALIGN The driver used NET_IP_ALIGN to remove some additional padding inside of the rx_fixup function. On many architectures NET_IP_ALIGN defaults to 2 which removed the correct amount of bytes. On MCORE2-machines commit ea812ca1b06113597adcd8e70c0f84a413d97544 introduces a change which sets NET_IP_ALIGN to 0 by default. Which triggered the bug on these machines. This fix introduces a new RXW_PADDING define and uses this instead of NET_IP_ALIGN. The name was taken from the original SMSC7500 driver which is provided by SMSC. Signed-off-by: Nico Erfurth Tested-by: Phil Sutter Signed-off-by: David S. Miller --- drivers/net/usb/smsc75xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 22a7cf951e72..a5b9b12ef268 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -51,6 +51,7 @@ #define USB_VENDOR_ID_SMSC (0x0424) #define USB_PRODUCT_ID_LAN7500 (0x7500) #define USB_PRODUCT_ID_LAN7505 (0x7505) +#define RXW_PADDING 2 #define check_warn(ret, fmt, args...) \ ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); }) @@ -1088,13 +1089,13 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b)); le32_to_cpus(&rx_cmd_b); - skb_pull(skb, 4 + NET_IP_ALIGN); + skb_pull(skb, 4 + RXW_PADDING); packet = skb->data; /* get the packet length */ - size = (rx_cmd_a & RX_CMD_A_LEN) - NET_IP_ALIGN; - align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4; + size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING; + align_count = (4 - ((size + RXW_PADDING) % 4)) % 4; if (unlikely(rx_cmd_a & RX_CMD_A_RED)) { netif_dbg(dev, rx_err, dev->net, -- cgit From 4f1a1eb530071c39fb239fd26c912a64284b1408 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Tue, 8 Nov 2011 09:59:01 -0500 Subject: MIPS: Kernel hangs occasionally during boot. The Kernel hangs occasionally during boot after "Calibrating delay loop..". This is caused by the c0_compare_int_usable() routine in cevt-r4k.c returning false which causes the system to disable the timer and hang later. The false return happens because the routine is using a series of four calls to irq_disable_hazard() as a delay while it waits for the timer changes to propagate to the cp0 cause register. On newer MIPS cores, like the 74K, the series of irq_disable_hazard() calls turn into ehb instructions and can take as little as a few clock ticks for all 4 instructions. This is not enough of a delay, so the routine thinks the timer is not working. This fix uses up to a max number of cycle counter ticks for the delay and uses back_to_back_c0_hazard() instead of irq_disable_hazard() to handle the hazard condition between cp0 writes and cp0 reads. Signed-off-by: Al Cooper Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/2911/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cevt-r4k.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 98c5a9737c14..e2d8e199be32 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -103,19 +103,10 @@ static int c0_compare_int_pending(void) /* * Compare interrupt can be routed and latched outside the core, - * so a single execution hazard barrier may not be enough to give - * it time to clear as seen in the Cause register. 4 time the - * pipeline depth seems reasonably conservative, and empirically - * works better in configurations with high CPU/bus clock ratios. + * so wait up to worst case number of cycle counter ticks for timer interrupt + * changes to propagate to the cause register. */ - -#define compare_change_hazard() \ - do { \ - irq_disable_hazard(); \ - irq_disable_hazard(); \ - irq_disable_hazard(); \ - irq_disable_hazard(); \ - } while (0) +#define COMPARE_INT_SEEN_TICKS 50 int c0_compare_int_usable(void) { @@ -126,8 +117,12 @@ int c0_compare_int_usable(void) * IP7 already pending? Try to clear it by acking the timer. */ if (c0_compare_int_pending()) { - write_c0_compare(read_c0_count()); - compare_change_hazard(); + cnt = read_c0_count(); + write_c0_compare(cnt); + back_to_back_c0_hazard(); + while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS)) + if (!c0_compare_int_pending()) + break; if (c0_compare_int_pending()) return 0; } @@ -136,7 +131,7 @@ int c0_compare_int_usable(void) cnt = read_c0_count(); cnt += delta; write_c0_compare(cnt); - compare_change_hazard(); + back_to_back_c0_hazard(); if ((int)(read_c0_count() - cnt) < 0) break; /* increase delta if the timer was already expired */ @@ -145,12 +140,17 @@ int c0_compare_int_usable(void) while ((int)(read_c0_count() - cnt) <= 0) ; /* Wait for expiry */ - compare_change_hazard(); + while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS)) + if (c0_compare_int_pending()) + break; if (!c0_compare_int_pending()) return 0; - - write_c0_compare(read_c0_count()); - compare_change_hazard(); + cnt = read_c0_count(); + write_c0_compare(cnt); + back_to_back_c0_hazard(); + while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS)) + if (!c0_compare_int_pending()) + break; if (c0_compare_int_pending()) return 0; -- cgit From a8d12007c795f3d69ee0b2d29f0abfefd55c6120 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 8 Nov 2011 18:02:10 +0000 Subject: n_gsm: Fix timings Alek Du reported that the code erroneously applies time to jiffies conversions twice to the t1 and t2 values. In normal use on a modem link this cases no visible problem but on a slower link it will break as with HZ=1000 as is typical we are running t1/t2 ten times too fast. Alek's original patch removed the conversion from the timer setting but we in fact have to be more careful as the contents of t1/t2 are visible via the device API and we thus need to correct the constants. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/tty/n_gsm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 4cb0d0a3e57b..fc7bbba585ce 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -66,14 +66,16 @@ static int debug; module_param(debug, int, 0600); -#define T1 (HZ/10) -#define T2 (HZ/3) -#define N2 3 +/* Defaults: these are from the specification */ + +#define T1 10 /* 100mS */ +#define T2 34 /* 333mS */ +#define N2 3 /* Retry 3 times */ /* Use long timers for testing at low speed with debug on */ #ifdef DEBUG_TIMING -#define T1 HZ -#define T2 (2 * HZ) +#define T1 100 +#define T2 200 #endif /* -- cgit From 71e63e748ee6f4bad482b8021386eeb74f6e47f1 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 4 Nov 2011 08:10:09 +0100 Subject: ARM: 7149/1: spi/pl022: Enable clock in probe Make sure we enable the clock before leaving probe. Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Signed-off-by: Russell King --- drivers/spi/spi-pl022.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index f103e470cb63..5559b2299198 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2184,6 +2184,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) goto err_clk_prep; } + status = clk_enable(pl022->clk); + if (status) { + dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n"); + goto err_no_clk_en; + } + /* Disable SSP */ writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); @@ -2237,6 +2243,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) free_irq(adev->irq[0], pl022); err_no_irq: + clk_disable(pl022->clk); + err_no_clk_en: clk_unprepare(pl022->clk); err_clk_prep: clk_put(pl022->clk); -- cgit From 8428e84d42179c2a00f5f6450866e70d802d1d05 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 7 Nov 2011 18:05:53 +0100 Subject: ARM: 7150/1: Allow kernel unaligned accesses on ARMv6+ processors Recent gcc versions generate unaligned accesses by default on ARMv6 and later processors. This patch ensures that the SCTLR.A bit is always cleared on such processors to avoid kernel traping before alignment_init() is called. Signed-off-by: Catalin Marinas Tested-by: John Linn Acked-by: Nicolas Pitre Cc: stable@vger.kernel.org Signed-off-by: Russell King --- arch/arm/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 566c54c2a1fe..08c82fd844a8 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -360,7 +360,7 @@ __secondary_data: * r13 = *virtual* address to jump to upon completion */ __enable_mmu: -#ifdef CONFIG_ALIGNMENT_TRAP +#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 orr r0, r0, #CR_A #else bic r0, r0, #CR_A -- cgit From 5f300acd8ae9f3d4585154370012ffc5c665330f Mon Sep 17 00:00:00 2001 From: Dirk B Date: Tue, 8 Nov 2011 18:16:39 +0100 Subject: ARM: 7152/1: distclean: Remove generated .dtb files The patch 'arm/dt: Add dtb make rule' adds support to create a .dtb file. But this is never removed afterwards. Remove the generated .dtb file if 'distclean' is called. Signed-off-by: Dirk Behme Acked-by: Rob Herring Acked-by: Grant Likely Cc: Shawn Guo Cc: Jason Liu Signed-off-by: Russell King --- arch/arm/boot/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 176062ac7f07..5df26a9976a2 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -65,6 +65,8 @@ $(obj)/%.dtb: $(src)/dts/%.dts $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y)) +clean-files := *.dtb + quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ -C none -a $(LOADADDR) -e $(STARTADDR) \ -- cgit From 042f36e1560cedfe524607791fa44607a3121f63 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Tue, 8 Nov 2011 13:27:31 -0500 Subject: IB/qib: Don't use schedule_work() It was mistakenly introduced by dde05cbdf8b1 ("IB/qib: Hold links until tuning data is available"). Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba7322.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 5bd2162b95dc..8b46b608c02f 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -5241,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) off */ if (ppd->dd->flags & QIB_HAS_QSFP) { qd->t_insert = get_jiffies_64(); - schedule_work(&qd->work); + queue_work(ib_wq, &qd->work); } spin_lock_irqsave(&ppd->sdma_lock, flags); if (__qib_sdma_running(ppd)) -- cgit From e50e705ca71db82a78a3e13fb7abf6b2171ac9c7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 8 Nov 2011 13:59:44 -0500 Subject: l2tp: fix l2tp_udp_recv_core() pskb_may_pull() can change skb->data, so we have to load ptr/optr at the right place. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index bf8d50c67931..cf0f308abf5e 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -756,9 +756,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, goto error; } - /* Point to L2TP header */ - optr = ptr = skb->data; - /* Trace packet contents, if enabled */ if (tunnel->debug & L2TP_MSG_DATA) { length = min(32u, skb->len); @@ -769,12 +766,15 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb, offset = 0; do { - printk(" %02X", ptr[offset]); + printk(" %02X", skb->data[offset]); } while (++offset < length); printk("\n"); } + /* Point to L2TP header */ + optr = ptr = skb->data; + /* Get L2TP header flags */ hdrflags = ntohs(*(__be16 *) ptr); -- cgit From 59caa5612ce916c4902c753aa61429eb76ac2b21 Mon Sep 17 00:00:00 2001 From: oftedal Date: Mon, 7 Nov 2011 11:47:53 +0000 Subject: sunhme: Allow usage on SBI based SBus systems To prevent the SBus driver for Sun Happy Meal cards from being loaded for PCI cards utilizing the same chipset, a filter was added to the probe function in commit 0b492fce3d72d982a7981905f85484a1e1ba7fde. The filter was implemented by checking the name of the parent node in the OF tree. This patch extends this filter, so that the driver will load on SBus systems that are based upon SBI SBus Bridges. Signed-off-by: Kjetil Oftedal Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunhme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index c517dac02ae1..cf14ab9db576 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2637,7 +2637,7 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i sbus_dp = op->dev.parent->of_node; /* We can match PCI devices too, do not accept those here. */ - if (strcmp(sbus_dp->name, "sbus")) + if (strcmp(sbus_dp->name, "sbus") && strcmp(sbus_dp->name, "sbi")) return err; if (is_qfe) { -- cgit From 6d67e9beb68bc6712b042c9723cecc87dc8e3f4c Mon Sep 17 00:00:00 2001 From: Feng King Date: Sat, 5 Nov 2011 04:23:23 +0000 Subject: tcp: Fix comments for Nagle algorithm TCP_NODELAY is weaker than TCP_CORK, when TCP_CORK was set, small segments will always pass Nagle test regardless of TCP_NODELAY option. Signed-off-by: Feng King 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 980b98f6288c..63170e297540 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1382,7 +1382,7 @@ static inline int tcp_minshall_check(const struct tcp_sock *tp) /* Return 0, if packet can be sent now without violation Nagle's rules: * 1. It is full sized. * 2. Or it contains FIN. (already checked by caller) - * 3. Or TCP_NODELAY was set. + * 3. Or TCP_CORK is not set, and TCP_NODELAY is set. * 4. Or TCP_CORK is not set, and all sent packets are ACKed. * With Minshall's modification: all sent small packets are ACKed. */ -- cgit From 20db93c34095553a01a9c31136658917bf1fa5d5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 8 Nov 2011 14:21:44 -0500 Subject: net: min_pmtu default is 552 Small fix in Documentation, since min_pmtu is 512 + 20 + 20 = 552 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index cb7f3148035d..f049a1ca186f 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -20,7 +20,7 @@ ip_no_pmtu_disc - BOOLEAN default FALSE min_pmtu - INTEGER - default 562 - minimum discovered Path MTU + default 552 - minimum discovered Path MTU route/max_size - INTEGER Maximum number of routes allowed in the kernel. Increase -- cgit From 2bc8ca40f951163b3bb75949479e2755c12c1b96 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 11 Oct 2011 01:12:02 +0000 Subject: ipv4: Fix inetpeer expire time information As we update the learned pmtu informations on demand, we might report a nagative expiration time value to userspace if the pmtu informations are already expired and we have not send a packet to that inetpeer after expiration. With this patch we send a expire time of null to userspace after expiration until the next packet is send to that inetpeer. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/route.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 155138d8ec8b..511f4a75149c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2845,7 +2845,7 @@ static int rt_fill_info(struct net *net, struct rtable *rt = skb_rtable(skb); struct rtmsg *r; struct nlmsghdr *nlh; - long expires = 0; + unsigned long expires = 0; const struct inet_peer *peer = rt->peer; u32 id = 0, ts = 0, tsage = 0, error; @@ -2902,8 +2902,12 @@ static int rt_fill_info(struct net *net, tsage = get_seconds() - peer->tcp_ts_stamp; } expires = ACCESS_ONCE(peer->pmtu_expires); - if (expires) - expires -= jiffies; + if (expires) { + if (time_before(jiffies, expires)) + expires -= jiffies; + else + expires = 0; + } } if (rt_is_input_route(rt)) { -- cgit From 917c16b2b69fc2eeb432eabca73258f08c58361e Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 8 Nov 2011 14:49:59 -0500 Subject: Btrfs: fix oops on NULL trans handle in btrfs_truncate If we fail to reserve space in the transaction during truncate, we can error out with a NULL trans handle. The cleanup code needs an extra check to make sure we aren't trying to use the bad handle. Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9d0eaa57d4ee..f60e2490bd0d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6529,14 +6529,16 @@ end_trans: ret = btrfs_orphan_del(NULL, inode); } - trans->block_rsv = &root->fs_info->trans_block_rsv; - ret = btrfs_update_inode(trans, root, inode); - if (ret && !err) - err = ret; + if (trans) { + trans->block_rsv = &root->fs_info->trans_block_rsv; + ret = btrfs_update_inode(trans, root, inode); + if (ret && !err) + err = ret; - nr = trans->blocks_used; - ret = btrfs_end_transaction_throttle(trans, root); - btrfs_btree_balance_dirty(root, nr); + nr = trans->blocks_used; + ret = btrfs_end_transaction_throttle(trans, root); + btrfs_btree_balance_dirty(root, nr); + } out: btrfs_free_block_rsv(root, rsv); -- cgit From 6aec187a90aeb883533c9180e2acac1e54c87f7d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 8 Nov 2011 14:56:50 -0500 Subject: drivers/media: video/a5k6aa is a module and so needs module.h This file uses core functions like module_init() and module_exit() and so it explicitly needs to include the module.h header. Signed-off-by: Paul Gortmaker --- drivers/media/video/s5k6aa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/s5k6aa.c b/drivers/media/video/s5k6aa.c index 2446736b7871..0df7f2a41814 100644 --- a/drivers/media/video/s5k6aa.c +++ b/drivers/media/video/s5k6aa.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include -- cgit From c26887d2a48600bfa87a27ce41ff78828bd7243c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Nov 2011 09:20:07 +0100 Subject: cfg80211: fix missing kernel-doc Two new struct members were not documented, fix that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 92cf1c2c30c9..95852e36713b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -456,6 +456,9 @@ enum station_parameters_apply_mask { * as the AC bitmap in the QoS info field * @max_sp: max Service Period. same format as the MAX_SP in the * QoS info field (but already shifted down) + * @sta_modify_mask: bitmap indicating which parameters changed + * (for those that don't have a natural "no change" value), + * see &enum station_parameters_apply_mask */ struct station_parameters { u8 *supported_rates; @@ -615,6 +618,7 @@ struct sta_bss_parameters { * user space MLME/SME implementation. The information is provided for * the cfg80211_new_sta() calls to notify user space of the IEs. * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. + * @sta_flags: station flags mask & values */ struct station_info { u32 filled; -- cgit From a59be0811c322f80aaa886b144239393efece42d Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Tue, 8 Nov 2011 14:01:13 +0100 Subject: ath: Fix NULL ptr dereference in ath_reg_apply_world_flags This happens with devices using a regulatory domain 0x68 that are only 5Ghz capable because ath_reg_apply_active_scan_flags assumes that we always have a 2,4Ghz band. CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 82cd838c, ra == 82cd8384 Oops[#1]: Cpu 0 $ 0 : 00000000 00000061 00000003 00000024 $ 4 : 00000003 000016c1 82f900ac 00000024 $ 8 : 00000000 82cda304 0058bad8 00000005 $12 : 005908f8 001e8481 00000003 1dcd6500 $16 : 00000002 00000000 82c700c0 82c700c0 $20 : 82d415e4 82c70d64 82c70200 82c715bc $24 : 00000000 11e1a300 $28 : 82ce2000 82ce3c70 82c715a8 82cd8384 Hi : 00000000 Lo : 0000001e epc : 82cd838c ath_reg_apply_world_flags+0x78/0x17c [ath] Not tainted ra : 82cd8384 ath_reg_apply_world_flags+0x70/0x17c [ath] Status: 1000d403 KERNEL EXL IE Cause : 80800008 BadVA : 00000000 PrId : 00019374 (MIPS 24Kc) Modules linked in: ath9k(+) ath9k_common ath9k_hw ath mac80211 cfg80211 compat_firmware_class compat arc4 aes_generic deflate ecb cbc leds_gpio button_hotplug gpio_buttons input_polldev ie Process insmod (pid: 464, threadinfo=82ce2000, task=838b31d8, tls=00000000) Stack : 00000000 00000002 82f900ac 82c700c0 82d415e4 82c70d64 00000000 00000068 82f900ac 82cd88f4 82c700c0 82cda304 00000001 000020f0 82f90000 82c70d40 00000002 82f90000 82f900ac 82d4207c 82d518a0 00000002 7fee6118 8017c0d8 00000008 8397ba00 82c70d40 00000000 82c70200 83813000 83813058 b0010000 82d518a0 00000002 7fee6118 82d4b8c8 83445cc0 80120dc0 83804000 800eeda0 ... Call Trace: [<82cd838c>] ath_reg_apply_world_flags+0x78/0x17c [ath] [<82cd88f4>] ath_regd_init+0x464/0x488 [ath] [<82d4207c>] ath9k_init_device+0x6a4/0x6b4 [ath9k] [<82d4b8c8>] ath_pci_probe+0x27c/0x358 [ath9k] [<80181de0>] pci_device_probe+0x64/0xa4 [<8019e874>] driver_probe_device+0xb8/0x190 [<8019e9b8>] __driver_attach+0x6c/0xa4 [<8019dfc0>] bus_for_each_dev+0x60/0xb0 [<8019d744>] bus_add_driver+0xc4/0x25c [<8019ed6c>] driver_register+0xe0/0x198 [<8018206c>] __pci_register_driver+0x50/0xe0 [<82dd0010>] ath9k_init+0x10/0x54 [ath9k] [<8006b4a0>] do_one_initcall+0x68/0x1ec [<800a901c>] sys_init_module+0xec/0x23c [<80062544>] stack_done+0x20/0x3c Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 028310f263c8..f1be57f0f5bb 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -253,6 +253,8 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, int r; sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + if (!sband) + return; /* * If no country IE has been received always enable active scan -- cgit From cc438fccd5783c9f7b4c4858358ac897dcf8a58d Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Tue, 8 Nov 2011 15:54:46 +0200 Subject: wl12xx: fix wl12xx_scan_sched_scan_ssid_list() check that all given ssids are in filters A minor fix for the check that verifies that all given SSIDs (in req) exist in the filters (the match sets) Signed-off-by: Eyal Shapira Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 128ccb79318c..fc29c671cf3b 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -559,7 +559,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, break; } /* Fail if SSID isn't present in the filters */ - if (j == req->n_ssids) { + if (j == cmd->n_ssids) { ret = -EINVAL; goto out_free; } -- cgit From b9c913f327ccc5cf422b6dc9b5acfbc9b86e7b62 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 8 Nov 2011 12:17:25 -0800 Subject: x86 platform drivers: make Dell laptop driver select needed LED support Otherwise we get compile errors like this: ERROR: "led_classdev_unregister" [drivers/platform/x86/dell-laptop.ko] undefined! ERROR: "led_classdev_register" [drivers/platform/x86/dell-laptop.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 when the dell-laptop support is enabled without the necessary LED support being enabled. Reported-by: Alessandro Suardi Acked-by: Matthew Garrett Signed-off-by: Linus Torvalds --- drivers/platform/x86/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f4e3d82379d7..598d5b82a6bc 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -85,6 +85,8 @@ config DELL_LAPTOP depends on RFKILL || RFKILL = n depends on POWER_SUPPLY depends on SERIO_I8042 + select LEDS_CLASS + select NEW_LEDS default n ---help--- This driver adds support for rfkill and backlight control to Dell -- cgit From 7fd2ae21a42d178982679b86086661292b4afe4a Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 8 Nov 2011 15:47:34 -0500 Subject: Btrfs: fix our reservations for updating an inode when completing io People have been reporting ENOSPC crashes in finish_ordered_io. This is because we try to steal from the delalloc block rsv to satisfy a reservation to update the inode. The problem with this is we don't explicitly save space for updating the inode when doing delalloc. This is kind of a problem and we've gotten away with this because way back when we just stole from the delalloc reserve without any questions, and this worked out fine because generally speaking the leaf had been modified either by the mtime update when we did the original write or because we just updated the leaf when we inserted the file extent item, only on rare occasions had the leaf not actually been modified, and that was still ok because we'd just use a block or two out of the over-reservation that is delalloc. Then came the delayed inode stuff. This is amazing, except it wants a full reservation for updating the inode since it may do it at some point down the road after we've written the blocks and we have to recow everything again. This worked out because the delayed inode stuff just stole from the global reserve, that is until recently when I changed that because it caused other problems. So here we are, we're doing everything right and being screwed for it. So take an extra reservation for the inode at delalloc reservation time and carry it through the life of the delalloc reservation. If we need it we can steal it in the delayed inode stuff. If we have already stolen it try and do a normal metadata reservation. If that fails try to steal from the delalloc reservation. If _that_ fails we'll get a WARN_ON() so I can start thinking of a better way to solve this and in the meantime we'll steal from the global reserve. With this patch I ran xfstests 13 in a loop for a couple of hours and didn't see any problems. Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/btrfs_inode.h | 4 +-- fs/btrfs/delayed-inode.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- fs/btrfs/extent-tree.c | 22 +++++++++++++--- fs/btrfs/inode.c | 1 + 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 5a5d325a3935..634608d2a6d0 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -147,14 +147,12 @@ struct btrfs_inode { * the btrfs file release call will add this inode to the * ordered operations list so that we make sure to flush out any * new data the application may have written before commit. - * - * yes, its silly to have a single bitflag, but we might grow more - * of these. */ unsigned ordered_data_close:1; unsigned orphan_meta_reserved:1; unsigned dummy_inode:1; unsigned in_defrag:1; + unsigned delalloc_meta_reserved:1; /* * always compress this one file diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index bbe8496d5339..313ee14cf3b7 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -617,12 +617,14 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, static int btrfs_delayed_inode_reserve_metadata( struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct inode *inode, struct btrfs_delayed_node *node) { struct btrfs_block_rsv *src_rsv; struct btrfs_block_rsv *dst_rsv; u64 num_bytes; int ret; + int release = false; src_rsv = trans->block_rsv; dst_rsv = &root->fs_info->delayed_block_rsv; @@ -652,11 +654,67 @@ static int btrfs_delayed_inode_reserve_metadata( if (!ret) node->bytes_reserved = num_bytes; return ret; + } else if (src_rsv == &root->fs_info->delalloc_block_rsv) { + spin_lock(&BTRFS_I(inode)->lock); + if (BTRFS_I(inode)->delalloc_meta_reserved) { + BTRFS_I(inode)->delalloc_meta_reserved = 0; + spin_unlock(&BTRFS_I(inode)->lock); + release = true; + goto migrate; + } + spin_unlock(&BTRFS_I(inode)->lock); + + /* Ok we didn't have space pre-reserved. This shouldn't happen + * too often but it can happen if we do delalloc to an existing + * inode which gets dirtied because of the time update, and then + * isn't touched again until after the transaction commits and + * then we try to write out the data. First try to be nice and + * reserve something strictly for us. If not be a pain and try + * to steal from the delalloc block rsv. + */ + ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes); + if (!ret) + goto out; + + ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); + if (!ret) + goto out; + + /* + * Ok this is a problem, let's just steal from the global rsv + * since this really shouldn't happen that often. + */ + WARN_ON(1); + ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv, + dst_rsv, num_bytes); + goto out; } +migrate: ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); - if (!ret) - node->bytes_reserved = num_bytes; + if (unlikely(ret)) { + /* This shouldn't happen */ + BUG_ON(release); + return ret; + } + +out: + /* + * Migrate only takes a reservation, it doesn't touch the size of the + * block_rsv. This is to simplify people who don't normally have things + * migrated from their block rsv. If they go to release their + * reservation, that will decrease the size as well, so if migrate + * reduced size we'd end up with a negative size. But for the + * delalloc_meta_reserved stuff we will only know to drop 1 reservation, + * but we could in fact do this reserve/migrate dance several times + * between the time we did the original reservation and we'd clean it + * up. So to take care of this, release the space for the meta + * reservation here. I think it may be time for a documentation page on + * how block rsvs. work. + */ + if (release) + btrfs_block_rsv_release(root, src_rsv, num_bytes); + node->bytes_reserved = num_bytes; return ret; } @@ -1708,7 +1766,8 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, goto release_node; } - ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node); + ret = btrfs_delayed_inode_reserve_metadata(trans, root, inode, + delayed_node); if (ret) goto release_node; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 18ea90c8943b..0b044e509e9f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4063,23 +4063,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, */ static unsigned drop_outstanding_extent(struct inode *inode) { + unsigned drop_inode_space = 0; unsigned dropped_extents = 0; BUG_ON(!BTRFS_I(inode)->outstanding_extents); BTRFS_I(inode)->outstanding_extents--; + if (BTRFS_I(inode)->outstanding_extents == 0 && + BTRFS_I(inode)->delalloc_meta_reserved) { + drop_inode_space = 1; + BTRFS_I(inode)->delalloc_meta_reserved = 0; + } + /* * If we have more or the same amount of outsanding extents than we have * reserved then we need to leave the reserved extents count alone. */ if (BTRFS_I(inode)->outstanding_extents >= BTRFS_I(inode)->reserved_extents) - return 0; + return drop_inode_space; dropped_extents = BTRFS_I(inode)->reserved_extents - BTRFS_I(inode)->outstanding_extents; BTRFS_I(inode)->reserved_extents -= dropped_extents; - return dropped_extents; + return dropped_extents + drop_inode_space; } /** @@ -4165,9 +4172,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) nr_extents = BTRFS_I(inode)->outstanding_extents - BTRFS_I(inode)->reserved_extents; BTRFS_I(inode)->reserved_extents += nr_extents; + } - to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); + /* + * Add an item to reserve for updating the inode when we complete the + * delalloc io. + */ + if (!BTRFS_I(inode)->delalloc_meta_reserved) { + nr_extents++; + BTRFS_I(inode)->delalloc_meta_reserved = 1; } + + to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); spin_unlock(&BTRFS_I(inode)->lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f60e2490bd0d..2b920596c126 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6607,6 +6607,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ei->orphan_meta_reserved = 0; ei->dummy_inode = 0; ei->in_defrag = 0; + ei->delalloc_meta_reserved = 0; ei->force_compress = BTRFS_COMPRESS_NONE; ei->delayed_node = NULL; -- cgit From dccefb3729c8c2b17e45c68cdc0d575f2473a5f0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 8 Nov 2011 12:49:29 -0800 Subject: x86 platform drivers: add POWER_SUPPLY to selected drivers for Dell The Kconfig loop detection goes crazy without this. Signed-off-by: Linus Torvalds --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 598d5b82a6bc..7f43cf86d776 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -83,8 +83,8 @@ config DELL_LAPTOP depends on EXPERIMENTAL depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL || RFKILL = n - depends on POWER_SUPPLY depends on SERIO_I8042 + select POWER_SUPPLY select LEDS_CLASS select NEW_LEDS default n -- cgit From 156acb166ea9a43d7fcdf9b8051694ce4e91dbfc Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 8 Nov 2011 22:34:00 +0100 Subject: PM / OPP: Use ERR_CAST instead of ERR_PTR(PTR_ERR()) Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...)) [The semantic patch that makes this change is available in scripts/coccinelle/api/err_cast.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/] Signed-off-by: Thomas Meyer Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 434a6c011675..95706fa24c73 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -669,7 +669,7 @@ struct srcu_notifier_head *opp_get_notifier(struct device *dev) struct device_opp *dev_opp = find_device_opp(dev); if (IS_ERR(dev_opp)) - return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */ + return ERR_CAST(dev_opp); /* matching type */ return &dev_opp->head; } -- cgit From 24ed6ddd9cbf084f1a2dfa3ef66287e5277002e1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 25 Oct 2011 21:14:10 +0200 Subject: m68k: Revive lost ARAnyM config options commit 0e152d80507b75c00aac60f2ffc586360687cd52 ("m68k: reorganize Kconfig options to improve mmu/non-mmu selections") accidentally dropped the ARAnyM config options. Re-add them to the "Platform devices" section. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/Kconfig.devices | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices index d214034be6a6..6033f5d4e67e 100644 --- a/arch/m68k/Kconfig.devices +++ b/arch/m68k/Kconfig.devices @@ -24,6 +24,37 @@ config PROC_HARDWARE including the model, CPU, MMU, clock speed, BogoMIPS rating, and memory size. +config NATFEAT + bool "ARAnyM emulator support" + depends on ATARI + help + This option enables support for ARAnyM native features, such as + access to a disk image as /dev/hda. + +config NFBLOCK + tristate "NatFeat block device support" + depends on BLOCK && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat block device + which allows direct access to the hard drives without using + the hardware emulation. + +config NFCON + tristate "NatFeat console driver" + depends on NATFEAT + help + Say Y to include support for the ARAnyM NatFeat console driver + which allows the console output to be redirected to the stderr + output of ARAnyM. + +config NFETH + tristate "NatFeat Ethernet support" + depends on ETHERNET && NATFEAT + help + Say Y to include support for the ARAnyM NatFeat network device + which will emulate a regular ethernet device while presenting an + ethertap device to the host system. + endmenu menu "Character devices" -- cgit From 59433a59b073b88cb32efd03af8ac9b13d56f4cf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 28 Oct 2011 22:37:21 +0200 Subject: m68k: Revive lost DIO bus config option commit 0e152d80507b75c00aac60f2ffc586360687cd52 ("m68k: reorganize Kconfig options to improve mmu/non-mmu selections") accidentally dropped the DIO bus config option. Re-add it to the "Bus support" section. Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig.bus | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus index 8294f0c1785e..3adb499584fb 100644 --- a/arch/m68k/Kconfig.bus +++ b/arch/m68k/Kconfig.bus @@ -2,6 +2,15 @@ if MMU comment "Bus Support" +config DIO + bool "DIO bus support" + depends on HP300 + default y + help + Say Y here to enable support for the "DIO" expansion bus used in + HP300 machines. If you are using such a system you almost certainly + want this. + config NUBUS bool depends on MAC -- cgit From 3ec7215e5d1a714ef65069a1d0999a31e4930bb7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 May 2011 21:40:59 +0200 Subject: ide-{cd,floppy,tape}: Do not include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The top of has this comment: * Please do not include this file in generic code. There is currently * no requirement for any architecture to implement anything held * within this file. * * Thanks. --rmk Remove inclusion of , to prevent the following compile error from happening soon: | include/linux/irq.h:132: error: redefinition of ‘struct irq_data’ | include/linux/irq.h:286: error: redefinition of ‘struct irq_chip’ Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner Acked-by: Borislav Petkov Cc: linux-ide@vger.kernel.org --- drivers/ide/ide-cd.c | 1 - drivers/ide/ide-floppy.c | 1 - drivers/ide/ide-tape.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 04b09564bfa9..8126824daccb 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -43,7 +43,6 @@ /* For SCSI -> ATAPI command conversion */ #include -#include #include #include #include diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 61fdf544fbd6..3d42043fec51 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7ecb1ade8874..ce8237d36159 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include -- cgit From c288bf2533e57174b90b07860c4391bcd1ea269c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Apr 2011 22:31:28 +0200 Subject: m68k/irq: Rename irq_controller to irq_chip Make it more similar to the genirq version: - Remove lock (unused as we don't do SMP anyway), - Prepend methods with irq_, - Make irq_startup() return unsigned int. Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/amiga/amiints.c | 9 +++-- arch/m68k/amiga/cia.c | 18 +++++----- arch/m68k/apollo/dn_ints.c | 11 +++--- arch/m68k/atari/ataints.c | 15 ++++---- arch/m68k/include/asm/irq.h | 15 ++++---- arch/m68k/kernel/ints.c | 86 ++++++++++++++++++++++----------------------- arch/m68k/mac/macints.c | 9 +++-- arch/m68k/q40/q40ints.c | 17 +++++---- arch/m68k/sun3/sun3ints.c | 13 ++++--- 9 files changed, 91 insertions(+), 102 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index c5b5212cc3f9..320c5d048dc7 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -52,11 +52,10 @@ static irqreturn_t ami_int3(int irq, void *dev_id); static irqreturn_t ami_int4(int irq, void *dev_id); static irqreturn_t ami_int5(int irq, void *dev_id); -static struct irq_controller amiga_irq_controller = { +static struct irq_chip amiga_irq_chip = { .name = "amiga", - .lock = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock), - .enable = amiga_enable_irq, - .disable = amiga_disable_irq, + .irq_enable = amiga_enable_irq, + .irq_disable = amiga_disable_irq, }; /* @@ -81,7 +80,7 @@ void __init amiga_init_IRQ(void) if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) pr_err("Couldn't register int%d\n", 5); - m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS); + m68k_setup_irq_chip(&amiga_irq_chip, IRQ_USER, AMI_STD_IRQS); /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index ecd0f7ca6f0e..637ef53112b6 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -121,11 +121,10 @@ static void cia_disable_irq(unsigned int irq) cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); } -static struct irq_controller cia_irq_controller = { +static struct irq_chip cia_irq_chip = { .name = "cia", - .lock = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock), - .enable = cia_enable_irq, - .disable = cia_disable_irq, + .irq_enable = cia_enable_irq, + .irq_disable = cia_disable_irq, }; /* @@ -158,23 +157,22 @@ static void auto_disable_irq(unsigned int irq) } } -static struct irq_controller auto_irq_controller = { +static struct irq_chip auto_irq_chip = { .name = "auto", - .lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock), - .enable = auto_enable_irq, - .disable = auto_disable_irq, + .irq_enable = auto_enable_irq, + .irq_disable = auto_disable_irq, }; void __init cia_init_IRQ(struct ciabase *base) { - m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS); + m68k_setup_irq_chip(&cia_irq_chip, base->cia_irq, CIA_IRQS); /* clear any pending interrupt and turn off all interrupts */ cia_set_irq(base, CIA_ICR_ALL); cia_able_irq(base, CIA_ICR_ALL); /* override auto int and install CIA handler */ - m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); + m68k_setup_irq_chip(&auto_irq_chip, base->handler_irq, 1); m68k_irq_startup(base->handler_irq); if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base)) diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index 5d47f3aa3810..d6e8f33466be 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -12,7 +12,7 @@ void dn_process_int(unsigned int irq, struct pt_regs *fp) *(volatile unsigned char *)(picb)=0x20; } -int apollo_irq_startup(unsigned int irq) +unsigned int apollo_irq_startup(unsigned int irq) { if (irq < 8) *(volatile unsigned char *)(pica+1) &= ~(1 << irq); @@ -29,16 +29,15 @@ void apollo_irq_shutdown(unsigned int irq) *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8)); } -static struct irq_controller apollo_irq_controller = { +static struct irq_chip apollo_irq_chip = { .name = "apollo", - .lock = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock), - .startup = apollo_irq_startup, - .shutdown = apollo_irq_shutdown, + .irq_startup = apollo_irq_startup, + .irq_shutdown = apollo_irq_shutdown, }; void __init dn_init_IRQ(void) { m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int); - m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16); + m68k_setup_irq_chip(&apollo_irq_chip, IRQ_APOLLO, 16); } diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 26a804e67bce..ac0ebdf6ca72 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -320,7 +320,7 @@ extern void atari_microwire_cmd(int cmd); extern int atari_SCC_reset_done; -static int atari_startup_irq(unsigned int irq) +static unsigned int atari_startup_irq(unsigned int irq) { m68k_irq_startup(irq); atari_turnon_irq(irq); @@ -338,13 +338,12 @@ static void atari_shutdown_irq(unsigned int irq) vectors[VEC_INT4] = falcon_hblhandler; } -static struct irq_controller atari_irq_controller = { +static struct irq_chip atari_irq_chip = { .name = "atari", - .lock = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock), - .startup = atari_startup_irq, - .shutdown = atari_shutdown_irq, - .enable = atari_enable_irq, - .disable = atari_disable_irq, + .irq_startup = atari_startup_irq, + .irq_shutdown = atari_shutdown_irq, + .irq_enable = atari_enable_irq, + .irq_disable = atari_disable_irq, }; /* @@ -361,7 +360,7 @@ static struct irq_controller atari_irq_controller = { void __init atari_init_IRQ(void) { m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL); - m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1); + m68k_setup_irq_chip(&atari_irq_chip, 1, NUM_ATARI_SOURCES - 1); /* Initialize the MFP(s) */ diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 69ed0d74d532..d8c6f68b7a78 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -93,16 +93,15 @@ struct irq_handler { const char *devname; }; -struct irq_controller { +struct irq_chip { const char *name; - spinlock_t lock; - int (*startup)(unsigned int irq); - void (*shutdown)(unsigned int irq); - void (*enable)(unsigned int irq); - void (*disable)(unsigned int irq); + unsigned int (*irq_startup)(unsigned int irq); + void (*irq_shutdown)(unsigned int irq); + void (*irq_enable)(unsigned int irq); + void (*irq_disable)(unsigned int irq); }; -extern int m68k_irq_startup(unsigned int); +extern unsigned int m68k_irq_startup(unsigned int); extern void m68k_irq_shutdown(unsigned int); /* @@ -113,7 +112,7 @@ extern irq_node_t *new_irq_node(void); extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, void (*handler)(unsigned int, struct pt_regs *)); -extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int); +extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); asmlinkage void m68k_handle_int(unsigned int); asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *); diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 761ee0440c99..f43ad7b93ab6 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -52,23 +52,21 @@ extern u16 user_irqvec_fixup[]; /* table for system interrupt handlers */ static struct irq_node *irq_list[NR_IRQS]; -static struct irq_controller *irq_controller[NR_IRQS]; +static struct irq_chip *irq_chip[NR_IRQS]; static int irq_depth[NR_IRQS]; static int m68k_first_user_vec; -static struct irq_controller auto_irq_controller = { +static struct irq_chip auto_irq_chip = { .name = "auto", - .lock = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock), - .startup = m68k_irq_startup, - .shutdown = m68k_irq_shutdown, + .irq_startup = m68k_irq_startup, + .irq_shutdown = m68k_irq_shutdown, }; -static struct irq_controller user_irq_controller = { +static struct irq_chip user_irq_chip = { .name = "user", - .lock = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock), - .startup = m68k_irq_startup, - .shutdown = m68k_irq_shutdown, + .irq_startup = m68k_irq_startup, + .irq_shutdown = m68k_irq_shutdown, }; #define NUM_IRQ_NODES 100 @@ -96,7 +94,7 @@ void __init init_IRQ(void) } for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) - irq_controller[i] = &auto_irq_controller; + irq_chip[i] = &auto_irq_chip; mach_init_IRQ(); } @@ -136,7 +134,7 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, BUG_ON(IRQ_USER + cnt > NR_IRQS); m68k_first_user_vec = vec; for (i = 0; i < cnt; i++) - irq_controller[IRQ_USER + i] = &user_irq_controller; + irq_chip[IRQ_USER + i] = &user_irq_chip; *user_irqvec_fixup = vec - IRQ_USER; if (handler) *user_irqhandler_fixup = (u32)handler; @@ -144,7 +142,7 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, } /** - * m68k_setup_irq_controller + * m68k_setup_irq_chip * @contr: irq controller which controls specified irq * @irq: first irq to be managed by the controller * @@ -153,13 +151,13 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, * be changed as well, but the controller probably should use m68k_irq_startup/ * m68k_irq_shutdown. */ -void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, +void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq, unsigned int cnt) { int i; for (i = 0; i < cnt; i++) - irq_controller[irq + i] = contr; + irq_chip[irq + i] = contr; } irq_node_t *new_irq_node(void) @@ -180,23 +178,23 @@ irq_node_t *new_irq_node(void) int setup_irq(unsigned int irq, struct irq_node *node) { - struct irq_controller *contr; + struct irq_chip *contr; struct irq_node **prev; unsigned long flags; - if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { printk("%s: Incorrect IRQ %d from %s\n", __func__, irq, node->devname); return -ENXIO; } - spin_lock_irqsave(&contr->lock, flags); + local_irq_save(flags); prev = irq_list + irq; if (*prev) { /* Can't share interrupts unless both agree to */ if (!((*prev)->flags & node->flags & IRQF_SHARED)) { - spin_unlock_irqrestore(&contr->lock, flags); + local_irq_restore(flags); return -EBUSY; } while (*prev) @@ -204,15 +202,15 @@ int setup_irq(unsigned int irq, struct irq_node *node) } if (!irq_list[irq]) { - if (contr->startup) - contr->startup(irq); + if (contr->irq_startup) + contr->irq_startup(irq); else - contr->enable(irq); + contr->irq_enable(irq); } node->next = NULL; *prev = node; - spin_unlock_irqrestore(&contr->lock, flags); + local_irq_restore(flags); return 0; } @@ -244,16 +242,16 @@ EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { - struct irq_controller *contr; + struct irq_chip *contr; struct irq_node **p, *node; unsigned long flags; - if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { printk("%s: Incorrect IRQ %d\n", __func__, irq); return; } - spin_lock_irqsave(&contr->lock, flags); + local_irq_save(flags); p = irq_list + irq; while ((node = *p)) { @@ -270,58 +268,58 @@ void free_irq(unsigned int irq, void *dev_id) __func__, irq); if (!irq_list[irq]) { - if (contr->shutdown) - contr->shutdown(irq); + if (contr->irq_shutdown) + contr->irq_shutdown(irq); else - contr->disable(irq); + contr->irq_disable(irq); } - spin_unlock_irqrestore(&contr->lock, flags); + local_irq_restore(flags); } EXPORT_SYMBOL(free_irq); void enable_irq(unsigned int irq) { - struct irq_controller *contr; + struct irq_chip *contr; unsigned long flags; - if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { printk("%s: Incorrect IRQ %d\n", __func__, irq); return; } - spin_lock_irqsave(&contr->lock, flags); + local_irq_save(flags); if (irq_depth[irq]) { if (!--irq_depth[irq]) { - if (contr->enable) - contr->enable(irq); + if (contr->irq_enable) + contr->irq_enable(irq); } } else WARN_ON(1); - spin_unlock_irqrestore(&contr->lock, flags); + local_irq_restore(flags); } EXPORT_SYMBOL(enable_irq); void disable_irq(unsigned int irq) { - struct irq_controller *contr; + struct irq_chip *contr; unsigned long flags; - if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { printk("%s: Incorrect IRQ %d\n", __func__, irq); return; } - spin_lock_irqsave(&contr->lock, flags); + local_irq_save(flags); if (!irq_depth[irq]++) { - if (contr->disable) - contr->disable(irq); + if (contr->irq_disable) + contr->irq_disable(irq); } - spin_unlock_irqrestore(&contr->lock, flags); + local_irq_restore(flags); } EXPORT_SYMBOL(disable_irq); @@ -330,7 +328,7 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); EXPORT_SYMBOL(disable_irq_nosync); -int m68k_irq_startup(unsigned int irq) +unsigned int m68k_irq_startup(unsigned int irq) { if (irq <= IRQ_AUTO_7) vectors[VEC_SPUR + irq] = auto_inthandler; @@ -413,13 +411,13 @@ asmlinkage void handle_badint(struct pt_regs *regs) int show_interrupts(struct seq_file *p, void *v) { - struct irq_controller *contr; + struct irq_chip *contr; struct irq_node *node; int i = *(loff_t *) v; /* autovector interrupts */ if (irq_list[i]) { - contr = irq_controller[i]; + contr = irq_chip[i]; node = irq_list[i]; seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); while ((node = node->next)) diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index f92190c159b4..ffa1b3f7e2b7 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -193,11 +193,10 @@ irqreturn_t mac_debug_handler(int, void *); void mac_enable_irq(unsigned int irq); void mac_disable_irq(unsigned int irq); -static struct irq_controller mac_irq_controller = { +static struct irq_chip mac_irq_chip = { .name = "mac", - .lock = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock), - .enable = mac_enable_irq, - .disable = mac_disable_irq, + .irq_enable = mac_enable_irq, + .irq_disable = mac_disable_irq, }; void __init mac_init_IRQ(void) @@ -205,7 +204,7 @@ void __init mac_init_IRQ(void) #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Setting things up...\n"); #endif - m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, + m68k_setup_irq_chip(&mac_irq_chip, IRQ_USER, NUM_MAC_SOURCES - IRQ_USER); /* Make sure the SONIC interrupt is cleared or things get ugly */ #ifdef SHUTUP_SONIC diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 9f0e3d59bf92..fa05a03f8dfe 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -41,14 +41,14 @@ static void q40_disable_irq(unsigned int); unsigned short q40_ablecount[35]; unsigned short q40_state[35]; -static int q40_irq_startup(unsigned int irq) +static unsigned int q40_irq_startup(unsigned int irq) { /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: case 11: case 12: case 13: printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq); - return -ENXIO; + /* FIXME return -ENXIO; */ } return 0; } @@ -57,13 +57,12 @@ static void q40_irq_shutdown(unsigned int irq) { } -static struct irq_controller q40_irq_controller = { +static struct irq_chip q40_irq_chip = { .name = "q40", - .lock = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock), - .startup = q40_irq_startup, - .shutdown = q40_irq_shutdown, - .enable = q40_enable_irq, - .disable = q40_disable_irq, + .irq_startup = q40_irq_startup, + .irq_shutdown = q40_irq_shutdown, + .irq_enable = q40_enable_irq, + .irq_disable = q40_disable_irq, }; /* @@ -81,7 +80,7 @@ static int disabled; void __init q40_init_IRQ(void) { - m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); + m68k_setup_irq_chip(&q40_irq_chip, 1, Q40_IRQ_MAX); /* setup handler for ISA ints */ m68k_setup_auto_interrupt(q40_irq_handler); diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 6464ad3ae3e6..97fa9edc5a9d 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -86,13 +86,12 @@ static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) __m68k_handle_int(irq, fp); } -static struct irq_controller sun3_irq_controller = { +static struct irq_chip sun3_irq_chip = { .name = "sun3", - .lock = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock), - .startup = m68k_irq_startup, - .shutdown = m68k_irq_shutdown, - .enable = sun3_enable_irq, - .disable = sun3_disable_irq, + .irq_startup = m68k_irq_startup, + .irq_shutdown = m68k_irq_shutdown, + .irq_enable = sun3_enable_irq, + .irq_disable = sun3_disable_irq, }; void __init sun3_init_IRQ(void) @@ -100,7 +99,7 @@ void __init sun3_init_IRQ(void) *sun3_intreg = 1; m68k_setup_auto_interrupt(sun3_inthandle); - m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7); + m68k_setup_irq_chip(&sun3_irq_chip, IRQ_AUTO_1, 7); m68k_setup_user_interrupt(VEC_USER, 128, NULL); if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) -- cgit From 0dde595be678c06e7de27c98f45403088f1b126a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 Apr 2011 21:39:08 +0200 Subject: m68k/irq: Kill irq_node_t typedef, always use struct irq_node Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/include/asm/irq.h | 8 ++++---- arch/m68k/kernel/ints.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index d8c6f68b7a78..bfc521f35bdf 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -75,13 +75,13 @@ struct pt_regs; * This structure is used to chain together the ISRs for a particular * interrupt source (if it supports chaining). */ -typedef struct irq_node { +struct irq_node { irqreturn_t (*handler)(int, void *); void *dev_id; struct irq_node *next; unsigned long flags; const char *devname; -} irq_node_t; +}; /* * This structure has only 4 elements for speed reasons @@ -105,9 +105,9 @@ extern unsigned int m68k_irq_startup(unsigned int); extern void m68k_irq_shutdown(unsigned int); /* - * This function returns a new irq_node_t + * This function returns a new struct irq_node */ -extern irq_node_t *new_irq_node(void); +extern struct irq_node *new_irq_node(void); extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index f43ad7b93ab6..9de8eb4eaefb 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -70,7 +70,7 @@ static struct irq_chip user_irq_chip = { }; #define NUM_IRQ_NODES 100 -static irq_node_t nodes[NUM_IRQ_NODES]; +static struct irq_node nodes[NUM_IRQ_NODES]; /* * void init_IRQ(void) @@ -160,9 +160,9 @@ void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq, irq_chip[irq + i] = contr; } -irq_node_t *new_irq_node(void) +struct irq_node *new_irq_node(void) { - irq_node_t *node; + struct irq_node *node; short i; for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { -- cgit From 6549d537922da6a6893e9bc1be9c2b89db663719 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 Apr 2011 21:59:23 +0200 Subject: m68k/irq: Rename irq_node to irq_data Make it more similar to the genirq version: - Add an irq field Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/include/asm/irq.h | 9 +++++---- arch/m68k/kernel/ints.c | 21 +++++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index bfc521f35bdf..3cb037c36d10 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -75,10 +75,11 @@ struct pt_regs; * This structure is used to chain together the ISRs for a particular * interrupt source (if it supports chaining). */ -struct irq_node { +struct irq_data { + unsigned int irq; irqreturn_t (*handler)(int, void *); void *dev_id; - struct irq_node *next; + struct irq_data *next; unsigned long flags; const char *devname; }; @@ -105,9 +106,9 @@ extern unsigned int m68k_irq_startup(unsigned int); extern void m68k_irq_shutdown(unsigned int); /* - * This function returns a new struct irq_node + * This function returns a new struct irq_data */ -extern struct irq_node *new_irq_node(void); +extern struct irq_data *new_irq_node(void); extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 9de8eb4eaefb..88779320d406 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -51,7 +51,7 @@ extern u32 user_irqhandler_fixup[]; extern u16 user_irqvec_fixup[]; /* table for system interrupt handlers */ -static struct irq_node *irq_list[NR_IRQS]; +static struct irq_data *irq_list[NR_IRQS]; static struct irq_chip *irq_chip[NR_IRQS]; static int irq_depth[NR_IRQS]; @@ -70,7 +70,7 @@ static struct irq_chip user_irq_chip = { }; #define NUM_IRQ_NODES 100 -static struct irq_node nodes[NUM_IRQ_NODES]; +static struct irq_data nodes[NUM_IRQ_NODES]; /* * void init_IRQ(void) @@ -160,9 +160,9 @@ void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq, irq_chip[irq + i] = contr; } -struct irq_node *new_irq_node(void) +struct irq_data *new_irq_node(void) { - struct irq_node *node; + struct irq_data *node; short i; for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { @@ -176,10 +176,10 @@ struct irq_node *new_irq_node(void) return NULL; } -int setup_irq(unsigned int irq, struct irq_node *node) +int setup_irq(unsigned int irq, struct irq_data *node) { struct irq_chip *contr; - struct irq_node **prev; + struct irq_data **prev; unsigned long flags; if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { @@ -219,13 +219,14 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *devname, void *dev_id) { - struct irq_node *node; + struct irq_data *node; int res; node = new_irq_node(); if (!node) return -ENOMEM; + node->irq = irq; node->handler = handler; node->flags = flags; node->dev_id = dev_id; @@ -243,7 +244,7 @@ EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { struct irq_chip *contr; - struct irq_node **p, *node; + struct irq_data **p, *node; unsigned long flags; if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { @@ -386,7 +387,7 @@ EXPORT_SYMBOL(irq_canonicalize); asmlinkage void m68k_handle_int(unsigned int irq) { - struct irq_node *node; + struct irq_data *node; kstat_cpu(0).irqs[irq]++; node = irq_list[irq]; do { @@ -412,7 +413,7 @@ asmlinkage void handle_badint(struct pt_regs *regs) int show_interrupts(struct seq_file *p, void *v) { struct irq_chip *contr; - struct irq_node *node; + struct irq_data *node; int i = *(loff_t *) v; /* autovector interrupts */ -- cgit From e8abf5e73cdb6c034d35ccba1f63a4801cd3dec5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 Apr 2011 22:53:04 +0200 Subject: m68k/irq: Switch irq_chip methods to "struct irq_data *data" Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/amiga/amiints.c | 16 ++++++++-------- arch/m68k/amiga/cia.c | 25 ++++++++++++++----------- arch/m68k/apollo/dn_ints.c | 8 ++++++-- arch/m68k/atari/ataints.c | 30 ++++++++++++++++++++++-------- arch/m68k/include/asm/irq.h | 13 +++++++------ arch/m68k/kernel/ints.c | 23 +++++++++++++++-------- arch/m68k/mac/macints.c | 14 ++++++++++++-- arch/m68k/q40/q40ints.c | 28 +++++++++++++++++----------- arch/m68k/sun3/sun3ints.c | 14 ++++++++++++-- 9 files changed, 113 insertions(+), 58 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index 320c5d048dc7..09a695babfe9 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -45,8 +45,8 @@ #include #include -static void amiga_enable_irq(unsigned int irq); -static void amiga_disable_irq(unsigned int irq); +static void amiga_irq_enable(struct irq_data *data); +static void amiga_irq_disable(struct irq_data *data); static irqreturn_t ami_int1(int irq, void *dev_id); static irqreturn_t ami_int3(int irq, void *dev_id); static irqreturn_t ami_int4(int irq, void *dev_id); @@ -54,8 +54,8 @@ static irqreturn_t ami_int5(int irq, void *dev_id); static struct irq_chip amiga_irq_chip = { .name = "amiga", - .irq_enable = amiga_enable_irq, - .irq_disable = amiga_disable_irq, + .irq_enable = amiga_irq_enable, + .irq_disable = amiga_irq_disable, }; /* @@ -102,14 +102,14 @@ void __init amiga_init_IRQ(void) * internal data, that may not be changed by the interrupt at the same time. */ -static void amiga_enable_irq(unsigned int irq) +static void amiga_irq_enable(struct irq_data *data) { - amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER)); + amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER)); } -static void amiga_disable_irq(unsigned int irq) +static void amiga_irq_disable(struct irq_data *data) { - amiga_custom.intena = 1 << (irq - IRQ_USER); + amiga_custom.intena = 1 << (data->irq - IRQ_USER); } /* diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 637ef53112b6..b04b453718d9 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -98,8 +98,9 @@ static irqreturn_t cia_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void cia_enable_irq(unsigned int irq) +static void cia_irq_enable(struct irq_data *data) { + unsigned int irq = data->irq; unsigned char mask; if (irq >= IRQ_AMIGA_CIAB) { @@ -113,8 +114,10 @@ static void cia_enable_irq(unsigned int irq) } } -static void cia_disable_irq(unsigned int irq) +static void cia_irq_disable(struct irq_data *data) { + unsigned int irq = data->irq; + if (irq >= IRQ_AMIGA_CIAB) cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); else @@ -123,8 +126,8 @@ static void cia_disable_irq(unsigned int irq) static struct irq_chip cia_irq_chip = { .name = "cia", - .irq_enable = cia_enable_irq, - .irq_disable = cia_disable_irq, + .irq_enable = cia_irq_enable, + .irq_disable = cia_irq_disable, }; /* @@ -133,9 +136,9 @@ static struct irq_chip cia_irq_chip = { * into this chain. */ -static void auto_enable_irq(unsigned int irq) +static void auto_irq_enable(struct irq_data *data) { - switch (irq) { + switch (data->irq) { case IRQ_AUTO_2: amiga_custom.intena = IF_SETCLR | IF_PORTS; break; @@ -145,9 +148,9 @@ static void auto_enable_irq(unsigned int irq) } } -static void auto_disable_irq(unsigned int irq) +static void auto_irq_disable(struct irq_data *data) { - switch (irq) { + switch (data->irq) { case IRQ_AUTO_2: amiga_custom.intena = IF_PORTS; break; @@ -159,8 +162,8 @@ static void auto_disable_irq(unsigned int irq) static struct irq_chip auto_irq_chip = { .name = "auto", - .irq_enable = auto_enable_irq, - .irq_disable = auto_disable_irq, + .irq_enable = auto_irq_enable, + .irq_disable = auto_irq_disable, }; void __init cia_init_IRQ(struct ciabase *base) @@ -173,7 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base) /* override auto int and install CIA handler */ m68k_setup_irq_chip(&auto_irq_chip, base->handler_irq, 1); - m68k_irq_startup(base->handler_irq); + m68k_irq_startup_irq(base->handler_irq); if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base)) pr_err("Couldn't register %s interrupt\n", base->name); diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index d6e8f33466be..2bdab498b6c1 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -12,8 +12,10 @@ void dn_process_int(unsigned int irq, struct pt_regs *fp) *(volatile unsigned char *)(picb)=0x20; } -unsigned int apollo_irq_startup(unsigned int irq) +unsigned int apollo_irq_startup(struct irq_data *data) { + unsigned int irq = data->irq; + if (irq < 8) *(volatile unsigned char *)(pica+1) &= ~(1 << irq); else @@ -21,8 +23,10 @@ unsigned int apollo_irq_startup(unsigned int irq) return 0; } -void apollo_irq_shutdown(unsigned int irq) +void apollo_irq_shutdown(struct irq_data *data) { + unsigned int irq = data->irq; + if (irq < 8) *(volatile unsigned char *)(pica+1) |= (1 << irq); else diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index ac0ebdf6ca72..7f4e5a9b77c5 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -320,30 +320,44 @@ extern void atari_microwire_cmd(int cmd); extern int atari_SCC_reset_done; -static unsigned int atari_startup_irq(unsigned int irq) +static unsigned int atari_irq_startup(struct irq_data *data) { - m68k_irq_startup(irq); + unsigned int irq = data->irq; + + m68k_irq_startup(data); atari_turnon_irq(irq); atari_enable_irq(irq); return 0; } -static void atari_shutdown_irq(unsigned int irq) +static void atari_irq_shutdown(struct irq_data *data) { + unsigned int irq = data->irq; + atari_disable_irq(irq); atari_turnoff_irq(irq); - m68k_irq_shutdown(irq); + m68k_irq_shutdown(data); if (irq == IRQ_AUTO_4) vectors[VEC_INT4] = falcon_hblhandler; } +static void atari_irq_enable(struct irq_data *data) +{ + atari_enable_irq(data->irq); +} + +static void atari_irq_disable(struct irq_data *data) +{ + atari_disable_irq(data->irq); +} + static struct irq_chip atari_irq_chip = { .name = "atari", - .irq_startup = atari_startup_irq, - .irq_shutdown = atari_shutdown_irq, - .irq_enable = atari_enable_irq, - .irq_disable = atari_disable_irq, + .irq_startup = atari_irq_startup, + .irq_shutdown = atari_irq_shutdown, + .irq_enable = atari_irq_enable, + .irq_disable = atari_irq_disable, }; /* diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 3cb037c36d10..423f064955f2 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -96,14 +96,15 @@ struct irq_handler { struct irq_chip { const char *name; - unsigned int (*irq_startup)(unsigned int irq); - void (*irq_shutdown)(unsigned int irq); - void (*irq_enable)(unsigned int irq); - void (*irq_disable)(unsigned int irq); + unsigned int (*irq_startup)(struct irq_data *data); + void (*irq_shutdown)(struct irq_data *data); + void (*irq_enable)(struct irq_data *data); + void (*irq_disable)(struct irq_data *data); }; -extern unsigned int m68k_irq_startup(unsigned int); -extern void m68k_irq_shutdown(unsigned int); +extern unsigned int m68k_irq_startup(struct irq_data *data); +extern unsigned int m68k_irq_startup_irq(unsigned int irq); +extern void m68k_irq_shutdown(struct irq_data *data); /* * This function returns a new struct irq_data diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 88779320d406..404d832f5d35 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -203,9 +203,9 @@ int setup_irq(unsigned int irq, struct irq_data *node) if (!irq_list[irq]) { if (contr->irq_startup) - contr->irq_startup(irq); + contr->irq_startup(node); else - contr->irq_enable(irq); + contr->irq_enable(node); } node->next = NULL; *prev = node; @@ -270,9 +270,9 @@ void free_irq(unsigned int irq, void *dev_id) if (!irq_list[irq]) { if (contr->irq_shutdown) - contr->irq_shutdown(irq); + contr->irq_shutdown(node); else - contr->irq_disable(irq); + contr->irq_disable(node); } local_irq_restore(flags); @@ -295,7 +295,7 @@ void enable_irq(unsigned int irq) if (irq_depth[irq]) { if (!--irq_depth[irq]) { if (contr->irq_enable) - contr->irq_enable(irq); + contr->irq_enable(irq_list[irq]); } } else WARN_ON(1); @@ -318,7 +318,7 @@ void disable_irq(unsigned int irq) local_irq_save(flags); if (!irq_depth[irq]++) { if (contr->irq_disable) - contr->irq_disable(irq); + contr->irq_disable(irq_list[irq]); } local_irq_restore(flags); } @@ -329,7 +329,7 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); EXPORT_SYMBOL(disable_irq_nosync); -unsigned int m68k_irq_startup(unsigned int irq) +unsigned int m68k_irq_startup_irq(unsigned int irq) { if (irq <= IRQ_AUTO_7) vectors[VEC_SPUR + irq] = auto_inthandler; @@ -338,8 +338,15 @@ unsigned int m68k_irq_startup(unsigned int irq) return 0; } -void m68k_irq_shutdown(unsigned int irq) +unsigned int m68k_irq_startup(struct irq_data *data) { + return m68k_irq_startup_irq(data->irq); +} + +void m68k_irq_shutdown(struct irq_data *data) +{ + unsigned int irq = data->irq; + if (irq <= IRQ_AUTO_7) vectors[VEC_SPUR + irq] = bad_inthandler; else diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index ffa1b3f7e2b7..3cee6d29cc5d 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -193,10 +193,20 @@ irqreturn_t mac_debug_handler(int, void *); void mac_enable_irq(unsigned int irq); void mac_disable_irq(unsigned int irq); +static void mac_irq_enable(struct irq_data *data) +{ + mac_enable_irq(data->irq); +} + +static void mac_irq_disable(struct irq_data *data) +{ + mac_disable_irq(data->irq); +} + static struct irq_chip mac_irq_chip = { .name = "mac", - .irq_enable = mac_enable_irq, - .irq_disable = mac_disable_irq, + .irq_enable = mac_irq_enable, + .irq_disable = mac_irq_disable, }; void __init mac_init_IRQ(void) diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index fa05a03f8dfe..cb245f972e1a 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -35,14 +35,16 @@ */ static void q40_irq_handler(unsigned int, struct pt_regs *fp); -static void q40_enable_irq(unsigned int); -static void q40_disable_irq(unsigned int); +static void q40_irq_enable(struct irq_data *data); +static void q40_irq_disable(struct irq_data *data); unsigned short q40_ablecount[35]; unsigned short q40_state[35]; -static unsigned int q40_irq_startup(unsigned int irq) +static unsigned int q40_irq_startup(struct irq_data *data) { + unsigned int irq = data->irq; + /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: @@ -53,7 +55,7 @@ static unsigned int q40_irq_startup(unsigned int irq) return 0; } -static void q40_irq_shutdown(unsigned int irq) +static void q40_irq_shutdown(struct irq_data *data) { } @@ -61,8 +63,8 @@ static struct irq_chip q40_irq_chip = { .name = "q40", .irq_startup = q40_irq_startup, .irq_shutdown = q40_irq_shutdown, - .irq_enable = q40_enable_irq, - .irq_disable = q40_disable_irq, + .irq_enable = q40_irq_enable, + .irq_disable = q40_irq_disable, }; /* @@ -85,8 +87,8 @@ void __init q40_init_IRQ(void) /* setup handler for ISA ints */ m68k_setup_auto_interrupt(q40_irq_handler); - m68k_irq_startup(IRQ_AUTO_2); - m68k_irq_startup(IRQ_AUTO_4); + m68k_irq_startup_irq(IRQ_AUTO_2); + m68k_irq_startup_irq(IRQ_AUTO_4); /* now enable some ints.. */ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ @@ -292,20 +294,24 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) return; } -void q40_enable_irq(unsigned int irq) +void q40_irq_enable(struct irq_data *data) { + unsigned int irq = data->irq; + if (irq >= 5 && irq <= 15) { mext_disabled--; if (mext_disabled > 0) - printk("q40_enable_irq : nested disable/enable\n"); + printk("q40_irq_enable : nested disable/enable\n"); if (mext_disabled == 0) master_outb(1, EXT_ENABLE_REG); } } -void q40_disable_irq(unsigned int irq) +void q40_irq_disable(struct irq_data *data) { + unsigned int irq = data->irq; + /* disable ISA iqs : only do something if the driver has been * verified to be Q40 "compatible" - right now IDE, NE2K * Any driver should not attempt to sleep across disable_irq !! diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 97fa9edc5a9d..5d45e0065d2e 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -86,12 +86,22 @@ static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) __m68k_handle_int(irq, fp); } +static void sun3_irq_enable(struct irq_data *data) +{ + sun3_enable_irq(data->irq); +}; + +static void sun3_irq_disable(struct irq_data *data) +{ + sun3_disable_irq(data->irq); +}; + static struct irq_chip sun3_irq_chip = { .name = "sun3", .irq_startup = m68k_irq_startup, .irq_shutdown = m68k_irq_shutdown, - .irq_enable = sun3_enable_irq, - .irq_disable = sun3_disable_irq, + .irq_enable = sun3_irq_enable, + .irq_disable = sun3_irq_disable, }; void __init sun3_init_IRQ(void) -- cgit From 13d6da35813babaa1bc8c6799b2666191911100e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 19 Apr 2011 20:10:53 +0200 Subject: m68k/irq: Rename setup_irq() to m68k_setup_irq() and make it static It has nothing to do with the standard one in Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/kernel/ints.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 404d832f5d35..e68a3bd5de6e 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -176,7 +176,7 @@ struct irq_data *new_irq_node(void) return NULL; } -int setup_irq(unsigned int irq, struct irq_data *node) +static int m68k_setup_irq(unsigned int irq, struct irq_data *node) { struct irq_chip *contr; struct irq_data **prev; @@ -232,7 +232,7 @@ int request_irq(unsigned int irq, node->dev_id = dev_id; node->devname = devname; - res = setup_irq(irq, node); + res = m68k_setup_irq(irq, node); if (res) node->handler = NULL; -- cgit From 40a72c8f711bdf8ae3e4f945261ced5432dcac4d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 27 May 2011 22:33:41 +0200 Subject: m68k/irq: Extract irq_set_chip() Signed-off-by: Geert Uytterhoeven Acked-by: Thomas Gleixner --- arch/m68k/kernel/ints.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index e68a3bd5de6e..4f9868e160bd 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -55,6 +55,12 @@ static struct irq_data *irq_list[NR_IRQS]; static struct irq_chip *irq_chip[NR_IRQS]; static int irq_depth[NR_IRQS]; +static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip) +{ + irq_chip[irq] = chip; + return 0; +} + static int m68k_first_user_vec; static struct irq_chip auto_irq_chip = { @@ -94,7 +100,7 @@ void __init init_IRQ(void) } for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) - irq_chip[i] = &auto_irq_chip; + irq_set_chip(i, &auto_irq_chip); mach_init_IRQ(); } @@ -134,7 +140,7 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, BUG_ON(IRQ_USER + cnt > NR_IRQS); m68k_first_user_vec = vec; for (i = 0; i < cnt; i++) - irq_chip[IRQ_USER + i] = &user_irq_chip; + irq_set_chip(IRQ_USER + i, &user_irq_chip); *user_irqvec_fixup = vec - IRQ_USER; if (handler) *user_irqhandler_fixup = (u32)handler; @@ -157,7 +163,7 @@ void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq, int i; for (i = 0; i < cnt; i++) - irq_chip[irq + i] = contr; + irq_set_chip(irq + i, contr); } struct irq_data *new_irq_node(void) -- cgit From edb347256c44366888debb4f9e8477ac700a9026 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2011 11:15:21 +0200 Subject: m68k/irq: Add m68k_setup_irq_controller() This is a wrapper around m68k_setup_irq_chip() that discards its dummy second parameter, to ease the future transition to genirq. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/amiints.c | 3 ++- arch/m68k/amiga/cia.c | 6 ++++-- arch/m68k/apollo/dn_ints.c | 3 ++- arch/m68k/atari/ataints.c | 3 ++- arch/m68k/include/asm/irq.h | 2 ++ arch/m68k/mac/macints.c | 2 +- arch/m68k/q40/q40ints.c | 3 ++- arch/m68k/sun3/sun3ints.c | 3 ++- 8 files changed, 17 insertions(+), 8 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index 09a695babfe9..8af5ea3eea67 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -80,7 +80,8 @@ void __init amiga_init_IRQ(void) if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) pr_err("Couldn't register int%d\n", 5); - m68k_setup_irq_chip(&amiga_irq_chip, IRQ_USER, AMI_STD_IRQS); + m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, + AMI_STD_IRQS); /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index b04b453718d9..84663ae824ef 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -168,14 +168,16 @@ static struct irq_chip auto_irq_chip = { void __init cia_init_IRQ(struct ciabase *base) { - m68k_setup_irq_chip(&cia_irq_chip, base->cia_irq, CIA_IRQS); + m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq, + base->cia_irq, CIA_IRQS); /* clear any pending interrupt and turn off all interrupts */ cia_set_irq(base, CIA_ICR_ALL); cia_able_irq(base, CIA_ICR_ALL); /* override auto int and install CIA handler */ - m68k_setup_irq_chip(&auto_irq_chip, base->handler_irq, 1); + m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq, + base->handler_irq, 1); m68k_irq_startup_irq(base->handler_irq); if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base)) diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index 2bdab498b6c1..bdc44282fdba 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -43,5 +43,6 @@ static struct irq_chip apollo_irq_chip = { void __init dn_init_IRQ(void) { m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int); - m68k_setup_irq_chip(&apollo_irq_chip, IRQ_APOLLO, 16); + m68k_setup_irq_controller(&apollo_irq_chip, handle_simple_irq, + IRQ_APOLLO, 16); } diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 7f4e5a9b77c5..6149ff994641 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -374,7 +374,8 @@ static struct irq_chip atari_irq_chip = { void __init atari_init_IRQ(void) { m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL); - m68k_setup_irq_chip(&atari_irq_chip, 1, NUM_ATARI_SOURCES - 1); + m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1, + NUM_ATARI_SOURCES - 1); /* Initialize the MFP(s) */ diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 423f064955f2..d0b7efd1f1e2 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -115,6 +115,8 @@ extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, void (*handler)(unsigned int, struct pt_regs *)); extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); +#define m68k_setup_irq_controller(chip, dummy, irq, cnt) \ + m68k_setup_irq_chip((chip), (irq), (cnt)) asmlinkage void m68k_handle_int(unsigned int); asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *); diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index 3cee6d29cc5d..98497d288a9b 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -214,7 +214,7 @@ void __init mac_init_IRQ(void) #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Setting things up...\n"); #endif - m68k_setup_irq_chip(&mac_irq_chip, IRQ_USER, + m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER, NUM_MAC_SOURCES - IRQ_USER); /* Make sure the SONIC interrupt is cleared or things get ugly */ #ifdef SHUTUP_SONIC diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index cb245f972e1a..a8a5ce8b18fc 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -82,7 +82,8 @@ static int disabled; void __init q40_init_IRQ(void) { - m68k_setup_irq_chip(&q40_irq_chip, 1, Q40_IRQ_MAX); + m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1, + Q40_IRQ_MAX); /* setup handler for ISA ints */ m68k_setup_auto_interrupt(q40_irq_handler); diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 5d45e0065d2e..20461278e535 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -109,7 +109,8 @@ void __init sun3_init_IRQ(void) *sun3_intreg = 1; m68k_setup_auto_interrupt(sun3_inthandle); - m68k_setup_irq_chip(&sun3_irq_chip, IRQ_AUTO_1, 7); + m68k_setup_irq_controller(&sun3_irq_chip, handle_simple_irq, + IRQ_AUTO_1, 7); m68k_setup_user_interrupt(VEC_USER, 128, NULL); if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) -- cgit From 1425df87c25b15400c9f26d57821bcfe01286b2a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jul 2011 20:39:19 +0200 Subject: m68k/irq: Rename {,__}m68k_handle_int() - Rename m68k_handle_int() to generic_handle_irq(), and drop the unneeded asmlinkage, - Rename __m68k_handle_int() to do_IRQ(). Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/amiints.c | 24 ++++++++++++------------ arch/m68k/amiga/cia.c | 2 +- arch/m68k/apollo/dn_ints.c | 2 +- arch/m68k/include/asm/irq.h | 4 ++-- arch/m68k/kernel/entry_mm.S | 4 ++-- arch/m68k/kernel/ints.c | 10 +++++----- arch/m68k/mac/baboon.c | 2 +- arch/m68k/mac/oss.c | 4 ++-- arch/m68k/mac/psc.c | 2 +- arch/m68k/mac/via.c | 6 +++--- arch/m68k/q40/q40ints.c | 8 ++++---- arch/m68k/sun3/sun3ints.c | 2 +- 12 files changed, 35 insertions(+), 35 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index 8af5ea3eea67..0daa7fce9df1 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -124,19 +124,19 @@ static irqreturn_t ami_int1(int irq, void *dev_id) /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { amiga_custom.intreq = IF_TBE; - m68k_handle_int(IRQ_AMIGA_TBE); + generic_handle_irq(IRQ_AMIGA_TBE); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { amiga_custom.intreq = IF_DSKBLK; - m68k_handle_int(IRQ_AMIGA_DSKBLK); + generic_handle_irq(IRQ_AMIGA_DSKBLK); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { amiga_custom.intreq = IF_SOFT; - m68k_handle_int(IRQ_AMIGA_SOFT); + generic_handle_irq(IRQ_AMIGA_SOFT); } return IRQ_HANDLED; } @@ -148,19 +148,19 @@ static irqreturn_t ami_int3(int irq, void *dev_id) /* if a blitter interrupt */ if (ints & IF_BLIT) { amiga_custom.intreq = IF_BLIT; - m68k_handle_int(IRQ_AMIGA_BLIT); + generic_handle_irq(IRQ_AMIGA_BLIT); } /* if a copper interrupt */ if (ints & IF_COPER) { amiga_custom.intreq = IF_COPER; - m68k_handle_int(IRQ_AMIGA_COPPER); + generic_handle_irq(IRQ_AMIGA_COPPER); } /* if a vertical blank interrupt */ if (ints & IF_VERTB) { amiga_custom.intreq = IF_VERTB; - m68k_handle_int(IRQ_AMIGA_VERTB); + generic_handle_irq(IRQ_AMIGA_VERTB); } return IRQ_HANDLED; } @@ -172,25 +172,25 @@ static irqreturn_t ami_int4(int irq, void *dev_id) /* if audio 0 interrupt */ if (ints & IF_AUD0) { amiga_custom.intreq = IF_AUD0; - m68k_handle_int(IRQ_AMIGA_AUD0); + generic_handle_irq(IRQ_AMIGA_AUD0); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { amiga_custom.intreq = IF_AUD1; - m68k_handle_int(IRQ_AMIGA_AUD1); + generic_handle_irq(IRQ_AMIGA_AUD1); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { amiga_custom.intreq = IF_AUD2; - m68k_handle_int(IRQ_AMIGA_AUD2); + generic_handle_irq(IRQ_AMIGA_AUD2); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { amiga_custom.intreq = IF_AUD3; - m68k_handle_int(IRQ_AMIGA_AUD3); + generic_handle_irq(IRQ_AMIGA_AUD3); } return IRQ_HANDLED; } @@ -202,13 +202,13 @@ static irqreturn_t ami_int5(int irq, void *dev_id) /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { /* acknowledge of IF_RBF must be done by the serial interrupt */ - m68k_handle_int(IRQ_AMIGA_RBF); + generic_handle_irq(IRQ_AMIGA_RBF); } /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { amiga_custom.intreq = IF_DSKSYN; - m68k_handle_int(IRQ_AMIGA_DSKSYN); + generic_handle_irq(IRQ_AMIGA_DSKSYN); } return IRQ_HANDLED; } diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 84663ae824ef..18c0e29976e3 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -93,7 +93,7 @@ static irqreturn_t cia_handler(int irq, void *dev_id) amiga_custom.intreq = base->int_mask; for (; ints; mach_irq++, ints >>= 1) { if (ints & 1) - m68k_handle_int(mach_irq); + generic_handle_irq(mach_irq); } return IRQ_HANDLED; } diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index bdc44282fdba..4b764312aed0 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -6,7 +6,7 @@ void dn_process_int(unsigned int irq, struct pt_regs *fp) { - __m68k_handle_int(irq, fp); + do_IRQ(irq, fp); *(volatile unsigned char *)(pica)=0x20; *(volatile unsigned char *)(picb)=0x20; diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index d0b7efd1f1e2..9a2bae8ef5b7 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -118,8 +118,8 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); #define m68k_setup_irq_controller(chip, dummy, irq, cnt) \ m68k_setup_irq_chip((chip), (irq), (cnt)) -asmlinkage void m68k_handle_int(unsigned int); -asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *); +extern void generic_handle_irq(unsigned int); +asmlinkage void do_IRQ(int irq, struct pt_regs *regs); #else #define irq_canonicalize(irq) (irq) diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S index bd0ec05263b2..f5927d0927b4 100644 --- a/arch/m68k/kernel/entry_mm.S +++ b/arch/m68k/kernel/entry_mm.S @@ -207,7 +207,7 @@ ENTRY(auto_inthandler) movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack auto_irqhandler_fixup = . + 2 - jsr __m68k_handle_int | process the IRQ + jsr do_IRQ | process the IRQ addql #8,%sp | pop parameters off stack ret_from_interrupt: @@ -241,7 +241,7 @@ user_irqvec_fixup = . + 2 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack user_irqhandler_fixup = . + 2 - jsr __m68k_handle_int | process the IRQ + jsr do_IRQ | process the IRQ addql #8,%sp | pop parameters off stack subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 4f9868e160bd..15dbbe297334 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -110,7 +110,7 @@ void __init init_IRQ(void) * @handler: called from auto vector interrupts * * setup the handler to be called from auto vector interrupts instead of the - * standard __m68k_handle_int(), it will be called with irq numbers in the range + * standard do_IRQ(), it will be called with irq numbers in the range * from IRQ_AUTO_1 - IRQ_AUTO_7. */ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) @@ -129,7 +129,7 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re * setup user vector interrupts, this includes activating the specified range * of interrupts, only then these interrupts can be requested (note: this is * different from auto vector interrupts). An optional handler can be installed - * to be called instead of the default __m68k_handle_int(), it will be called + * to be called instead of the default do_IRQ(), it will be called * with irq numbers starting from IRQ_USER. */ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, @@ -398,7 +398,7 @@ unsigned int irq_canonicalize(unsigned int irq) EXPORT_SYMBOL(irq_canonicalize); -asmlinkage void m68k_handle_int(unsigned int irq) +void generic_handle_irq(unsigned int irq) { struct irq_data *node; kstat_cpu(0).irqs[irq]++; @@ -409,11 +409,11 @@ asmlinkage void m68k_handle_int(unsigned int irq) } while (node); } -asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) { struct pt_regs *old_regs; old_regs = set_irq_regs(regs); - m68k_handle_int(irq); + generic_handle_irq(irq); set_irq_regs(old_regs); } diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index 2a96bebd8969..f264791b8694 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -72,7 +72,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) do { if (events & irq_bit) { baboon->mb_ifr &= ~irq_bit; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } irq_bit <<= 1; irq_num++; diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index a9c0f5ab4cc0..ad512419affc 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -113,7 +113,7 @@ static irqreturn_t oss_irq(int irq, void *dev_id) /* FIXME: call sound handler */ } else if (events & OSS_IP_SCSI) { oss->irq_pending &= ~OSS_IP_SCSI; - m68k_handle_int(IRQ_MAC_SCSI); + generic_handle_irq(IRQ_MAC_SCSI); } else { /* FIXME: error check here? */ } @@ -148,7 +148,7 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id) irq_bit >>= 1; if (events & irq_bit) { oss->irq_pending &= ~irq_bit; - m68k_handle_int(NUBUS_SOURCE_BASE + i); + generic_handle_irq(NUBUS_SOURCE_BASE + i); } } while(events & (irq_bit - 1)); return IRQ_HANDLED; diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index a4c3eb60706e..26c2b6595808 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -152,7 +152,7 @@ irqreturn_t psc_irq(int irq, void *dev_id) do { if (events & irq_bit) { psc_write_byte(pIFR, irq_bit); - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } irq_num++; irq_bit <<= 1; diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index e71166daec6a..067857046137 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -460,7 +460,7 @@ irqreturn_t via1_irq(int irq, void *dev_id) do { if (events & irq_bit) { via1[vIFR] = irq_bit; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } ++irq_num; irq_bit <<= 1; @@ -482,7 +482,7 @@ irqreturn_t via2_irq(int irq, void *dev_id) do { if (events & irq_bit) { via2[gIFR] = irq_bit | rbv_clear; - m68k_handle_int(irq_num); + generic_handle_irq(irq_num); } ++irq_num; irq_bit <<= 1; @@ -514,7 +514,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) do { if (events & slot_bit) { events &= ~slot_bit; - m68k_handle_int(slot_irq); + generic_handle_irq(slot_irq); } --slot_irq; slot_bit >>= 1; diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index a8a5ce8b18fc..afe600c03659 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -220,11 +220,11 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) switch (irq) { case 4: case 6: - __m68k_handle_int(Q40_IRQ_SAMPLE, fp); + do_IRQ(Q40_IRQ_SAMPLE, fp); return; } if (mir & Q40_IRQ_FRAME_MASK) { - __m68k_handle_int(Q40_IRQ_FRAME, fp); + do_IRQ(Q40_IRQ_FRAME, fp); master_outb(-1, FRAME_CLEAR_REG); } if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { @@ -259,7 +259,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) goto iirq; } q40_state[irq] |= IRQ_INPROGRESS; - __m68k_handle_int(irq, fp); + do_IRQ(irq, fp); q40_state[irq] &= ~IRQ_INPROGRESS; /* naively enable everything, if that fails than */ @@ -290,7 +290,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) mir = master_inb(IIRQ_REG); /* should test whether keyboard irq is really enabled, doing it in defhand */ if (mir & Q40_IRQ_KEYB_MASK) - __m68k_handle_int(Q40_IRQ_KEYBOARD, fp); + do_IRQ(Q40_IRQ_KEYBOARD, fp); return; } diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 20461278e535..20ffee7dc319 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -83,7 +83,7 @@ static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) { *sun3_intreg &= ~(1 << irq); - __m68k_handle_int(irq, fp); + do_IRQ(irq, fp); } static void sun3_irq_enable(struct irq_data *data) -- cgit From 5a2394534b160ce18f9a705cf9de40e77648f8a2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Jul 2011 22:33:13 +0200 Subject: m68k/irq: Remove obsolete IRQ_FLG_* users The m68k core irq code stopped honoring these flags during the irq restructuring in 2006. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/amiints.c | 29 ----------------------------- arch/m68k/hp300/time.c | 2 +- arch/m68k/kernel/ints.c | 19 ------------------- arch/m68k/mac/iop.c | 10 ++++------ arch/m68k/mac/oss.c | 13 +++++-------- arch/m68k/mac/via.c | 22 ++++++++-------------- arch/m68k/mvme147/config.c | 3 +-- drivers/macintosh/via-macii.c | 2 +- drivers/macintosh/via-maciisi.c | 4 ++-- 9 files changed, 22 insertions(+), 82 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index 0daa7fce9df1..e5f3033499e7 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -4,35 +4,6 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. - * - * 11/07/96: rewritten interrupt handling, irq lists are exists now only for - * this sources where it makes sense (VERTB/PORTS/EXTER) and you must - * be careful that dev_id for this sources is unique since this the - * only possibility to distinguish between different handlers for - * free_irq. irq lists also have different irq flags: - * - IRQ_FLG_FAST: handler is inserted at top of list (after other - * fast handlers) - * - IRQ_FLG_SLOW: handler is inserted at bottom of list and before - * they're executed irq level is set to the previous - * one, but handlers don't need to be reentrant, if - * reentrance occurred, slow handlers will be just - * called again. - * The whole interrupt handling for CIAs is moved to cia.c - * /Roman Zippel - * - * 07/08/99: rewamp of the interrupt handling - we now have two types of - * interrupts, normal and fast handlers, fast handlers being - * marked with IRQF_DISABLED and runs with all other interrupts - * disabled. Normal interrupts disable their own source but - * run with all other interrupt sources enabled. - * PORTS and EXTER interrupts are always shared even if the - * drivers do not explicitly mark this when calling - * request_irq which they really should do. - * This is similar to the way interrupts are handled on all - * other architectures and makes a ton of sense besides - * having the advantage of making it easier to share - * drivers. - * /Jes */ #include diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index f6312c7d8727..c87fe69b0728 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector) asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); - if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector)) + if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector)) pr_err("Couldn't register timer interrupt\n"); out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 15dbbe297334..f6a469865125 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -4,25 +4,6 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. - * - * 07/03/96: Timer initialization, and thus mach_sched_init(), - * removed from request_irq() and moved to init_time(). - * We should therefore consider renaming our add_isr() and - * remove_isr() to request_irq() and free_irq() - * respectively, so they are compliant with the other - * architectures. /Jes - * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. - * Removed irq list support, if any machine needs an irq server - * it must implement this itself (as it's already done), instead - * only default handler are used with mach_default_handler. - * request_irq got some flags different from other architectures: - * - IRQ_FLG_REPLACE : Replace an existing handler (the default one - * can be replaced without this flag) - * - IRQ_FLG_LOCK : handler can't be replaced - * There are other machine depending flags, see there - * If you want to replace a default handler you should know what - * you're doing, since it might handle different other irq sources - * which must be served /Roman Zippel */ #include diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 1ad4e9d80eba..a5462cc0bfd6 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -305,15 +305,13 @@ void __init iop_register_interrupts(void) { if (iop_ism_present) { if (oss_present) { - if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, - IRQ_FLG_LOCK, "ISM IOP", - (void *) IOP_NUM_ISM)) + if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0, + "ISM IOP", (void *)IOP_NUM_ISM)) pr_err("Couldn't register ISM IOP interrupt\n"); oss_irq_enable(IRQ_MAC_ADB); } else { - if (request_irq(IRQ_VIA2_0, iop_ism_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP", - (void *) IOP_NUM_ISM)) + if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP", + (void *)IOP_NUM_ISM)) pr_err("Couldn't register ISM IOP interrupt\n"); } if (!iop_alive(iop_base[IOP_NUM_ISM])) { diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index ad512419affc..1eb60f071007 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -65,17 +65,14 @@ void __init oss_init(void) void __init oss_register_interrupts(void) { - if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, - "scsi", (void *) oss)) + if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss)) pr_err("Couldn't register %s interrupt\n", "scsi"); - if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, - "nubus", (void *) oss)) + if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus", + (void *)oss)) pr_err("Couldn't register %s interrupt\n", "nubus"); - if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, - "sound", (void *) oss)) + if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss)) pr_err("Couldn't register %s interrupt\n", "sound"); - if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, - "via1", (void *) via1)) + if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1)) pr_err("Couldn't register %s interrupt\n", "via1"); } diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 067857046137..af9ed33bec14 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -281,7 +281,7 @@ void __init via_init_clock(irq_handler_t func) via1[vT1CL] = MAC_CLOCK_LOW; via1[vT1CH] = MAC_CLOCK_HIGH; - if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func)) + if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func)) pr_err("Couldn't register %s interrupt\n", "timer"); } @@ -292,25 +292,19 @@ void __init via_init_clock(irq_handler_t func) void __init via_register_interrupts(void) { if (via_alt_mapping) { - if (request_irq(IRQ_AUTO_1, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", - (void *) via1)) + if (request_irq(IRQ_AUTO_1, via1_irq, 0, "software", + (void *)via1)) pr_err("Couldn't register %s interrupt\n", "software"); - if (request_irq(IRQ_AUTO_6, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", - (void *) via1)) + if (request_irq(IRQ_AUTO_6, via1_irq, 0, "via1", (void *)via1)) pr_err("Couldn't register %s interrupt\n", "via1"); } else { - if (request_irq(IRQ_AUTO_1, via1_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", - (void *) via1)) + if (request_irq(IRQ_AUTO_1, via1_irq, 0, "via1", (void *)via1)) pr_err("Couldn't register %s interrupt\n", "via1"); } - if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, - "via2", (void *) via2)) + if (request_irq(IRQ_AUTO_2, via2_irq, 0, "via2", (void *)via2)) pr_err("Couldn't register %s interrupt\n", "via2"); - if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, - IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2)) + if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 0, "nubus", + (void *)via2)) pr_err("Couldn't register %s interrupt\n", "nubus"); } diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 6cb9c3a9b6c9..01f2adf3f19f 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id) void mvme147_sched_init (irq_handler_t timer_routine) { tick_handler = timer_routine; - if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE, - "timer 1", NULL)) + if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL)) pr_err("Couldn't register timer interrupt\n"); /* Init the clock with a value */ diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 817f37a875c9..c9570fcf1cce 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -159,7 +159,7 @@ int macii_init(void) err = macii_init_via(); if (err) goto out; - err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB", + err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB", macii_interrupt); if (err) goto out; diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c index 9ab5b0c34f0d..34d02a91b29f 100644 --- a/drivers/macintosh/via-maciisi.c +++ b/drivers/macintosh/via-maciisi.c @@ -122,8 +122,8 @@ maciisi_init(void) return err; } - if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, - "ADB", maciisi_interrupt)) { + if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB", + maciisi_interrupt)) { printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB); return -EAGAIN; } -- cgit From 4936f63cb790e265eb30a1e1630bb90bd6af0e7a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 21 Apr 2011 22:50:52 +0200 Subject: m68k/irq: Add genirq support Disabled on all platforms for now Signed-off-by: Geert Uytterhoeven [v1] Acked-by: Thomas Gleixner --- arch/m68k/Kconfig | 17 ++++++++++++++ arch/m68k/include/asm/hardirq.h | 5 ++++ arch/m68k/include/asm/irq.h | 41 +++++++++++++++++++++++++------- arch/m68k/kernel/Makefile | 9 +++++-- arch/m68k/kernel/ints.c | 52 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 112 insertions(+), 12 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6c28582fb98f..a7597e119ab0 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -84,6 +84,23 @@ config MMU_SUN3 bool depends on MMU && !MMU_MOTOROLA +config USE_GENERIC_HARDIRQS + bool "Use genirq" + depends on MMU + depends on !AMIGA + depends on !ATARI + depends on !MAC + depends on !APOLLO + depends on !MVME147 + depends on !MVME16x + depends on !BVME6000 + depends on !HP300 + depends on !SUN3X + depends on !Q40 + depends on !SUN3 + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW + menu "Platform setup" source arch/m68k/Kconfig.cpu diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h index 870e5347155b..db30ed276878 100644 --- a/arch/m68k/include/asm/hardirq.h +++ b/arch/m68k/include/asm/hardirq.h @@ -18,6 +18,11 @@ #ifdef CONFIG_MMU +static inline void ack_bad_irq(unsigned int irq) +{ + pr_crit("unexpected IRQ trap at vector %02x\n", irq); +} + /* entry.S is sensitive to the offsets of these fields */ typedef struct { unsigned int __softirq_pending; diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 9a2bae8ef5b7..518e61f2fccb 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -27,11 +27,6 @@ #ifdef CONFIG_MMU -#include -#include -#include -#include - /* * Interrupt source definitions * General interrupt sources are the level 1-7. @@ -54,10 +49,6 @@ #define IRQ_USER 8 -extern unsigned int irq_canonicalize(unsigned int irq); - -struct pt_regs; - /* * various flags for request_irq() - the Amiga now uses the standard * mechanism like all other architectures - IRQF_DISABLED and @@ -71,6 +62,15 @@ struct pt_regs; #define IRQ_FLG_STD (0x8000) /* internally used */ #endif +#ifndef CONFIG_GENERIC_HARDIRQS + +#include +#include +#include +#include + +struct pt_regs; + /* * This structure is used to chain together the ISRs for a particular * interrupt source (if it supports chaining). @@ -121,10 +121,33 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); extern void generic_handle_irq(unsigned int); asmlinkage void do_IRQ(int irq, struct pt_regs *regs); +#else /* CONFIG_GENERIC_HARDIRQS */ + +struct irq_data; +struct irq_chip; +struct irq_desc; +extern unsigned int m68k_irq_startup(struct irq_data *data); +extern unsigned int m68k_irq_startup_irq(unsigned int irq); +extern void m68k_irq_shutdown(struct irq_data *data); +extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, + struct pt_regs *)); +extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, + void (*handler)(unsigned int, + struct pt_regs *)); +extern void m68k_setup_irq_controller(struct irq_chip *, + void (*handle)(unsigned int irq, + struct irq_desc *desc), + unsigned int irq, unsigned int cnt); + +#endif /* CONFIG_GENERIC_HARDIRQS */ + +extern unsigned int irq_canonicalize(unsigned int irq); + #else #define irq_canonicalize(irq) (irq) #endif /* CONFIG_MMU */ asmlinkage void do_IRQ(int irq, struct pt_regs *regs); +extern atomic_t irq_err_count; #endif /* _M68K_IRQ_H_ */ diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index e7f0f2e5ad44..141425785c4e 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -9,13 +9,18 @@ extra-y += vmlinux.lds obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ sys_m68k.o syscalltable.o time.o traps.o -obj-$(CONFIG_MMU) += ints.o devres.o vectors.o +obj-$(CONFIG_MMU) += ints.o vectors.o devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o ifndef CONFIG_MMU_SUN3 obj-y += dma.o endif ifndef CONFIG_MMU -obj-y += init_task.o irq.o +obj-y += init_task.o +endif +ifdef CONFIG_GENERIC_HARDIRQS +obj-y += irq.o +else +obj-y += devres.o endif diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index f6a469865125..cea439f9819b 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -31,6 +31,7 @@ extern u32 auto_irqhandler_fixup[]; extern u32 user_irqhandler_fixup[]; extern u16 user_irqvec_fixup[]; +#ifndef CONFIG_GENERIC_HARDIRQS /* table for system interrupt handlers */ static struct irq_data *irq_list[NR_IRQS]; static struct irq_chip *irq_chip[NR_IRQS]; @@ -41,6 +42,8 @@ static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip) irq_chip[irq] = chip; return 0; } +#define irq_set_chip_and_handler(irq, chip, dummy) irq_set_chip(irq, chip) +#endif /* !CONFIG_GENERIC_HARDIRQS */ static int m68k_first_user_vec; @@ -56,8 +59,10 @@ static struct irq_chip user_irq_chip = { .irq_shutdown = m68k_irq_shutdown, }; +#ifndef CONFIG_GENERIC_HARDIRQS #define NUM_IRQ_NODES 100 static struct irq_data nodes[NUM_IRQ_NODES]; +#endif /* !CONFIG_GENERIC_HARDIRQS */ /* * void init_IRQ(void) @@ -81,7 +86,7 @@ void __init init_IRQ(void) } for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) - irq_set_chip(i, &auto_irq_chip); + irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq); mach_init_IRQ(); } @@ -128,6 +133,35 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, flush_icache(); } +#ifdef CONFIG_GENERIC_HARDIRQS + +/** + * m68k_setup_irq_controller + * @chip: irq chip which controls specified irq + * @handle: flow handler which handles specified irq + * @irq: first irq to be managed by the controller + * @cnt: number of irqs to be managed by the controller + * + * Change the controller for the specified range of irq, which will be used to + * manage these irq. auto/user irq already have a default controller, which can + * be changed as well, but the controller probably should use m68k_irq_startup/ + * m68k_irq_shutdown. + */ +void m68k_setup_irq_controller(struct irq_chip *chip, + irq_flow_handler_t handle, unsigned int irq, + unsigned int cnt) +{ + int i; + + for (i = 0; i < cnt; i++) { + irq_set_chip(irq + i, chip); + if (handle) + irq_set_handler(irq + i, handle); + } +} + +#else /* !CONFIG_GENERIC_HARDIRQS */ + /** * m68k_setup_irq_chip * @contr: irq controller which controls specified irq @@ -316,6 +350,8 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); EXPORT_SYMBOL(disable_irq_nosync); +#endif /* !CONFIG_GENERIC_HARDIRQS */ + unsigned int m68k_irq_startup_irq(unsigned int irq) { if (irq <= IRQ_AUTO_7) @@ -341,6 +377,8 @@ void m68k_irq_shutdown(struct irq_data *data) } +#ifndef CONFIG_GENERIC_HARDIRQS + /* * Do we need these probe functions on the m68k? * @@ -367,6 +405,7 @@ int probe_irq_off (unsigned long irqs) } EXPORT_SYMBOL(probe_irq_off); +#endif /* CONFIG_GENERIC_HARDIRQS */ unsigned int irq_canonicalize(unsigned int irq) { @@ -379,6 +418,7 @@ unsigned int irq_canonicalize(unsigned int irq) EXPORT_SYMBOL(irq_canonicalize); +#ifndef CONFIG_GENERIC_HARDIRQS void generic_handle_irq(unsigned int irq) { struct irq_data *node; @@ -428,3 +468,13 @@ void init_irq_proc(void) /* Insert /proc/irq driver here */ } #endif + +#else /* CONFIG_GENERIC_HARDIRQS */ + +asmlinkage void handle_badint(struct pt_regs *regs) +{ + atomic_inc(&irq_err_count); + pr_warn("unexpected interrupt from %u\n", regs->vector); +} + +#endif /* CONFIG_GENERIC_HARDIRQS */ -- cgit From e59629ddc6eddbd00e81b4afb814583cfcc4706d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 29 Apr 2011 23:35:21 +0200 Subject: m68k/atari: Convert Atari to genirq Signed-off-by: Geert Uytterhoeven [v1] Acked-by: Thomas Gleixner --- arch/m68k/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index a7597e119ab0..9d60f4004076 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -88,7 +88,6 @@ config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU depends on !AMIGA - depends on !ATARI depends on !MAC depends on !APOLLO depends on !MVME147 -- cgit From 34971bad3a1511db7b76eeb2337819967a135075 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 18 Aug 2011 19:36:30 +0200 Subject: m68k/atari: Remove code and comments about different irq types This code was obsoleted during the irq restructuring in 2006. Signed-off-by: Geert Uytterhoeven --- arch/m68k/atari/ataints.c | 236 ---------------------------------------------- 1 file changed, 236 deletions(-) diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 6149ff994641..af544557dd1d 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -60,244 +60,8 @@ * ): Autovector interrupts are 1..7, then follow ST-MFP, * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can * be allocated by atari_register_vme_int(). - * - * Each interrupt can be of three types: - * - * - SLOW: The handler runs with all interrupts enabled, except the one it - * was called by (to avoid reentering). This should be the usual method. - * But it is currently possible only for MFP ints, since only the MFP - * offers an easy way to mask interrupts. - * - * - FAST: The handler runs with all interrupts disabled. This should be used - * only for really fast handlers, that just do actions immediately - * necessary, and let the rest do a bottom half or task queue. - * - * - PRIORITIZED: The handler can be interrupted by higher-level ints - * (greater IPL, no MFP priorities!). This is the method of choice for ints - * which should be slow, but are not from a MFP. - * - * The feature of more than one handler for one int source is still there, but - * only applicable if all handers are of the same type. To not slow down - * processing of ints with only one handler by the chaining feature, the list - * calling function atari_call_irq_list() is only plugged in at the time the - * second handler is registered. - * - * Implementation notes: For fast-as-possible int handling, there are separate - * entry points for each type (slow/fast/prio). The assembler handler calls - * the irq directly in the usual case, no C wrapper is involved. In case of - * multiple handlers, atari_call_irq_list() is registered as handler and calls - * in turn the real irq's. To ease access from assembler level to the irq - * function pointer and accompanying data, these two are stored in a separate - * array, irq_handler[]. The rest of data (type, name) are put into a second - * array, irq_param, that is accessed from C only. For each slow interrupt (32 - * in all) there are separate handler functions, which makes it possible to - * hard-code the MFP register address and value, are necessary to mask the - * int. If there'd be only one generic function, lots of calculations would be - * needed to determine MFP register and int mask from the vector number :-( - * - * Furthermore, slow ints may not lower the IPL below its previous value - * (before the int happened). This is needed so that an int of class PRIO, on - * that this int may be stacked, cannot be reentered. This feature is - * implemented as follows: If the stack frame format is 1 (throwaway), the int - * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level - * 2, which still blocks the HSYNC, but no interrupts of interest. If the - * frame format is 0, the int is nested, and the old IPL value can be found in - * the sr copy in the frame. */ -#if 0 - -#define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) - -typedef void (*asm_irq_handler)(void); - -struct irqhandler { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - void *dev_id; -}; - -struct irqparam { - unsigned long flags; - const char *devname; -}; - -/* - * Array with irq's and their parameter data. This array is accessed from low - * level assembler code, so an element size of 8 allows usage of index scaling - * addressing mode. - */ -static struct irqhandler irq_handler[NUM_INT_SOURCES]; - -/* - * This array hold the rest of parameters of int handlers: type - * (slow,fast,prio) and the name of the handler. These values are only - * accessed from C - */ -static struct irqparam irq_param[NUM_INT_SOURCES]; - -/* check for valid int number (complex, sigh...) */ -#define IS_VALID_INTNO(n) \ - ((n) > 0 && \ - /* autovec and ST-MFP ok anyway */ \ - (((n) < TTMFP_SOURCE_BASE) || \ - /* TT-MFP ok if present */ \ - ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \ - ATARIHW_PRESENT(TT_MFP)) || \ - /* SCC ok if present and number even */ \ - ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \ - !((n) & 1) && ATARIHW_PRESENT(SCC)) || \ - /* greater numbers ok if they are registered VME vectors */ \ - ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \ - free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE))))) - - -/* - * Here start the assembler entry points for interrupts - */ - -#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void) - -#define BUILD_SLOW_IRQ(n) \ -asmlinkage void IRQ_NAME(n); \ -/* Dummy function to allow asm with operands. */ \ -void atari_slow_irq_##n##_dummy (void) { \ -__asm__ (__ALIGN_STR "\n" \ -"atari_slow_irq_" #n "_handler:\t" \ -" addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \ - SAVE_ALL_INT "\n" \ - GET_CURRENT(%%d0) "\n" \ -" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ - /* get old IPL from stack frame */ \ -" bfextu %%sp@(%c2){#5,#3},%%d0\n" \ -" movew %%sr,%%d1\n" \ -" bfins %%d0,%%d1{#21,#3}\n" \ -" movew %%d1,%%sr\n" /* set IPL = previous value */ \ -" addql #1,%a0\n" \ -" lea %a1,%%a0\n" \ -" pea %%sp@\n" /* push addr of frame */ \ -" movel %%a0@(4),%%sp@-\n" /* push handler data */ \ -" pea (%c3+8)\n" /* push int number */ \ -" movel %%a0@,%%a0\n" \ -" jbsr %%a0@\n" /* call the handler */ \ -" addql #8,%%sp\n" \ -" addql #4,%%sp\n" \ -" orw #0x0600,%%sr\n" \ -" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \ -" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \ -" jbra ret_from_interrupt\n" \ - : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \ - "n" (PT_OFF_SR), "n" (n), \ - "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a) \ - : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \ - "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \ -); \ - for (;;); /* fake noreturn */ \ -} - -BUILD_SLOW_IRQ(0); -BUILD_SLOW_IRQ(1); -BUILD_SLOW_IRQ(2); -BUILD_SLOW_IRQ(3); -BUILD_SLOW_IRQ(4); -BUILD_SLOW_IRQ(5); -BUILD_SLOW_IRQ(6); -BUILD_SLOW_IRQ(7); -BUILD_SLOW_IRQ(8); -BUILD_SLOW_IRQ(9); -BUILD_SLOW_IRQ(10); -BUILD_SLOW_IRQ(11); -BUILD_SLOW_IRQ(12); -BUILD_SLOW_IRQ(13); -BUILD_SLOW_IRQ(14); -BUILD_SLOW_IRQ(15); -BUILD_SLOW_IRQ(16); -BUILD_SLOW_IRQ(17); -BUILD_SLOW_IRQ(18); -BUILD_SLOW_IRQ(19); -BUILD_SLOW_IRQ(20); -BUILD_SLOW_IRQ(21); -BUILD_SLOW_IRQ(22); -BUILD_SLOW_IRQ(23); -BUILD_SLOW_IRQ(24); -BUILD_SLOW_IRQ(25); -BUILD_SLOW_IRQ(26); -BUILD_SLOW_IRQ(27); -BUILD_SLOW_IRQ(28); -BUILD_SLOW_IRQ(29); -BUILD_SLOW_IRQ(30); -BUILD_SLOW_IRQ(31); - -asm_irq_handler slow_handlers[32] = { - [0] = atari_slow_irq_0_handler, - [1] = atari_slow_irq_1_handler, - [2] = atari_slow_irq_2_handler, - [3] = atari_slow_irq_3_handler, - [4] = atari_slow_irq_4_handler, - [5] = atari_slow_irq_5_handler, - [6] = atari_slow_irq_6_handler, - [7] = atari_slow_irq_7_handler, - [8] = atari_slow_irq_8_handler, - [9] = atari_slow_irq_9_handler, - [10] = atari_slow_irq_10_handler, - [11] = atari_slow_irq_11_handler, - [12] = atari_slow_irq_12_handler, - [13] = atari_slow_irq_13_handler, - [14] = atari_slow_irq_14_handler, - [15] = atari_slow_irq_15_handler, - [16] = atari_slow_irq_16_handler, - [17] = atari_slow_irq_17_handler, - [18] = atari_slow_irq_18_handler, - [19] = atari_slow_irq_19_handler, - [20] = atari_slow_irq_20_handler, - [21] = atari_slow_irq_21_handler, - [22] = atari_slow_irq_22_handler, - [23] = atari_slow_irq_23_handler, - [24] = atari_slow_irq_24_handler, - [25] = atari_slow_irq_25_handler, - [26] = atari_slow_irq_26_handler, - [27] = atari_slow_irq_27_handler, - [28] = atari_slow_irq_28_handler, - [29] = atari_slow_irq_29_handler, - [30] = atari_slow_irq_30_handler, - [31] = atari_slow_irq_31_handler -}; - -asmlinkage void atari_fast_irq_handler( void ); -asmlinkage void atari_prio_irq_handler( void ); - -/* Dummy function to allow asm with operands. */ -void atari_fast_prio_irq_dummy (void) { -__asm__ (__ALIGN_STR "\n" -"atari_fast_irq_handler:\n\t" - "orw #0x700,%%sr\n" /* disable all interrupts */ -"atari_prio_irq_handler:\n\t" - "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */ - SAVE_ALL_INT "\n\t" - GET_CURRENT(%%d0) "\n\t" - /* get vector number from stack frame and convert to source */ - "bfextu %%sp@(%c1){#4,#10},%%d0\n\t" - "subw #(0x40-8),%%d0\n\t" - "jpl 1f\n\t" - "addw #(0x40-8-0x18),%%d0\n" - "1:\tlea %a0,%%a0\n\t" - "addql #1,%%a0@(%%d0:l:4)\n\t" - "lea irq_handler,%%a0\n\t" - "lea %%a0@(%%d0:l:8),%%a0\n\t" - "pea %%sp@\n\t" /* push frame address */ - "movel %%a0@(4),%%sp@-\n\t" /* push handler data */ - "movel %%d0,%%sp@-\n\t" /* push int number */ - "movel %%a0@,%%a0\n\t" - "jsr %%a0@\n\t" /* and call the handler */ - "addql #8,%%sp\n\t" - "addql #4,%%sp\n\t" - "jbra ret_from_interrupt" - : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC), - "m" (preempt_count()), "di" (HARDIRQ_OFFSET) -); - for (;;); -} -#endif - /* * Bitmap for free interrupt vector numbers * (new vectors starting from 0x70 can be allocated by -- cgit From 92b1bd5f1aa88ce4760c02814bfcbb58ad521984 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 31 May 2011 11:11:01 +0200 Subject: m68k/amiga: Refactor amiints.c - Remove filename in comments, - Reorder functions so we no longer need forward declarations. Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/amiints.c | 98 +++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index e5f3033499e7..c8f9eac121a1 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -1,5 +1,5 @@ /* - * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code + * Amiga Linux interrupt handling code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive @@ -16,56 +16,6 @@ #include #include -static void amiga_irq_enable(struct irq_data *data); -static void amiga_irq_disable(struct irq_data *data); -static irqreturn_t ami_int1(int irq, void *dev_id); -static irqreturn_t ami_int3(int irq, void *dev_id); -static irqreturn_t ami_int4(int irq, void *dev_id); -static irqreturn_t ami_int5(int irq, void *dev_id); - -static struct irq_chip amiga_irq_chip = { - .name = "amiga", - .irq_enable = amiga_irq_enable, - .irq_disable = amiga_irq_disable, -}; - -/* - * void amiga_init_IRQ(void) - * - * Parameters: None - * - * Returns: Nothing - * - * This function should be called during kernel startup to initialize - * the amiga IRQ handling routines. - */ - -void __init amiga_init_IRQ(void) -{ - if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL)) - pr_err("Couldn't register int%d\n", 1); - if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL)) - pr_err("Couldn't register int%d\n", 3); - if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL)) - pr_err("Couldn't register int%d\n", 4); - if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) - pr_err("Couldn't register int%d\n", 5); - - m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, - AMI_STD_IRQS); - - /* turn off PCMCIA interrupts */ - if (AMIGAHW_PRESENT(PCMCIA)) - gayle.inten = GAYLE_IRQ_IDE; - - /* turn off all interrupts and enable the master interrupt bit */ - amiga_custom.intena = 0x7fff; - amiga_custom.intreq = 0x7fff; - amiga_custom.intena = IF_SETCLR | IF_INTEN; - - cia_init_IRQ(&ciaa_base); - cia_init_IRQ(&ciab_base); -} /* * Enable/disable a particular machine specific interrupt source. @@ -84,6 +34,13 @@ static void amiga_irq_disable(struct irq_data *data) amiga_custom.intena = 1 << (data->irq - IRQ_USER); } +static struct irq_chip amiga_irq_chip = { + .name = "amiga", + .irq_enable = amiga_irq_enable, + .irq_disable = amiga_irq_disable, +}; + + /* * The builtin Amiga hardware interrupt handlers. */ @@ -183,3 +140,42 @@ static irqreturn_t ami_int5(int irq, void *dev_id) } return IRQ_HANDLED; } + + +/* + * void amiga_init_IRQ(void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function should be called during kernel startup to initialize + * the amiga IRQ handling routines. + */ + +void __init amiga_init_IRQ(void) +{ + if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL)) + pr_err("Couldn't register int%d\n", 1); + if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL)) + pr_err("Couldn't register int%d\n", 3); + if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL)) + pr_err("Couldn't register int%d\n", 4); + if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) + pr_err("Couldn't register int%d\n", 5); + + m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, + AMI_STD_IRQS); + + /* turn off PCMCIA interrupts */ + if (AMIGAHW_PRESENT(PCMCIA)) + gayle.inten = GAYLE_IRQ_IDE; + + /* turn off all interrupts and enable the master interrupt bit */ + amiga_custom.intena = 0x7fff; + amiga_custom.intreq = 0x7fff; + amiga_custom.intena = IF_SETCLR | IF_INTEN; + + cia_init_IRQ(&ciaa_base); + cia_init_IRQ(&ciab_base); +} -- cgit From 978ef7e6d0e02083e4a62ab4411922bdeffa36a4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 31 May 2011 22:08:28 +0200 Subject: m68k/amiga: Convert Amiga to genirq Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 1 - arch/m68k/amiga/amiints.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 9d60f4004076..9000921385aa 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -87,7 +87,6 @@ config MMU_SUN3 config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU - depends on !AMIGA depends on !MAC depends on !APOLLO depends on !MVME147 diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index c8f9eac121a1..c3da5342f495 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -9,6 +9,9 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#endif #include #include -- cgit From fb1b646aa3bcae2f8211136a6b40228c7c9d236c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 1 Jun 2011 11:49:18 +0200 Subject: m68k/amiga: Optimize interrupts using chain handlers Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/amiints.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index c3da5342f495..a8da47126584 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -48,6 +48,99 @@ static struct irq_chip amiga_irq_chip = { * The builtin Amiga hardware interrupt handlers. */ +#ifdef CONFIG_GENERIC_HARDIRQS +static void ami_int1(unsigned int irq, struct irq_desc *desc) +{ + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; + + /* if serial transmit buffer empty, interrupt */ + if (ints & IF_TBE) { + amiga_custom.intreq = IF_TBE; + generic_handle_irq(IRQ_AMIGA_TBE); + } + + /* if floppy disk transfer complete, interrupt */ + if (ints & IF_DSKBLK) { + amiga_custom.intreq = IF_DSKBLK; + generic_handle_irq(IRQ_AMIGA_DSKBLK); + } + + /* if software interrupt set, interrupt */ + if (ints & IF_SOFT) { + amiga_custom.intreq = IF_SOFT; + generic_handle_irq(IRQ_AMIGA_SOFT); + } +} + +static void ami_int3(unsigned int irq, struct irq_desc *desc) +{ + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; + + /* if a blitter interrupt */ + if (ints & IF_BLIT) { + amiga_custom.intreq = IF_BLIT; + generic_handle_irq(IRQ_AMIGA_BLIT); + } + + /* if a copper interrupt */ + if (ints & IF_COPER) { + amiga_custom.intreq = IF_COPER; + generic_handle_irq(IRQ_AMIGA_COPPER); + } + + /* if a vertical blank interrupt */ + if (ints & IF_VERTB) { + amiga_custom.intreq = IF_VERTB; + generic_handle_irq(IRQ_AMIGA_VERTB); + } +} + +static void ami_int4(unsigned int irq, struct irq_desc *desc) +{ + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; + + /* if audio 0 interrupt */ + if (ints & IF_AUD0) { + amiga_custom.intreq = IF_AUD0; + generic_handle_irq(IRQ_AMIGA_AUD0); + } + + /* if audio 1 interrupt */ + if (ints & IF_AUD1) { + amiga_custom.intreq = IF_AUD1; + generic_handle_irq(IRQ_AMIGA_AUD1); + } + + /* if audio 2 interrupt */ + if (ints & IF_AUD2) { + amiga_custom.intreq = IF_AUD2; + generic_handle_irq(IRQ_AMIGA_AUD2); + } + + /* if audio 3 interrupt */ + if (ints & IF_AUD3) { + amiga_custom.intreq = IF_AUD3; + generic_handle_irq(IRQ_AMIGA_AUD3); + } +} + +static void ami_int5(unsigned int irq, struct irq_desc *desc) +{ + unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; + + /* if serial receive buffer full interrupt */ + if (ints & IF_RBF) { + /* acknowledge of IF_RBF must be done by the serial interrupt */ + generic_handle_irq(IRQ_AMIGA_RBF); + } + + /* if a disk sync interrupt */ + if (ints & IF_DSKSYN) { + amiga_custom.intreq = IF_DSKSYN; + generic_handle_irq(IRQ_AMIGA_DSKSYN); + } +} +#else /* !CONFIG_GENERIC_HARDIRQS */ static irqreturn_t ami_int1(int irq, void *dev_id) { unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; @@ -143,6 +236,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id) } return IRQ_HANDLED; } +#endif /* !CONFIG_GENERIC_HARDIRQS */ /* @@ -158,6 +252,15 @@ static irqreturn_t ami_int5(int irq, void *dev_id) void __init amiga_init_IRQ(void) { +#ifdef CONFIG_GENERIC_HARDIRQS + m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, + AMI_STD_IRQS); + + irq_set_chained_handler(IRQ_AUTO_1, ami_int1); + irq_set_chained_handler(IRQ_AUTO_3, ami_int3); + irq_set_chained_handler(IRQ_AUTO_4, ami_int4); + irq_set_chained_handler(IRQ_AUTO_5, ami_int5); +#else /* !CONFIG_GENERIC_HARDIRQS */ if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL)) pr_err("Couldn't register int%d\n", 1); if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL)) @@ -169,6 +272,7 @@ void __init amiga_init_IRQ(void) m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, AMI_STD_IRQS); +#endif /* !CONFIG_GENERIC_HARDIRQS */ /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) -- cgit From ddc7fd25d09678f8252c0321ef4b66e8451abe7d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Jul 2011 21:48:30 +0200 Subject: m68k/mac: Convert Mac to genirq Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 1 - arch/m68k/mac/baboon.c | 3 +++ arch/m68k/mac/oss.c | 3 +++ arch/m68k/mac/psc.c | 3 +++ arch/m68k/mac/via.c | 3 +++ 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 9000921385aa..9ba1a89e0032 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -87,7 +87,6 @@ config MMU_SUN3 config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU - depends on !MAC depends on !APOLLO depends on !MVME147 depends on !MVME16x diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index f264791b8694..ff11746b0621 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -11,6 +11,9 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#endif #include #include diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 1eb60f071007..ed952704e6ee 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#endif #include #include diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index 26c2b6595808..0a34b7afc376 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -18,6 +18,9 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#endif #include #include diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index af9ed33bec14..bde156caa46d 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -28,6 +28,9 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#endif #include #include -- cgit From 9145db564eae98134de8eb8d64b47d7177eccfdd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 10 Aug 2011 12:48:29 +0200 Subject: m68k/mac: Optimize interrupts using chain handlers Signed-off-by: Geert Uytterhoeven --- arch/m68k/mac/baboon.c | 38 +++++++++++++ arch/m68k/mac/oss.c | 106 +++++++++++++++++++++++++++++------- arch/m68k/mac/psc.c | 74 +++++++++++++++++++------ arch/m68k/mac/via.c | 143 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 298 insertions(+), 63 deletions(-) diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index ff11746b0621..425144cbfa7d 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -56,6 +56,39 @@ void __init baboon_init(void) * Baboon interrupt handler. This works a lot like a VIA. */ +#ifdef CONFIG_GENERIC_HARDIRQS +static void baboon_irq(unsigned int irq, struct irq_desc *desc) +{ + int irq_bit, irq_num; + unsigned char events; + +#ifdef DEBUG_IRQS + printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n", + (uint) baboon->mb_control, (uint) baboon->mb_ifr, + (uint) baboon->mb_status); +#endif + + events = baboon->mb_ifr & 0x07; + if (!events) + return; + + irq_num = IRQ_BABOON_0; + irq_bit = 1; + do { + if (events & irq_bit) { + baboon->mb_ifr &= ~irq_bit; + generic_handle_irq(irq_num); + } + irq_bit <<= 1; + irq_num++; + } while(events >= irq_bit); +#if 0 + if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL); + /* for now we need to smash all interrupts */ + baboon->mb_ifr &= ~events; +#endif +} +#else static irqreturn_t baboon_irq(int irq, void *dev_id) { int irq_bit, irq_num; @@ -87,6 +120,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) #endif return IRQ_HANDLED; } +#endif /* * Register the Baboon interrupt dispatcher on nubus slot $C. @@ -95,8 +129,12 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) void __init baboon_register_interrupts(void) { baboon_disabled = 0; +#ifdef CONFIG_GENERIC_HARDIRQS + irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); +#else if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon)) pr_err("Couldn't register baboon interrupt\n"); +#endif } /* diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index ed952704e6ee..cc784c2ff6e8 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -32,10 +32,11 @@ int oss_present; volatile struct mac_oss *oss; -static irqreturn_t oss_irq(int, void *); -static irqreturn_t oss_nubus_irq(int, void *); - +#ifdef CONFIG_GENERIC_HARDIRQS +extern void via1_irq(unsigned int irq, struct irq_desc *desc); +#else extern irqreturn_t via1_irq(int, void *); +#endif /* * Initialize the OSS @@ -62,23 +63,6 @@ void __init oss_init(void) oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1; } -/* - * Register the OSS and NuBus interrupt dispatchers. - */ - -void __init oss_register_interrupts(void) -{ - if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "scsi"); - if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus", - (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "nubus"); - if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "sound"); - if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); -} - /* * Initialize OSS for Nubus access */ @@ -92,6 +76,34 @@ void __init oss_nubus_init(void) * and SCSI; everything else is routed to its own autovector IRQ. */ +#ifdef CONFIG_GENERIC_HARDIRQS +static void oss_irq(unsigned int irq, struct irq_desc *desc) +{ + int events; + + events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); + if (!events) + return; + +#ifdef DEBUG_IRQS + if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { + printk("oss_irq: irq %u events = 0x%04X\n", irq, + (int) oss->irq_pending); + } +#endif + /* FIXME: how do you clear a pending IRQ? */ + + if (events & OSS_IP_SOUND) { + oss->irq_pending &= ~OSS_IP_SOUND; + /* FIXME: call sound handler */ + } else if (events & OSS_IP_SCSI) { + oss->irq_pending &= ~OSS_IP_SCSI; + generic_handle_irq(IRQ_MAC_SCSI); + } else { + /* FIXME: error check here? */ + } +} +#else static irqreturn_t oss_irq(int irq, void *dev_id) { int events; @@ -119,6 +131,7 @@ static irqreturn_t oss_irq(int irq, void *dev_id) } return IRQ_HANDLED; } +#endif /* * Nubus IRQ handler, OSS style @@ -126,6 +139,34 @@ static irqreturn_t oss_irq(int irq, void *dev_id) * Unlike the VIA/RBV this is on its own autovector interrupt level. */ +#ifdef CONFIG_GENERIC_HARDIRQS +static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc) +{ + int events, irq_bit, i; + + events = oss->irq_pending & OSS_IP_NUBUS; + if (!events) + return; + +#ifdef DEBUG_NUBUS_INT + if (console_loglevel > 7) { + printk("oss_nubus_irq: events = 0x%04X\n", events); + } +#endif + /* There are only six slots on the OSS, not seven */ + + i = 6; + irq_bit = 0x40; + do { + --i; + irq_bit >>= 1; + if (events & irq_bit) { + oss->irq_pending &= ~irq_bit; + generic_handle_irq(NUBUS_SOURCE_BASE + i); + } + } while(events & (irq_bit - 1)); +} +#else static irqreturn_t oss_nubus_irq(int irq, void *dev_id) { int events, irq_bit, i; @@ -153,6 +194,31 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id) } while(events & (irq_bit - 1)); return IRQ_HANDLED; } +#endif + +/* + * Register the OSS and NuBus interrupt dispatchers. + */ + +void __init oss_register_interrupts(void) +{ +#ifdef CONFIG_GENERIC_HARDIRQS + irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); + irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); +#else /* !CONFIG_GENERIC_HARDIRQS */ + if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss)) + pr_err("Couldn't register %s interrupt\n", "scsi"); + if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus", + (void *)oss)) + pr_err("Couldn't register %s interrupt\n", "nubus"); + if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss)) + pr_err("Couldn't register %s interrupt\n", "sound"); + if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1)) + pr_err("Couldn't register %s interrupt\n", "via1"); +#endif /* !CONFIG_GENERIC_HARDIRQS */ +} /* * Enable an OSS interrupt diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index 0a34b7afc376..52840b8c03b8 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -33,8 +33,6 @@ int psc_present; volatile __u8 *psc; -irqreturn_t psc_irq(int, void *); - /* * Debugging dump, used in various places to see what's going on. */ @@ -115,26 +113,40 @@ void __init psc_init(void) } /* - * Register the PSC interrupt dispatchers for autovector interrupts 3-6. + * PSC interrupt handler. It's a lot like the VIA interrupt handler. */ -void __init psc_register_interrupts(void) +#ifdef CONFIG_GENERIC_HARDIRQS +static void psc_irq(unsigned int irq, struct irq_desc *desc) { - if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) - pr_err("Couldn't register psc%d interrupt\n", 3); - if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) - pr_err("Couldn't register psc%d interrupt\n", 4); - if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) - pr_err("Couldn't register psc%d interrupt\n", 5); - if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) - pr_err("Couldn't register psc%d interrupt\n", 6); -} + unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc); + int pIFR = pIFRbase + offset; + int pIER = pIERbase + offset; + int irq_num; + unsigned char irq_bit, events; -/* - * PSC interrupt handler. It's a lot like the VIA interrupt handler. - */ +#ifdef DEBUG_IRQS + printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n", + irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); +#endif -irqreturn_t psc_irq(int irq, void *dev_id) + events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; + if (!events) + return; + + irq_num = irq << 3; + irq_bit = 1; + do { + if (events & irq_bit) { + psc_write_byte(pIFR, irq_bit); + generic_handle_irq(irq_num); + } + irq_num++; + irq_bit <<= 1; + } while (events >= irq_bit); +} +#else +static irqreturn_t psc_irq(int irq, void *dev_id) { int pIFR = pIFRbase + ((int) dev_id); int pIER = pIERbase + ((int) dev_id); @@ -162,6 +174,34 @@ irqreturn_t psc_irq(int irq, void *dev_id) } while (events >= irq_bit); return IRQ_HANDLED; } +#endif + +/* + * Register the PSC interrupt dispatchers for autovector interrupts 3-6. + */ + +void __init psc_register_interrupts(void) +{ +#ifdef CONFIG_GENERIC_HARDIRQS + irq_set_chained_handler(IRQ_AUTO_3, psc_irq); + irq_set_handler_data(IRQ_AUTO_3, (void *)0x30); + irq_set_chained_handler(IRQ_AUTO_4, psc_irq); + irq_set_handler_data(IRQ_AUTO_4, (void *)0x40); + irq_set_chained_handler(IRQ_AUTO_5, psc_irq); + irq_set_handler_data(IRQ_AUTO_5, (void *)0x50); + irq_set_chained_handler(IRQ_AUTO_6, psc_irq); + irq_set_handler_data(IRQ_AUTO_6, (void *)0x60); +#else /* !CONFIG_GENERIC_HARDIRQS */ + if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) + pr_err("Couldn't register psc%d interrupt\n", 3); + if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) + pr_err("Couldn't register psc%d interrupt\n", 4); + if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) + pr_err("Couldn't register psc%d interrupt\n", 5); + if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) + pr_err("Couldn't register psc%d interrupt\n", 6); +#endif /* !CONFIG_GENERIC_HARDIRQS */ +} void psc_irq_enable(int irq) { int irq_src = IRQ_SRC(irq); diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index bde156caa46d..b8156ac496a0 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -80,9 +80,6 @@ static int gIER,gIFR,gBufA,gBufB; static u8 nubus_disabled; void via_debug_dump(void); -irqreturn_t via1_irq(int, void *); -irqreturn_t via2_irq(int, void *); -irqreturn_t via_nubus_irq(int, void *); void via_irq_enable(int irq); void via_irq_disable(int irq); void via_irq_clear(int irq); @@ -288,29 +285,6 @@ void __init via_init_clock(irq_handler_t func) pr_err("Couldn't register %s interrupt\n", "timer"); } -/* - * Register the interrupt dispatchers for VIA or RBV machines only. - */ - -void __init via_register_interrupts(void) -{ - if (via_alt_mapping) { - if (request_irq(IRQ_AUTO_1, via1_irq, 0, "software", - (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "software"); - if (request_irq(IRQ_AUTO_6, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); - } else { - if (request_irq(IRQ_AUTO_1, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); - } - if (request_irq(IRQ_AUTO_2, via2_irq, 0, "via2", (void *)via2)) - pr_err("Couldn't register %s interrupt\n", "via2"); - if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 0, "nubus", - (void *)via2)) - pr_err("Couldn't register %s interrupt\n", "nubus"); -} - /* * Debugging dump, used in various places to see what's going on. */ @@ -443,6 +417,49 @@ void __init via_nubus_init(void) * via6522.c :-), disable/pending masks added. */ +#ifdef CONFIG_GENERIC_HARDIRQS +void via1_irq(unsigned int irq, struct irq_desc *desc) +{ + int irq_num; + unsigned char irq_bit, events; + + events = via1[vIFR] & via1[vIER] & 0x7F; + if (!events) + return; + + irq_num = VIA1_SOURCE_BASE; + irq_bit = 1; + do { + if (events & irq_bit) { + via1[vIFR] = irq_bit; + generic_handle_irq(irq_num); + } + ++irq_num; + irq_bit <<= 1; + } while (events >= irq_bit); +} + +static void via2_irq(unsigned int irq, struct irq_desc *desc) +{ + int irq_num; + unsigned char irq_bit, events; + + events = via2[gIFR] & via2[gIER] & 0x7F; + if (!events) + return; + + irq_num = VIA2_SOURCE_BASE; + irq_bit = 1; + do { + if (events & irq_bit) { + via2[gIFR] = irq_bit | rbv_clear; + generic_handle_irq(irq_num); + } + ++irq_num; + irq_bit <<= 1; + } while (events >= irq_bit); +} +#else irqreturn_t via1_irq(int irq, void *dev_id) { int irq_num; @@ -486,12 +503,49 @@ irqreturn_t via2_irq(int irq, void *dev_id) } while (events >= irq_bit); return IRQ_HANDLED; } +#endif /* * Dispatch Nubus interrupts. We are called as a secondary dispatch by the * VIA2 dispatcher as a fast interrupt handler. */ +#ifdef CONFIG_GENERIC_HARDIRQS +void via_nubus_irq(unsigned int irq, struct irq_desc *desc) +{ + int slot_irq; + unsigned char slot_bit, events; + + events = ~via2[gBufA] & 0x7F; + if (rbv_present) + events &= via2[rSIER]; + else + events &= ~via2[vDirA]; + if (!events) + return; + + do { + slot_irq = IRQ_NUBUS_F; + slot_bit = 0x40; + do { + if (events & slot_bit) { + events &= ~slot_bit; + generic_handle_irq(slot_irq); + } + --slot_irq; + slot_bit >>= 1; + } while (events); + + /* clear the CA1 interrupt and make certain there's no more. */ + via2[gIFR] = 0x02 | rbv_clear; + events = ~via2[gBufA] & 0x7F; + if (rbv_present) + events &= via2[rSIER]; + else + events &= ~via2[vDirA]; + } while (events); +} +#else irqreturn_t via_nubus_irq(int irq, void *dev_id) { int slot_irq; @@ -527,6 +581,43 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) } while (events); return IRQ_HANDLED; } +#endif + +/* + * Register the interrupt dispatchers for VIA or RBV machines only. + */ + +void __init via_register_interrupts(void) +{ +#ifdef CONFIG_GENERIC_HARDIRQS + if (via_alt_mapping) { + /* software interrupt */ + irq_set_chained_handler(IRQ_AUTO_1, via1_irq); + /* via1 interrupt */ + irq_set_chained_handler(IRQ_AUTO_6, via1_irq); + } else { + irq_set_chained_handler(IRQ_AUTO_1, via1_irq); + } + irq_set_chained_handler(IRQ_AUTO_2, via2_irq); + irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq); +#else + if (via_alt_mapping) { + if (request_irq(IRQ_AUTO_1, via1_irq, 0, "software", + (void *)via1)) + pr_err("Couldn't register %s interrupt\n", "software"); + if (request_irq(IRQ_AUTO_6, via1_irq, 0, "via1", (void *)via1)) + pr_err("Couldn't register %s interrupt\n", "via1"); + } else { + if (request_irq(IRQ_AUTO_1, via1_irq, 0, "via1", (void *)via1)) + pr_err("Couldn't register %s interrupt\n", "via1"); + } + if (request_irq(IRQ_AUTO_2, via2_irq, 0, "via2", (void *)via2)) + pr_err("Couldn't register %s interrupt\n", "via2"); + if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 0, "nubus", + (void *)via2)) + pr_err("Couldn't register %s interrupt\n", "nubus"); +#endif +} void via_irq_enable(int irq) { int irq_src = IRQ_SRC(irq); -- cgit From efaf6d28fc768bfa373f7377c4b0484cbdf9f67e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 13 Aug 2011 21:02:22 +0200 Subject: m68k/hp300: Convert HP9000/300 and HP9000/400 to genirq Signed-off-by: Geert Uytterhoeven Cc: Philip Blundell --- arch/m68k/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 9ba1a89e0032..e4bd0c974643 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -91,7 +91,6 @@ config USE_GENERIC_HARDIRQS depends on !MVME147 depends on !MVME16x depends on !BVME6000 - depends on !HP300 depends on !SUN3X depends on !Q40 depends on !SUN3 -- cgit From 6c490c4da4642ec9e7569c8b50a98a22c71ad184 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 13 Aug 2011 21:11:00 +0200 Subject: m68k/vme: Convert VME to genirq Signed-off-by: Geert Uytterhoeven Cc: Richard Hirst --- arch/m68k/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index e4bd0c974643..8ae37a8fba40 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -88,9 +88,6 @@ config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU depends on !APOLLO - depends on !MVME147 - depends on !MVME16x - depends on !BVME6000 depends on !SUN3X depends on !Q40 depends on !SUN3 -- cgit From bc7485acd09405d9544783d773ee040af4a5c861 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 18 Aug 2011 14:45:57 +0200 Subject: m68k/apollo: Convert Apollo to genirq Replace the custom user vector interrupt handler that calls do_IRQ() and does an EOI by handle_fasteoi_irq(). Signed-off-by: Geert Uytterhoeven Cc: Peter De Schrijver --- arch/m68k/Kconfig | 1 - arch/m68k/apollo/dn_ints.c | 25 +++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 8ae37a8fba40..f2dc708d3da9 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -87,7 +87,6 @@ config MMU_SUN3 config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU - depends on !APOLLO depends on !SUN3X depends on !Q40 depends on !SUN3 diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index 4b764312aed0..fc190b34b621 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -1,9 +1,14 @@ #include - +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#else #include +#endif + #include #include +#ifndef CONFIG_GENERIC_HARDIRQS void dn_process_int(unsigned int irq, struct pt_regs *fp) { do_IRQ(irq, fp); @@ -11,6 +16,7 @@ void dn_process_int(unsigned int irq, struct pt_regs *fp) *(volatile unsigned char *)(pica)=0x20; *(volatile unsigned char *)(picb)=0x20; } +#endif unsigned int apollo_irq_startup(struct irq_data *data) { @@ -33,16 +39,31 @@ void apollo_irq_shutdown(struct irq_data *data) *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8)); } +#ifdef CONFIG_GENERIC_HARDIRQS +void apollo_irq_eoi(struct irq_data *data) +{ + *(volatile unsigned char *)(pica) = 0x20; + *(volatile unsigned char *)(picb) = 0x20; +} +#endif + static struct irq_chip apollo_irq_chip = { .name = "apollo", .irq_startup = apollo_irq_startup, .irq_shutdown = apollo_irq_shutdown, +#ifdef CONFIG_GENERIC_HARDIRQS + .irq_eoi = apollo_irq_eoi, +#endif }; void __init dn_init_IRQ(void) { +#ifdef CONFIG_GENERIC_HARDIRQS + m68k_setup_user_interrupt(VEC_USER + 96, 16, NULL); +#else m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int); - m68k_setup_irq_controller(&apollo_irq_chip, handle_simple_irq, +#endif + m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq, IRQ_APOLLO, 16); } -- cgit From 4045513286462a3c12140fac0559f09bcb5e7f10 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 18 Aug 2011 22:46:01 +0200 Subject: m68k/sun3: Use the kstat_irqs_cpu() wrapper Signed-off-by: Geert Uytterhoeven Acked-by: Sam Creasey --- arch/m68k/sun3/sun3ints.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 20ffee7dc319..1273eb879a15 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -51,14 +51,19 @@ void sun3_disable_irq(unsigned int irq) static irqreturn_t sun3_int7(int irq, void *dev_id) { + unsigned int cnt; + *sun3_intreg |= (1 << irq); - if (!(kstat_cpu(0).irqs[irq] % 2000)) - sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]); + cnt = kstat_irqs_cpu(irq, 0); + if (!(cnt % 2000)) + sun3_leds(led_pattern[cnt % 16000 / 2000]); return IRQ_HANDLED; } static irqreturn_t sun3_int5(int irq, void *dev_id) { + unsigned int cnt; + #ifdef CONFIG_SUN3 intersil_clear(); #endif @@ -68,8 +73,9 @@ static irqreturn_t sun3_int5(int irq, void *dev_id) #endif xtime_update(1); update_process_times(user_mode(get_irq_regs())); - if (!(kstat_cpu(0).irqs[irq] % 20)) - sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]); + cnt = kstat_irqs_cpu(irq, 0); + if (!(cnt % 20)) + sun3_leds(led_pattern[cnt % 160 / 20]); return IRQ_HANDLED; } -- cgit From dda7535912255015ecf7264c1d6691a09f8ba487 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 18 Aug 2011 14:46:46 +0200 Subject: m68k/sun3: Convert Sun3/3x to genirq Replace the custom irq handler that masks the irq and calls do_IRQ(), and the unmasking in the individual handlers, by handle_level_irq(). Signed-off-by: Geert Uytterhoeven Cc: Sam Creasey --- arch/m68k/Kconfig | 2 -- arch/m68k/sun3/sun3ints.c | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index f2dc708d3da9..290f9c838b35 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -87,9 +87,7 @@ config MMU_SUN3 config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU - depends on !SUN3X depends on !Q40 - depends on !SUN3 select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 1273eb879a15..626b601931e9 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -53,7 +53,9 @@ static irqreturn_t sun3_int7(int irq, void *dev_id) { unsigned int cnt; +#ifndef CONFIG_GENERIC_HARDIRQS *sun3_intreg |= (1 << irq); +#endif cnt = kstat_irqs_cpu(irq, 0); if (!(cnt % 2000)) sun3_leds(led_pattern[cnt % 16000 / 2000]); @@ -67,7 +69,9 @@ static irqreturn_t sun3_int5(int irq, void *dev_id) #ifdef CONFIG_SUN3 intersil_clear(); #endif +#ifndef CONFIG_GENERIC_HARDIRQS *sun3_intreg |= (1 << irq); +#endif #ifdef CONFIG_SUN3 intersil_clear(); #endif @@ -85,12 +89,14 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id) return IRQ_HANDLED; } +#ifndef CONFIG_GENERIC_HARDIRQS static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) { *sun3_intreg &= ~(1 << irq); do_IRQ(irq, fp); } +#endif static void sun3_irq_enable(struct irq_data *data) { @@ -108,15 +114,21 @@ static struct irq_chip sun3_irq_chip = { .irq_shutdown = m68k_irq_shutdown, .irq_enable = sun3_irq_enable, .irq_disable = sun3_irq_disable, +#ifdef CONFIG_GENERIC_HARDIRQS + .irq_mask = sun3_irq_disable, + .irq_unmask = sun3_irq_enable, +#endif }; void __init sun3_init_IRQ(void) { *sun3_intreg = 1; +#ifndef CONFIG_GENERIC_HARDIRQS m68k_setup_auto_interrupt(sun3_inthandle); - m68k_setup_irq_controller(&sun3_irq_chip, handle_simple_irq, - IRQ_AUTO_1, 7); +#endif + m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1, + 7); m68k_setup_user_interrupt(VEC_USER, 128, NULL); if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) -- cgit From a03010ed9b399fdbc28ac8836e0a6d4b15403f9f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 18 Aug 2011 14:47:16 +0200 Subject: m68k/q40: Convert Q40/Q60 to genirq q40_irq_handler() must be kept to translate ISA IRQs to the range 1-15. q40_probe_irq_o{ff,n}() become unused. Signed-off-by: Geert Uytterhoeven Cc: Richard Zidlicky --- arch/m68k/Kconfig | 1 - arch/m68k/include/asm/q40ints.h | 2 ++ arch/m68k/q40/q40ints.c | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 290f9c838b35..06198ced2245 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -87,7 +87,6 @@ config MMU_SUN3 config USE_GENERIC_HARDIRQS bool "Use genirq" depends on MMU - depends on !Q40 select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW diff --git a/arch/m68k/include/asm/q40ints.h b/arch/m68k/include/asm/q40ints.h index 3d970afb708f..01cdbb4da465 100644 --- a/arch/m68k/include/asm/q40ints.h +++ b/arch/m68k/include/asm/q40ints.h @@ -25,5 +25,7 @@ #define Q40_IRQ14_MASK (1<<6) #define Q40_IRQ15_MASK (1<<7) +#ifndef CONFIG_GENERIC_HARDIRQS extern unsigned long q40_probe_irq_on (void); extern int q40_probe_irq_off (unsigned long irqs); +#endif diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index afe600c03659..f1e5288f043f 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -15,10 +15,14 @@ #include #include #include +#ifdef CONFIG_GENERIC_HARDIRQS +#include +#else +#include +#endif #include #include -#include #include #include @@ -326,6 +330,7 @@ void q40_irq_disable(struct irq_data *data) } } +#ifndef CONFIG_GENERIC_HARDIRQS unsigned long q40_probe_irq_on(void) { printk("irq probing not working - reconfigure the driver to avoid this\n"); @@ -335,3 +340,4 @@ int q40_probe_irq_off(unsigned long irqs) { return -1; } +#endif -- cgit From d890d73995257b4e10cdd7d55bad80e34a71ba22 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 11 Sep 2011 11:28:04 +0200 Subject: m68k/irq: Remove obsolete m68k irq framework Signed-off-by: Geert Uytterhoeven --- arch/m68k/Kconfig | 10 +- arch/m68k/amiga/amiints.c | 114 --------------- arch/m68k/apollo/dn_ints.c | 22 --- arch/m68k/include/asm/irq.h | 63 --------- arch/m68k/include/asm/q40ints.h | 5 - arch/m68k/kernel/Makefile | 10 +- arch/m68k/kernel/ints.c | 297 ---------------------------------------- arch/m68k/mac/baboon.c | 41 ------ arch/m68k/mac/oss.c | 78 ----------- arch/m68k/mac/psc.c | 44 ------ arch/m68k/mac/via.c | 104 -------------- arch/m68k/q40/q40ints.c | 16 --- arch/m68k/sun3/sun3ints.c | 20 --- 13 files changed, 4 insertions(+), 820 deletions(-) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 06198ced2245..361d54019bb0 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -4,8 +4,8 @@ config M68K select HAVE_IDE select HAVE_AOUT if MMU select GENERIC_ATOMIC64 if MMU - select HAVE_GENERIC_HARDIRQS if !MMU - select GENERIC_IRQ_SHOW if !MMU + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS config RWSEM_GENERIC_SPINLOCK @@ -84,12 +84,6 @@ config MMU_SUN3 bool depends on MMU && !MMU_MOTOROLA -config USE_GENERIC_HARDIRQS - bool "Use genirq" - depends on MMU - select HAVE_GENERIC_HARDIRQS - select GENERIC_IRQ_SHOW - menu "Platform setup" source arch/m68k/Kconfig.cpu diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index a8da47126584..47b5f90002ab 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -9,9 +9,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#endif #include #include @@ -48,7 +46,6 @@ static struct irq_chip amiga_irq_chip = { * The builtin Amiga hardware interrupt handlers. */ -#ifdef CONFIG_GENERIC_HARDIRQS static void ami_int1(unsigned int irq, struct irq_desc *desc) { unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; @@ -140,103 +137,6 @@ static void ami_int5(unsigned int irq, struct irq_desc *desc) generic_handle_irq(IRQ_AMIGA_DSKSYN); } } -#else /* !CONFIG_GENERIC_HARDIRQS */ -static irqreturn_t ami_int1(int irq, void *dev_id) -{ - unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; - - /* if serial transmit buffer empty, interrupt */ - if (ints & IF_TBE) { - amiga_custom.intreq = IF_TBE; - generic_handle_irq(IRQ_AMIGA_TBE); - } - - /* if floppy disk transfer complete, interrupt */ - if (ints & IF_DSKBLK) { - amiga_custom.intreq = IF_DSKBLK; - generic_handle_irq(IRQ_AMIGA_DSKBLK); - } - - /* if software interrupt set, interrupt */ - if (ints & IF_SOFT) { - amiga_custom.intreq = IF_SOFT; - generic_handle_irq(IRQ_AMIGA_SOFT); - } - return IRQ_HANDLED; -} - -static irqreturn_t ami_int3(int irq, void *dev_id) -{ - unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; - - /* if a blitter interrupt */ - if (ints & IF_BLIT) { - amiga_custom.intreq = IF_BLIT; - generic_handle_irq(IRQ_AMIGA_BLIT); - } - - /* if a copper interrupt */ - if (ints & IF_COPER) { - amiga_custom.intreq = IF_COPER; - generic_handle_irq(IRQ_AMIGA_COPPER); - } - - /* if a vertical blank interrupt */ - if (ints & IF_VERTB) { - amiga_custom.intreq = IF_VERTB; - generic_handle_irq(IRQ_AMIGA_VERTB); - } - return IRQ_HANDLED; -} - -static irqreturn_t ami_int4(int irq, void *dev_id) -{ - unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; - - /* if audio 0 interrupt */ - if (ints & IF_AUD0) { - amiga_custom.intreq = IF_AUD0; - generic_handle_irq(IRQ_AMIGA_AUD0); - } - - /* if audio 1 interrupt */ - if (ints & IF_AUD1) { - amiga_custom.intreq = IF_AUD1; - generic_handle_irq(IRQ_AMIGA_AUD1); - } - - /* if audio 2 interrupt */ - if (ints & IF_AUD2) { - amiga_custom.intreq = IF_AUD2; - generic_handle_irq(IRQ_AMIGA_AUD2); - } - - /* if audio 3 interrupt */ - if (ints & IF_AUD3) { - amiga_custom.intreq = IF_AUD3; - generic_handle_irq(IRQ_AMIGA_AUD3); - } - return IRQ_HANDLED; -} - -static irqreturn_t ami_int5(int irq, void *dev_id) -{ - unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; - - /* if serial receive buffer full interrupt */ - if (ints & IF_RBF) { - /* acknowledge of IF_RBF must be done by the serial interrupt */ - generic_handle_irq(IRQ_AMIGA_RBF); - } - - /* if a disk sync interrupt */ - if (ints & IF_DSKSYN) { - amiga_custom.intreq = IF_DSKSYN; - generic_handle_irq(IRQ_AMIGA_DSKSYN); - } - return IRQ_HANDLED; -} -#endif /* !CONFIG_GENERIC_HARDIRQS */ /* @@ -252,7 +152,6 @@ static irqreturn_t ami_int5(int irq, void *dev_id) void __init amiga_init_IRQ(void) { -#ifdef CONFIG_GENERIC_HARDIRQS m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, AMI_STD_IRQS); @@ -260,19 +159,6 @@ void __init amiga_init_IRQ(void) irq_set_chained_handler(IRQ_AUTO_3, ami_int3); irq_set_chained_handler(IRQ_AUTO_4, ami_int4); irq_set_chained_handler(IRQ_AUTO_5, ami_int5); -#else /* !CONFIG_GENERIC_HARDIRQS */ - if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL)) - pr_err("Couldn't register int%d\n", 1); - if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL)) - pr_err("Couldn't register int%d\n", 3); - if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL)) - pr_err("Couldn't register int%d\n", 4); - if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL)) - pr_err("Couldn't register int%d\n", 5); - - m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, - AMI_STD_IRQS); -#endif /* !CONFIG_GENERIC_HARDIRQS */ /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index fc190b34b621..b7d0aa37d199 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -1,23 +1,9 @@ #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#else -#include -#endif #include #include -#ifndef CONFIG_GENERIC_HARDIRQS -void dn_process_int(unsigned int irq, struct pt_regs *fp) -{ - do_IRQ(irq, fp); - - *(volatile unsigned char *)(pica)=0x20; - *(volatile unsigned char *)(picb)=0x20; -} -#endif - unsigned int apollo_irq_startup(struct irq_data *data) { unsigned int irq = data->irq; @@ -39,31 +25,23 @@ void apollo_irq_shutdown(struct irq_data *data) *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8)); } -#ifdef CONFIG_GENERIC_HARDIRQS void apollo_irq_eoi(struct irq_data *data) { *(volatile unsigned char *)(pica) = 0x20; *(volatile unsigned char *)(picb) = 0x20; } -#endif static struct irq_chip apollo_irq_chip = { .name = "apollo", .irq_startup = apollo_irq_startup, .irq_shutdown = apollo_irq_shutdown, -#ifdef CONFIG_GENERIC_HARDIRQS .irq_eoi = apollo_irq_eoi, -#endif }; void __init dn_init_IRQ(void) { -#ifdef CONFIG_GENERIC_HARDIRQS m68k_setup_user_interrupt(VEC_USER + 96, 16, NULL); -#else - m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int); -#endif m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq, IRQ_APOLLO, 16); } diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 518e61f2fccb..94349a525bc2 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -62,67 +62,6 @@ #define IRQ_FLG_STD (0x8000) /* internally used */ #endif -#ifndef CONFIG_GENERIC_HARDIRQS - -#include -#include -#include -#include - -struct pt_regs; - -/* - * This structure is used to chain together the ISRs for a particular - * interrupt source (if it supports chaining). - */ -struct irq_data { - unsigned int irq; - irqreturn_t (*handler)(int, void *); - void *dev_id; - struct irq_data *next; - unsigned long flags; - const char *devname; -}; - -/* - * This structure has only 4 elements for speed reasons - */ -struct irq_handler { - int (*handler)(int, void *); - unsigned long flags; - void *dev_id; - const char *devname; -}; - -struct irq_chip { - const char *name; - unsigned int (*irq_startup)(struct irq_data *data); - void (*irq_shutdown)(struct irq_data *data); - void (*irq_enable)(struct irq_data *data); - void (*irq_disable)(struct irq_data *data); -}; - -extern unsigned int m68k_irq_startup(struct irq_data *data); -extern unsigned int m68k_irq_startup_irq(unsigned int irq); -extern void m68k_irq_shutdown(struct irq_data *data); - -/* - * This function returns a new struct irq_data - */ -extern struct irq_data *new_irq_node(void); - -extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); -extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, - void (*handler)(unsigned int, struct pt_regs *)); -extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); -#define m68k_setup_irq_controller(chip, dummy, irq, cnt) \ - m68k_setup_irq_chip((chip), (irq), (cnt)) - -extern void generic_handle_irq(unsigned int); -asmlinkage void do_IRQ(int irq, struct pt_regs *regs); - -#else /* CONFIG_GENERIC_HARDIRQS */ - struct irq_data; struct irq_chip; struct irq_desc; @@ -139,8 +78,6 @@ extern void m68k_setup_irq_controller(struct irq_chip *, struct irq_desc *desc), unsigned int irq, unsigned int cnt); -#endif /* CONFIG_GENERIC_HARDIRQS */ - extern unsigned int irq_canonicalize(unsigned int irq); #else diff --git a/arch/m68k/include/asm/q40ints.h b/arch/m68k/include/asm/q40ints.h index 01cdbb4da465..22f12c9eb910 100644 --- a/arch/m68k/include/asm/q40ints.h +++ b/arch/m68k/include/asm/q40ints.h @@ -24,8 +24,3 @@ #define Q40_IRQ10_MASK (1<<5) #define Q40_IRQ14_MASK (1<<6) #define Q40_IRQ15_MASK (1<<7) - -#ifndef CONFIG_GENERIC_HARDIRQS -extern unsigned long q40_probe_irq_on (void); -extern int q40_probe_irq_off (unsigned long irqs); -#endif diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 141425785c4e..c5696193281a 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -6,11 +6,10 @@ extra-$(CONFIG_MMU) := head.o extra-$(CONFIG_SUN3) := sun3-head.o extra-y += vmlinux.lds -obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ - sys_m68k.o syscalltable.o time.o traps.o +obj-y := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \ + signal.o sys_m68k.o syscalltable.o time.o traps.o obj-$(CONFIG_MMU) += ints.o vectors.o -devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o ifndef CONFIG_MMU_SUN3 obj-y += dma.o @@ -18,9 +17,4 @@ endif ifndef CONFIG_MMU obj-y += init_task.o endif -ifdef CONFIG_GENERIC_HARDIRQS -obj-y += irq.o -else -obj-y += devres.o -endif diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index cea439f9819b..e2b056b3a314 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -31,20 +31,6 @@ extern u32 auto_irqhandler_fixup[]; extern u32 user_irqhandler_fixup[]; extern u16 user_irqvec_fixup[]; -#ifndef CONFIG_GENERIC_HARDIRQS -/* table for system interrupt handlers */ -static struct irq_data *irq_list[NR_IRQS]; -static struct irq_chip *irq_chip[NR_IRQS]; -static int irq_depth[NR_IRQS]; - -static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip) -{ - irq_chip[irq] = chip; - return 0; -} -#define irq_set_chip_and_handler(irq, chip, dummy) irq_set_chip(irq, chip) -#endif /* !CONFIG_GENERIC_HARDIRQS */ - static int m68k_first_user_vec; static struct irq_chip auto_irq_chip = { @@ -59,11 +45,6 @@ static struct irq_chip user_irq_chip = { .irq_shutdown = m68k_irq_shutdown, }; -#ifndef CONFIG_GENERIC_HARDIRQS -#define NUM_IRQ_NODES 100 -static struct irq_data nodes[NUM_IRQ_NODES]; -#endif /* !CONFIG_GENERIC_HARDIRQS */ - /* * void init_IRQ(void) * @@ -133,8 +114,6 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, flush_icache(); } -#ifdef CONFIG_GENERIC_HARDIRQS - /** * m68k_setup_irq_controller * @chip: irq chip which controls specified irq @@ -160,198 +139,6 @@ void m68k_setup_irq_controller(struct irq_chip *chip, } } -#else /* !CONFIG_GENERIC_HARDIRQS */ - -/** - * m68k_setup_irq_chip - * @contr: irq controller which controls specified irq - * @irq: first irq to be managed by the controller - * - * Change the controller for the specified range of irq, which will be used to - * manage these irq. auto/user irq already have a default controller, which can - * be changed as well, but the controller probably should use m68k_irq_startup/ - * m68k_irq_shutdown. - */ -void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq, - unsigned int cnt) -{ - int i; - - for (i = 0; i < cnt; i++) - irq_set_chip(irq + i, contr); -} - -struct irq_data *new_irq_node(void) -{ - struct irq_data *node; - short i; - - for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { - if (!node->handler) { - memset(node, 0, sizeof(*node)); - return node; - } - } - - printk ("new_irq_node: out of nodes\n"); - return NULL; -} - -static int m68k_setup_irq(unsigned int irq, struct irq_data *node) -{ - struct irq_chip *contr; - struct irq_data **prev; - unsigned long flags; - - if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { - printk("%s: Incorrect IRQ %d from %s\n", - __func__, irq, node->devname); - return -ENXIO; - } - - local_irq_save(flags); - - prev = irq_list + irq; - if (*prev) { - /* Can't share interrupts unless both agree to */ - if (!((*prev)->flags & node->flags & IRQF_SHARED)) { - local_irq_restore(flags); - return -EBUSY; - } - while (*prev) - prev = &(*prev)->next; - } - - if (!irq_list[irq]) { - if (contr->irq_startup) - contr->irq_startup(node); - else - contr->irq_enable(node); - } - node->next = NULL; - *prev = node; - - local_irq_restore(flags); - - return 0; -} - -int request_irq(unsigned int irq, - irq_handler_t handler, - unsigned long flags, const char *devname, void *dev_id) -{ - struct irq_data *node; - int res; - - node = new_irq_node(); - if (!node) - return -ENOMEM; - - node->irq = irq; - node->handler = handler; - node->flags = flags; - node->dev_id = dev_id; - node->devname = devname; - - res = m68k_setup_irq(irq, node); - if (res) - node->handler = NULL; - - return res; -} - -EXPORT_SYMBOL(request_irq); - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irq_chip *contr; - struct irq_data **p, *node; - unsigned long flags; - - if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { - printk("%s: Incorrect IRQ %d\n", __func__, irq); - return; - } - - local_irq_save(flags); - - p = irq_list + irq; - while ((node = *p)) { - if (node->dev_id == dev_id) - break; - p = &node->next; - } - - if (node) { - *p = node->next; - node->handler = NULL; - } else - printk("%s: Removing probably wrong IRQ %d\n", - __func__, irq); - - if (!irq_list[irq]) { - if (contr->irq_shutdown) - contr->irq_shutdown(node); - else - contr->irq_disable(node); - } - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(free_irq); - -void enable_irq(unsigned int irq) -{ - struct irq_chip *contr; - unsigned long flags; - - if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { - printk("%s: Incorrect IRQ %d\n", - __func__, irq); - return; - } - - local_irq_save(flags); - if (irq_depth[irq]) { - if (!--irq_depth[irq]) { - if (contr->irq_enable) - contr->irq_enable(irq_list[irq]); - } - } else - WARN_ON(1); - local_irq_restore(flags); -} - -EXPORT_SYMBOL(enable_irq); - -void disable_irq(unsigned int irq) -{ - struct irq_chip *contr; - unsigned long flags; - - if (irq >= NR_IRQS || !(contr = irq_chip[irq])) { - printk("%s: Incorrect IRQ %d\n", - __func__, irq); - return; - } - - local_irq_save(flags); - if (!irq_depth[irq]++) { - if (contr->irq_disable) - contr->irq_disable(irq_list[irq]); - } - local_irq_restore(flags); -} - -EXPORT_SYMBOL(disable_irq); - -void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); - -EXPORT_SYMBOL(disable_irq_nosync); - -#endif /* !CONFIG_GENERIC_HARDIRQS */ - unsigned int m68k_irq_startup_irq(unsigned int irq) { if (irq <= IRQ_AUTO_7) @@ -377,36 +164,6 @@ void m68k_irq_shutdown(struct irq_data *data) } -#ifndef CONFIG_GENERIC_HARDIRQS - -/* - * Do we need these probe functions on the m68k? - * - * ... may be useful with ISA devices - */ -unsigned long probe_irq_on (void) -{ -#ifdef CONFIG_Q40 - if (MACH_IS_Q40) - return q40_probe_irq_on(); -#endif - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off (unsigned long irqs) -{ -#ifdef CONFIG_Q40 - if (MACH_IS_Q40) - return q40_probe_irq_off(irqs); -#endif - return 0; -} - -EXPORT_SYMBOL(probe_irq_off); -#endif /* CONFIG_GENERIC_HARDIRQS */ - unsigned int irq_canonicalize(unsigned int irq) { #ifdef CONFIG_Q40 @@ -418,63 +175,9 @@ unsigned int irq_canonicalize(unsigned int irq) EXPORT_SYMBOL(irq_canonicalize); -#ifndef CONFIG_GENERIC_HARDIRQS -void generic_handle_irq(unsigned int irq) -{ - struct irq_data *node; - kstat_cpu(0).irqs[irq]++; - node = irq_list[irq]; - do { - node->handler(irq, node->dev_id); - node = node->next; - } while (node); -} - -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs; - old_regs = set_irq_regs(regs); - generic_handle_irq(irq); - set_irq_regs(old_regs); -} - -asmlinkage void handle_badint(struct pt_regs *regs) -{ - kstat_cpu(0).irqs[0]++; - printk("unexpected interrupt from %u\n", regs->vector); -} - -int show_interrupts(struct seq_file *p, void *v) -{ - struct irq_chip *contr; - struct irq_data *node; - int i = *(loff_t *) v; - - /* autovector interrupts */ - if (irq_list[i]) { - contr = irq_chip[i]; - node = irq_list[i]; - seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); - while ((node = node->next)) - seq_printf(p, ", %s", node->devname); - seq_puts(p, "\n"); - } - return 0; -} - -#ifdef CONFIG_PROC_FS -void init_irq_proc(void) -{ - /* Insert /proc/irq driver here */ -} -#endif - -#else /* CONFIG_GENERIC_HARDIRQS */ asmlinkage void handle_badint(struct pt_regs *regs) { atomic_inc(&irq_err_count); pr_warn("unexpected interrupt from %u\n", regs->vector); } - -#endif /* CONFIG_GENERIC_HARDIRQS */ diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index 425144cbfa7d..b55ead284971 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -11,9 +11,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#endif #include #include @@ -56,7 +54,6 @@ void __init baboon_init(void) * Baboon interrupt handler. This works a lot like a VIA. */ -#ifdef CONFIG_GENERIC_HARDIRQS static void baboon_irq(unsigned int irq, struct irq_desc *desc) { int irq_bit, irq_num; @@ -88,39 +85,6 @@ static void baboon_irq(unsigned int irq, struct irq_desc *desc) baboon->mb_ifr &= ~events; #endif } -#else -static irqreturn_t baboon_irq(int irq, void *dev_id) -{ - int irq_bit, irq_num; - unsigned char events; - -#ifdef DEBUG_IRQS - printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n", - (uint) baboon->mb_control, (uint) baboon->mb_ifr, - (uint) baboon->mb_status); -#endif - - if (!(events = baboon->mb_ifr & 0x07)) - return IRQ_NONE; - - irq_num = IRQ_BABOON_0; - irq_bit = 1; - do { - if (events & irq_bit) { - baboon->mb_ifr &= ~irq_bit; - generic_handle_irq(irq_num); - } - irq_bit <<= 1; - irq_num++; - } while(events >= irq_bit); -#if 0 - if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL); - /* for now we need to smash all interrupts */ - baboon->mb_ifr &= ~events; -#endif - return IRQ_HANDLED; -} -#endif /* * Register the Baboon interrupt dispatcher on nubus slot $C. @@ -129,12 +93,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id) void __init baboon_register_interrupts(void) { baboon_disabled = 0; -#ifdef CONFIG_GENERIC_HARDIRQS irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); -#else - if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon)) - pr_err("Couldn't register baboon interrupt\n"); -#endif } /* diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index cc784c2ff6e8..a4c82dab9ff1 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -19,9 +19,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#endif #include #include @@ -32,11 +30,7 @@ int oss_present; volatile struct mac_oss *oss; -#ifdef CONFIG_GENERIC_HARDIRQS extern void via1_irq(unsigned int irq, struct irq_desc *desc); -#else -extern irqreturn_t via1_irq(int, void *); -#endif /* * Initialize the OSS @@ -76,7 +70,6 @@ void __init oss_nubus_init(void) * and SCSI; everything else is routed to its own autovector IRQ. */ -#ifdef CONFIG_GENERIC_HARDIRQS static void oss_irq(unsigned int irq, struct irq_desc *desc) { int events; @@ -103,35 +96,6 @@ static void oss_irq(unsigned int irq, struct irq_desc *desc) /* FIXME: error check here? */ } } -#else -static irqreturn_t oss_irq(int irq, void *dev_id) -{ - int events; - - events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); - if (!events) - return IRQ_NONE; - -#ifdef DEBUG_IRQS - if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { - printk("oss_irq: irq %d events = 0x%04X\n", irq, - (int) oss->irq_pending); - } -#endif - /* FIXME: how do you clear a pending IRQ? */ - - if (events & OSS_IP_SOUND) { - oss->irq_pending &= ~OSS_IP_SOUND; - /* FIXME: call sound handler */ - } else if (events & OSS_IP_SCSI) { - oss->irq_pending &= ~OSS_IP_SCSI; - generic_handle_irq(IRQ_MAC_SCSI); - } else { - /* FIXME: error check here? */ - } - return IRQ_HANDLED; -} -#endif /* * Nubus IRQ handler, OSS style @@ -139,7 +103,6 @@ static irqreturn_t oss_irq(int irq, void *dev_id) * Unlike the VIA/RBV this is on its own autovector interrupt level. */ -#ifdef CONFIG_GENERIC_HARDIRQS static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc) { int events, irq_bit, i; @@ -166,35 +129,6 @@ static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc) } } while(events & (irq_bit - 1)); } -#else -static irqreturn_t oss_nubus_irq(int irq, void *dev_id) -{ - int events, irq_bit, i; - - events = oss->irq_pending & OSS_IP_NUBUS; - if (!events) - return IRQ_NONE; - -#ifdef DEBUG_NUBUS_INT - if (console_loglevel > 7) { - printk("oss_nubus_irq: events = 0x%04X\n", events); - } -#endif - /* There are only six slots on the OSS, not seven */ - - i = 6; - irq_bit = 0x40; - do { - --i; - irq_bit >>= 1; - if (events & irq_bit) { - oss->irq_pending &= ~irq_bit; - generic_handle_irq(NUBUS_SOURCE_BASE + i); - } - } while(events & (irq_bit - 1)); - return IRQ_HANDLED; -} -#endif /* * Register the OSS and NuBus interrupt dispatchers. @@ -202,22 +136,10 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id) void __init oss_register_interrupts(void) { -#ifdef CONFIG_GENERIC_HARDIRQS irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq); irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); -#else /* !CONFIG_GENERIC_HARDIRQS */ - if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "scsi"); - if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus", - (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "nubus"); - if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss)) - pr_err("Couldn't register %s interrupt\n", "sound"); - if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); -#endif /* !CONFIG_GENERIC_HARDIRQS */ } /* diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index 52840b8c03b8..e6c2d20f328d 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -18,9 +18,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#endif #include #include @@ -116,7 +114,6 @@ void __init psc_init(void) * PSC interrupt handler. It's a lot like the VIA interrupt handler. */ -#ifdef CONFIG_GENERIC_HARDIRQS static void psc_irq(unsigned int irq, struct irq_desc *desc) { unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc); @@ -145,36 +142,6 @@ static void psc_irq(unsigned int irq, struct irq_desc *desc) irq_bit <<= 1; } while (events >= irq_bit); } -#else -static irqreturn_t psc_irq(int irq, void *dev_id) -{ - int pIFR = pIFRbase + ((int) dev_id); - int pIER = pIERbase + ((int) dev_id); - int irq_num; - unsigned char irq_bit, events; - -#ifdef DEBUG_IRQS - printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n", - irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); -#endif - - events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; - if (!events) - return IRQ_NONE; - - irq_num = irq << 3; - irq_bit = 1; - do { - if (events & irq_bit) { - psc_write_byte(pIFR, irq_bit); - generic_handle_irq(irq_num); - } - irq_num++; - irq_bit <<= 1; - } while (events >= irq_bit); - return IRQ_HANDLED; -} -#endif /* * Register the PSC interrupt dispatchers for autovector interrupts 3-6. @@ -182,7 +149,6 @@ static irqreturn_t psc_irq(int irq, void *dev_id) void __init psc_register_interrupts(void) { -#ifdef CONFIG_GENERIC_HARDIRQS irq_set_chained_handler(IRQ_AUTO_3, psc_irq); irq_set_handler_data(IRQ_AUTO_3, (void *)0x30); irq_set_chained_handler(IRQ_AUTO_4, psc_irq); @@ -191,16 +157,6 @@ void __init psc_register_interrupts(void) irq_set_handler_data(IRQ_AUTO_5, (void *)0x50); irq_set_chained_handler(IRQ_AUTO_6, psc_irq); irq_set_handler_data(IRQ_AUTO_6, (void *)0x60); -#else /* !CONFIG_GENERIC_HARDIRQS */ - if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) - pr_err("Couldn't register psc%d interrupt\n", 3); - if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) - pr_err("Couldn't register psc%d interrupt\n", 4); - if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) - pr_err("Couldn't register psc%d interrupt\n", 5); - if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) - pr_err("Couldn't register psc%d interrupt\n", 6); -#endif /* !CONFIG_GENERIC_HARDIRQS */ } void psc_irq_enable(int irq) { diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index b8156ac496a0..f1600ad26621 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -28,9 +28,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#endif #include #include @@ -417,7 +415,6 @@ void __init via_nubus_init(void) * via6522.c :-), disable/pending masks added. */ -#ifdef CONFIG_GENERIC_HARDIRQS void via1_irq(unsigned int irq, struct irq_desc *desc) { int irq_num; @@ -459,58 +456,12 @@ static void via2_irq(unsigned int irq, struct irq_desc *desc) irq_bit <<= 1; } while (events >= irq_bit); } -#else -irqreturn_t via1_irq(int irq, void *dev_id) -{ - int irq_num; - unsigned char irq_bit, events; - - events = via1[vIFR] & via1[vIER] & 0x7F; - if (!events) - return IRQ_NONE; - - irq_num = VIA1_SOURCE_BASE; - irq_bit = 1; - do { - if (events & irq_bit) { - via1[vIFR] = irq_bit; - generic_handle_irq(irq_num); - } - ++irq_num; - irq_bit <<= 1; - } while (events >= irq_bit); - return IRQ_HANDLED; -} - -irqreturn_t via2_irq(int irq, void *dev_id) -{ - int irq_num; - unsigned char irq_bit, events; - - events = via2[gIFR] & via2[gIER] & 0x7F; - if (!events) - return IRQ_NONE; - - irq_num = VIA2_SOURCE_BASE; - irq_bit = 1; - do { - if (events & irq_bit) { - via2[gIFR] = irq_bit | rbv_clear; - generic_handle_irq(irq_num); - } - ++irq_num; - irq_bit <<= 1; - } while (events >= irq_bit); - return IRQ_HANDLED; -} -#endif /* * Dispatch Nubus interrupts. We are called as a secondary dispatch by the * VIA2 dispatcher as a fast interrupt handler. */ -#ifdef CONFIG_GENERIC_HARDIRQS void via_nubus_irq(unsigned int irq, struct irq_desc *desc) { int slot_irq; @@ -545,43 +496,6 @@ void via_nubus_irq(unsigned int irq, struct irq_desc *desc) events &= ~via2[vDirA]; } while (events); } -#else -irqreturn_t via_nubus_irq(int irq, void *dev_id) -{ - int slot_irq; - unsigned char slot_bit, events; - - events = ~via2[gBufA] & 0x7F; - if (rbv_present) - events &= via2[rSIER]; - else - events &= ~via2[vDirA]; - if (!events) - return IRQ_NONE; - - do { - slot_irq = IRQ_NUBUS_F; - slot_bit = 0x40; - do { - if (events & slot_bit) { - events &= ~slot_bit; - generic_handle_irq(slot_irq); - } - --slot_irq; - slot_bit >>= 1; - } while (events); - - /* clear the CA1 interrupt and make certain there's no more. */ - via2[gIFR] = 0x02 | rbv_clear; - events = ~via2[gBufA] & 0x7F; - if (rbv_present) - events &= via2[rSIER]; - else - events &= ~via2[vDirA]; - } while (events); - return IRQ_HANDLED; -} -#endif /* * Register the interrupt dispatchers for VIA or RBV machines only. @@ -589,7 +503,6 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id) void __init via_register_interrupts(void) { -#ifdef CONFIG_GENERIC_HARDIRQS if (via_alt_mapping) { /* software interrupt */ irq_set_chained_handler(IRQ_AUTO_1, via1_irq); @@ -600,23 +513,6 @@ void __init via_register_interrupts(void) } irq_set_chained_handler(IRQ_AUTO_2, via2_irq); irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq); -#else - if (via_alt_mapping) { - if (request_irq(IRQ_AUTO_1, via1_irq, 0, "software", - (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "software"); - if (request_irq(IRQ_AUTO_6, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); - } else { - if (request_irq(IRQ_AUTO_1, via1_irq, 0, "via1", (void *)via1)) - pr_err("Couldn't register %s interrupt\n", "via1"); - } - if (request_irq(IRQ_AUTO_2, via2_irq, 0, "via2", (void *)via2)) - pr_err("Couldn't register %s interrupt\n", "via2"); - if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 0, "nubus", - (void *)via2)) - pr_err("Couldn't register %s interrupt\n", "nubus"); -#endif } void via_irq_enable(int irq) { diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index f1e5288f043f..2b888491f29a 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -15,11 +15,7 @@ #include #include #include -#ifdef CONFIG_GENERIC_HARDIRQS #include -#else -#include -#endif #include #include @@ -329,15 +325,3 @@ void q40_irq_disable(struct irq_data *data) printk("disable_irq nesting count %d\n",mext_disabled); } } - -#ifndef CONFIG_GENERIC_HARDIRQS -unsigned long q40_probe_irq_on(void) -{ - printk("irq probing not working - reconfigure the driver to avoid this\n"); - return -1; -} -int q40_probe_irq_off(unsigned long irqs) -{ - return -1; -} -#endif diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 626b601931e9..7eb378195cf7 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -53,9 +53,6 @@ static irqreturn_t sun3_int7(int irq, void *dev_id) { unsigned int cnt; -#ifndef CONFIG_GENERIC_HARDIRQS - *sun3_intreg |= (1 << irq); -#endif cnt = kstat_irqs_cpu(irq, 0); if (!(cnt % 2000)) sun3_leds(led_pattern[cnt % 16000 / 2000]); @@ -69,9 +66,6 @@ static irqreturn_t sun3_int5(int irq, void *dev_id) #ifdef CONFIG_SUN3 intersil_clear(); #endif -#ifndef CONFIG_GENERIC_HARDIRQS - *sun3_intreg |= (1 << irq); -#endif #ifdef CONFIG_SUN3 intersil_clear(); #endif @@ -89,15 +83,6 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id) return IRQ_HANDLED; } -#ifndef CONFIG_GENERIC_HARDIRQS -static void sun3_inthandle(unsigned int irq, struct pt_regs *fp) -{ - *sun3_intreg &= ~(1 << irq); - - do_IRQ(irq, fp); -} -#endif - static void sun3_irq_enable(struct irq_data *data) { sun3_enable_irq(data->irq); @@ -114,19 +99,14 @@ static struct irq_chip sun3_irq_chip = { .irq_shutdown = m68k_irq_shutdown, .irq_enable = sun3_irq_enable, .irq_disable = sun3_irq_disable, -#ifdef CONFIG_GENERIC_HARDIRQS .irq_mask = sun3_irq_disable, .irq_unmask = sun3_irq_enable, -#endif }; void __init sun3_init_IRQ(void) { *sun3_intreg = 1; -#ifndef CONFIG_GENERIC_HARDIRQS - m68k_setup_auto_interrupt(sun3_inthandle); -#endif m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1, 7); m68k_setup_user_interrupt(VEC_USER, 128, NULL); -- cgit From f30a6484f1bcb410d0af0c24f34b8e3d92682a05 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 11 Sep 2011 11:54:50 +0200 Subject: m68k/irq: Remove obsolete support for user vector interrupt fixups It was used on Apollo only, before its conversion to genirq. Signed-off-by: Geert Uytterhoeven --- arch/m68k/apollo/dn_ints.c | 2 +- arch/m68k/atari/ataints.c | 2 +- arch/m68k/bvme6000/config.c | 2 +- arch/m68k/include/asm/irq.h | 4 +--- arch/m68k/kernel/entry_mm.S | 3 +-- arch/m68k/kernel/ints.c | 11 ++--------- arch/m68k/mvme147/config.c | 2 +- arch/m68k/mvme16x/config.c | 2 +- arch/m68k/sun3/sun3ints.c | 2 +- 9 files changed, 10 insertions(+), 20 deletions(-) diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index b7d0aa37d199..17be1e7e2df2 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -41,7 +41,7 @@ static struct irq_chip apollo_irq_chip = { void __init dn_init_IRQ(void) { - m68k_setup_user_interrupt(VEC_USER + 96, 16, NULL); + m68k_setup_user_interrupt(VEC_USER + 96, 16); m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq, IRQ_APOLLO, 16); } diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index af544557dd1d..6d196dadfdbc 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -137,7 +137,7 @@ static struct irq_chip atari_irq_chip = { void __init atari_init_IRQ(void) { - m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL); + m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER); m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1, NUM_ATARI_SOURCES - 1); diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 1edd95095cb4..81286476f740 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -86,7 +86,7 @@ static void bvme6000_get_model(char *model) */ static void __init bvme6000_init_IRQ(void) { - m68k_setup_user_interrupt(VEC_USER, 192, NULL); + m68k_setup_user_interrupt(VEC_USER, 192); } void __init config_bvme6000(void) diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 94349a525bc2..6198df5ff245 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -70,9 +70,7 @@ extern unsigned int m68k_irq_startup_irq(unsigned int irq); extern void m68k_irq_shutdown(struct irq_data *data); extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)); -extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, - void (*handler)(unsigned int, - struct pt_regs *)); +extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt); extern void m68k_setup_irq_controller(struct irq_chip *, void (*handle)(unsigned int irq, struct irq_desc *desc), diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S index f5927d0927b4..c713f514843d 100644 --- a/arch/m68k/kernel/entry_mm.S +++ b/arch/m68k/kernel/entry_mm.S @@ -48,7 +48,7 @@ .globl sys_fork, sys_clone, sys_vfork .globl ret_from_interrupt, bad_interrupt .globl auto_irqhandler_fixup -.globl user_irqvec_fixup, user_irqhandler_fixup +.globl user_irqvec_fixup .text ENTRY(buserr) @@ -240,7 +240,6 @@ user_irqvec_fixup = . + 2 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack -user_irqhandler_fixup = . + 2 jsr do_IRQ | process the IRQ addql #8,%sp | pop parameters off stack diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index e2b056b3a314..74fefac00899 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -28,7 +28,6 @@ #endif extern u32 auto_irqhandler_fixup[]; -extern u32 user_irqhandler_fixup[]; extern u16 user_irqvec_fixup[]; static int m68k_first_user_vec; @@ -91,16 +90,12 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re * m68k_setup_user_interrupt * @vec: first user vector interrupt to handle * @cnt: number of active user vector interrupts - * @handler: called from user vector interrupts * * setup user vector interrupts, this includes activating the specified range * of interrupts, only then these interrupts can be requested (note: this is - * different from auto vector interrupts). An optional handler can be installed - * to be called instead of the default do_IRQ(), it will be called - * with irq numbers starting from IRQ_USER. + * different from auto vector interrupts). */ -void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, - void (*handler)(unsigned int, struct pt_regs *)) +void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt) { int i; @@ -109,8 +104,6 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, for (i = 0; i < cnt; i++) irq_set_chip(IRQ_USER + i, &user_irq_chip); *user_irqvec_fixup = vec - IRQ_USER; - if (handler) - *user_irqhandler_fixup = (u32)handler; flush_icache(); } diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 01f2adf3f19f..5de924ef42ed 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -81,7 +81,7 @@ static void mvme147_get_model(char *model) void __init mvme147_init_IRQ(void) { - m68k_setup_user_interrupt(VEC_USER, 192, NULL); + m68k_setup_user_interrupt(VEC_USER, 192); } void __init config_mvme147(void) diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 0b28e2621653..31a66d99cbca 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(struct seq_file *m) static void __init mvme16x_init_IRQ (void) { - m68k_setup_user_interrupt(VEC_USER, 192, NULL); + m68k_setup_user_interrupt(VEC_USER, 192); } #define pcc2chip ((volatile u_char *)0xfff42000) diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index 7eb378195cf7..78b60f53e90a 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -109,7 +109,7 @@ void __init sun3_init_IRQ(void) m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1, 7); - m68k_setup_user_interrupt(VEC_USER, 128, NULL); + m68k_setup_user_interrupt(VEC_USER, 128); if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL)) pr_err("Couldn't register %s interrupt\n", "int5"); -- cgit From 2690e2148b730c53acb8797821468d0ea1673f25 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 11 Sep 2011 23:40:50 +1000 Subject: m68k/mac: Remove mac_irq_{en,dis}able() wrappers Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/macintosh.h | 2 ++ arch/m68k/mac/baboon.c | 7 ++----- arch/m68k/mac/macints.c | 25 +++++++------------------ 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index c2a1c5eac1a6..12ebe43b008b 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -12,6 +12,8 @@ extern void mac_reset(void); extern void mac_poweroff(void); extern void mac_init_IRQ(void); extern int mac_irq_pending(unsigned int); +extern void mac_irq_enable(struct irq_data *data); +extern void mac_irq_disable(struct irq_data *data); /* * Floppy driver magic hook - probably shouldn't be here diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index b55ead284971..b403924a1cad 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -21,9 +21,6 @@ /* #define DEBUG_IRQS */ -extern void mac_enable_irq(unsigned int); -extern void mac_disable_irq(unsigned int); - int baboon_present; static volatile struct baboon *baboon; static unsigned char baboon_disabled; @@ -111,7 +108,7 @@ void baboon_irq_enable(int irq) baboon_disabled &= ~(1 << irq_idx); if (!baboon_disabled) - mac_enable_irq(IRQ_NUBUS_C); + mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C)); } void baboon_irq_disable(int irq) @@ -124,7 +121,7 @@ void baboon_irq_disable(int irq) baboon_disabled |= 1 << irq_idx; if (baboon_disabled) - mac_disable_irq(IRQ_NUBUS_C); + mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C)); } void baboon_irq_clear(int irq) diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index 98497d288a9b..ba220b70ab8c 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -190,19 +190,6 @@ irqreturn_t mac_debug_handler(int, void *); /* #define DEBUG_MACINTS */ -void mac_enable_irq(unsigned int irq); -void mac_disable_irq(unsigned int irq); - -static void mac_irq_enable(struct irq_data *data) -{ - mac_enable_irq(data->irq); -} - -static void mac_irq_disable(struct irq_data *data) -{ - mac_disable_irq(data->irq); -} - static struct irq_chip mac_irq_chip = { .name = "mac", .irq_enable = mac_irq_enable, @@ -250,16 +237,17 @@ void __init mac_init_IRQ(void) } /* - * mac_enable_irq - enable an interrupt source - * mac_disable_irq - disable an interrupt source + * mac_irq_enable - enable an interrupt source + * mac_irq_disable - disable an interrupt source * mac_clear_irq - clears a pending interrupt - * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) + * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending) * * These routines are just dispatchers to the VIA/OSS/PSC routines. */ -void mac_enable_irq(unsigned int irq) +void mac_irq_enable(struct irq_data *data) { + int irq = data->irq; int irq_src = IRQ_SRC(irq); switch(irq_src) { @@ -292,8 +280,9 @@ void mac_enable_irq(unsigned int irq) } } -void mac_disable_irq(unsigned int irq) +void mac_irq_disable(struct irq_data *data) { + int irq = data->irq; int irq_src = IRQ_SRC(irq); switch(irq_src) { -- cgit From 8ff8584e51d4d3fbe08ede413c4a221223766323 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 8 Nov 2011 14:54:55 -0800 Subject: MIPS: Hook up process_vm_readv and process_vm_writev system calls. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2918/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/unistd.h | 18 ++++++++++++------ arch/mips/kernel/scall32-o32.S | 2 ++ arch/mips/kernel/scall64-64.S | 2 ++ arch/mips/kernel/scall64-n32.S | 2 ++ arch/mips/kernel/scall64-o32.S | 2 ++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index ecea7871dec2..d8dad5340ea3 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -365,16 +365,18 @@ #define __NR_syncfs (__NR_Linux + 342) #define __NR_sendmmsg (__NR_Linux + 343) #define __NR_setns (__NR_Linux + 344) +#define __NR_process_vm_readv (__NR_Linux + 345) +#define __NR_process_vm_writev (__NR_Linux + 346) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 344 +#define __NR_Linux_syscalls 346 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 344 +#define __NR_O32_Linux_syscalls 346 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -686,16 +688,18 @@ #define __NR_syncfs (__NR_Linux + 301) #define __NR_sendmmsg (__NR_Linux + 302) #define __NR_setns (__NR_Linux + 303) +#define __NR_process_vm_readv (__NR_Linux + 304) +#define __NR_process_vm_writev (__NR_Linux + 305) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 303 +#define __NR_Linux_syscalls 305 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 303 +#define __NR_64_Linux_syscalls 305 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -1012,16 +1016,18 @@ #define __NR_syncfs (__NR_Linux + 306) #define __NR_sendmmsg (__NR_Linux + 307) #define __NR_setns (__NR_Linux + 308) +#define __NR_process_vm_readv (__NR_Linux + 309) +#define __NR_process_vm_writev (__NR_Linux + 310) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 308 +#define __NR_Linux_syscalls 310 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 308 +#define __NR_N32_Linux_syscalls 310 #ifdef __KERNEL__ diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 47920657968d..a632bc144efa 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -591,6 +591,8 @@ einval: li v0, -ENOSYS sys sys_syncfs 1 sys sys_sendmmsg 4 sys sys_setns 2 + sys sys_process_vm_readv 6 /* 4345 */ + sys sys_process_vm_writev 6 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index fb7334bea731..3b5a5e9ae49c 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -430,4 +430,6 @@ sys_call_table: PTR sys_syncfs PTR sys_sendmmsg PTR sys_setns + PTR sys_process_vm_readv + PTR sys_process_vm_writev /* 5305 */ .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 6de1f598346e..6be6f7020923 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -430,4 +430,6 @@ EXPORT(sysn32_call_table) PTR sys_syncfs PTR compat_sys_sendmmsg PTR sys_setns + PTR compat_sys_process_vm_readv + PTR compat_sys_process_vm_writev /* 6310 */ .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 1d813169e453..54228553691d 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -548,4 +548,6 @@ sys_call_table: PTR sys_syncfs PTR compat_sys_sendmmsg PTR sys_setns + PTR compat_sys_process_vm_readv /* 4345 */ + PTR compat_sys_process_vm_writev .size sys_call_table,.-sys_call_table -- cgit From 76ee4557137ce12a60a1e1a070ed341182163a64 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 8 Nov 2011 19:57:59 +0900 Subject: ARM: EXYNOS: Fix compiler error with THIS_MODULE CC arch/arm/mach-exynos/cpuidle.o arch/arm/mach-exynos/cpuidle.c:36: error: 'THIS_MODULE' undeclared here (not in a function) arch/arm/mach-exynos/cpuidle.c: In function 'exynos4_enter_idle': arch/arm/mach-exynos/cpuidle.c:42: error: storage size of 'before' isn't known arch/arm/mach-exynos/cpuidle.c:42: error: storage size of 'after' isn't known arch/arm/mach-exynos/cpuidle.c:46: error: implicit declaration of function 'do_gettimeofday' arch/arm/mach-exynos/cpuidle.c:52: error: 'USEC_PER_SEC' undeclared (first use in this function) arch/arm/mach-exynos/cpuidle.c:52: error: (Each undeclared identifier is reported only once arch/arm/mach-exynos/cpuidle.c:52: error: for each function it appears in.) arch/arm/mach-exynos/cpuidle.c:42: warning: unused variable 'after' arch/arm/mach-exynos/cpuidle.c:42: warning: unused variable 'before' make[1]: *** [arch/arm/mach-exynos/cpuidle.o] Error 1 Signed-off-by: Kyungmin Park [kgene.kim@samsung.com: Fixed as per Stephen's suggestion] Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index 35f6502144ae..4ebb382c5979 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include -- cgit From 6d2dd054295e26dad0a84e2fe2029a1428242f8b Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 31 Oct 2011 23:50:16 -0200 Subject: [libata] libata-scsi.c: Add function parameter documentation Add the documentation of parameters of ata_change_queue_depth to silence the warning of make xmldocs Signed-off-by: Marcos paulo de Souza Acked-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 72a9770ac42f..2a5412e7e9c1 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1217,6 +1217,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) /** * __ata_change_queue_depth - helper for ata_scsi_change_queue_depth + * @ap: ATA port to which the device change the queue depth + * @sdev: SCSI device to configure queue depth for + * @queue_depth: new queue depth + * @reason: calling context * * libsas and libata have different approaches for associating a sdev to * its ata_port. -- cgit From 003456145f0d23b73f080abd1fd7981788438693 Mon Sep 17 00:00:00 2001 From: JiSheng Zhang Date: Mon, 31 Oct 2011 21:20:10 +0800 Subject: ahci_platform: use dev_get_platdata() Use dev_get_platdata() to retrieve the struct ahci_platform_data data from the platform. Signed-off-by: JiSheng Zhang Signed-off-by: Jeff Garzik --- drivers/ata/ahci_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 004f2ce3dc73..ec555951176e 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -65,7 +65,7 @@ static struct scsi_host_template ahci_platform_sht = { static int __init ahci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev->platform_data; + struct ahci_platform_data *pdata = dev_get_platdata(dev); const struct platform_device_id *id = platform_get_device_id(pdev); struct ata_port_info pi = ahci_port_info[id->driver_data]; const struct ata_port_info *ppi[] = { &pi, NULL }; @@ -191,7 +191,7 @@ err0: static int __devexit ahci_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev->platform_data; + struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); -- cgit From 142924cf402f9c0568004f0e2a27988fe3556c61 Mon Sep 17 00:00:00 2001 From: Chris Dunlop Date: Mon, 24 Oct 2011 10:38:18 +1100 Subject: sata_sis.c: trivial spelling fix Trivial spelling fix. Signed-off-by: Chris Dunlop Signed-off-by: Jeff Garzik --- drivers/ata/sata_sis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 447d9c05fb5a..95ec435f0eb4 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -104,7 +104,7 @@ static const struct ata_port_info sis_port_info = { }; MODULE_AUTHOR("Uwe Koziolek"); -MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller"); +MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sis_pci_tbl); MODULE_VERSION(DRV_VERSION); -- cgit From 7a46c0780babea7d0b3f277a33ea243be38eb942 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Wed, 19 Oct 2011 17:17:02 -0700 Subject: [libata] Issue SRST to Sil3726 PMP Reenable sending SRST to devices connected behind a Sil3726 PMP. This allow staggered spinups and handles drives that spins up slowly. While the drives spin up, the PMP will not accept SRST. Most controller reissues the reset until the drive is ready, while some [Sil3124] returns an error. In ata_eh_error, wait 10s before reset the ATA port and try again. Signed-off-by: Gwendal Grignou Acked-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 12 +++++++++++- drivers/ata/libata-pmp.c | 7 ++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index f22957c2769a..a9b282038000 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2883,7 +2883,7 @@ int ata_eh_reset(struct ata_link *link, int classify, sata_scr_read(link, SCR_STATUS, &sstatus)) rc = -ERESTART; - if (rc == -ERESTART || try >= max_tries) { + if (try >= max_tries) { /* * Thaw host port even if reset failed, so that the port * can be retried on the next phy event. This risks @@ -2909,6 +2909,16 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_acquire(ap); } + /* + * While disks spinup behind PMP, some controllers fail sending SRST. + * They need to be reset - as well as the PMP - before retrying. + */ + if (rc == -ERESTART) { + if (ata_is_host_link(link)) + ata_eh_thaw_port(ap); + goto out; + } + if (try == max_tries - 1) { sata_down_spd_limit(link, 0); if (slave) diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 104462dbc524..21b80c555c60 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -389,12 +389,9 @@ static void sata_pmp_quirks(struct ata_port *ap) /* link reports offline after LPM */ link->flags |= ATA_LFLAG_NO_LPM; - /* Class code report is unreliable and SRST - * times out under certain configurations. - */ + /* Class code report is unreliable. */ if (link->pmp < 5) - link->flags |= ATA_LFLAG_NO_SRST | - ATA_LFLAG_ASSUME_ATA; + link->flags |= ATA_LFLAG_ASSUME_ATA; /* port 5 is for SEMB device and it doesn't like SRST */ if (link->pmp == 5) -- cgit From c9703765f3d5ab27909011dee4a05affe48e4442 Mon Sep 17 00:00:00 2001 From: Keng-Yu Lin Date: Wed, 9 Nov 2011 01:47:36 -0500 Subject: [libata] ahci: Add ASMedia ASM1061 support Signed-off-by: Keng-Yu Lin Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ include/linux/pci_ids.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fb7b90b05922..cf26222a93c5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -390,6 +390,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Promise */ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ + /* Asmedia */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3fdf251389de..172ba70306d1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2405,6 +2405,8 @@ #define PCI_VENDOR_ID_AZWAVE 0x1a3b +#define PCI_VENDOR_ID_ASMEDIA 0x1b21 + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- cgit From 8d1c963a2e0c57dfe7f9c356389902e500cf1cfd Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 8 Nov 2011 20:37:26 +0100 Subject: ALSA: HDA: Remove quirk for Toshiba T110 According to the bug reporter, model=auto is needed to make the internal microphone work. BugLink: https://bugs.launchpad.net/bugs/819699 Reported-by: Andrej (agno01) Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5e706e4d1737..0de21193a2b0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3062,7 +3062,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), - SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", CXT5066_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), -- cgit From 0836b5cdd23d573bf7ec57f73ff774b3ad660bf4 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Fri, 4 Nov 2011 01:13:20 +0000 Subject: ARM: picoxcell: add extra temp register to addruart 639da5ee3 (ARM: add an extra temp register to the low level debugging addruart macro) didn't include picoxcell as it hadn't been merged at the time. Fix up the compile breakage by adding the extra temp parameter. Signed-off-by: Jamie Iles --- arch/arm/mach-picoxcell/include/mach/debug-macro.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-picoxcell/include/mach/debug-macro.S b/arch/arm/mach-picoxcell/include/mach/debug-macro.S index 8f2c234ed9d9..58d4ee3ae949 100644 --- a/arch/arm/mach-picoxcell/include/mach/debug-macro.S +++ b/arch/arm/mach-picoxcell/include/mach/debug-macro.S @@ -14,7 +14,7 @@ #define UART_SHIFT 2 - .macro addruart, rp, rv + .macro addruart, rp, rv, tmp ldr \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE) ldr \rp, =PICOXCELL_UART1_BASE .endm -- cgit From f7f9bdfadfda07afb904a9767468e38c2d1a6033 Mon Sep 17 00:00:00 2001 From: Julian Wollrath Date: Wed, 9 Nov 2011 10:02:40 +0100 Subject: ALSA: hda - fix internal mic on Dell Vostro 3500 laptop Fix the not working internal mic on Dell Vostro 3500 laptop by introducing the new model dell-vostro-3500. Signed-off-by: Julian Wollrath Cc: Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_sigmatel.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 4f3443230d89..edad99abec21 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -349,6 +349,7 @@ STAC92HD83* ref Reference board mic-ref Reference board with power management for ports dell-s14 Dell laptop + dell-vostro-3500 Dell Vostro 3500 laptop hp HP laptops with (inverted) mute-LED hp-dv7-4000 HP dv-7 4000 auto BIOS setup (default) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4e715fefebef..edc2b7bc177c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -95,6 +95,7 @@ enum { STAC_92HD83XXX_REF, STAC_92HD83XXX_PWR_REF, STAC_DELL_S14, + STAC_DELL_VOSTRO_3500, STAC_92HD83XXX_HP, STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, @@ -1659,6 +1660,12 @@ static const unsigned int dell_s14_pin_configs[10] = { 0x40f000f0, 0x40f000f0, }; +static const unsigned int dell_vostro_3500_pin_configs[10] = { + 0x02a11020, 0x0221101f, 0x400000f0, 0x90170110, + 0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160, + 0x400000f4, 0x400000f5, +}; + static const unsigned int hp_dv7_4000_pin_configs[10] = { 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, @@ -1675,6 +1682,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, [STAC_DELL_S14] = dell_s14_pin_configs, + [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, }; @@ -1684,6 +1692,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = "ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_DELL_S14] = "dell-s14", + [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", [STAC_92HD83XXX_HP] = "hp", [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", @@ -1697,6 +1706,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD83XXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, "unknown Dell", STAC_DELL_S14), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, + "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, "HP", STAC_92HD83XXX_HP), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, -- cgit From 55c0008be67a27944b6705251d9a8d4c56c67701 Mon Sep 17 00:00:00 2001 From: Alexey Fisher Date: Wed, 9 Nov 2011 11:39:24 +0100 Subject: ALSA: snd_usb_audio: add Logitech HD Webcam c510 to quirk-384 Logitech HD Webcam c510 provide wrong mixer resolution. Add it to "res = 384" quirk. Signed-off-by: Alexey Fisher Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c5444e00f0c6..ab23869c01bb 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -799,6 +799,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x046d, 0x0808): case USB_ID(0x046d, 0x0809): + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ case USB_ID(0x046d, 0x0991): /* Most audio usb devices lie about volume resolution. * Most Logitech webcams have res = 384. -- cgit From 44656fa03926e7363ab41c565619800a4b3b1322 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 8 Nov 2011 10:20:10 -0800 Subject: kbuild: Fix missing system calls check on mips. Commit 5f7efb4 (Kbuild: append missing-syscalls to the default target list) broke MIPS build. Reported-tested-and-acked-by: Ralf Baechle Signed-off-by: David Daney Signed-off-by: Michal Marek --- Kbuild | 2 +- arch/mips/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Kbuild b/Kbuild index 4caab4f6cba7..b8b708ad6dc3 100644 --- a/Kbuild +++ b/Kbuild @@ -92,7 +92,7 @@ always += missing-syscalls targets += missing-syscalls quiet_cmd_syscalls = CALL $< - cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags) + cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags) $(missing_syscalls_flags) missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE $(call cmd,syscalls) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 9b4cb00407d7..0be318609fc6 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64 archprepare: ifdef CONFIG_MIPS32_N32 @echo ' Checking missing-syscalls for N32' - $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32" + $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32" endif ifdef CONFIG_MIPS32_O32 @echo ' Checking missing-syscalls for O32' - $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32" + $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32" endif install: -- cgit From e0e20753c15fc418d94fee826af394907df856d8 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 27 Oct 2011 20:38:24 -0700 Subject: pinctrl: fix "warning: 'struct pinctrl_dev' declared inside parameter list" when pinctl subsystem is not selected, when compiling drivers including the include/linux/pinctrl/pinctrl.h, we will get the warning as below: In file included from include/linux/pinctrl/pinmux.h:17, from drivers/tty/serial/sirfsoc_uart.c:25: include/linux/pinctrl/pinctrl.h:126: warning: 'struct pinctrl_dev' declared inside parameter list include/linux/pinctrl/pinctrl.h:126: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Barry Song Signed-off-by: Linus Walleij --- include/linux/pinctrl/pinctrl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 3605e947fa90..04c011038f32 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -121,6 +121,7 @@ extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev); extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); #else +struct pinctrl_dev; /* Sufficiently stupid default function when pinctrl is not in use */ static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) -- cgit From b3c41f4c18de9aa90315dd0d197f8485b00e3cc5 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 18 Sep 2011 09:56:35 +0800 Subject: ARM: at91: usart: drop static map regs for dbgu In commit fb149f9e28354 we introduce ioremap support for static map_io, we do not need this register entry anymore. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91cap9_devices.c | 5 ++--- arch/arm/mach-at91/at91rm9200_devices.c | 5 ++--- arch/arm/mach-at91/at91sam9260_devices.c | 5 ++--- arch/arm/mach-at91/at91sam9261_devices.c | 5 ++--- arch/arm/mach-at91/at91sam9263_devices.c | 5 ++--- arch/arm/mach-at91/at91sam9g45_devices.c | 5 ++--- arch/arm/mach-at91/at91sam9rl_devices.c | 5 ++--- 7 files changed, 14 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index a4401d6b5b07..b9739baa21e4 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -1021,8 +1021,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -1035,7 +1035,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 01d8bbd1468b..66591fa53e05 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -877,8 +877,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -891,7 +891,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 24b6f8c0440d..25e3464fb07f 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -837,8 +837,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -851,7 +851,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 3b70b3897d95..ae78f4d03b73 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -816,8 +816,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -830,7 +830,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 3faa1fde9ad9..ad017eb1f8df 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -1196,8 +1196,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -1210,7 +1210,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 000b5e1da965..ad00953a7f4f 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1332,8 +1332,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -1346,7 +1346,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 305a851b5bff..429b6d7e9492 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -908,8 +908,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {} #if defined(CONFIG_SERIAL_ATMEL) static struct resource dbgu_resources[] = { [0] = { - .start = AT91_VA_BASE_SYS + AT91_DBGU, - .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .start = AT91_BASE_SYS + AT91_DBGU, + .end = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -922,7 +922,6 @@ static struct resource dbgu_resources[] = { static struct atmel_uart_data dbgu_data = { .use_dma_tx = 0, .use_dma_rx = 0, /* DBGU not capable of receive DMA */ - .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), }; static u64 dbgu_dmamask = DMA_BIT_MASK(32); -- cgit From 30458edf667b77012573e649fced3cf5c01efe82 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 2 Nov 2011 15:02:43 +0800 Subject: at91: vmalloc fix missing AT91_VIRT_BASE define VMALLOC_END is defined in terms of AT91_VIRT_BASE but this needs mach/hardware.h for it's definition. In file included from arch/arm/mach-at91/board-usb-a926x.c:26:0: include/linux/mm.h: In function 'is_vmalloc_addr': include/linux/mm.h:305:41: error: 'AT91_VIRT_BASE' undeclared (first use in this function) include/linux/mm.h:305:41: note: each undeclared identifier is reported only once for each function it appears in Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Signed-off-by: Jamie Iles --- arch/arm/mach-at91/include/mach/vmalloc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-at91/include/mach/vmalloc.h b/arch/arm/mach-at91/include/mach/vmalloc.h index 8eb459f3f5b7..8e4a1bd0ab1d 100644 --- a/arch/arm/mach-at91/include/mach/vmalloc.h +++ b/arch/arm/mach-at91/include/mach/vmalloc.h @@ -21,6 +21,8 @@ #ifndef __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H +#include + #define VMALLOC_END (AT91_VIRT_BASE & PGDIR_MASK) #endif -- cgit From b2eb5309fbc680406d6bf3b182178f0cfaf951fb Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 19 Sep 2011 19:26:52 +0800 Subject: at91/yl-9200: Fix section mismatch Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- arch/arm/mach-at91/board-yl-9200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 649b052231f5..12a3f955162b 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -384,7 +384,7 @@ static struct spi_board_info yl9200_spi_devices[] = { #include + +const char *name: Optional. Set this to help identify +the memory region, it will show up in the corresponding sysfs node. + + int memtype: Required if the mapping is used. Set this to UIO_MEM_PHYS if you you have physical memory on your @@ -553,7 +558,7 @@ instead to remember such an address. -Please do not touch the kobj element of +Please do not touch the map element of struct uio_mem! It is used by the UIO framework to set up sysfs files for this mapping. Simply leave it alone. -- cgit From b872a37437e93df9d112ce674752b3b3a0a17020 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Nov 2011 09:33:56 -0500 Subject: drm/radeon: add some missing FireMV pci ids Noticed by Egbert. Signed-off-by: Alex Deucher Cc: stable@kernel.org Cc: Egbert Eich Signed-off-by: Dave Airlie --- include/drm/drm_pciids.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 3d53efd25ab9..f81676f1b310 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -4,6 +4,7 @@ */ #define radeon_PCI_IDS \ {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ + {0x1002, 0x3151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x3155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -55,6 +56,7 @@ {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ -- cgit From 6c47e5c23aa2a7c54ad7ac13af4bd56cd9e703bf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Nov 2011 14:32:01 -0500 Subject: drm/radeon/kms: fix up gpio i2c mask bits for r4xx Fixes i2c test failures when i2c_algo_bit.bit_test=1. The hw doesn't actually require a mask, so just set it to the default mask bits for r1xx-r4xx radeon ddc. Signed-off-by: Alex Deucher Cc: stable@kernel.org Cc: Jean Delvare Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index d2d179267af3..0a4ec1ed02c0 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -85,6 +85,18 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + /* some evergreen boards have bad data for this entry */ if (ASIC_IS_DCE4(rdev)) { if ((i == 7) && -- cgit From 6991b8f2a3193397461104a27be417addb8d032b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Nov 2011 17:52:51 -0500 Subject: drm/radeon/kms: fix segfault in pm rework Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 0a4ec1ed02c0..fecd705a1a5f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2008,14 +2008,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) return state_index; /* last mode is usually default, array is low to high */ for (i = 0; i < num_modes; i++) { + rdev->pm.power_state[state_index].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + if (!rdev->pm.power_state[state_index].clock_info) + return state_index; + rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; switch (frev) { case 1: - rdev->pm.power_state[state_index].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); - if (!rdev->pm.power_state[state_index].clock_info) - return state_index; - rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); rdev->pm.power_state[state_index].clock_info[0].sclk = @@ -2051,11 +2051,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) state_index++; break; case 2: - rdev->pm.power_state[state_index].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); - if (!rdev->pm.power_state[state_index].clock_info) - return state_index; - rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); rdev->pm.power_state[state_index].clock_info[0].sclk = @@ -2092,11 +2087,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) state_index++; break; case 3: - rdev->pm.power_state[state_index].clock_info = - kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); - if (!rdev->pm.power_state[state_index].clock_info) - return state_index; - rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); rdev->pm.power_state[state_index].clock_info[0].sclk = -- cgit From 52b3bfc69efc44447ed2db25dd999aef64b3c970 Mon Sep 17 00:00:00 2001 From: Lucas Kannebley Tavares Date: Fri, 28 Oct 2011 13:52:08 -0200 Subject: jsm: Change maintainership Breno Leitao has passed the maintainership on to me. Signed-off-by: Lucas Kannebley Tavares Acked-by: Breno Leitao Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4808256446f2..cc6a46645432 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3710,7 +3710,7 @@ F: fs/jbd2/ F: include/linux/jbd2.h JSM Neo PCI based serial card -M: Breno Leitao +M: Lucas Tavares L: linux-serial@vger.kernel.org S: Maintained F: drivers/tty/serial/jsm/ -- cgit From c2a3e84f950e7ddba1f3914b005861d46ae60359 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 25 Oct 2011 19:19:43 -0700 Subject: tty: hvc_dcc: Fix duplicate character inputs Reading from the DCC grabs a character from the buffer and clears the status bit. Since this is a context-changing operation, instructions following the character read that rely on the status bit being accurate need to be synchronized with an ISB. In this case, the status bit check needs to execute after the character read otherwise we run the risk of reading the character and checking the status bit before the read can clear the status bit in the first place. When this happens, the user will see the same character they typed twice, instead of once. Add an ISB after the read and the write, so that the status check is synchronized with the read/write operations. Signed-off-by: Stephen Boyd Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_dcc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c index 435f6facbc23..44fbebab5075 100644 --- a/drivers/tty/hvc/hvc_dcc.c +++ b/drivers/tty/hvc/hvc_dcc.c @@ -46,6 +46,7 @@ static inline char __dcc_getchar(void) asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg" : "=r" (__c)); + isb(); return __c; } @@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c) asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char" : /* no output register */ : "r" (c)); + isb(); } static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count) -- cgit From a1d7cfe29f13cf45f8094929864b9c66bf0cd91b Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 27 Oct 2011 15:45:18 +0900 Subject: pch_uart: Fix hw-flow control issue Using hardware flow control, currently, register of the control-bit(AFE) is not set. This patch fixes the issue. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 21febef926aa..2f07a6702eab 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1280,6 +1280,7 @@ static void pch_uart_set_termios(struct uart_port *port, if (rtn) goto out; + pch_uart_set_mctrl(&priv->port, priv->port.mctrl); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); -- cgit From 8249f743f732ccbc3056428945ab1d9bd36d46bf Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 28 Oct 2011 09:38:49 +0900 Subject: pch_uart: Support new device LAPIS Semiconductor ML7831 IOH ML7831 is companion chip for Intel Atom E6xx series. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 14 +++++++------- drivers/tty/serial/pch_uart.c | 8 ++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 5f479dada6f2..925a1e547a83 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60 Support for the IFX6x60 modem devices on Intel MID platforms. config SERIAL_PCH_UART - tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART" + tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART" depends on PCI select SERIAL_CORE help @@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART which is an IOH(Input/Output Hub) for x86 embedded processor. Enabling PCH_DMA, this PCH UART works as DMA mode. - This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ - Output Hub), ML7213 and ML7223. - ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is - for MP(Media Phone) use. - ML7213/ML7223 is companion chip for Intel Atom E6xx series. - ML7213/ML7223 is completely compatible for Intel EG20T PCH. + This driver also can be used for LAPIS Semiconductor IOH(Input/ + Output Hub), ML7213, ML7223 and ML7831. + ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is + for MP(Media Phone) use and ML7831 IOH is for general purpose use. + ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. + ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. config SERIAL_MSM_SMD bool "Enable tty device interface for some SMD ports" diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 2f07a6702eab..2ef0e7d02991 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -258,6 +258,8 @@ enum pch_uart_num_t { pch_ml7213_uart2, pch_ml7223_uart0, pch_ml7223_uart1, + pch_ml7831_uart0, + pch_ml7831_uart1, }; static struct pch_uart_driver_data drv_dat[] = { @@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = { [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, + [pch_ml7831_uart0] = {PCH_UART_8LINE, 0}, + [pch_ml7831_uart1] = {PCH_UART_2LINE, 1}, }; static unsigned int default_baud = 9600; @@ -1553,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { .driver_data = pch_ml7223_uart0}, {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D), .driver_data = pch_ml7223_uart1}, + {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811), + .driver_data = pch_ml7831_uart0}, + {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812), + .driver_data = pch_ml7831_uart1}, {0,}, }; -- cgit From eca9dfa846a3d0eeb865e290851f4bfe4fb34fdd Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 28 Oct 2011 09:38:50 +0900 Subject: pch_uart: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor On October 1 in 2011, OKI SEMICONDUCTOR Co., Ltd. changed the company name in to LAPIS Semiconductor Co., Ltd. Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 2ef0e7d02991..ac852b5a8f93 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1,5 +1,5 @@ /* - *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. + *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. * *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 @@ -46,8 +46,8 @@ enum { /* Set the max number of UART port * Intel EG20T PCH: 4 port - * OKI SEMICONDUCTOR ML7213 IOH: 3 port - * OKI SEMICONDUCTOR ML7223 IOH: 2 port + * LAPIS Semiconductor ML7213 IOH: 3 port + * LAPIS Semiconductor ML7223 IOH: 2 port */ #define PCH_UART_NR 4 -- cgit From 9636b755da7b498094bdf15b4ce9f6fd16995e4e Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 11 Oct 2011 17:05:43 -0700 Subject: tty/serial: Prevent drop of DCD on suspend for Tegra UARTs On Tegra UARTs (except UART1), the DTR / DCD / DSR lines are not externally accessible. Instead, the DTR line internally appears to be looped back to be the input to the DCD and DSR lines. The net effect of this is that when we drop DTR (like when we suspend), we'll see DCD drop too. ...and when we see DCD drop, we treat that as a hangup. In order to prevent this hangup from occurring at every sleep, we need to force DTR to remain high on Tegra UARTs. This patch uses the mcr_mask / mcr_force fields, which were originally added for the kludge ALPHA_KLUDGE_MCR. Using these fields does not prevent us from removing ALPHA_KLUDGE_MCR--we can just remove the "if" tests I have added and always init mcr_mask / mcr_force from the serial8250_config. NOTE: If we have people that are using UARTA on a Tegra and need to control DTR, we'll need to either add a separate port type for UARTA or we'll need to add some tegra-specific code to detect whether the DTR needs to be left high. Signed-off-by: Doug Anderson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250.c | 14 ++++++++++++++ drivers/tty/serial/8250.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index eeadf1b8e093..2b0a4b63c5f7 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -308,6 +308,8 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01, .flags = UART_CAP_FIFO | UART_CAP_RTOIE, + .mcr_mask = ~UART_MCR_DTR, + .mcr_force = UART_MCR_DTR, }, [PORT_XR17D15X] = { .name = "XR17D15X", @@ -1229,6 +1231,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) up->port.fifosize = uart_config[up->port.type].fifo_size; up->capabilities = uart_config[up->port.type].flags; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; + if (!ALPHA_KLUDGE_MCR) { + up->mcr_mask = uart_config[up->port.type].mcr_mask; + up->mcr_force = uart_config[up->port.type].mcr_force; + } if (up->port.type == PORT_UNKNOWN) goto out; @@ -1987,6 +1993,10 @@ static int serial8250_startup(struct uart_port *port) up->port.fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; + if (!ALPHA_KLUDGE_MCR) { + up->mcr_mask = uart_config[up->port.type].mcr_mask; + up->mcr_force = uart_config[up->port.type].mcr_force; + } up->mcr = 0; if (up->port.iotype != up->cur_iotype) @@ -2793,6 +2803,10 @@ serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type) up->port.fifosize = uart_config[type].fifo_size; up->capabilities = uart_config[type].flags; up->tx_loadsz = uart_config[type].tx_loadsz; + if (!ALPHA_KLUDGE_MCR) { + up->mcr_mask = uart_config[type].mcr_mask; + up->mcr_force = uart_config[type].mcr_force; + } } static void __init diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index 6edf4a6a22d4..1f7510051707 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h @@ -35,6 +35,8 @@ struct serial8250_config { unsigned short tx_loadsz; unsigned char fcr; unsigned int flags; + unsigned char mcr_mask; + unsigned char mcr_force; }; #define UART_CAP_FIFO (1 << 8) /* UART has FIFO */ -- cgit From 604fdb75094a7367e1794fd0f62183380364ce13 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 10 Nov 2011 13:17:55 +0000 Subject: serial,mfd: Fix CMSPAR setup This is referenced the wrong way. Mika Westerberg added some checks to the tty to support multiple console, but the real problem is simply referencing the termios object via the wrong path. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mfd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 286c386d9c46..e272d3919c67 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, { struct uart_hsu_port *up = container_of(port, struct uart_hsu_port, port); - struct tty_struct *tty = port->state->port.tty; unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; @@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, } /* CMSPAR isn't supported by this driver */ - if (tty) - tty->termios->c_cflag &= ~CMSPAR; + termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; -- cgit From 90f04c2926cfb5bf74533b0a7766bc896f6a0c0e Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 11 Nov 2011 10:55:27 +0900 Subject: pch_uart: Fix DMA resource leak issue Changing UART mode PIO->DMA->PIO->DMA like below, pch_uart driver can't get DMA channel resource. setserial /dev/ttyPCH0 ^low_latency setserial /dev/ttyPCH0 low_latency CAUSE: Changing mode using setserial command, ".startup" function which gets DMA channel is called before ".verify_port" function which sets dma-flag(use_dma/use_dma_flag) as 1. PIO->DMA .startup: Since dma-flag is 0, DMA channel is not requested. .verify_port: dma-flag is set as 1. .shutdown: N/A DMA->PIO .startup: Since dma-flag is 1, DMA channel is requested. .verify_port: dma-flag is set as 0. .shutdown: Since dma-flag is 0, DMA channel is not released. This means DMA channel resource leak occurs. Next time, this driver can't get DMA channel resource forever. MODIFICATION: Currently, when release DMA channel resource, this driver checks dma-flag. However, this specification occurs the above issue. This driver must check whether dma_request_channel is executed or not. The values are saved in private data variable "chan_tx/chan_tx". These variables mean if the value is NULL, DMA channel is not requested, if not NULL, DMA channel is requested. This patch fixes the issue. Signed-off-by: Tomoya MORINAGA Acked-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index ac852b5a8f93..d6aba8c087e4 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -632,6 +632,7 @@ static void pch_request_dma(struct uart_port *port) dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n", __func__); dma_release_channel(priv->chan_tx); + priv->chan_tx = NULL; return; } @@ -1219,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port) dev_err(priv->port.dev, "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); - if (priv->use_dma_flag) - pch_free_dma(port); + pch_free_dma(port); free_irq(priv->port.irq, priv); } -- cgit From 93f3350c46fa5dfcc9650eb19b186e71ffc924c3 Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Wed, 9 Nov 2011 15:51:49 +0100 Subject: RS485: fix inconsistencies in the meaning of some variables The crisv10.c and the atmel_serial.c serial drivers intepret the fields of the serial_rs485 structure in a different way. In particular, crisv10.c uses SER_RS485_RTS_AFTER_SEND and SER_RS485_RTS_ON_SEND for the voltage of the RTS pin; atmel_serial.c, instead, uses these values to know if a delay must be set before and after sending. This patch makes the usage of these variables consistent across all drivers and fixes the Documentation as well. From now on, SER_RS485_RTS_AFTER_SEND and SER_RS485_RTS_ON_SEND will be used to set the voltage of the RTS pin (as in the crisv10.c driver); the delay will be understood by looking only at the value of delay_rts_before_send and delay_rts_after_send. Signed-off-by: Claudio Scordino Signed-off-by: Darron Black Acked-by: Jesper Nilsson Acked-by: Nicolas Ferre Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- Documentation/serial/serial-rs485.txt | 14 +++++++++++--- drivers/tty/serial/atmel_serial.c | 16 +++------------- drivers/tty/serial/crisv10.c | 10 ++-------- include/linux/serial.h | 14 ++++++++------ 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt index 079cb3df62cf..41c8378c0b2f 100644 --- a/Documentation/serial/serial-rs485.txt +++ b/Documentation/serial/serial-rs485.txt @@ -97,15 +97,23 @@ struct serial_rs485 rs485conf; - /* Set RS485 mode: */ + /* Enable RS485 mode: */ rs485conf.flags |= SER_RS485_ENABLED; + /* Set logical level for RTS pin equal to 1 when sending: */ + rs485conf.flags |= SER_RS485_RTS_ON_SEND; + /* or, set logical level for RTS pin equal to 0 when sending: */ + rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND); + + /* Set logical level for RTS pin equal to 1 after sending: */ + rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; + /* or, set logical level for RTS pin equal to 0 after sending: */ + rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND); + /* Set rts delay before send, if needed: */ - rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND; rs485conf.delay_rts_before_send = ...; /* Set rts delay after send, if needed: */ - rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; rs485conf.delay_rts_after_send = ...; /* Set this flag if you want to receive data even whilst sending data */ diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4a0f86fa1e90..4c823f341d98 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) if (rs485conf->flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; - if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) + if ((rs485conf->delay_rts_after_send) > 0) UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; } else { @@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) if (atmel_port->rs485.flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); - if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + if ((atmel_port->rs485.delay_rts_after_send) > 0) UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; @@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, if (atmel_port->rs485.flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); - if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + if ((atmel_port->rs485.delay_rts_after_send) > 0) UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; @@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, rs485conf->delay_rts_after_send = rs485_delay[1]; rs485conf->flags = 0; - if (rs485conf->delay_rts_before_send == 0 && - rs485conf->delay_rts_after_send == 0) { - rs485conf->flags |= SER_RS485_RTS_ON_SEND; - } else { - if (rs485conf->delay_rts_before_send) - rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; - if (rs485conf->delay_rts_after_send) - rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; - } - if (of_get_property(np, "rs485-rx-during-tx", NULL)) rs485conf->flags |= SER_RS485_RX_DURING_TX; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index b7435043f2fe..1dfba7b779c8 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty, e100_disable_rx(info); e100_enable_rx_irq(info); #endif - if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) && - (info->rs485.delay_rts_before_send > 0)) - msleep(info->rs485.delay_rts_before_send); + if (info->rs485.delay_rts_before_send > 0) + msleep(info->rs485.delay_rts_before_send); } #endif /* CONFIG_ETRAX_RS485 */ @@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty, rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send; rs485data.flags = 0; - if (rs485data.delay_rts_before_send != 0) - rs485data.flags |= SER_RS485_RTS_BEFORE_SEND; - else - rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND); if (rs485ctrl.enabled) rs485data.flags |= SER_RS485_ENABLED; @@ -4531,7 +4526,6 @@ static int __init rs_init(void) /* Set sane defaults */ info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND); info->rs485.flags |= SER_RS485_RTS_AFTER_SEND; - info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND); info->rs485.delay_rts_before_send = 0; info->rs485.flags &= ~(SER_RS485_ENABLED); #endif diff --git a/include/linux/serial.h b/include/linux/serial.h index 97ff8e27a6cc..3d86517fe7d5 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -207,13 +207,15 @@ struct serial_icounter_struct { struct serial_rs485 { __u32 flags; /* RS485 feature flags */ -#define SER_RS485_ENABLED (1 << 0) -#define SER_RS485_RTS_ON_SEND (1 << 1) -#define SER_RS485_RTS_AFTER_SEND (1 << 2) -#define SER_RS485_RTS_BEFORE_SEND (1 << 3) +#define SER_RS485_ENABLED (1 << 0) /* If enabled */ +#define SER_RS485_RTS_ON_SEND (1 << 1) /* Logical level for + RTS pin when + sending */ +#define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logical level for + RTS pin after sent*/ #define SER_RS485_RX_DURING_TX (1 << 4) - __u32 delay_rts_before_send; /* Milliseconds */ - __u32 delay_rts_after_send; /* Milliseconds */ + __u32 delay_rts_before_send; /* Delay before send (milliseconds) */ + __u32 delay_rts_after_send; /* Delay after send (milliseconds) */ __u32 padding[5]; /* Memory is cheap, new structs are a royal PITA .. */ }; -- cgit From db3e74b582915d66e10b0c73a62763418f54c340 Mon Sep 17 00:00:00 2001 From: Mitsuo Hayasaka Date: Thu, 10 Nov 2011 01:33:10 +0000 Subject: xfs: use doalloc flag in xfs_qm_dqattach_one() The doalloc arg in xfs_qm_dqattach_one() is a flag that indicates whether a new area to handle quota information will be allocated if needed. Originally, it was passed to xfs_qm_dqget(), but has been removed by the following commit (probably by mistake): commit 8e9b6e7fa4544ea8a0e030c8987b918509c8ff47 Author: Christoph Hellwig Date: Sun Feb 8 21:51:42 2009 +0100 xfs: remove the unused XFS_QMOPT_DQLOCK flag As the result, xfs_qm_dqget() called from xfs_qm_dqattach_one() never allocates the new area even if it is needed. This patch gives the doalloc arg to xfs_qm_dqget() in xfs_qm_dqattach_one() to fix this problem. Signed-off-by: Mitsuo Hayasaka Cc: Alex Elder Cc: Christoph Hellwig Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_qm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 5cff443f6cdb..0bbb1a41998b 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -674,7 +674,8 @@ xfs_qm_dqattach_one( * disk and we didn't ask it to allocate; * ESRCH if quotas got turned off suddenly. */ - error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp); + error = xfs_qm_dqget(ip->i_mount, ip, id, type, + doalloc | XFS_QMOPT_DOWARN, &dqp); if (error) return error; -- cgit From af8db1508f2c9f3b6e633e2d2d906c6557c617f9 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 15 Nov 2011 21:52:29 +0100 Subject: PM / driver core: disable device's runtime PM during shutdown There may be an issue when the user issue "reboot/shutdown" command, then the device has shut down its hardware, after that, this runtime-pm featured device's driver will probably be scheduled to do its suspend routine, and at its suspend routine, it may access hardware, but the device has already shutdown physically, then the system hang may be occurred. I ran out this issue using an auto-suspend supported USB devices, like 3G modem, keyboard. The usb runtime suspend routine may be scheduled after the usb controller has been shut down, and the usb runtime suspend routine will try to suspend its roothub(controller), it will access register, then the system hang occurs as the controller is shutdown. Signed-off-by: Peter Chen Acked-by: Ming Lei Acked-by: Greg Kroah-Hartman Cc: stable@kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/base/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 82c865452c70..d8b3d89db043 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -1742,6 +1743,8 @@ void device_shutdown(void) */ list_del_init(&dev->kobj.entry); spin_unlock(&devices_kset->list_lock); + /* Disable all device's runtime power management */ + pm_runtime_disable(dev); if (dev->bus && dev->bus->shutdown) { dev_dbg(dev, "shutdown\n"); -- cgit From e88d2468718b0789b4c33da2f7e1cef2a1eee279 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 15 Nov 2011 12:57:00 -0800 Subject: sparc: Stash orig_i0 into %g6 instead of %g2 As per the comments added by this commit, %g2 turns out to not be a usable place to save away orig_i0 for syscall restart handling. In fact all of %g2, %g3, %g4, and %g5 are assumed to be saved across a system call by various bits of code in glibc. %g1 can't be used because that holds the syscall number, which would need to be saved and restored for syscall restart handling too, and that would only compound our problems :-) This leaves us with %g6 and %g7 which are for "system use". %g7 is used as the "thread register" by glibc, but %g6 is used as a compiler and assembler temporary scratch register. And in no instance is %g6 used to hold a value across a system call. Therefore %g6 is safe for storing away orig_i0, at least for now. Signed-off-by: David S. Miller --- arch/sparc/kernel/signal32.c | 2 +- arch/sparc/kernel/signal_32.c | 20 +++++++++++++++----- arch/sparc/kernel/signal_64.c | 20 +++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 2e86fd1ddc7b..023b8860dc97 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -837,7 +837,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs) if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { restart_syscall = 1; - orig_i0 = regs->u_regs[UREG_G2]; + orig_i0 = regs->u_regs[UREG_G6]; } if (signr > 0) { diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 7dfaff64cd6b..d54c6e53aba0 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -523,12 +523,22 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) * register for GDB to save and restore in order to get * orig_i0 correct for syscall restarts when debugging. * - * However, we luckily can use the fact that several registers - * are volatile across system calls. One such register is - * %g2, so use that as a place to save away orig_i0. + * Although it should be the case that most of the global + * registers are volatile across a system call, glibc already + * depends upon that fact that we preserve them. So we can't + * just use any global register to save away the orig_i0 value. + * + * In particular %g2, %g3, %g4, and %g5 are all assumed to be + * preserved across a system call trap by various pieces of + * code in glibc. + * + * %g7 is used as the "thread register". %g6 is not used in + * any fixed manner. %g6 is used as a scratch register and + * a compiler temporary, but it's value is never used across + * a system call. Therefore %g6 is usable for orig_i0 storage. */ if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) - regs->u_regs[UREG_G2] = orig_i0; + regs->u_regs[UREG_G6] = orig_i0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; @@ -544,7 +554,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) restart_syscall = 0; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) { restart_syscall = 1; - orig_i0 = regs->u_regs[UREG_G2]; + orig_i0 = regs->u_regs[UREG_G6]; } diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 1ddf0dedb929..f0836cd0e2f2 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -533,13 +533,23 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) * register for GDB to save and restore in order to get * orig_i0 correct for syscall restarts when debugging. * - * However, we luckily can use the fact that several registers - * are volatile across system calls. One such register is - * %g2, so use that as a place to save away orig_i0. + * Although it should be the case that most of the global + * registers are volatile across a system call, glibc already + * depends upon that fact that we preserve them. So we can't + * just use any global register to save away the orig_i0 value. + * + * In particular %g2, %g3, %g4, and %g5 are all assumed to be + * preserved across a system call trap by various pieces of + * code in glibc. + * + * %g7 is used as the "thread register". %g6 is not used in + * any fixed manner. %g6 is used as a scratch register and + * a compiler temporary, but it's value is never used across + * a system call. Therefore %g6 is usable for orig_i0 storage. */ if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) - regs->u_regs[UREG_G2] = orig_i0; + regs->u_regs[UREG_G6] = orig_i0; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; @@ -560,7 +570,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { restart_syscall = 1; - orig_i0 = regs->u_regs[UREG_G2]; + orig_i0 = regs->u_regs[UREG_G6]; } if (signr > 0) { -- cgit From 3486140e30fcc16c0b8cd9545fbe5e2e66bf6941 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 15 Nov 2011 07:12:39 +0000 Subject: net-next:asix:PHY_MODE_RTL8211CL should be 0xC Use correct value for rtl phy support. (rtl phy are in AX88178 devices like NWU220G and USB2-ET1000). Signed-off-by: Allan Chou Tested-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e81e22e3d1d2..873860d46e9e 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -163,7 +163,7 @@ #define MARVELL_CTRL_TXDELAY 0x0002 #define MARVELL_CTRL_RXDELAY 0x0080 -#define PHY_MODE_RTL8211CL 0x0004 +#define PHY_MODE_RTL8211CL 0x000C /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ struct asix_data { -- cgit From a77929a278651d4451c872178d4d7aac8908aa8e Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 15 Nov 2011 07:12:40 +0000 Subject: net-next:asix:poll in asix_get_phyid in case phy not ready Sometimes the phy isn't ready after reset...poll and pray it will be soon. Signed-off-by: Freddy Xin Signed-off-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 873860d46e9e..b4675e89e42c 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -652,9 +652,17 @@ static u32 asix_get_phyid(struct usbnet *dev) { int phy_reg; u32 phy_id; + int i; - phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); - if (phy_reg < 0) + /* Poll for the rare case the FW or phy isn't ready yet. */ + for (i = 0; i < 100; i++) { + phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); + if (phy_reg != 0 && phy_reg != 0xFFFF) + break; + mdelay(1); + } + + if (phy_reg <= 0 || phy_reg == 0xFFFF) return 0; phy_id = (phy_reg & 0xffff) << 16; -- cgit From d3665188a79254c0698aa161e2c36dcda4e9ef55 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 15 Nov 2011 07:12:41 +0000 Subject: net-next:asix: reduce AX88772 init time by about 2 seconds ax88772_reset takes about 2 seconds and is called twice. Once from ax88772_bind() directly and again indirectly from usbnet_open(). Reset the USB FW/Phy enough to blink the LEDs when inserted. Signed-off-by: Allan Chou Signed-off-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index b4675e89e42c..8462be589558 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1083,7 +1083,7 @@ static const struct net_device_ops ax88772_netdev_ops = { static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) { - int ret; + int ret, embd_phy; struct asix_data *data = (struct asix_data *)&dev->data; u8 buf[ETH_ALEN]; u32 phyid; @@ -1108,16 +1108,36 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.reg_num_mask = 0x1f; dev->mii.phy_id = asix_get_phy_addr(dev); - phyid = asix_get_phyid(dev); - dbg("PHYID=0x%08x", phyid); - dev->net->netdev_ops = &ax88772_netdev_ops; dev->net->ethtool_ops = &ax88772_ethtool_ops; - ret = ax88772_reset(dev); + embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); + + /* Reset the PHY to normal operation mode */ + ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); + if (ret < 0) { + dbg("Select PHY #1 failed: %d", ret); + return ret; + } + + ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL); if (ret < 0) return ret; + msleep(150); + + ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); + if (ret < 0) + return ret; + + msleep(150); + + ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE); + + /* Read PHYID register *AFTER* the PHY was reset properly */ + phyid = asix_get_phyid(dev); + dbg("PHYID=0x%08x", phyid); + /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ if (dev->driver_info->flags & FLAG_FRAMING_AX) { /* hard_mtu is still the default - the device does not support -- cgit From b2d3ad291fab1783cc12eef3dd91c5fa98c2e5d5 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 15 Nov 2011 07:12:42 +0000 Subject: net-next:asix: V2 more fixes for ax88178 phy init sequence Now works on Samsung Series 5 (chromebook) Two fixes here: o use 0x7F mask for phymode o read phyid *AFTER* phy is powered up (via GPIOs) Signed-off-by: Allan Chou Signed-off-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 8462be589558..f870ab964e3a 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1248,6 +1248,7 @@ static int ax88178_reset(struct usbnet *dev) __le16 eeprom; u8 status; int gpio0 = 0; + u32 phyid; asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); dbg("GPIO Status: 0x%04x", status); @@ -1263,12 +1264,13 @@ static int ax88178_reset(struct usbnet *dev) data->ledmode = 0; gpio0 = 1; } else { - data->phymode = le16_to_cpu(eeprom) & 7; + data->phymode = le16_to_cpu(eeprom) & 0x7F; data->ledmode = le16_to_cpu(eeprom) >> 8; gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; } dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); + /* Power up external GigaPHY through AX88178 GPIO pin */ asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); if ((le16_to_cpu(eeprom) >> 8) != 1) { asix_write_gpio(dev, 0x003c, 30); @@ -1280,6 +1282,13 @@ static int ax88178_reset(struct usbnet *dev) asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); } + /* Read PHYID register *AFTER* powering up PHY */ + phyid = asix_get_phyid(dev); + dbg("PHYID=0x%08x", phyid); + + /* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */ + asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL); + asix_sw_reset(dev, 0); msleep(150); @@ -1424,7 +1433,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) { int ret; u8 buf[ETH_ALEN]; - u32 phyid; struct asix_data *data = (struct asix_data *)&dev->data; data->eeprom_len = AX88772_EEPROM_LEN; @@ -1451,12 +1459,12 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &ax88178_netdev_ops; dev->net->ethtool_ops = &ax88178_ethtool_ops; - phyid = asix_get_phyid(dev); - dbg("PHYID=0x%08x", phyid); + /* Blink LEDS so users know driver saw dongle */ + asix_sw_reset(dev, 0); + msleep(150); - ret = ax88178_reset(dev); - if (ret < 0) - return ret; + asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); + msleep(150); /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ if (dev->driver_info->flags & FLAG_FRAMING_AX) { -- cgit From 46993f02d88ae9fc6dfb4e8625d80a1630e7863b Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 15 Nov 2011 07:12:43 +0000 Subject: net-next:asix: V2 Update VERSION Only update VERSION to reflect previous changes. Signed-off-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index f870ab964e3a..e6fed4d4cb77 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -36,7 +36,7 @@ #include #include -#define DRIVER_VERSION "26-Sep-2011" +#define DRIVER_VERSION "08-Nov-2011" #define DRIVER_NAME "asix" /* ASIX AX8817X based USB 2.0 Ethernet Devices */ -- cgit From 6edf0c9b1c26d047370cf2f35ff6bb3082243ec3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 15 Nov 2011 16:01:09 -0800 Subject: Revert "tty/serial: Prevent drop of DCD on suspend for Tegra UARTs" This reverts commit 9636b755da7b498094bdf15b4ce9f6fd16995e4e. It wasn't supposed to be applied, thanks to Doug for letting me know. Cc: Doug Anderson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250.c | 14 -------------- drivers/tty/serial/8250.h | 2 -- 2 files changed, 16 deletions(-) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 2b0a4b63c5f7..eeadf1b8e093 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -308,8 +308,6 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01, .flags = UART_CAP_FIFO | UART_CAP_RTOIE, - .mcr_mask = ~UART_MCR_DTR, - .mcr_force = UART_MCR_DTR, }, [PORT_XR17D15X] = { .name = "XR17D15X", @@ -1231,10 +1229,6 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) up->port.fifosize = uart_config[up->port.type].fifo_size; up->capabilities = uart_config[up->port.type].flags; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; - if (!ALPHA_KLUDGE_MCR) { - up->mcr_mask = uart_config[up->port.type].mcr_mask; - up->mcr_force = uart_config[up->port.type].mcr_force; - } if (up->port.type == PORT_UNKNOWN) goto out; @@ -1993,10 +1987,6 @@ static int serial8250_startup(struct uart_port *port) up->port.fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; - if (!ALPHA_KLUDGE_MCR) { - up->mcr_mask = uart_config[up->port.type].mcr_mask; - up->mcr_force = uart_config[up->port.type].mcr_force; - } up->mcr = 0; if (up->port.iotype != up->cur_iotype) @@ -2803,10 +2793,6 @@ serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type) up->port.fifosize = uart_config[type].fifo_size; up->capabilities = uart_config[type].flags; up->tx_loadsz = uart_config[type].tx_loadsz; - if (!ALPHA_KLUDGE_MCR) { - up->mcr_mask = uart_config[type].mcr_mask; - up->mcr_force = uart_config[type].mcr_force; - } } static void __init diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index 1f7510051707..6edf4a6a22d4 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h @@ -35,8 +35,6 @@ struct serial8250_config { unsigned short tx_loadsz; unsigned char fcr; unsigned int flags; - unsigned char mcr_mask; - unsigned char mcr_force; }; #define UART_CAP_FIFO (1 << 8) /* UART has FIFO */ -- cgit From 9f35a33b8d06263a165efe3541d9aa0cdbd70b3b Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 15 Nov 2011 22:09:45 +0000 Subject: KEYS: Fix a NULL pointer deref in the user-defined key type Fix a NULL pointer deref in the user-defined key type whereby updating a negative key into a fully instantiated key will cause an oops to occur when the code attempts to free the non-existent old payload. This results in an oops that looks something like the following: BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] __call_rcu+0x11/0x13e PGD 3391d067 PUD 3894a067 PMD 0 Oops: 0002 [#1] SMP CPU 1 Pid: 4354, comm: keyctl Not tainted 3.1.0-fsdevel+ #1140 /DG965RY RIP: 0010:[] [] __call_rcu+0x11/0x13e RSP: 0018:ffff88003d591df8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000000000006e RDX: ffffffff8161d0c0 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88003d591e18 R08: 0000000000000000 R09: ffffffff8152fa6c R10: 0000000000000000 R11: 0000000000000300 R12: ffff88003b8f9538 R13: ffffffff8161d0c0 R14: ffff88003b8f9d50 R15: ffff88003c69f908 FS: 00007f97eb18c720(0000) GS:ffff88003bd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 000000003d47a000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process keyctl (pid: 4354, threadinfo ffff88003d590000, task ffff88003c78a040) Stack: ffff88003e0ffde0 ffff88003b8f9538 0000000000000001 ffff88003b8f9d50 ffff88003d591e28 ffffffff810860f0 ffff88003d591e68 ffffffff8117bfea ffff88003d591e68 ffffffff00000000 ffff88003e0ffde1 ffff88003e0ffde0 Call Trace: [] call_rcu_sched+0x10/0x12 [] user_update+0x8d/0xa2 [] key_create_or_update+0x236/0x270 [] sys_add_key+0x123/0x17e [] system_call_fastpath+0x16/0x1b Signed-off-by: David Howells Acked-by: Jeff Layton Acked-by: Neil Horman Acked-by: Steve Dickson Acked-by: James Morris Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- security/keys/user_defined.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 5b366d7af3c4..69ff52c08e97 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -102,7 +102,8 @@ int user_update(struct key *key, const void *data, size_t datalen) key->expiry = 0; } - kfree_rcu(zap, rcu); + if (zap) + kfree_rcu(zap, rcu); error: return ret; -- cgit From cb871513f656bdfc48b185b55f37857b5c750c40 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 15 Nov 2011 14:35:52 -0800 Subject: Revert "leds: save the delay values after a successful call to blink_set()" Revert commit 6123b0e274503a0d3588e84fbe07c9aa01bfaf5d. The problem this patch intends to solve has alreadqy been fixed by commit 7a5caabd090b ("drivers/leds/ledtrig-timer.c: fix broken sysfs delay handling"). Signed-off-by: Johan Hovold Cc: Antonio Ospite Cc: Johannes Berg Cc: Richard Purdie Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/led-class.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 661b692573e7..6d5628bb0601 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -270,11 +270,8 @@ void led_blink_set(struct led_classdev *led_cdev, del_timer_sync(&led_cdev->blink_timer); if (led_cdev->blink_set && - !led_cdev->blink_set(led_cdev, delay_on, delay_off)) { - led_cdev->blink_delay_on = *delay_on; - led_cdev->blink_delay_off = *delay_off; + !led_cdev->blink_set(led_cdev, delay_on, delay_off)) return; - } /* blink with 1 Hz as default if nothing specified */ if (!*delay_on && !*delay_off) -- cgit From 12340313cf940e61beb52b996a5845ffa290626d Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 15 Nov 2011 14:35:59 -0800 Subject: MAINTAINERS: add new cgroup list to CC notice As discussed at Kernel Summit(2011), new cgroups mailing list is opened by James. This list is for discussing general cgroup design and patches including all subsystems and for getting more attentions to cgroups/namespaces related issues by developpers. Signed-off-by: KAMEZAWA Hiroyuki Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 071a99674347..aca136b84508 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1930,6 +1930,7 @@ CONTROL GROUPS (CGROUPS) M: Paul Menage M: Li Zefan L: containers@lists.linux-foundation.org +L: cgroups@vger.kernel.org S: Maintained F: include/linux/cgroup* F: kernel/cgroup* @@ -4304,6 +4305,7 @@ MEMORY RESOURCE CONTROLLER M: Balbir Singh M: Daisuke Nishimura M: KAMEZAWA Hiroyuki +L: cgroups@vger.kernel.org L: linux-mm@kvack.org S: Maintained F: mm/memcontrol.c -- cgit From 001ef5e4554b851cf50fe03bc4c266c28ed8e62d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 15 Nov 2011 14:36:02 -0800 Subject: drivers/misc/eeprom: fix dependecy on 'PPC_MPC5200_GPIO' The driver for the DigsyMTC display configuration EEPROMs device got added by commit 469dded183 ("misc/eeprom: add eeprom access driver for digsy_mtc board"). Its Kconfig symbol depends on PPC_MPC5200_GPIO. But at the time that driver got added PPC_MPC5200_GPIO was already renamed to GPIO_MPC5200, by commit 6eae1ace68 ("gpio: Move mpc5200 gpio driver to drivers/gpio"). So make this driver depend on GPIO_MPC5200. And since GPIO_MPC5200 itself implies that GPIOLIB is set, that dependency can be dropped. Signed-off-by: Paul Bolle Acked-by: Anatolij Gustschin Cc: Grant Likely Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/eeprom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 26cf12ca7f50..701edf658970 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig @@ -85,7 +85,7 @@ config EEPROM_93XX46 config EEPROM_DIGSY_MTC_CFG bool "DigsyMTC display configuration EEPROMs device" - depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO + depends on GPIO_MPC5200 && SPI_GPIO help This option enables access to display configuration EEPROMs on digsy_mtc board. You have to additionally select Microwire -- cgit From 5aecc85abdb9ac2b0e6548d13652a34142e7ae89 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 15 Nov 2011 14:36:07 -0800 Subject: oom: do not kill tasks with oom_score_adj OOM_SCORE_ADJ_MIN Commit c9f01245 ("oom: remove oom_disable_count") has removed the oom_disable_count counter which has been used for early break out from oom_badness so we could never select a task with oom_score_adj set to OOM_SCORE_ADJ_MIN (oom disabled). Now that the counter is gone we are always going through heuristics calculation and we always return a non zero positive value. This means that we can end up killing a task with OOM disabled because it is indistinguishable from regular tasks with 1% resp. CAP_SYS_ADMIN tasks with 3% usage of memory or tasks with oom_score_adj set but OOM enabled. Let's break out early if the task should have OOM disabled. Signed-off-by: Michal Hocko Acked-by: David Rientjes Acked-by: KOSAKI Motohiro Cc: Oleg Nesterov Cc: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 471dedb463ab..76f2c5ae908e 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -185,6 +185,11 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, if (!p) return 0; + if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { + task_unlock(p); + return 0; + } + /* * The memory controller may have a limit of 0 bytes, so avoid a divide * by zero, if necessary. -- cgit From 66e13e66b6c4e5b2ecd6225e1f8437640cfb6498 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 15 Nov 2011 14:36:09 -0800 Subject: drivers/firmware/dmi_scan.c: make dmi_name_in_vendors more focused The current implementation of dmi_name_in_vendors() is an invitation to lazy coding and false positives [1]. Searching for a string in 8 know what you're looking for, so you should know where to look. strstr isn't fast, especially when it fails, so we should avoid calling it when it just can't succeed. Looking at the current users of the function, it seems clear to me that they are looking for a system or board vendor name, so let's limit dmi_name_in_vendors to these two DMI fields. This much better matches the function name, BTW. [1] We currently have code looking for short names in DMI data, such as "IBM", "ASUS" or "Acer". I let you guess what will happen the day other vendors ship products named, for example, "SCHREIBMEISTER", "PEGASUS" or "Acerola". Signed-off-by: Jean Delvare Cc: Andi Kleen Cc: Jesse Barnes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dmi_scan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index bcb1126e3d00..153980be4ee6 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -585,14 +585,12 @@ int dmi_name_in_serial(const char *str) } /** - * dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information. + * dmi_name_in_vendors - Check if string is in the DMI system or board vendor name * @str: Case sensitive Name */ int dmi_name_in_vendors(const char *str) { - static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR, - DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR, - DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE }; + static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE }; int i; for (i = 0; fields[i] != DMI_NONE; i++) { int f = fields[i]; -- cgit From ea4039a34c4c206d015d34a49d0b00868e37db1d Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 15 Nov 2011 14:36:12 -0800 Subject: hugetlb: release pages in the error path of hugetlb_cow() If we fail to prepare an anon_vma, the {new, old}_page should be released, or they will leak. Signed-off-by: Hillf Danton Reviewed-by: Andrea Arcangeli Cc: Hugh Dickins Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index dae27ba3be2c..bb28a5f9db8d 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2422,6 +2422,8 @@ retry_avoidcopy: * anon_vma prepared. */ if (unlikely(anon_vma_prepare(vma))) { + page_cache_release(new_page); + page_cache_release(old_page); /* Caller expects lock to be held */ spin_lock(&mm->page_table_lock); return VM_FAULT_OOM; -- cgit From 8889023a4ab5f32325b568e7626fd2233cf64fa5 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Nov 2011 01:43:23 +0100 Subject: unicore32: Fix typo 'PUV3_I2C' Signed-off-by: Paul Bolle Acked-by: Guan Xuetao --- arch/unicore32/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index e57dcce9bfda..942ed6174f1d 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -237,13 +237,13 @@ menu "PKUnity NetBook-0916 Features" config I2C_BATTERY_BQ27200 tristate "I2C Battery BQ27200 Support" - select PUV3_I2C + select I2C_PUV3 select POWER_SUPPLY select BATTERY_BQ27x00 config I2C_EEPROM_AT24 tristate "I2C EEPROMs AT24 support" - select PUV3_I2C + select I2C_PUV3 select MISC_DEVICES select EEPROM_AT24 -- cgit From ed96dfbcfea92233d27db9d3c77fc91a58c959bf Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 15 Nov 2011 14:54:51 -0800 Subject: unicore32, exec: remove redundant set_fs(USER_DS) The address limit is already set in flush_old_exec() so this set_fs(USER_DS) is redundant. Signed-off-by: Mathias Krause Cc: Guan Xuetao Signed-off-by: Andrew Morton Acked-by: Guan Xuetao --- arch/unicore32/include/asm/processor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h index e11cb0786578..f0d780a51f9b 100644 --- a/arch/unicore32/include/asm/processor.h +++ b/arch/unicore32/include/asm/processor.h @@ -53,7 +53,6 @@ struct thread_struct { #define start_thread(regs, pc, sp) \ ({ \ unsigned long *stack = (unsigned long *)sp; \ - set_fs(USER_DS); \ memset(regs->uregs, 0, sizeof(regs->uregs)); \ regs->UCreg_asr = USER_MODE; \ regs->UCreg_pc = pc & ~1; /* pc */ \ -- cgit From 9c8b39077b0a5b0990bb707fcd7b5913d7b322b8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 8 Nov 2011 19:56:05 -0500 Subject: powerpc: Fix build breakage in jump_label.c Should do what other architectures do and wrap all that code into the appropriate ifdef Signed-off-by: Al Viro Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/jump_label.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c index 368d158d665d..a1ed8a8c7cb4 100644 --- a/arch/powerpc/kernel/jump_label.c +++ b/arch/powerpc/kernel/jump_label.c @@ -11,6 +11,7 @@ #include #include +#ifdef HAVE_JUMP_LABEL void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) { @@ -21,3 +22,4 @@ void arch_jump_label_transform(struct jump_entry *entry, else patch_instruction(addr, PPC_INST_NOP); } +#endif -- cgit From 4933402075d4f38a82c491a4afca6ca7661aa0a8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 8 Nov 2011 19:57:05 -0500 Subject: carma-fpga: Missed switch from of_register_platform_driver() ... by 6 months Signed-off-by: Al Viro Signed-off-by: Benjamin Herrenschmidt --- drivers/misc/carma/carma-fpga-program.c | 9 ++++----- drivers/misc/carma/carma-fpga.c | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index 7ce6065dc20e..eb5cd28bc6d8 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c @@ -945,8 +945,7 @@ static int fpga_of_remove(struct platform_device *op) /* CTL-CPLD Version Register */ #define CTL_CPLD_VERSION 0x2000 -static int fpga_of_probe(struct platform_device *op, - const struct of_device_id *match) +static int fpga_of_probe(struct platform_device *op) { struct device_node *of_node = op->dev.of_node; struct device *this_device; @@ -1107,7 +1106,7 @@ static struct of_device_id fpga_of_match[] = { {}, }; -static struct of_platform_driver fpga_of_driver = { +static struct platform_driver fpga_of_driver = { .probe = fpga_of_probe, .remove = fpga_of_remove, .driver = { @@ -1124,12 +1123,12 @@ static struct of_platform_driver fpga_of_driver = { static int __init fpga_init(void) { led_trigger_register_simple("fpga", &ledtrig_fpga); - return of_register_platform_driver(&fpga_of_driver); + return platform_driver_register(&fpga_of_driver); } static void __exit fpga_exit(void) { - of_unregister_platform_driver(&fpga_of_driver); + platform_driver_unregister(&fpga_of_driver); led_trigger_unregister_simple(ledtrig_fpga); } diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 3965821fef17..14e974b2a781 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c @@ -1249,8 +1249,7 @@ static bool dma_filter(struct dma_chan *chan, void *data) return true; } -static int data_of_probe(struct platform_device *op, - const struct of_device_id *match) +static int data_of_probe(struct platform_device *op) { struct device_node *of_node = op->dev.of_node; struct device *this_device; @@ -1401,7 +1400,7 @@ static struct of_device_id data_of_match[] = { {}, }; -static struct of_platform_driver data_of_driver = { +static struct platform_driver data_of_driver = { .probe = data_of_probe, .remove = data_of_remove, .driver = { @@ -1417,12 +1416,12 @@ static struct of_platform_driver data_of_driver = { static int __init data_init(void) { - return of_register_platform_driver(&data_of_driver); + return platform_driver_register(&data_of_driver); } static void __exit data_exit(void) { - of_unregister_platform_driver(&data_of_driver); + platform_driver_unregister(&data_of_driver); } MODULE_AUTHOR("Ira W. Snyder "); -- cgit From 5f861ed40200c5c61b698f8d795349112579bcdb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 8 Nov 2011 19:58:17 -0500 Subject: powerpc/fsl_udc_core: Fix dumb typo Signed-off-by: Al Viro Signed-off-by: Benjamin Herrenschmidt --- drivers/usb/gadget/fsl_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b2c44e1d5813..d786ba31fc07 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1717,7 +1717,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) static inline enum usb_device_speed portscx_device_speed(u32 reg) { - switch (speed & PORTSCX_PORT_SPEED_MASK) { + switch (reg & PORTSCX_PORT_SPEED_MASK) { case PORTSCX_PORT_SPEED_HIGH: return USB_SPEED_HIGH; case PORTSCX_PORT_SPEED_FULL: -- cgit From 82640a6b9166c993104e255b414298cbec6ecd45 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 8 Nov 2011 21:10:29 -0500 Subject: powerpc/fsl: MCU_MPC8349EMITX wants I2C built-in, modular won't do... Signed-off-by: Al Viro Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index e4588721ef34..3fe6d927ad70 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -347,7 +347,7 @@ config SIMPLE_GPIO config MCU_MPC8349EMITX bool "MPC8349E-mITX MCU driver" - depends on I2C && PPC_83xx + depends on I2C=y && PPC_83xx select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help -- cgit From bbc24a25e29136a56cf5015ef23eb2c2e8828023 Mon Sep 17 00:00:00 2001 From: Suzuki Poulose Date: Mon, 14 Nov 2011 16:43:50 +0000 Subject: powerpc/4xx: Fix typos in kexec config dependencies Kexec is not supported on 47x. 47x is a variant of 44x with slightly different MMU and SMP support. There was a typo in the config dependency for kexec. This patch fixes the same. Signed-off-by: Suzuki K. Poulose Signed-off-by: Paul Bolle Cc: Kumar Gala Cc: Josh Boyer Cc: linux ppc dev Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/misc_32.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b177caa56d95..951e18f5335b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !47x)) && EXPERIMENTAL + depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index f7d760ab5ca1..7cd07b42ca1a 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -738,7 +738,7 @@ relocate_new_kernel: mr r5, r31 li r0, 0 -#elif defined(CONFIG_44x) && !defined(CONFIG_47x) +#elif defined(CONFIG_44x) && !defined(CONFIG_PPC_47x) /* * Code for setting up 1:1 mapping for PPC440x for KEXEC -- cgit From 6d1e2c6c1a0b800473db4df8595c95745be548ea Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 14 Nov 2011 12:55:47 +0000 Subject: powerpc: panic if we can't instantiate RTAS I had to debug a strange situation where all manner of things were failing. SMT threads, storage and network were all completely broken. The root cause was we couldn't find enough memory to instantiate RTAS - this was a network install so the initrd was huge. Instead of limping along and failing in mysterious ways we should just panic up front if RTAS exists and we can't allocate space for it. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/prom_init.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index b4fa66127495..cc584865b3df 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1579,10 +1579,8 @@ static void __init prom_instantiate_rtas(void) return; base = alloc_down(size, PAGE_SIZE, 0); - if (base == 0) { - prom_printf("RTAS allocation failed !\n"); - return; - } + if (base == 0) + prom_panic("Could not allocate memory for RTAS\n"); rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); if (!IHANDLE_VALID(rtas_inst)) { -- cgit From d715e433b7ad19c02fc4becf0d5e9a59f97925de Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 14 Nov 2011 12:54:47 +0000 Subject: powerpc: Copy down exception vectors after feature fixups kdump fails because we try to execute an HV only instruction. Feature fixups are being applied after we copy the exception vectors down to 0 so they miss out on any updates. We have always had this issue but it only became critical in v3.0 when we added CFAR support (breaks POWER5) and v3.1 when we added POWERNV (breaks everyone). Signed-off-by: Anton Blanchard Cc: [v3.0+] Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/sections.h | 2 +- arch/powerpc/include/asm/synch.h | 1 + arch/powerpc/kernel/kvm.c | 1 - arch/powerpc/kernel/setup_32.c | 2 ++ arch/powerpc/kernel/setup_64.c | 1 + arch/powerpc/lib/feature-fixups.c | 23 +++++++++++++++++++++++ 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 6fbce725c710..a0f358d4a00c 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -8,7 +8,7 @@ #ifdef __powerpc64__ -extern char _end[]; +extern char __end_interrupts[]; static inline int in_kernel_text(unsigned long addr) { diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/asm/synch.h index d7cab44643c5..87878c68d1c2 100644 --- a/arch/powerpc/include/asm/synch.h +++ b/arch/powerpc/include/asm/synch.h @@ -13,6 +13,7 @@ extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup; extern void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end); +extern void do_final_fixups(void); static inline void eieio(void) { diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 35f27646c4ff..2985338d0e10 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c @@ -132,7 +132,6 @@ static void kvm_patch_ins_b(u32 *inst, int addr) /* On relocatable kernels interrupts handlers and our code can be in different regions, so we don't patch them */ - extern u32 __end_interrupts; if ((ulong)inst < (ulong)&__end_interrupts) return; #endif diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index c1ce86357ecb..ac7610815113 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -107,6 +107,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr) PTRRELOC(&__start___lwsync_fixup), PTRRELOC(&__stop___lwsync_fixup)); + do_final_fixups(); + return KERNELBASE + offset; } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 1a9dea80a69b..fb9bb46e7e88 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -359,6 +359,7 @@ void __init setup_system(void) &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); do_lwsync_fixups(cur_cpu_spec->cpu_features, &__start___lwsync_fixup, &__stop___lwsync_fixup); + do_final_fixups(); /* * Unflatten the device-tree passed by prom_init or kexec diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index 0d08d0171392..7a8a7487cee8 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include struct fixup_entry { @@ -128,6 +130,27 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) } } +void do_final_fixups(void) +{ +#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE) + int *src, *dest; + unsigned long length; + + if (PHYSICAL_START == 0) + return; + + src = (int *)(KERNELBASE + PHYSICAL_START); + dest = (int *)KERNELBASE; + length = (__end_interrupts - _stext) / sizeof(int); + + while (length--) { + patch_instruction(dest, *src); + src++; + dest++; + } +#endif +} + #ifdef CONFIG_FTR_FIXUP_SELFTEST #define check(x) \ -- cgit From 2cd76629f6c40f7b227ba7b3885ce10e6ec0face Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Thu, 10 Nov 2011 16:04:17 +0000 Subject: powerpc/trace: Add a dummy stack frame for trace_hardirqs_off The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1. If an exception occurs in user mode, there is only one stack frame on the stack and accessing the CALLER_ADDR1 will causes the following call trace. So we create a dummy stack frame to make trace_hardirqs_off happy. WARNING: at kernel/smp.c:459 Modules linked in: NIP: c0093280 LR: c00930a0 CTR: c0010780 REGS: edb87ae0 TRAP: 0700 Not tainted (3.1.0) MSR: 00021002 CR: 28002888 XER: 00000000 TASK = edce2ac0[17658] 'mthread-lock-on' THREAD: edb86000 CPU: 5 GPR00: 00000001 edb87b90 edce2ac0 00000005 c0019594 edb87bd8 00000001 00000fe3 GPR08: 00041000 c084138c 4e20120d edb87b90 48002888 1001aa7c 00000000 00000000 GPR16: 48830000 10012a8c 00000000 10000af4 00000001 c0810000 00000000 00000000 GPR24: ee9aa920 c0816a18 00000000 00000005 c0019594 edb87bd8 ee20178c edb87b90 NIP [c0093280] smp_call_function_many+0x214/0x2b4 LR [c00930a0] smp_call_function_many+0x34/0x2b4 Call Trace: [edb87b90] [c00930a0] smp_call_function_many+0x34/0x2b4 (unreliable) [edb87bd0] [c00194ec] __flush_tlb_page+0xac/0x100 [edb87c00] [c001957c] flush_tlb_page+0x3c/0x54 [edb87c10] [c00180ac] ptep_set_access_flags+0x74/0x12c [edb87c40] [c0128068] handle_pte_fault+0x2f0/0x9ac [edb87cb0] [c0128c3c] handle_mm_fault+0x104/0x1dc [edb87ce0] [c05f40f4] do_page_fault+0x2dc/0x630 [edb87e50] [c001078c] handle_page_fault+0xc/0x80 Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/entry_32.S | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 56212bc0ab08..4f80cf1ce77b 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -215,7 +215,22 @@ reenable_mmu: /* re-enable mmu so we can */ stw r9,8(r1) stw r11,12(r1) stw r3,ORIG_GPR3(r1) + /* + * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1. + * If from user mode there is only one stack frame on the stack, and + * accessing CALLER_ADDR1 will cause oops. So we need create a dummy + * stack frame to make trace_hardirqs_off happy. + */ + andi. r12,r12,MSR_PR + beq 11f + stwu r1,-16(r1) + bl trace_hardirqs_off + addi r1,r1,16 + b 12f + +11: bl trace_hardirqs_off +12: lwz r0,GPR0(r1) lwz r3,ORIG_GPR3(r1) lwz r4,GPR4(r1) -- cgit From de1d9248eadd27539eba449b4d09428252e80c04 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 9 Nov 2011 20:39:49 +0000 Subject: powerpc: Add hvcall.h include to book3s_hv.c If you build with KVM and UP it fails with the following due to a missing include. /arch/powerpc/kvm/book3s_hv.c: In function 'do_h_register_vpa': arch/powerpc/kvm/book3s_hv.c:156:10: error: 'H_PARAMETER' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:156:10: note: each undeclared identifier is reported only once for each function it appears in arch/powerpc/kvm/book3s_hv.c:192:12: error: 'H_RESOURCE' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:222:9: error: 'H_SUCCESS' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c: In function 'kvmppc_pseries_do_hcall': arch/powerpc/kvm/book3s_hv.c:228:30: error: 'H_SUCCESS' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:232:7: error: 'H_CEDE' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:234:7: error: 'H_PROD' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:238:10: error: 'H_PARAMETER' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:250:7: error: 'H_CONFER' undeclared (first use in this function) arch/powerpc/kvm/book3s_hv.c:252:7: error: 'H_REGISTER_VPA' undeclared (first use in this function) make[2]: *** [arch/powerpc/kvm/book3s_hv.o] Error 1 Signed-off-by: Michael Neuling cc: stable@kernel.org (3.1 only) Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kvm/book3s_hv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 0cdbc07cec14..0cb137a9b038 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include -- cgit From 72f3bea075287785ed32b777b6dd2636aa7002e8 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 8 Nov 2011 12:37:26 +0000 Subject: powerpc/ps3: Fix lost SMP IPIs Fixes the PS3 bootup hang introduced in 3.0-rc1 by: commit 317f394160e9beb97d19a84c39b7e5eb3d7815a sched: Move the second half of ttwu() to the remote cpu Move the PS3's LV1 EOI call lv1_end_of_interrupt_ext() from ps3_chip_eoi() to ps3_get_irq() for IPI messages. If lv1_send_event_locally() is called between a previous call to lv1_send_event_locally() and the coresponding call to lv1_end_of_interrupt_ext() the second event will not be delivered to the target cpu. The PS3's SMP IPIs are implemented using lv1_send_event_locally(), so if two IPI messages of the same type are sent to the same target in a relatively short period of time the second IPI event can become lost when lv1_end_of_interrupt_ext() is called from ps3_chip_eoi(). CC: stable@kernel.org Signed-off-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/ps3/interrupt.c | 23 ++++++++++++++++++++++- arch/powerpc/platforms/ps3/platform.h | 1 + arch/powerpc/platforms/ps3/smp.c | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 404bc52b7806..1d6f4f478fe2 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -88,6 +88,7 @@ struct ps3_private { struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); u64 ppe_id; u64 thread_id; + unsigned long ipi_mask; }; static DEFINE_PER_CPU(struct ps3_private, ps3_private); @@ -144,7 +145,11 @@ static void ps3_chip_unmask(struct irq_data *d) static void ps3_chip_eoi(struct irq_data *d) { const struct ps3_private *pd = irq_data_get_irq_chip_data(d); - lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq); + + /* non-IPIs are EOIed here. */ + + if (!test_bit(63 - d->irq, &pd->ipi_mask)) + lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq); } /** @@ -691,6 +696,16 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) cpu, virq, pd->bmp.ipi_debug_brk_mask); } +void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq) +{ + struct ps3_private *pd = &per_cpu(ps3_private, cpu); + + set_bit(63 - virq, &pd->ipi_mask); + + DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__, + cpu, virq, pd->ipi_mask); +} + static unsigned int ps3_get_irq(void) { struct ps3_private *pd = &__get_cpu_var(ps3_private); @@ -720,6 +735,12 @@ static unsigned int ps3_get_irq(void) BUG(); } #endif + + /* IPIs are EOIed here. */ + + if (test_bit(63 - plug, &pd->ipi_mask)) + lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug); + return plug; } diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 9a196a88eda7..1a633ed0fe98 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h @@ -43,6 +43,7 @@ void ps3_mm_shutdown(void); void ps3_init_IRQ(void); void ps3_shutdown_IRQ(int cpu); void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); +void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq); /* smp */ diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 4c44794faac0..f609345b6c3a 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -94,6 +94,8 @@ static void __init ps3_smp_setup_cpu(int cpu) if (result) virqs[i] = NO_IRQ; + else + ps3_register_ipi_irq(cpu, virqs[i]); } ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); -- cgit From 7eaf09eefe5b98a530bc5f7b317b9aba1628cf61 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 8 Nov 2011 12:38:21 +0000 Subject: powerpc/ps3: Fix SMP lockdep boot warning Move the PS3 IPI message setup from ps3_smp_setup_cpu() to ps3_smp_probe(). Fixes startup warnings like these: ------------[ cut here ]------------ WARNING: at kernel/lockdep.c:2649 Modules linked in: ... ---[ end trace 31fd0ba7d8756001 ]--- Signed-off-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/ps3/smp.c | 64 ++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index f609345b6c3a..efc1cd8c034a 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -59,48 +59,49 @@ static void ps3_smp_message_pass(int cpu, int msg) static int ps3_smp_probe(void) { - return 2; -} + int cpu; -static void __init ps3_smp_setup_cpu(int cpu) -{ - int result; - unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); - int i; + for (cpu = 0; cpu < 2; cpu++) { + int result; + unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); + int i; - DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); - /* - * Check assumptions on ps3_ipi_virqs[] indexing. If this - * check fails, then a different mapping of PPC_MSG_ - * to index needs to be setup. - */ + /* + * Check assumptions on ps3_ipi_virqs[] indexing. If this + * check fails, then a different mapping of PPC_MSG_ + * to index needs to be setup. + */ - BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); - BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); - BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2); - BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); + BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); + BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); + BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2); + BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); - for (i = 0; i < MSG_COUNT; i++) { - result = ps3_event_receive_port_setup(cpu, &virqs[i]); + for (i = 0; i < MSG_COUNT; i++) { + result = ps3_event_receive_port_setup(cpu, &virqs[i]); - if (result) - continue; + if (result) + continue; - DBG("%s:%d: (%d, %d) => virq %u\n", - __func__, __LINE__, cpu, i, virqs[i]); + DBG("%s:%d: (%d, %d) => virq %u\n", + __func__, __LINE__, cpu, i, virqs[i]); - result = smp_request_message_ipi(virqs[i], i); + result = smp_request_message_ipi(virqs[i], i); - if (result) - virqs[i] = NO_IRQ; - else - ps3_register_ipi_irq(cpu, virqs[i]); - } + if (result) + virqs[i] = NO_IRQ; + else + ps3_register_ipi_irq(cpu, virqs[i]); + } - ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); + ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); - DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); + DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); + } + + return 2; } void ps3_smp_cleanup_cpu(int cpu) @@ -123,7 +124,6 @@ static struct smp_ops_t ps3_smp_ops = { .probe = ps3_smp_probe, .message_pass = ps3_smp_message_pass, .kick_cpu = smp_generic_kick_cpu, - .setup_cpu = ps3_smp_setup_cpu, }; void smp_init_ps3(void) -- cgit From 4dcfe1025b513c2c1da5bf5586adb0e80148f612 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 10 Nov 2011 13:01:10 +0100 Subject: sched: Avoid SMT siblings in select_idle_sibling() if possible Avoid select_idle_sibling() from picking a sibling thread if there's an idle core that shares cache. This fixes SMT balancing in the increasingly common case where there's a shared cache core available to balance to. Tested-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: Suresh Siddha Link: http://lkml.kernel.org/r/1321350377.1421.55.camel@twins Signed-off-by: Ingo Molnar --- kernel/sched_fair.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 7e51b5bb27cc..ba0e1f49a22f 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2326,7 +2326,8 @@ static int select_idle_sibling(struct task_struct *p, int target) int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); struct sched_domain *sd; - int i; + struct sched_group *sg; + int i, smt = 0; /* * If the task is going to be woken-up on this cpu and if it is @@ -2346,25 +2347,38 @@ static int select_idle_sibling(struct task_struct *p, int target) * Otherwise, iterate the domains and find an elegible idle cpu. */ rcu_read_lock(); +again: for_each_domain(target, sd) { - if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) - break; + if (!smt && (sd->flags & SD_SHARE_CPUPOWER)) + continue; - for_each_cpu_and(i, sched_domain_span(sd), tsk_cpus_allowed(p)) { - if (idle_cpu(i)) { - target = i; - break; + if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) { + if (!smt) { + smt = 1; + goto again; } + break; } - /* - * Lets stop looking for an idle sibling when we reached - * the domain that spans the current cpu and prev_cpu. - */ - if (cpumask_test_cpu(cpu, sched_domain_span(sd)) && - cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) - break; + sg = sd->groups; + do { + if (!cpumask_intersects(sched_group_cpus(sg), + tsk_cpus_allowed(p))) + goto next; + + for_each_cpu(i, sched_group_cpus(sg)) { + if (!idle_cpu(i)) + goto next; + } + + target = cpumask_first_and(sched_group_cpus(sg), + tsk_cpus_allowed(p)); + goto done; +next: + sg = sg->next; + } while (sg != sd->groups); } +done: rcu_read_unlock(); return target; -- cgit From fccfdc6f0d8c83c854eeb6d93aa158f0e551bd49 Mon Sep 17 00:00:00 2001 From: Paul Turner Date: Mon, 7 Nov 2011 20:26:34 -0800 Subject: sched: Fix buglet in return_cfs_rq_runtime() In return_cfs_rq_runtime() we want to return bandwidth when there are no remaining tasks, not "return" when this is the case. Signed-off-by: Paul Turner Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111108042736.623812423@google.com Signed-off-by: Ingo Molnar --- kernel/sched_fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index ba0e1f49a22f..a78ed2736ba7 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1756,7 +1756,7 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq) static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) { - if (!cfs_rq->runtime_enabled || !cfs_rq->nr_running) + if (!cfs_rq->runtime_enabled || cfs_rq->nr_running) return; __return_cfs_rq_runtime(cfs_rq); -- cgit From 3bb9068278ea524581237abadd41377a14717e7d Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 16 Nov 2011 09:21:48 +0100 Subject: loop: prevent information leak after failed read If read was not fully successful we have to fail whole bio to prevent information leak of old pages ##Testcase_begin dd if=/dev/zero of=./file bs=1M count=1 losetup /dev/loop0 ./file -o 4096 truncate -s 0 ./file # OOps loop offset is now beyond i_size, so read will silently fail. # So bio's pages would not be cleared, may which result in information leak. hexdump -C /dev/loop0 ##testcase_end Signed-off-by: Dmitry Monakhov Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/loop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 3d806820280e..0d567397c254 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -372,7 +372,8 @@ do_lo_receive(struct loop_device *lo, if (retval < 0) return retval; - + if (retval != bvec->bv_len) + return -EIO; return 0; } -- cgit From 0c614e2d3e6ee6ff13c6181f380787cea1d82d1d Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 16 Nov 2011 09:21:48 +0100 Subject: include/linux/bio.h: use a static inline function for bio_integrity_clone() When CONFIG_BLK_DEV_INTEGRITY is not set, we get these warnings: drivers/md/dm.c: In function 'split_bvec': drivers/md/dm.c:1061:3: warning: statement with no effect drivers/md/dm.c: In function 'clone_bio': drivers/md/dm.c:1088:3: warning: statement with no effect Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- include/linux/bio.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/bio.h b/include/linux/bio.h index a3c071c9e189..d2a3cc23d828 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -519,7 +519,11 @@ extern void bio_integrity_init(void); #define bioset_integrity_create(a, b) (0) #define bio_integrity_prep(a) (0) #define bio_integrity_enabled(a) (0) -#define bio_integrity_clone(a, b, c, d) (0) +static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src, + gfp_t gfp_mask, struct bio_set *bs) +{ + return 0; +} #define bioset_integrity_free(a) do { } while (0) #define bio_integrity_free(a, b) do { } while (0) #define bio_integrity_endio(a, b) do { } while (0) -- cgit From 7035b5df3c071ccaf2f1694b96bd8958b0eb37ca Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 16 Nov 2011 09:21:49 +0100 Subject: loop: cleanup set_status interface 1) Anyone who has read access to loopdev has permission to call set_status and may change important parameters such as lo_offset, lo_sizelimit and so on, which contradicts to read access pattern and definitely equals to write access pattern. 2) Add lo_offset over i_size check to prevent blkdev_size overflow. ##Testcase_bagin #dd if=/dev/zero of=./file bs=1k count=1 #losetup /dev/loop0 ./file /* userspace_application */ struct loop_info64 loinf; fd = open("/dev/loop0", O_RDONLY); ioctl(fd, LOOP_GET_STATUS64, &loinf); /* Set offset to any value which is bigger than i_size, and sizelimit * to nonzero value*/ loinf.lo_offset = 4096*1024; loinf.lo_sizelimit = 1024; ioctl(fd, LOOP_SET_STATUS64, &loinf); /* After this loop device will have size similar to 0x7fffffffffxxxx */ #blockdev --getsz /dev/loop0 ##OUTPUT: 36028797018955968 ##Testcase_end [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Dmitry Monakhov Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/loop.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0d567397c254..68b205a9338f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -161,17 +161,19 @@ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { &xor_funcs }; -static loff_t get_loop_size(struct loop_device *lo, struct file *file) +static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file) { - loff_t size, offset, loopsize; + loff_t size, loopsize; /* Compute loopsize in bytes */ size = i_size_read(file->f_mapping->host); - offset = lo->lo_offset; loopsize = size - offset; - if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize) - loopsize = lo->lo_sizelimit; + /* offset is beyond i_size, wierd but possible */ + if (loopsize < 0) + return 0; + if (sizelimit > 0 && sizelimit < loopsize) + loopsize = sizelimit; /* * Unfortunately, if we want to do I/O on the device, * the number of 512-byte sectors has to fit into a sector_t. @@ -179,17 +181,25 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file) return loopsize >> 9; } +static loff_t get_loop_size(struct loop_device *lo, struct file *file) +{ + return get_size(lo->lo_offset, lo->lo_sizelimit, file); +} + static int -figure_loop_size(struct loop_device *lo) +figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) { - loff_t size = get_loop_size(lo, lo->lo_backing_file); + loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); sector_t x = (sector_t)size; if (unlikely((loff_t)x != size)) return -EFBIG; - + if (lo->lo_offset != offset) + lo->lo_offset = offset; + if (lo->lo_sizelimit != sizelimit) + lo->lo_sizelimit = sizelimit; set_capacity(lo->lo_disk, x); - return 0; + return 0; } static inline int @@ -1059,9 +1069,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (lo->lo_offset != info->lo_offset || lo->lo_sizelimit != info->lo_sizelimit) { - lo->lo_offset = info->lo_offset; - lo->lo_sizelimit = info->lo_sizelimit; - if (figure_loop_size(lo)) + if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) return -EFBIG; } loop_config_discard(lo); @@ -1247,7 +1255,7 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) err = -ENXIO; if (unlikely(lo->lo_state != Lo_bound)) goto out; - err = figure_loop_size(lo); + err = figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); if (unlikely(err)) goto out; sec = get_capacity(lo->lo_disk); @@ -1285,13 +1293,19 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, goto out_unlocked; break; case LOOP_SET_STATUS: - err = loop_set_status_old(lo, (struct loop_info __user *) arg); + err = -EPERM; + if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) + err = loop_set_status_old(lo, + (struct loop_info __user *)arg); break; case LOOP_GET_STATUS: err = loop_get_status_old(lo, (struct loop_info __user *) arg); break; case LOOP_SET_STATUS64: - err = loop_set_status64(lo, (struct loop_info64 __user *) arg); + err = -EPERM; + if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) + err = loop_set_status64(lo, + (struct loop_info64 __user *) arg); break; case LOOP_GET_STATUS64: err = loop_get_status64(lo, (struct loop_info64 __user *) arg); -- cgit From 0007a4c90a11a5371c8b3f80b220fa402a399189 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 16 Nov 2011 09:21:49 +0100 Subject: cciss: auto engage SCSI mid layer at driver load time A long time ago, probably in 2002, one of the distros, or maybe more than one, loaded block drivers prior to loading the SCSI mid layer. This meant that the cciss driver, being a block driver, could not engage the SCSI mid layer at init time without panicking, and relied on being poked by a userland program after the system was up (and the SCSI mid layer was therefore present) to engage the SCSI mid layer. This is no longer the case, and cciss can safely rely on the SCSI mid layer being present at init time and engage the SCSI mid layer straight away. This means that users will see their tape drives and medium changers at driver load time without need for a script in /etc/rc.d that does this: for x in /proc/driver/cciss/cciss* do echo "engage scsi" > $x done However, if no tape drives or medium changers are detected, the SCSI mid layer will not be engaged. If a tape drive or medium change is later hot-added to the system it will then be necessary to use the above script or similar for the device(s) to be acceesible. Signed-off-by: Stephen M. Cameron Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- Documentation/blockdev/cciss.txt | 14 ++++++-------- drivers/block/cciss.c | 1 + drivers/block/cciss_scsi.c | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/blockdev/cciss.txt b/Documentation/blockdev/cciss.txt index 71464e09ec18..b79d0a13e7cd 100644 --- a/Documentation/blockdev/cciss.txt +++ b/Documentation/blockdev/cciss.txt @@ -98,14 +98,12 @@ You must enable "SCSI tape drive support for Smart Array 5xxx" and "SCSI support" in your kernel configuration to be able to use SCSI tape drives with your Smart Array 5xxx controller. -Additionally, note that the driver will not engage the SCSI core at init -time. The driver must be directed to dynamically engage the SCSI core via -the /proc filesystem entry which the "block" side of the driver creates as -/proc/driver/cciss/cciss* at runtime. This is because at driver init time, -the SCSI core may not yet be initialized (because the driver is a block -driver) and attempting to register it with the SCSI core in such a case -would cause a hang. This is best done via an initialization script -(typically in /etc/init.d, but could vary depending on distribution). +Additionally, note that the driver will engage the SCSI core at init +time if any tape drives or medium changers are detected. The driver may +also be directed to dynamically engage the SCSI core via the /proc filesystem +entry which the "block" side of the driver creates as +/proc/driver/cciss/cciss* at runtime. This is best done via a script. + For example: for x in /proc/driver/cciss/cciss[0-9]* diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 5b690194dd99..8004ac30a7a8 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -5163,6 +5163,7 @@ reinit_after_soft_reset: h->cciss_max_sectors = 8192; rebuild_lun_table(h, 1, 0); + cciss_engage_scsi(h); h->busy_initializing = 0; return 1; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 951a4e33b92b..e820b68d2f6c 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -1720,5 +1720,6 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) /* If no tape support, then these become defined out of existence */ #define cciss_scsi_setup(cntl_num) +#define cciss_engage_scsi(h) #endif /* CONFIG_CISS_SCSI_TAPE */ -- cgit From 3540d5e89b2ac268fcfc9b07a50a9ba4acc2e5e5 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 16 Nov 2011 09:21:50 +0100 Subject: block: avoid unnecessary plug list flush get_request_wait() could sleep and flush the plug list. If the list is already flushed, don't flush again. Signed-off-by: Shaohua Li Reviewed-by: Namhyung Kim Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- block/blk-core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index f43c8a5840ae..6403c12f8aad 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1379,15 +1379,17 @@ get_rq: */ if (list_empty(&plug->list)) trace_block_plug(q); - else if (!plug->should_sort) { - struct request *__rq; + else { + if (!plug->should_sort) { + struct request *__rq; - __rq = list_entry_rq(plug->list.prev); - if (__rq->q != q) - plug->should_sort = 1; + __rq = list_entry_rq(plug->list.prev); + if (__rq->q != q) + plug->should_sort = 1; + } + if (request_count >= BLK_MAX_REQUEST_COUNT) + blk_flush_plug_list(plug, false); } - if (request_count >= BLK_MAX_REQUEST_COUNT) - blk_flush_plug_list(plug, false); list_add_tail(&req->queuelist, &plug->list); drive_stat_acct(req, 1); } else { -- cgit From 121f099412bd6576dfb3d94222e89d9341362177 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Nov 2011 09:21:50 +0100 Subject: bio: change some signed vars to unsigned This is just a cleanup patch to silence a static checker warning. The problem is that we cap "nr_iovecs" so it can't be larger than "UIO_MAXIOV" but we don't check for negative values. It turns out this is prevented at other layers, but logically it doesn't make sense to have negative nr_iovecs so making it unsigned is nicer. Signed-off-by: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- fs/bio.c | 7 ++++--- include/linux/bio.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index 41c93c722244..b1fe82cf88cf 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -337,7 +337,7 @@ static void bio_fs_destructor(struct bio *bio) * RETURNS: * Pointer to new bio on success, NULL on failure. */ -struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) +struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) { struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); @@ -365,7 +365,7 @@ static void bio_kmalloc_destructor(struct bio *bio) * %__GFP_WAIT, the allocation is guaranteed to succeed. * **/ -struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs) +struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs) { struct bio *bio; @@ -696,7 +696,8 @@ static void bio_free_map_data(struct bio_map_data *bmd) kfree(bmd); } -static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, +static struct bio_map_data *bio_alloc_map_data(int nr_segs, + unsigned int iov_count, gfp_t gfp_mask) { struct bio_map_data *bmd; diff --git a/include/linux/bio.h b/include/linux/bio.h index d2a3cc23d828..847994aef0e9 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -211,8 +211,8 @@ extern void bio_pair_release(struct bio_pair *dbio); extern struct bio_set *bioset_create(unsigned int, unsigned int); extern void bioset_free(struct bio_set *); -extern struct bio *bio_alloc(gfp_t, int); -extern struct bio *bio_kmalloc(gfp_t, int); +extern struct bio *bio_alloc(gfp_t, unsigned int); +extern struct bio *bio_kmalloc(gfp_t, unsigned int); extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); -- cgit From a2c2a0e668e26e020731ce2a40e6474d1d37210a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Nov 2011 09:21:50 +0100 Subject: paride: fix potential information leak in pg_read() Smatch has a new check for Rosenberg type information leaks where structs are copied to the user with uninitialized stack data in them. i In this case, the pg_write_hdr struct has a hole in it. struct pg_write_hdr { char magic; /* 0 1 */ char func; /* 1 1 */ /* XXX 2 bytes hole, try to pack */ int dlen; /* 4 4 */ Signed-off-by: Dan Carpenter Cc: Tim Waugh Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/paride/pg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 6b9a2000d56a..a79fb4f7ff62 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -630,6 +630,7 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t if (dev->status & 0x10) return -ETIME; + memset(&hdr, 0, sizeof(hdr)); hdr.magic = PG_MAGIC; hdr.dlen = dev->dlen; copy = 0; -- cgit From 019ceb7d5d252ce71001a157cf29f4ac28501b72 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 16 Nov 2011 09:21:50 +0100 Subject: block: add missed trace_block_plug After flush plug list, the list has no request, so we need to add a trace_block_plug(). Signed-off-by: Shaohua Li Reviewed-by: Namhyung Kim Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- block/blk-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index 6403c12f8aad..ea70e6c80cd3 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1387,8 +1387,10 @@ get_rq: if (__rq->q != q) plug->should_sort = 1; } - if (request_count >= BLK_MAX_REQUEST_COUNT) + if (request_count >= BLK_MAX_REQUEST_COUNT) { blk_flush_plug_list(plug, false); + trace_block_plug(q); + } } list_add_tail(&req->queuelist, &plug->list); drive_stat_acct(req, 1); -- cgit From b95d68b8179764e29558b75cec35ef4a6a98925b Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:46 +0800 Subject: ALSA: hda - fix ELD memory leak memset(eld) clears eld->proc_entry which will leak the struct snd_info_entry when unloading module. Fix it by - memset only the fields before eld->eld_buffer - set eld->eld_valid to true _after_ all eld fields have been filled Cc: Cc: Pierre-louis Bossart Acked-by: Stephen Warren Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 5 +---- sound/pci/hda/hda_local.h | 3 +++ sound/pci/hda/patch_hdmi.c | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 1c8ddf547a2d..a065d6d2d6ff 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,10 +297,10 @@ static int hdmi_update_eld(struct hdmi_eld *e, buf + ELD_FIXED_BYTES + mnl + 3 * i); } + e->eld_valid = true; return 0; out_fail: - e->eld_ver = 0; return -EINVAL; } @@ -323,9 +323,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, * ELD is valid, actual eld_size is assigned in hdmi_update_eld() */ - if (!eld->eld_valid) - return -ENOENT; - size = snd_hdmi_get_eld_size(codec, nid); if (size == 0) { /* wfg: workaround for ASUS P5E-VM HDMI board */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 6579e0f2bb57..618ddad17236 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -653,6 +653,9 @@ struct hdmi_eld { int spk_alloc; int sad_count; struct cea_sad sad[ELD_MAX_SAD]; + /* + * all fields above eld_buffer will be cleared before updating ELD + */ char eld_buffer[ELD_MAX_SIZE]; #ifdef CONFIG_PROC_FS struct snd_info_entry *proc_entry; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 81b7b791b3c3..aebfee50bd88 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -980,20 +980,19 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, * the unsolicited response to avoid custom WARs. */ int present = snd_hda_pin_sense(codec, pin_nid); + bool eld_valid = false; - memset(eld, 0, sizeof(*eld)); + memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); if (eld->monitor_present) - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - else - eld->eld_valid = 0; + eld_valid = !!(present & AC_PINSENSE_ELDV); printk(KERN_INFO "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); + codec->addr, pin_nid, eld->monitor_present, eld_valid); - if (eld->eld_valid) + if (eld_valid) if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); -- cgit From 744626dada90cb1231a65b08874aa7a9f11c2ea8 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:47 +0800 Subject: ALSA: hda - delayed ELD repoll The Intel HDMI chips (ironlake at least) are found to have ~250ms delay between the ELD_Valid=1 hotplug event is send and the ELD buffer becomes actually readable. During the time the ELD buffer is mysteriously all 0. Fix it by scheduling a delayed work to re-read ELD buffer after 300ms. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index aebfee50bd88..a76139b60154 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -65,7 +65,10 @@ struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + + struct hda_codec *codec; struct hdmi_eld sink_eld; + struct delayed_work work; }; struct hdmi_spec { @@ -745,8 +748,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, * Unsolicited events */ -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry); static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { @@ -766,7 +768,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) return; eld = &spec->pins[pin_idx].sink_eld; - hdmi_present_sense(codec, pin_nid, eld); + hdmi_present_sense(&spec->pins[pin_idx], true); /* * HDMI sink's ELD info cannot always be retrieved for now, e.g. @@ -968,9 +970,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) { + struct hda_codec *codec = per_pin->codec; + struct hdmi_eld *eld = &per_pin->sink_eld; + hda_nid_t pin_nid = per_pin->pin_nid; /* * Always execute a GetPinSense verb here, even when called from * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -992,13 +996,27 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld_valid); - if (eld_valid) + if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); + else if (retry) { + queue_delayed_work(codec->bus->workq, + &per_pin->work, + msecs_to_jiffies(300)); + } + } snd_hda_input_jack_report(codec, pin_nid); } +static void hdmi_repoll_eld(struct work_struct *work) +{ + struct hdmi_spec_per_pin *per_pin = + container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); + + hdmi_present_sense(per_pin, false); +} + static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct hdmi_spec *spec = codec->spec; @@ -1227,7 +1245,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (err < 0) return err; - hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); + hdmi_present_sense(per_pin, false); return 0; } @@ -1278,6 +1296,8 @@ static int generic_hdmi_init(struct hda_codec *codec) AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | pin_nid); + per_pin->codec = codec; + INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); snd_hda_eld_proc_new(codec, eld, pin_idx); } return 0; @@ -1292,10 +1312,12 @@ static void generic_hdmi_free(struct hda_codec *codec) struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; struct hdmi_eld *eld = &per_pin->sink_eld; + cancel_delayed_work(&per_pin->work); snd_hda_eld_proc_free(codec, eld); } snd_hda_input_jack_free(codec); + flush_workqueue(codec->bus->workq); kfree(spec); } -- cgit From 2d1b439bdb3cee0ae5ccbd7f65e1e5852b1c2718 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 16 Nov 2011 16:29:48 +0800 Subject: ALSA: hda - move eld->spk_alloc fixup to hdmi_update_eld() It looks more natural and saves two lines of code. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 8 ++++++++ sound/pci/hda/patch_hdmi.c | 10 ---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index a065d6d2d6ff..7ae7578bdcc0 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,6 +297,14 @@ static int hdmi_update_eld(struct hdmi_eld *e, buf + ELD_FIXED_BYTES + mnl + 3 * i); } + /* + * HDMI sink's ELD info cannot always be retrieved for now, e.g. + * in console or for audio devices. Assume the highest speakers + * configuration, to _not_ prohibit multi-channel audio playback. + */ + if (!e->spk_alloc) + e->spk_alloc = 0xffff; + e->eld_valid = true; return 0; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index a76139b60154..9850c5b481ea 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -757,7 +757,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) int pd = !!(res & AC_UNSOL_RES_PD); int eldv = !!(res & AC_UNSOL_RES_ELDV); int pin_idx; - struct hdmi_eld *eld; printk(KERN_INFO "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", @@ -766,17 +765,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) pin_idx = pin_nid_to_pin_index(spec, pin_nid); if (pin_idx < 0) return; - eld = &spec->pins[pin_idx].sink_eld; hdmi_present_sense(&spec->pins[pin_idx], true); - - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!eld->spk_alloc) - eld->spk_alloc = 0xffff; } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -- cgit From 25d7d59d1f7321be85bda175c9a1bb85ca1b5881 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 10:52:01 +0100 Subject: ALSA: hda - Update URLs in document Some stuff was moved from kernel.org to other places. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 03e2771ddeef..91fee3b45fb8 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt @@ -579,7 +579,7 @@ Development Tree ~~~~~~~~~~~~~~~~ The latest development codes for HD-audio are found on sound git tree: -- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git +- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git The master branch or for-next branches can be used as the main development branches in general while the HD-audio specific patches @@ -594,7 +594,7 @@ is, installed via the usual spells: configure, make and make install(-modules). See INSTALL in the package. The snapshot tarballs are found at: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/ +- ftp://ftp.suse.com/pub/people/tiwai/snapshot/ Sending a Bug Report @@ -696,7 +696,7 @@ via hda-verb won't change the mixer value. The hda-verb program is found in the ftp directory: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/ Also a git repository is available: @@ -764,7 +764,7 @@ operation, the jack plugging simulation, etc. The package is found in: -- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/ +- ftp://ftp.suse.com/pub/people/tiwai/misc/ A git repository is available: -- cgit From ec84d529b689f4ae31813cf74673f3271c36c83a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 14 Nov 2011 16:12:52 +0000 Subject: ARM: PMU: re-export release_pmu symbol to modules Commit b0e89590 ("ARM: PMU: move CPU PMU platform device handling and init into perf") inadvertently removed the EXPORT_SYMBOL_GPL on release_pmu, so out-of-tree modules can no longer play nice with perf, even if they tried in the first place. This patch re-exports the symbol. Reported-by: Jon Medhurst (Tixy) Signed-off-by: Will Deacon --- arch/arm/kernel/pmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2c3407ee8576..2334bf8a650a 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -33,3 +33,4 @@ release_pmu(enum arm_pmu_type type) { clear_bit_unlock(type, pmu_lock); } +EXPORT_SYMBOL_GPL(release_pmu); -- cgit From 14e25c5eeb90d4f61cc94933307d04a19738ad2f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 16 Nov 2011 10:05:18 +0000 Subject: ARM: PMU: remove pmu_init declaration pmu_init no longer exists, so don't declare it in asm/pmu.h. Reported-by: Pawel Moll Signed-off-by: Will Deacon --- arch/arm/include/asm/pmu.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 71d99b83cdb9..0bda22c094a6 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -55,16 +55,6 @@ reserve_pmu(enum arm_pmu_type type); extern void release_pmu(enum arm_pmu_type type); -/** - * init_pmu() - Initialise the PMU. - * - * Initialise the system ready for PMU enabling. This should typically set the - * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do - * the actual hardware initialisation. - */ -extern int -init_pmu(enum arm_pmu_type type); - #else /* CONFIG_CPU_HAS_PMU */ #include -- cgit From bf14fc54d6386ccd1ef3f1b0ff69e7a765cf8ded Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 6 Jun 2011 12:35:46 +0100 Subject: ARM: highbank: convert logical CPU numbers to physical numbers This patch uses the new cpu_logical_map() macro for converting logical CPU numbers into physical numbers when releasing CPUs during the SMP boot and CPU hotplug paths. Acked-by: Rob Herring Signed-off-by: Will Deacon --- arch/arm/mach-highbank/highbank.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index b82dcf08e747..88660d500f5b 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,9 @@ static void __init highbank_map_io(void) void highbank_set_cpu_jump(int cpu, void *jump_addr) { +#ifdef CONFIG_SMP + cpu = cpu_logical_map(cpu); +#endif writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu)); __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16); outer_clean_range(HB_JUMP_TABLE_PHYS(cpu), -- cgit From eaa142ca3dee1478aca1a645bb0e5a249a33241a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 9 Aug 2011 12:24:07 +0100 Subject: ARM: mach-imx: convert logical CPU numbers to physical numbers This patch uses the new cpu_logical_map() macro for converting logical CPU numbers into physical numbers when releasing CPUs during the SMP boot and CPU hotplug paths. Cc: Sascha Hauer Acked-by: Shawn Guo Signed-off-by: Will Deacon --- arch/arm/mach-imx/src.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 36cacbd0dcc2..a8e33681b732 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define SRC_SCR 0x000 @@ -23,10 +24,15 @@ static void __iomem *src_base; +#ifndef CONFIG_SMP +#define cpu_logical_map(cpu) 0 +#endif + void imx_enable_cpu(int cpu, bool enable) { u32 mask, val; + cpu = cpu_logical_map(cpu); mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1); val = readl_relaxed(src_base + SRC_SCR); val = enable ? val | mask : val & ~mask; @@ -35,6 +41,7 @@ void imx_enable_cpu(int cpu, bool enable) void imx_set_cpu_jump(int cpu, void *jump_addr) { + cpu = cpu_logical_map(cpu); writel_relaxed(BSYM(virt_to_phys(jump_addr)), src_base + SRC_GPR1 + cpu * 8); } -- cgit From 499d05ecf990a7a7bbf9e0a273f9969f8ec69efc Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 16 Nov 2011 19:34:48 +0800 Subject: mm: Make task in balance_dirty_pages() killable There is no reason why task in balance_dirty_pages() shouldn't be killable and it helps in recovering from some error conditions (like when filesystem goes in error state and cannot accept writeback anymore but we still want to kill processes using it to be able to unmount it). There will be follow up patches to further abort the generic_perform_write() and other filesystem write loops, to avoid large write + SIGKILL combination exceeding the dirty limit and possibly strange OOM. Reported-by: Kazuya Mio Tested-by: Kazuya Mio Reviewed-by: Neil Brown Reviewed-by: KOSAKI Motohiro Signed-off-by: Jan Kara Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index a3278f005230..79c34419fadd 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1133,7 +1133,7 @@ pause: pages_dirtied, pause, start_time); - __set_current_state(TASK_UNINTERRUPTIBLE); + __set_current_state(TASK_KILLABLE); io_schedule_timeout(pause); dirty_thresh = hard_dirty_limit(dirty_thresh); @@ -1145,6 +1145,9 @@ pause: */ if (nr_dirty < dirty_thresh) break; + + if (fatal_signal_pending(current)) + break; } if (!dirty_exceeded && bdi->dirty_exceeded) -- cgit From 0e2a5f10fb550835e199a3b56a80ed88232188e9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 4 Nov 2011 08:16:58 -0200 Subject: perf python: Fix undefined symbol problem Recently we made perf_evsel__init call hists__init, which broke the perf python binding: [root@emilia linux]# ./tools/perf/python/twatch.py Traceback (most recent call last): File "./tools/perf/python/twatch.py", line 16, in import perf ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: hists__init Fix it by moving the hists__init function to its only caller, evsel.c. This way we avoid dragging in other parts of tools/perf/util/ to the perf python binding. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-5nffmdt5mu6ozxgj54oi4qon@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 10 ++++++++++ tools/perf/util/hist.c | 10 ---------- tools/perf/util/hist.h | 2 -- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e42626422587..d7915d4e77cb 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -34,6 +34,16 @@ int __perf_evsel__sample_size(u64 sample_type) return size; } +static void hists__init(struct hists *hists) +{ + memset(hists, 0, sizeof(*hists)); + hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; + hists->entries_in = &hists->entries_in_array[0]; + hists->entries_collapsed = RB_ROOT; + hists->entries = RB_ROOT; + pthread_mutex_init(&hists->lock, NULL); +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a36a3fa81ffb..abef2703cd24 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1211,13 +1211,3 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp) return ret; } - -void hists__init(struct hists *hists) -{ - memset(hists, 0, sizeof(*hists)); - hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; - hists->entries_in = &hists->entries_in_array[0]; - hists->entries_collapsed = RB_ROOT; - hists->entries = RB_ROOT; - pthread_mutex_init(&hists->lock, NULL); -} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index c86c1d27bd1e..89289c8e935e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -63,8 +63,6 @@ struct hists { struct callchain_cursor callchain_cursor; }; -void hists__init(struct hists *hists); - struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, struct symbol *parent, u64 period); -- cgit From 47fbe53bef3b219a365ebf3eca949d6cd4c5291c Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 13 Nov 2011 10:45:27 -0700 Subject: perf session: Fix crash with invalid CPU list commit 5d67be9 added the option to specify a range of CPUs of interest, but does not catch an invalid CPU list: $ perf script -c foo Segmentation fault (core dumped) Cc: Anton Blanchard Link: http://lkml.kernel.org/r/1321206327-5881-1-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 85c1e6b76f0a..0f4555ce9063 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1333,6 +1333,10 @@ int perf_session__cpu_bitmap(struct perf_session *session, } map = cpu_map__new(cpu_list); + if (map == NULL) { + pr_err("Invalid cpu_list\n"); + return -1; + } for (i = 0; i < map->nr; i++) { int cpu = map->map[i]; -- cgit From 12b248eba4fd189216cad14b7dd1cfdacdf90cdf Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Thu, 17 Nov 2011 01:13:34 +0900 Subject: ARM: S5P: Fix export.h inclusion Commit 32aaeffbd4a7 ("Merge branch 'modsplit-Oct31 2011'...") breaks build like following and this fixes it to add inclusion . arch/arm/plat-s5p/sysmmu.c:302: error: 'THIS_MODULE' undeclared here (not in a function) Signed-off-by: Kukjin Kim --- arch/arm/plat-s5p/sysmmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c index e1cbc728c775..c8bec9c7655d 100644 --- a/arch/arm/plat-s5p/sysmmu.c +++ b/arch/arm/plat-s5p/sysmmu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include -- cgit From a69e4c28b2bddc21b5752b1da8f43ab0a817305c Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Thu, 17 Nov 2011 01:14:38 +0900 Subject: ARM: SAMSUNG: inclusion export.h instead of module.h Only for THIS_MODULE, the file should be added instead of . Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410-module.c | 2 +- arch/arm/plat-s3c24xx/cpu-freq-debugfs.c | 2 +- arch/arm/plat-samsung/pd.c | 2 +- arch/arm/plat-samsung/pwm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 66668565ee75..f208154b1382 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ -#include +#include #include #include diff --git a/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c index a9276667c2fb..c7adad0e8de0 100644 --- a/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c +++ b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c @@ -12,7 +12,7 @@ */ #include -#include +#include #include #include #include diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c index efe1d564473e..312b510d86b7 100644 --- a/arch/arm/plat-samsung/pd.c +++ b/arch/arm/plat-samsung/pd.c @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c index dc1185dcf80d..c559d8438c70 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/arch/arm/plat-samsung/pwm.c @@ -11,7 +11,7 @@ * the Free Software Foundation; either version 2 of the License. */ -#include +#include #include #include #include -- cgit From dc2c83582eac2682808b80e9dce7d2cac2b20596 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Nov 2011 01:17:18 +0900 Subject: ARM: SAMSUNG: include linux/types.h at gpio-cfg.h Include linux/types.h to fix below build error: CC drivers/power/max8903_charger.o In file included from arch/arm/plat-samsung/include/plat/gpio-fns.h:27, from arch/arm/mach-s3c2410/include/mach/gpio-fns.h:1, from arch/arm/mach-s3c2410/include/mach/gpio.h:27, from /home/axel/repos/git/linux-2.6/arch/arm/include/asm/gpio.h:5, from include/linux/gpio.h:30, from drivers/power/max8903_charger.c:23: arch/arm/plat-samsung/include/plat/gpio-cfg.h:27: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'samsung_gpio_pull_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h:28: error: expected '=', ',', ';', 'asm' or '__attribute__' before 's5p_gpio_drvstr_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h:55: error: expected specifier-qualifier-list before 'samsung_gpio_pull_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h:146: error: expected declaration specifiers or '...' before 'samsung_gpio_pull_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h:154: error: expected '=', ',', ';', 'asm' or '__attribute__' before 's3c_gpio_getpull' arch/arm/plat-samsung/include/plat/gpio-cfg.h:173: error: expected declaration specifiers or '...' before 'samsung_gpio_pull_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h: In function 's3c_gpio_cfgrange_nopull': arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: '__force' undeclared (first use in this function) arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: (Each undeclared identifier is reported only once arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: for each function it appears in.) arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: expected ')' before 'samsung_gpio_pull_t' arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: expected ')' before numeric constant arch/arm/plat-samsung/include/plat/gpio-cfg.h:178: error: too many arguments to function 's3c_gpio_cfgall_range' arch/arm/plat-samsung/include/plat/gpio-cfg.h: At top level: arch/arm/plat-samsung/include/plat/gpio-cfg.h:197: error: expected '=', ',', ';', 'asm' or '__attribute__' before 's5p_gpio_get_drvstr' arch/arm/plat-samsung/include/plat/gpio-cfg.h:208: error: expected declaration specifiers or '...' before 's5p_gpio_drvstr_t' make[2]: *** [drivers/power/max8903_charger.o] Error 1 make[1]: *** [drivers/power] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Cc: stable@kernel.org Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/gpio-cfg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index d48245bb02b3..df8155b9d4d1 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -24,6 +24,8 @@ #ifndef __PLAT_GPIO_CFG_H #define __PLAT_GPIO_CFG_H __FILE__ +#include + typedef unsigned int __bitwise__ samsung_gpio_pull_t; typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; -- cgit From 05ee7964a470d29889ac48cc8274c1b5a1904a11 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 18:05:11 +0100 Subject: ALSA: hda - Fix the connection selection of ADCs on Cirrus codecs spec->cur_adc isn't set until cs_capture_pcm_prepare() is called although the driver tries to select the connection at init time and at auto-mic switch. This results in the access to the widget NID 0, which is obviously invalid, also a wrong capture source. This patch fixes the issue by issuing the connect-select verb conditionally at appropriate places. Reported-and-tested-by: Dylan Reid Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2a2d8645ba09..2fbab8e29576 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -237,6 +237,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); } +static void cs_update_input_select(struct hda_codec *codec) +{ + struct cs_spec *spec = codec->spec; + if (spec->cur_adc) + snd_hda_codec_write(codec, spec->cur_adc, 0, + AC_VERB_SET_CONNECT_SEL, + spec->adc_idx[spec->cur_input]); +} + /* * Analog capture */ @@ -250,6 +259,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_adc = spec->adc_nid[spec->cur_input]; spec->cur_adc_stream_tag = stream_tag; spec->cur_adc_format = format; + cs_update_input_select(codec); snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); return 0; } @@ -689,10 +699,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx, spec->cur_adc_stream_tag, 0, spec->cur_adc_format); } - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[idx]); spec->cur_input = idx; + cs_update_input_select(codec); return 1; } @@ -973,10 +981,7 @@ static void cs_automic(struct hda_codec *codec) } else { spec->cur_input = spec->last_input; } - - snd_hda_codec_write_cache(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } else { if (present) change_cur_input(codec, spec->automic_idx, 0); @@ -1073,9 +1078,7 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); else { spec->cur_adc = spec->adc_nid[spec->cur_input]; - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } } else { change_cur_input(codec, spec->cur_input, 1); -- cgit From cd12909cb576d37311fe35868780e82d5007d0c8 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 29 Sep 2011 16:53:32 +0100 Subject: xen: map foreign pages for shared rings by updating the PTEs directly When mapping a foreign page with xenbus_map_ring_valloc() with the GNTTABOP_map_grant_ref hypercall, set the GNTMAP_contains_pte flag and pass a pointer to the PTE (in init_mm). After the page is mapped, the usual fault mechanism can be used to update additional MMs. This allows the vmalloc_sync_all() to be removed from alloc_vm_area(). Signed-off-by: David Vrabel Acked-by: Andrew Morton [v1: Squashed fix by Michal for no-mmu case] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Michal Simek --- arch/x86/xen/grant-table.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 11 ++++++++--- include/linux/vmalloc.h | 2 +- mm/nommu.c | 2 +- mm/vmalloc.c | 27 +++++++++++++-------------- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index 6bbfd7ac5e81..5a40d24ba331 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, if (shared == NULL) { struct vm_struct *area = - alloc_vm_area(PAGE_SIZE * max_nr_gframes); + alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL); BUG_ON(area == NULL); shared = area->addr; *__shared = shared; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 81c3ce6b8bbe..1906125eab49 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -436,19 +437,20 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn); int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) { struct gnttab_map_grant_ref op = { - .flags = GNTMAP_host_map, + .flags = GNTMAP_host_map | GNTMAP_contains_pte, .ref = gnt_ref, .dom = dev->otherend_id, }; struct vm_struct *area; + pte_t *pte; *vaddr = NULL; - area = alloc_vm_area(PAGE_SIZE); + area = alloc_vm_area(PAGE_SIZE, &pte); if (!area) return -ENOMEM; - op.host_addr = (unsigned long)area->addr; + op.host_addr = arbitrary_virt_to_machine(pte).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) BUG(); @@ -527,6 +529,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) struct gnttab_unmap_grant_ref op = { .host_addr = (unsigned long)vaddr, }; + unsigned int level; /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr) * method so that we don't have to muck with vmalloc internals here. @@ -548,6 +551,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) } op.handle = (grant_handle_t)area->phys_addr; + op.host_addr = arbitrary_virt_to_machine( + lookup_address((unsigned long)vaddr, &level)).maddr; if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) BUG(); diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 687fb11e2010..4bde182fcf93 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -119,7 +119,7 @@ unmap_kernel_range(unsigned long addr, unsigned long size) #endif /* Allocate/destroy a 'vmalloc' VM area. */ -extern struct vm_struct *alloc_vm_area(size_t size); +extern struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes); extern void free_vm_area(struct vm_struct *area); /* for /dev/kmem */ diff --git a/mm/nommu.c b/mm/nommu.c index 73419c55eda6..b982290fd962 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -454,7 +454,7 @@ void __attribute__((weak)) vmalloc_sync_all(void) * between processes, it syncs the pagetable across all * processes. */ -struct vm_struct *alloc_vm_area(size_t size) +struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes) { BUG(); return NULL; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index b669aa6f6caf..3231bf332878 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -2141,23 +2141,30 @@ void __attribute__((weak)) vmalloc_sync_all(void) static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data) { - /* apply_to_page_range() does all the hard work. */ + pte_t ***p = data; + + if (p) { + *(*p) = pte; + (*p)++; + } return 0; } /** * alloc_vm_area - allocate a range of kernel address space * @size: size of the area + * @ptes: returns the PTEs for the address space * * Returns: NULL on failure, vm_struct on success * * This function reserves a range of kernel address space, and * allocates pagetables to map that range. No actual mappings - * are created. If the kernel address space is not shared - * between processes, it syncs the pagetable across all - * processes. + * are created. + * + * If @ptes is non-NULL, pointers to the PTEs (in init_mm) + * allocated for the VM area are returned. */ -struct vm_struct *alloc_vm_area(size_t size) +struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes) { struct vm_struct *area; @@ -2171,19 +2178,11 @@ struct vm_struct *alloc_vm_area(size_t size) * of kernel virtual address space and mapped into init_mm. */ if (apply_to_page_range(&init_mm, (unsigned long)area->addr, - area->size, f, NULL)) { + size, f, ptes ? &ptes : NULL)) { free_vm_area(area); return NULL; } - /* - * If the allocated address space is passed to a hypercall - * before being used then we cannot rely on a page fault to - * trigger an update of the page tables. So sync all the page - * tables here. - */ - vmalloc_sync_all(); - return area; } EXPORT_SYMBOL_GPL(alloc_vm_area); -- cgit From 5f76d7078ce784916d55fc4e1bb0a42985f085a6 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Wed, 19 Oct 2011 18:05:27 -0400 Subject: xen: Remove hanging references to CONFIG_XEN_PLATFORM_PCI In 5fbdc10395cd500d6ff844825a918c4e6f38de37 the XEN_PLATFORM_PCI config option was removed, but references in header files remained. Clean up those references. Signed-off-by: Daniel De Graaf Signed-off-by: Konrad Rzeszutek Wilk --- include/xen/platform_pci.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h index a785a3b0c8c7..438c256c274b 100644 --- a/include/xen/platform_pci.h +++ b/include/xen/platform_pci.h @@ -29,8 +29,7 @@ static inline int xen_must_unplug_nics(void) { #if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \ defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \ - (defined(CONFIG_XEN_PLATFORM_PCI) || \ - defined(CONFIG_XEN_PLATFORM_PCI_MODULE)) + defined(CONFIG_XEN_PVHVM) return 1; #else return 0; @@ -40,8 +39,7 @@ static inline int xen_must_unplug_nics(void) { static inline int xen_must_unplug_disks(void) { #if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \ defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \ - (defined(CONFIG_XEN_PLATFORM_PCI) || \ - defined(CONFIG_XEN_PLATFORM_PCI_MODULE)) + defined(CONFIG_XEN_PVHVM) return 1; #else return 0; -- cgit From 72e9cf2ab12ef3e050577ffebdb0c88a28df821d Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Wed, 19 Oct 2011 17:59:37 -0400 Subject: xen/balloon: Avoid OOM when requesting highmem If highmem pages are requested from the balloon on a system without highmem, the implementation of alloc_xenballooned_pages will allocate all available memory trying to find highmem pages to return. Allow low memory to be returned when highmem pages are requested to avoid this loop. Signed-off-by: Daniel De Graaf Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/balloon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index a767884a6c7a..31ab82fda38a 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -501,7 +501,7 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target); * alloc_xenballooned_pages - get pages that have been ballooned out * @nr_pages: Number of pages to get * @pages: pages returned - * @highmem: highmem or lowmem pages + * @highmem: allow highmem pages * @return 0 on success, error otherwise */ int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) @@ -511,7 +511,7 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) mutex_lock(&balloon_mutex); while (pgno < nr_pages) { page = balloon_retrieve(highmem); - if (page && PageHighMem(page) == highmem) { + if (page && (highmem || !PageHighMem(page))) { pages[pgno++] = page; } else { enum bp_state st; -- cgit From 90d4f5534d14815bd94c10e8ceccc57287657ecc Mon Sep 17 00:00:00 2001 From: Zhenzhong Duan Date: Thu, 27 Oct 2011 22:28:59 -0700 Subject: xen:pvhvm: enable PVHVM VCPU placement when using more than 32 CPUs. PVHVM running with more than 32 vcpus and pv_irq/pv_time enabled need VCPU placement to work, or else it will softlockup. CC: stable@kernel.org Acked-by: Stefano Stabellini Signed-off-by: Zhenzhong Duan Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index da8afd576a6b..1f928659c338 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1356,7 +1356,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, int cpu = (long)hcpu; switch (action) { case CPU_UP_PREPARE: - per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; + xen_vcpu_setup(cpu); if (xen_have_vector_callback) xen_init_lock_cpu(cpu); break; @@ -1386,7 +1386,6 @@ static void __init xen_hvm_guest_init(void) xen_hvm_smp_init(); register_cpu_notifier(&xen_hvm_cpu_notifier); xen_unplug_emulated_devices(); - have_vcpu_info_placement = 0; x86_init.irqs.intr_init = xen_init_IRQ; xen_hvm_init_time_ops(); xen_hvm_init_mmu_ops(); -- cgit From fc6e0c3b909157748ce1c0c0f2a9935a5ee3c812 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:23:32 +0300 Subject: xen-gntdev: integer overflow in gntdev_alloc_map() The multiplications here can overflow resulting in smaller buffer sizes than expected. "count" comes from a copy_from_user(). Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/gntdev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 39871326afa2..afca14d9042e 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -114,11 +114,11 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) if (NULL == add) return NULL; - add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); - add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); - add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); - add->kmap_ops = kzalloc(sizeof(add->kmap_ops[0]) * count, GFP_KERNEL); - add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); + add->grants = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL); + add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL); + add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL); + add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL); + add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL); if (NULL == add->grants || NULL == add->map_ops || NULL == add->unmap_ops || -- cgit From 21643e69a4c06f7ef155fbc70e3fba13fba4a756 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:24:08 +0300 Subject: xen-gntalloc: integer overflow in gntalloc_ioctl_alloc() On 32 bit systems a high value of op.count could lead to an integer overflow in the kzalloc() and gref_ids would be smaller than expected. If the you triggered another integer overflow in "if (gref_size + op.count > limit)" then you'd probably get memory corruption inside add_grefs(). CC: stable@kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/gntalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index f6832f46aea4..23c60cf4313e 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -280,7 +280,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv, goto out; } - gref_ids = kzalloc(sizeof(gref_ids[0]) * op.count, GFP_TEMPORARY); + gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_TEMPORARY); if (!gref_ids) { rc = -ENOMEM; goto out; -- cgit From 99cb2ddcc617f43917e94a4147aa3ccdb2bcd77e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:24:36 +0300 Subject: xen-gntalloc: signedness bug in add_grefs() gref->gref_id is unsigned so the error handling didn't work. gnttab_grant_foreign_access() returns an int type, so we can add a cast here, and it doesn't cause any problems. gnttab_grant_foreign_access() can return a variety of errors including -ENOSPC, -ENOSYS and -ENOMEM. CC: stable@kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/gntalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index 23c60cf4313e..e1c4c6e5b469 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -135,7 +135,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op, /* Grant foreign access to the page. */ gref->gref_id = gnttab_grant_foreign_access(op->domid, pfn_to_mfn(page_to_pfn(gref->page)), readonly); - if (gref->gref_id < 0) { + if ((int)gref->gref_id < 0) { rc = gref->gref_id; goto undo; } -- cgit From 4cecf6d401a01d054afc1e5f605bcbfe553cb9b9 Mon Sep 17 00:00:00 2001 From: Salman Qazi Date: Tue, 15 Nov 2011 14:12:06 -0800 Subject: sched, x86: Avoid unnecessary overflow in sched_clock (Added the missing signed-off-by line) In hundreds of days, the __cycles_2_ns calculation in sched_clock has an overflow. cyc * per_cpu(cyc2ns, cpu) exceeds 64 bits, causing the final value to become zero. We can solve this without losing any precision. We can decompose TSC into quotient and remainder of division by the scale factor, and then use this to convert TSC into nanoseconds. Signed-off-by: Salman Qazi Acked-by: John Stultz Reviewed-by: Paul Turner Cc: stable@kernel.org Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111115221121.7262.88871.stgit@dungbeetle.mtv.corp.google.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/timer.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index fa7b9176b76c..431793e5d484 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -32,6 +32,22 @@ extern int no_timer_check; * (mathieu.desnoyers@polymtl.ca) * * -johnstul@us.ibm.com "math is hard, lets go shopping!" + * + * In: + * + * ns = cycles * cyc2ns_scale / SC + * + * Although we may still have enough bits to store the value of ns, + * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, + * leading to an incorrect result. + * + * To avoid this, we can decompose 'cycles' into quotient and remainder + * of division by SC. Then, + * + * ns = (quot * SC + rem) * cyc2ns_scale / SC + * = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC + * + * - sqazi@google.com */ DECLARE_PER_CPU(unsigned long, cyc2ns); @@ -41,9 +57,14 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset); static inline unsigned long long __cycles_2_ns(unsigned long long cyc) { + unsigned long long quot; + unsigned long long rem; int cpu = smp_processor_id(); unsigned long long ns = per_cpu(cyc2ns_offset, cpu); - ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR; + quot = (cyc >> CYC2NS_SCALE_FACTOR); + rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1); + ns += quot * per_cpu(cyc2ns, cpu) + + ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR); return ns; } -- cgit From f4a0d5abef14562c37dee5a1d49180f494106230 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 24 Oct 2011 08:17:42 -0400 Subject: encrypted-keys: fix error return code Fix request_master_key() error return code. Signed-off-by: Mimi Zohar --- security/keys/encrypted-keys/encrypted.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index dcc843cb0f80..41144f71d615 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -444,7 +444,7 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload, goto out; if (IS_ERR(mkey)) { - int ret = PTR_ERR(epayload); + int ret = PTR_ERR(mkey); if (ret == -ENOTSUPP) pr_info("encrypted_key: key %s not supported", -- cgit From 9c69898783a0121399ec078d40d4ccc00e3cb0df Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Sun, 16 Oct 2011 19:17:48 -0400 Subject: encrypted-keys: module build fixes Encrypted keys are encrypted/decrypted using either a trusted or user-defined key type, which is referred to as the 'master' key. The master key may be of type trusted iff the trusted key is builtin or both the trusted key and encrypted keys are built as modules. This patch resolves the build dependency problem. - Use "masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS)" construct to encapsulate the above logic. (Suggested by Dimtry Kasatkin.) - Fixing the encrypted-keys Makefile, results in a module name change from encrypted.ko to encrypted-keys.ko. - Add module dependency for request_trusted_key() definition Signed-off-by: Mimi Zohar --- security/keys/encrypted-keys/Makefile | 8 ++++++-- security/keys/encrypted-keys/encrypted.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile index 6bc7a86d1027..d6f8433250a5 100644 --- a/security/keys/encrypted-keys/Makefile +++ b/security/keys/encrypted-keys/Makefile @@ -2,5 +2,9 @@ # Makefile for encrypted keys # -obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o -obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o +obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o + +encrypted-keys-y := encrypted.o ecryptfs_format.o +masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o +masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o +encrypted-keys-y += $(masterkey-y) $(masterkey-m-m) diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h index b6ade8945250..8136a2d44c63 100644 --- a/security/keys/encrypted-keys/encrypted.h +++ b/security/keys/encrypted-keys/encrypted.h @@ -2,7 +2,8 @@ #define __ENCRYPTED_KEY_H #define ENCRYPTED_DEBUG 0 -#ifdef CONFIG_TRUSTED_KEYS +#if defined(CONFIG_TRUSTED_KEYS) || \ + (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE)) extern struct key *request_trusted_key(const char *trusted_desc, u8 **master_key, size_t *master_keylen); #else -- cgit From f9849100851b28c8ad83e86d68d5110497a4e9d6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 16 Nov 2011 11:52:12 +0000 Subject: watchdog: Don't overwrite error value in wm831x_wdt_set_timeout() Reported-by: Dan Carpenter Signed-off-by: Mark Brown Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm831x_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 7be38556aed0..e789a47db41f 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -150,7 +150,7 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev, if (wm831x_wdt_cfgs[i].time == timeout) break; if (i == ARRAY_SIZE(wm831x_wdt_cfgs)) - ret = -EINVAL; + return -EINVAL; ret = wm831x_reg_unlock(wm831x); if (ret == 0) { -- cgit From 20403e845f9988446c5b48024ff4d0c3a5929f7d Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Wed, 16 Nov 2011 12:46:13 +0400 Subject: watchdog: fix initialisation printout in s3c2410_wdt Looks like a typo creeped in, and driver prints s3c2410-wdt s3c2410-wdt: watchdog active, reset abled, irq abled instead of s3c2410-wdt s3c2410-wdt: watchdog active, reset enabled, irq enabled Also it may completely disinform about irq status, as it prints "irq enabled" when S3C2410_WTCON_INTEN is in fact 0. Fix it. Signed-off-by: Dmitry Artamonow Tested-by: Thomas Abraham Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 5de7e4fa5b8a..a79e3840782a 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -401,8 +401,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n", (wtcon & S3C2410_WTCON_ENABLE) ? "" : "in", - (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", - (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); + (wtcon & S3C2410_WTCON_RSTEN) ? "en" : "dis", + (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis"); return 0; -- cgit From 8d514bbf37eecf0a3e309284728637816a36764b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 16 Nov 2011 16:06:09 -0500 Subject: btrfs: fix double mntput() in mount_subvol() Signed-off-by: Al Viro --- fs/btrfs/super.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8bd9d6d0e07a..969a7747e889 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -861,7 +861,6 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, if (!is_subvolume_inode(path.dentry->d_inode)) { path_put(&path); - mntput(mnt); error = -EINVAL; printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n", subvol_name); -- cgit From c13344958780b4046305ee6235d686c846535529 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 16 Nov 2011 16:12:14 -0500 Subject: switch create_mnt_ns() to saner calling conventions, fix double mntput() in nfs Life is much saner if create_mnt_ns(mnt) drops mnt in case of error... Switch it to such calling conventions, switch callers, fix double mntput() in fs/nfs/super.c one. Signed-off-by: Al Viro --- fs/btrfs/super.c | 4 +--- fs/namespace.c | 2 ++ fs/nfs/super.c | 23 ++++++++--------------- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 969a7747e889..cfbedd7755b0 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -843,10 +843,8 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, return ERR_CAST(mnt); ns_private = create_mnt_ns(mnt); - if (IS_ERR(ns_private)) { - mntput(mnt); + if (IS_ERR(ns_private)) return ERR_CAST(ns_private); - } /* * This will trigger the automount of the subvol so we can just diff --git a/fs/namespace.c b/fs/namespace.c index e5e1c7d1839b..aea4b7689840 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2483,6 +2483,8 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) __mnt_make_longterm(mnt); new_ns->root = mnt; list_add(&new_ns->list, &new_ns->root->mnt_list); + } else { + mntput(mnt); } return new_ns; } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 480b3b6bf71e..46d69f38fd55 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2794,22 +2794,21 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, int ret; ns_private = create_mnt_ns(root_mnt); - ret = PTR_ERR(ns_private); if (IS_ERR(ns_private)) - goto out_mntput; + return ERR_CAST(ns_private); ret = nfs_referral_loop_protect(); - if (ret != 0) - goto out_put_mnt_ns; - - ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, - export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); + if (ret == 0) { + ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, + export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, + &path); + nfs_referral_loop_unprotect(); + } - nfs_referral_loop_unprotect(); put_mnt_ns(ns_private); if (ret != 0) - goto out_err; + return ERR_PTR(ret); s = path.mnt->mnt_sb; atomic_inc(&s->s_active); @@ -2818,12 +2817,6 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, path_put(&path); down_write(&s->s_umount); return dentry; -out_put_mnt_ns: - put_mnt_ns(ns_private); -out_mntput: - mntput(root_mnt); -out_err: - return ERR_PTR(ret); } static struct dentry *nfs4_try_mount(int flags, const char *dev_name, -- cgit From 709e8697af1c86772c1a6fccda6d4b0e2e226547 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 14 Nov 2011 10:56:56 +0000 Subject: tcp: clear xmit timers in tcp_v4_syn_recv_sock() Simon Kirby reported divides by zero errors in __tcp_select_window() This happens when inet_csk_route_child_sock() returns a NULL pointer : We free new socket while we eventually armed keepalive timer in tcp_create_openreq_child() Fix this by a call to tcp_clear_xmit_timers() [ This is a followup to commit 918eb39962dff (net: add missing bh_unlock_sock() calls) ] Reported-by: Simon Kirby Signed-off-by: Eric Dumazet Tested-by: Simon Kirby Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a7443159c400..a9db4b1a2215 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1510,6 +1510,7 @@ exit: NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: + tcp_clear_xmit_timers(newsk); bh_unlock_sock(newsk); sock_put(newsk); goto exit; -- cgit From 6cc31d09bedeb6f25951b18c23b6aee5df0a242c Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 15 Nov 2011 02:31:12 +0000 Subject: qeth: return with -EPERM if sniffing is not enabled Without appropriate configuration at the SE, a HiperSockets device cannot be used for sniffing. Setting the sniffer attribute is rejected with -EPERM. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_sys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 0ea2fbfe0e99..d979bb26522f 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -335,10 +335,10 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, QETH_IN_BUF_COUNT_MAX) qeth_realloc_buffer_pool(card, QETH_IN_BUF_COUNT_MAX); - break; } else rc = -EPERM; - default: /* fall through */ + break; + default: rc = -EINVAL; } out: -- cgit From 7c01a8e56bf8a03b9b50a770de36abfee03c4fc5 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 15 Nov 2011 02:31:13 +0000 Subject: qeth: remove WARN_ON leftover The patch "qeth: exploit asynchronous delivery of storage blocks" added a WARN_ON in qeth_schedule_recovery. A device recovery should not cause a kernel warning. This is obviously a debugging left-over that we forgot to remove. Signed-off-by: Christian Borntraeger Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 81534437373a..fff57de78943 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -881,7 +881,6 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread); void qeth_schedule_recovery(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "startrec"); - WARN_ON(1); if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) schedule_work(&card->kernel_thread_starter); } -- cgit From 1d503563f7601a249d015d3fad40b08e8d6a394b Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 15 Nov 2011 02:31:14 +0000 Subject: netiucv: reinsert dev_alloc_name for device naming Invocation of dev_alloc_name() is re-inserted, because the created net_device name is used to create the device name for the iucv bus. This device is created before the register_netdev call. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 3251333a23df..b6a6356d09b3 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1994,6 +1994,8 @@ static struct net_device *netiucv_init_netdevice(char *username) netiucv_setup_netdevice); if (!dev) return NULL; + if (dev_alloc_name(dev, dev->name) < 0) + goto out_netdev; privptr = netdev_priv(dev); privptr->fsm = init_fsm("netiucvdev", dev_state_names, -- cgit From 1d36cb479f204a0fedc1a3e7ce7b32c0a2c48769 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 15 Nov 2011 02:31:15 +0000 Subject: qeth: l3 fix rcu splat in xmit when use dst_get_neighbour to get neighbour, we need rcu_read_lock to protect, since dst_get_neighbour uses rcu_dereference. Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e4c1176ee25b..4d5307ddbe55 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2756,11 +2756,13 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) struct neighbour *n = NULL; struct dst_entry *dst; + rcu_read_lock(); dst = skb_dst(skb); if (dst) n = dst_get_neighbour(dst); if (n) { cast_type = n->type; + rcu_read_unlock(); if ((cast_type == RTN_BROADCAST) || (cast_type == RTN_MULTICAST) || (cast_type == RTN_ANYCAST)) @@ -2768,6 +2770,8 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) else return RTN_UNSPEC; } + rcu_read_unlock(); + /* try something else */ if (skb->protocol == ETH_P_IPV6) return (skb_network_header(skb)[24] == 0xff) ? @@ -2847,6 +2851,8 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr); + + rcu_read_lock(); dst = skb_dst(skb); if (dst) n = dst_get_neighbour(dst); @@ -2893,6 +2899,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, QETH_CAST_UNICAST | QETH_HDR_PASSTHRU; } } + rcu_read_unlock(); } static inline void qeth_l3_hdr_csum(struct qeth_card *card, -- cgit From 0284a0fdf3def1beb4de509f87472520b23883c9 Mon Sep 17 00:00:00 2001 From: Einar Lueck Date: Tue, 15 Nov 2011 02:31:16 +0000 Subject: qeth: Reduce CPU consumption through less SIGA-r calls Patch avoids SIGA-r calls in case of SIGA-r required. It only calls SIGA-r if a threshold of free buffer is reached. CPU consumption is reduced as a consequence. Signed-off-by: Einar Lueck Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index b77c65ed1381..4abc79d3963f 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -236,8 +236,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, #define QETH_IN_BUF_COUNT_MAX 128 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12) #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \ - ((card)->ssqd.qdioac1 & AC1_SIGA_INPUT_NEEDED ? 1 : \ - ((card)->qdio.in_buf_pool.buf_count / 2)) + ((card)->qdio.in_buf_pool.buf_count / 2) /* buffers we have to be behind before we get a PCI */ #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1) -- cgit From fa2da8cdae1dd64f78fc915ca1d1a4a93c71e7cb Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 15 Nov 2011 08:09:14 +0000 Subject: bridge: correct IPv6 checksum after pull Bridge multicast snooping of ICMPv6 would incorrectly report a checksum problem when used with Ethernet devices like sky2 that use CHECKSUM_COMPLETE. When bytes are removed from skb, the computed checksum needs to be adjusted. Signed-off-by: Stephen Hemminger Tested-by: Martin Volf Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2eefe275b338..a5f4e5769809 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1501,6 +1501,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, __skb_pull(skb2, offset); skb_reset_transport_header(skb2); + skb_postpull_rcsum(skb2, skb_network_header(skb2), + skb_network_header_len(skb2)); icmp6_type = icmp6_hdr(skb2)->icmp6_type; -- cgit From eccab1ec87d093d5104e6aade674223b5b625d39 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 15 Nov 2011 09:36:30 +0000 Subject: net/cadence: enable by default NET_ATMEL so the defconfig of the atmel continue to have the support of the network as before Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 98849a1fc749..b48378a41e49 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -7,6 +7,7 @@ config HAVE_NET_MACB config NET_ATMEL bool "Atmel devices" + default y depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) ---help--- If you have a network (Ethernet) card belonging to this class, say Y. -- cgit From eb2afd4a622985eaccfa8c7fc83e890b8930e0ab Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 15 Nov 2011 12:07:33 +0000 Subject: bnx2x: cache-in compressed fw image Re-request fw from fs may fail for different reasons, once the fw was loaded we won't release it until driver is removed. This also resolves the boot problem when initial fw is located on initrd, but rootfs is still unavailable, in this case device reset will fail due to absence of fw files. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 50 ++++++++++++++---------- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 15 +++---- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6486ab8c8fc8..2f6361e949f0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10548,33 +10548,38 @@ do { \ int bnx2x_init_firmware(struct bnx2x *bp) { - const char *fw_file_name; struct bnx2x_fw_file_hdr *fw_hdr; int rc; - if (CHIP_IS_E1(bp)) - fw_file_name = FW_FILE_NAME_E1; - else if (CHIP_IS_E1H(bp)) - fw_file_name = FW_FILE_NAME_E1H; - else if (!CHIP_IS_E1x(bp)) - fw_file_name = FW_FILE_NAME_E2; - else { - BNX2X_ERR("Unsupported chip revision\n"); - return -EINVAL; - } - BNX2X_DEV_INFO("Loading %s\n", fw_file_name); + if (!bp->firmware) { + const char *fw_file_name; - rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev); - if (rc) { - BNX2X_ERR("Can't load firmware file %s\n", fw_file_name); - goto request_firmware_exit; - } + if (CHIP_IS_E1(bp)) + fw_file_name = FW_FILE_NAME_E1; + else if (CHIP_IS_E1H(bp)) + fw_file_name = FW_FILE_NAME_E1H; + else if (!CHIP_IS_E1x(bp)) + fw_file_name = FW_FILE_NAME_E2; + else { + BNX2X_ERR("Unsupported chip revision\n"); + return -EINVAL; + } + BNX2X_DEV_INFO("Loading %s\n", fw_file_name); - rc = bnx2x_check_firmware(bp); - if (rc) { - BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name); - goto request_firmware_exit; + rc = request_firmware(&bp->firmware, fw_file_name, + &bp->pdev->dev); + if (rc) { + BNX2X_ERR("Can't load firmware file %s\n", + fw_file_name); + goto request_firmware_exit; + } + + rc = bnx2x_check_firmware(bp); + if (rc) { + BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name); + goto request_firmware_exit; + } } fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data; @@ -10630,6 +10635,7 @@ static void bnx2x_release_firmware(struct bnx2x *bp) kfree(bp->init_ops); kfree(bp->init_data); release_firmware(bp->firmware); + bp->firmware = NULL; } @@ -10925,6 +10931,8 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) if (bp->doorbells) iounmap(bp->doorbells); + bnx2x_release_firmware(bp); + bnx2x_free_mem_bp(bp); free_netdev(dev); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 0440425c83d6..14517691f8db 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -5380,7 +5380,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp, rc = drv->init_fw(bp); if (rc) { BNX2X_ERR("Error loading firmware\n"); - goto fw_init_err; + goto init_err; } /* Handle the beginning of COMMON_XXX pases separatelly... */ @@ -5388,25 +5388,25 @@ static int bnx2x_func_hw_init(struct bnx2x *bp, case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: rc = bnx2x_func_init_cmn_chip(bp, drv); if (rc) - goto init_hw_err; + goto init_err; break; case FW_MSG_CODE_DRV_LOAD_COMMON: rc = bnx2x_func_init_cmn(bp, drv); if (rc) - goto init_hw_err; + goto init_err; break; case FW_MSG_CODE_DRV_LOAD_PORT: rc = bnx2x_func_init_port(bp, drv); if (rc) - goto init_hw_err; + goto init_err; break; case FW_MSG_CODE_DRV_LOAD_FUNCTION: rc = bnx2x_func_init_func(bp, drv); if (rc) - goto init_hw_err; + goto init_err; break; default: @@ -5414,10 +5414,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp, rc = -EINVAL; } -init_hw_err: - drv->release_fw(bp); - -fw_init_err: +init_err: drv->gunzip_end(bp); /* In case of success, complete the comand immediatelly: no ramrods -- cgit From 5e773fdc535cf3f4fa8023fe2ce20dcf774dae8a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 15 Nov 2011 13:56:14 +0000 Subject: pch_gbe: Move #include of module.h The first #include must be pch_gbe.h as it does a #define of pr_fmt. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c index 9c075ea2682e..9cb5f912e489 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c @@ -18,8 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ -#include /* for __MODULE_STRING */ #include "pch_gbe.h" +#include /* for __MODULE_STRING */ #define OPTION_UNSET -1 #define OPTION_DISABLED 0 -- cgit From 377a4673147d0144cf4951bf91f4c867a2c18e5e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 16 Nov 2011 17:58:46 -0500 Subject: MAINTAINERS: change email address for shemminger My old email account at linux-foundation is no longer usable after the LF breakin. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4808256446f2..aa11a574e74e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2576,7 +2576,7 @@ S: Maintained F: drivers/net/ethernet/i825xx/eexpress.* ETHERNET BRIDGE -M: Stephen Hemminger +M: Stephen Hemminger L: bridge@lists.linux-foundation.org L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net:Bridge @@ -4462,7 +4462,7 @@ S: Supported F: drivers/infiniband/hw/nes/ NETEM NETWORK EMULATOR -M: Stephen Hemminger +M: Stephen Hemminger L: netem@lists.linux-foundation.org S: Maintained F: net/sched/sch_netem.c @@ -5977,7 +5977,7 @@ S: Maintained F: drivers/usb/misc/sisusbvga/ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS -M: Stephen Hemminger +M: Stephen Hemminger L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/marvell/sk* -- cgit From 9b7c547f7747991fe62f622698ea1bf470f256f4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 16 Nov 2011 21:44:33 +0800 Subject: ARM: Update mach-types to fix mxs build breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add entry m28evk to fix the following mxs build breakage. CHK include/generated/compile.h CC arch/arm/mach-mxs/clock-mx28.o arch/arm/mach-mxs/clock-mx28.c: In function 'clk_misc_init': arch/arm/mach-mxs/clock-mx28.c:748: error: implicit declaration of function 'machine_is_m28evk' make[1]: *** [arch/arm/mach-mxs/clock-mx28.o] Error 1 make: *** [arch/arm/mach-mxs] Error 2 Signed-off-by: Shawn Guo Acked-by: Uwe Kleine-König --- arch/arm/tools/mach-types | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 5bdeef969847..ccbe16f47227 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1123,5 +1123,6 @@ blissc MACH_BLISSC BLISSC 3491 thales_adc MACH_THALES_ADC THALES_ADC 3492 ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493 atdgp318 MACH_ATDGP318 ATDGP318 3494 +m28evk MACH_M28EVK M28EVK 3613 smdk4212 MACH_SMDK4212 SMDK4212 3638 smdk4412 MACH_SMDK4412 SMDK4412 3765 -- cgit From e4b3bbe31d9a1e9540c6e9c95f5e7fd92acbcacf Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 11 Nov 2011 20:11:14 +0800 Subject: ARM: pxa168/gplugd: add the correct SSP device There is no SSP0, but SSP1 is used on gplugd as an I2S port. Acked-by: Tanmay Upadhyay Signed-off-by: Eric Miao --- arch/arm/mach-mmp/gplugd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 69156568bc41..4665767a4f79 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -182,7 +182,7 @@ static void __init gplugd_init(void) /* on-chip devices */ pxa168_add_uart(3); - pxa168_add_ssp(0); + pxa168_add_ssp(1); pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info)); pxa168_add_eth(&gplugd_eth_platform_data); -- cgit From 0d2f096b8785b67c38afcf6e1fbb9674af2e05ca Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Wed, 16 Nov 2011 10:50:56 -0800 Subject: random: Fix handing of arch_get_random_long in get_random_bytes() If there is an architecture-specific random number generator we use it to acquire randomness one "long" at a time. We should put these random words into consecutive words in the result buffer - not just overwrite the first word again and again. Signed-off-by: Tony Luck Acked-by: Thomas Gleixner Link: http://lkml.kernel.org/r/4ec4061010261a4cb0@agluck-desktop.sc.intel.com Signed-off-by: H. Peter Anvin --- drivers/char/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 63e19ba56bbe..6035ab8d5ef7 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes) if (!arch_get_random_long(&v)) break; - memcpy(buf, &v, chunk); + memcpy(p, &v, chunk); p += chunk; nbytes -= chunk; } -- cgit From 396464dfbba8f734c57346489b871e7ed64dcdd1 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 14 Nov 2011 15:20:49 +0900 Subject: drm/exynos: Add disable of manager Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 + drivers/gpu/drm/exynos/exynos_drm_encoder.c | 18 +++++++++ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 61 +++++++++++++++++------------ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 2d74f8550e20..5e02e6ecc2e0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -147,12 +147,14 @@ struct exynos_drm_display_ops { * @mode_set: convert drm_display_mode to hw specific display mode and * would be called by encoder->mode_set(). * @commit: set current hw specific display mode to hw. + * @disable: disable hardware specific display mode. * @enable_vblank: specific driver callback for enabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt. */ struct exynos_drm_manager_ops { void (*mode_set)(struct device *subdrv_dev, void *mode); void (*commit)(struct device *subdrv_dev); + void (*disable)(struct device *subdrv_dev); int (*enable_vblank)(struct device *subdrv_dev); void (*disable_vblank)(struct device *subdrv_dev); }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 866f419f485b..153061415baf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -53,9 +53,27 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct drm_connector *connector; struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_manager_ops *manager_ops = manager->ops; DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); + switch (mode) { + case DRM_MODE_DPMS_ON: + if (manager_ops && manager_ops->commit) + manager_ops->commit(manager->dev); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + /* TODO */ + if (manager_ops && manager_ops->disable) + manager_ops->disable(manager->dev); + break; + default: + DRM_ERROR("unspecified mode %d\n", mode); + break; + } + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->encoder == encoder) { struct exynos_drm_display_ops *display_ops = diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 272c3b53c062..db3b3d9e731d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -177,6 +177,40 @@ static void fimd_commit(struct device *dev) writel(val, ctx->regs + VIDCON0); } +static void fimd_disable(struct device *dev) +{ + struct fimd_context *ctx = get_fimd_context(dev); + struct exynos_drm_subdrv *subdrv = &ctx->subdrv; + struct drm_device *drm_dev = subdrv->drm_dev; + struct exynos_drm_manager *manager = &subdrv->manager; + u32 val; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* fimd dma off */ + val = readl(ctx->regs + VIDCON0); + val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F); + writel(val, ctx->regs + VIDCON0); + + /* + * if vblank is enabled status with dma off then + * it disables vsync interrupt. + */ + if (drm_dev->vblank_enabled[manager->pipe] && + atomic_read(&drm_dev->vblank_refcount[manager->pipe])) { + drm_vblank_put(drm_dev, manager->pipe); + + /* + * if vblank_disable_allowed is 0 then disable + * vsync interrupt right now else the vsync interrupt + * would be disabled by drm timer once a current process + * gives up ownershop of vblank event. + */ + if (!drm_dev->vblank_disable_allowed) + drm_vblank_off(drm_dev, manager->pipe); + } +} + static int fimd_enable_vblank(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); @@ -220,6 +254,7 @@ static void fimd_disable_vblank(struct device *dev) static struct exynos_drm_manager_ops fimd_manager_ops = { .commit = fimd_commit, + .disable = fimd_disable, .enable_vblank = fimd_enable_vblank, .disable_vblank = fimd_disable_vblank, }; @@ -447,9 +482,6 @@ static void fimd_win_commit(struct device *dev) static void fimd_win_disable(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct drm_device *drm_dev = subdrv->drm_dev; - struct exynos_drm_manager *manager = &subdrv->manager; int win = ctx->default_win; u32 val; @@ -473,29 +505,6 @@ static void fimd_win_disable(struct device *dev) val &= ~SHADOWCON_CHx_ENABLE(win); val &= ~SHADOWCON_WINx_PROTECT(win); writel(val, ctx->regs + SHADOWCON); - - /* fimd dma off. */ - val = readl(ctx->regs + VIDCON0); - val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F); - writel(val, ctx->regs + VIDCON0); - - /* - * if vblank is enabled status with dma off then - * it disables vsync interrupt. - */ - if (drm_dev->vblank_enabled[manager->pipe] && - atomic_read(&drm_dev->vblank_refcount[manager->pipe])) { - drm_vblank_put(drm_dev, manager->pipe); - - /* - * if vblank_disable_allowed is 0 then disable vsync interrupt - * right now else the vsync interrupt would be disabled by drm - * timer once a current process gives up ownershop of - * vblank event. - */ - if (!drm_dev->vblank_disable_allowed) - drm_vblank_off(drm_dev, manager->pipe); - } } static struct exynos_drm_overlay_ops fimd_overlay_ops = { -- cgit From ca22e3cc25f180859561f36d51bf21278db5ae11 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 15 Nov 2011 16:25:39 +0900 Subject: drm/exynos: fixed wrong err ptr usage and destroy call in exeception - exynos_drm_buf_create() returns err pointer so NULL check is wrong. - Case that exynos_gem_obj is not created, destroy call in exception handle lable uses this pointer. so instead buffer is directly used. Signed-off-by: Seung-Woo Kim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index b1b94b1e4400..aba0fe47f7ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -128,30 +128,25 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, struct exynos_drm_gem_obj *exynos_gem_obj = NULL; struct exynos_drm_gem_buf *buffer; - int ret; size = roundup(size, PAGE_SIZE); DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); buffer = exynos_drm_buf_create(dev, size); - if (!buffer) - return ERR_PTR(-ENOMEM); + if (IS_ERR(buffer)) { + return ERR_CAST(buffer); + } exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size); if (IS_ERR(exynos_gem_obj)) { - ret = PTR_ERR(exynos_gem_obj); - goto err_gem_init; + exynos_drm_buf_destroy(dev, buffer); + return exynos_gem_obj; } exynos_gem_obj->buffer = buffer; return exynos_gem_obj; - -err_gem_init: - exynos_drm_buf_destroy(dev, exynos_gem_obj->buffer); - - return ERR_PTR(ret); } int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, -- cgit From bbc13ab9d26f4ff675775dd7dc24d5cae17b85d5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 16 Nov 2011 06:00:08 +0000 Subject: r6040: fix check against MCRO_HASHEN bit in r6040_multicast_list We are checking whether the MCR0_HASHEN bit is set using a logical and instead of bitwise and, fix that. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/rdc/r6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index 1fc01ca72b46..4bf68cfef390 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -940,7 +940,7 @@ static void r6040_multicast_list(struct net_device *dev) iowrite16(lp->mcr0, ioaddr + MCR0); /* Fill the MAC hash tables with their values */ - if (lp->mcr0 && MCR0_HASH_EN) { + if (lp->mcr0 & MCR0_HASH_EN) { iowrite16(hash_table[0], ioaddr + MAR0); iowrite16(hash_table[1], ioaddr + MAR1); iowrite16(hash_table[2], ioaddr + MAR2); -- cgit From 1401a8008a09e079236261be37e98847c799760a Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:42:55 +0000 Subject: sky2: fix hang on shutdown (and other irq issues) There are several problems with recent change to how IRQ's are setup. * synchronize_irq in sky2_shutdown would hang because there was no IRQ setup. * when device was set to down, some IRQ bits left enabled so a hardware error would produce IRQ with no handler * quick link on Optima chip set was enabled without handler * suspend/resume would leave IRQ on with no handler if device was down Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 45 ++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index fdc6c394c683..f9c4529299bd 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1747,6 +1747,11 @@ static int sky2_up(struct net_device *dev) sky2_hw_up(sky2); + if (hw->chip_id == CHIP_ID_YUKON_OPT || + hw->chip_id == CHIP_ID_YUKON_PRM || + hw->chip_id == CHIP_ID_YUKON_OP_2) + imask |= Y2_IS_PHY_QLNK; /* enable PHY Quick Link */ + /* Enable interrupts from phy/mac for port */ imask = sky2_read32(hw, B0_IMSK); imask |= portirq_msk[port]; @@ -2101,15 +2106,21 @@ static int sky2_down(struct net_device *dev) netif_info(sky2, ifdown, dev, "disabling interface\n"); - /* Disable port IRQ */ - sky2_write32(hw, B0_IMSK, - sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]); - sky2_read32(hw, B0_IMSK); - if (hw->ports == 1) { + sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); + napi_disable(&hw->napi); free_irq(hw->pdev->irq, hw); } else { + u32 imask; + + /* Disable port IRQ */ + imask = sky2_read32(hw, B0_IMSK); + imask &= ~portirq_msk[sky2->port]; + sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_IMSK); + synchronize_irq(hw->pdev->irq); napi_synchronize(&hw->napi); } @@ -3258,7 +3269,6 @@ static void sky2_reset(struct sky2_hw *hw) hw->chip_id == CHIP_ID_YUKON_PRM || hw->chip_id == CHIP_ID_YUKON_OP_2) { u16 reg; - u32 msk; if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) { /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */ @@ -3281,11 +3291,6 @@ static void sky2_reset(struct sky2_hw *hw) sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PSM_CONFIG_REG4, reg); - /* enable PHY Quick Link */ - msk = sky2_read32(hw, B0_IMSK); - msk |= Y2_IS_PHY_QLNK; - sky2_write32(hw, B0_IMSK, msk); - /* check if PSMv2 was running before */ reg = sky2_pci_read16(hw, PSM_CONFIG_REG3); if (reg & PCI_EXP_LNKCTL_ASPMC) @@ -3412,7 +3417,9 @@ static void sky2_all_down(struct sky2_hw *hw) sky2_read32(hw, B0_IMSK); sky2_write32(hw, B0_IMSK, 0); - synchronize_irq(hw->pdev->irq); + + if (hw->ports > 1 || netif_running(hw->dev[0])) + synchronize_irq(hw->pdev->irq); napi_disable(&hw->napi); for (i = 0; i < hw->ports; i++) { @@ -3430,7 +3437,7 @@ static void sky2_all_down(struct sky2_hw *hw) static void sky2_all_up(struct sky2_hw *hw) { - u32 imask = Y2_IS_BASE; + u32 imask = 0; int i; for (i = 0; i < hw->ports; i++) { @@ -3446,11 +3453,13 @@ static void sky2_all_up(struct sky2_hw *hw) netif_wake_queue(dev); } - sky2_write32(hw, B0_IMSK, imask); - sky2_read32(hw, B0_IMSK); - - sky2_read32(hw, B0_Y2_SP_LISR); - napi_enable(&hw->napi); + if (imask || hw->ports > 1) { + imask |= Y2_IS_BASE; + sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_IMSK); + sky2_read32(hw, B0_Y2_SP_LISR); + napi_enable(&hw->napi); + } } static void sky2_restart(struct work_struct *work) -- cgit From f9687c44d322ca1bcbc362c8a54084425fda3ab8 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:42:56 +0000 Subject: sky2: pci posting issues A couple of the reset and setup paths have possible PCI posting issues. When setting registers, a read is necessary to force the writes to complete. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index f9c4529299bd..98ad38a5588f 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -869,6 +869,7 @@ static void sky2_wol_init(struct sky2_port *sky2) /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + sky2_read32(hw, B0_CTST); } static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) @@ -2045,6 +2046,8 @@ static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); + + sky2_read32(hw, B0_CTST); } static void sky2_hw_down(struct sky2_port *sky2) -- cgit From 926d0977b28793533a99ec66484385b5f602e9c8 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:42:57 +0000 Subject: sky2: rename up/down functions The code is clearer if the up/down functions are renamed to open/close like other drivers. Purely syntax change. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 98ad38a5588f..98d435a187b1 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1728,7 +1728,7 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name) /* Bring up network interface. */ -static int sky2_up(struct net_device *dev) +static int sky2_open(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; @@ -2098,7 +2098,7 @@ static void sky2_hw_down(struct sky2_port *sky2) } /* Network shutdown */ -static int sky2_down(struct net_device *dev) +static int sky2_close(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; @@ -2601,7 +2601,7 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) if (netif_running(dev)) { sky2_tx_complete(sky2, last); - /* Wake unless it's detached, and called e.g. from sky2_down() */ + /* Wake unless it's detached, and called e.g. from sky2_close() */ if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) netif_wake_queue(dev); } @@ -3391,7 +3391,7 @@ static void sky2_detach(struct net_device *dev) netif_tx_lock(dev); netif_device_detach(dev); /* stop txq */ netif_tx_unlock(dev); - sky2_down(dev); + sky2_close(dev); } } @@ -3401,7 +3401,7 @@ static int sky2_reattach(struct net_device *dev) int err = 0; if (netif_running(dev)) { - err = sky2_up(dev); + err = sky2_open(dev); if (err) { netdev_info(dev, "could not restart %d\n", err); dev_close(dev); @@ -4568,7 +4568,7 @@ static int sky2_device_event(struct notifier_block *unused, struct net_device *dev = ptr; struct sky2_port *sky2 = netdev_priv(dev); - if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug) + if (dev->netdev_ops->ndo_open != sky2_open || !sky2_debug) return NOTIFY_DONE; switch (event) { @@ -4633,8 +4633,8 @@ static __exit void sky2_debug_cleanup(void) not allowing netpoll on second port */ static const struct net_device_ops sky2_netdev_ops[2] = { { - .ndo_open = sky2_up, - .ndo_stop = sky2_down, + .ndo_open = sky2_open, + .ndo_stop = sky2_close, .ndo_start_xmit = sky2_xmit_frame, .ndo_do_ioctl = sky2_ioctl, .ndo_validate_addr = eth_validate_addr, @@ -4650,8 +4650,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = { #endif }, { - .ndo_open = sky2_up, - .ndo_stop = sky2_down, + .ndo_open = sky2_open, + .ndo_stop = sky2_close, .ndo_start_xmit = sky2_xmit_frame, .ndo_do_ioctl = sky2_ioctl, .ndo_validate_addr = eth_validate_addr, -- cgit From b1cb82566242fbb54d5c655e23995a8f7bd37ecf Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:42:58 +0000 Subject: sky2: reduce default Tx ring size The default Tx ring size for the sky2 driver is quite large and could cause excess buffer bloat for many users. The minimum ring size possible and still allow handling the worst case packet on 64bit platforms is 38 which gets rounded up to a power of 2. But most packets only require a couple of ring elements. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 98d435a187b1..3777fb348b86 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -68,7 +68,7 @@ #define MAX_SKB_TX_LE (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1)) #define TX_MIN_PENDING (MAX_SKB_TX_LE+1) #define TX_MAX_PENDING 1024 -#define TX_DEF_PENDING 127 +#define TX_DEF_PENDING 63 #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 -- cgit From 00427a7387a1c91ddb6b69e50916173d8aca66e0 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:42:59 +0000 Subject: sky2: used fixed RSS key Rather than generating a different RSS key on each boot, just use a predetermined value that will map same flow to same value on every device. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 3777fb348b86..48c9e1281c7e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1275,6 +1275,14 @@ static void rx_set_checksum(struct sky2_port *sky2) ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } +/* + * Fixed initial key as seed to RSS. + */ +static const uint32_t rss_init_key[10] = { + 0x7c3351da, 0x51c5cf4e, 0x44adbdd1, 0xe8d38d18, 0x48897c43, + 0xb1d60e7e, 0x6a3dd760, 0x01a2e453, 0x16f46f13, 0x1a0e7b30 +}; + /* Enable/disable receive hash calculation (RSS) */ static void rx_set_rss(struct net_device *dev, u32 features) { @@ -1290,12 +1298,9 @@ static void rx_set_rss(struct net_device *dev, u32 features) /* Program RSS initial values */ if (features & NETIF_F_RXHASH) { - u32 key[nkeys]; - - get_random_bytes(key, nkeys * sizeof(u32)); for (i = 0; i < nkeys; i++) sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4), - key[i]); + rss_init_key[i]); /* Need to turn on (undocumented) flag to make hashing work */ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), -- cgit From d9fa7c86f1fca60693beea187c963cfda4a54a06 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Nov 2011 13:43:00 +0000 Subject: sky2: version 1.30 Update version number. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 48c9e1281c7e..539de09cffc9 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -50,7 +50,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.29" +#define DRV_VERSION "1.30" /* * The Yukon II chipset takes 64 bit command blocks (called list elements) -- cgit From ea441d1104cf1efb471fa81bc91e9fd1e6ae29fd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 16 Nov 2011 21:43:59 -0500 Subject: new helper: mount_subtree() takes vfsmount and relative path, does lookup within that vfsmount (possibly triggering automounts) and returns the result as root of subtree suitable for return by ->mount() (i.e. a reference to dentry and an active reference to its superblock grabbed, superblock locked exclusive). btrfs and nfs switched to it instead of open-coding the sucker. Signed-off-by: Al Viro --- fs/btrfs/super.c | 35 ++++++----------------------------- fs/namespace.c | 28 ++++++++++++++++++++++++++++ fs/nfs/super.c | 30 ++++++------------------------ include/linux/fs.h | 1 + 4 files changed, 41 insertions(+), 53 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index cfbedd7755b0..17ee7fc5e64e 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -825,13 +825,9 @@ static char *setup_root_args(char *args) static struct dentry *mount_subvol(const char *subvol_name, int flags, const char *device_name, char *data) { - struct super_block *s; struct dentry *root; struct vfsmount *mnt; - struct mnt_namespace *ns_private; char *newargs; - struct path path; - int error; newargs = setup_root_args(data); if (!newargs) @@ -842,36 +838,17 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, if (IS_ERR(mnt)) return ERR_CAST(mnt); - ns_private = create_mnt_ns(mnt); - if (IS_ERR(ns_private)) - return ERR_CAST(ns_private); - - /* - * This will trigger the automount of the subvol so we can just - * drop the mnt we have here and return the dentry that we - * found. - */ - error = vfs_path_lookup(mnt->mnt_root, mnt, subvol_name, - LOOKUP_FOLLOW, &path); - put_mnt_ns(ns_private); - if (error) - return ERR_PTR(error); + root = mount_subtree(mnt, subvol_name); - if (!is_subvolume_inode(path.dentry->d_inode)) { - path_put(&path); - error = -EINVAL; + if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) { + struct super_block *s = root->d_sb; + dput(root); + root = ERR_PTR(-EINVAL); + deactivate_locked_super(s); printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n", subvol_name); - return ERR_PTR(-EINVAL); } - /* Get a ref to the sb and the dentry we found and return it */ - s = path.mnt->mnt_sb; - atomic_inc(&s->s_active); - root = dget(path.dentry); - path_put(&path); - down_write(&s->s_umount); - return root; } diff --git a/fs/namespace.c b/fs/namespace.c index aea4b7689840..50ee30345b4f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2490,6 +2490,34 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) } EXPORT_SYMBOL(create_mnt_ns); +struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) +{ + struct mnt_namespace *ns; + struct path path; + int err; + + ns = create_mnt_ns(mnt); + if (IS_ERR(ns)) + return ERR_CAST(ns); + + err = vfs_path_lookup(mnt->mnt_root, mnt, + name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); + + put_mnt_ns(ns); + + if (err) + return ERR_PTR(err); + + /* trade a vfsmount reference for active sb one */ + atomic_inc(&path.mnt->mnt_sb->s_active); + mntput(path.mnt); + /* lock the sucker */ + down_write(&path.mnt->mnt_sb->s_umount); + /* ... and return the root of (sub)tree on it */ + return path.dentry; +} +EXPORT_SYMBOL(mount_subtree); + SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 46d69f38fd55..134777406ee3 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2787,35 +2787,17 @@ static void nfs_referral_loop_unprotect(void) static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, const char *export_path) { - struct mnt_namespace *ns_private; - struct super_block *s; struct dentry *dentry; - struct path path; - int ret; + int ret = nfs_referral_loop_protect(); - ns_private = create_mnt_ns(root_mnt); - if (IS_ERR(ns_private)) - return ERR_CAST(ns_private); - - ret = nfs_referral_loop_protect(); - if (ret == 0) { - ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt, - export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, - &path); - nfs_referral_loop_unprotect(); - } - - put_mnt_ns(ns_private); - - if (ret != 0) + if (ret) { + mntput(root_mnt); return ERR_PTR(ret); + } - s = path.mnt->mnt_sb; - atomic_inc(&s->s_active); - dentry = dget(path.dentry); + dentry = mount_subtree(root_mnt, export_path); + nfs_referral_loop_unprotect(); - path_put(&path); - down_write(&s->s_umount); return dentry; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 0c4df261af7e..e3130220ce3e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1886,6 +1886,7 @@ extern struct dentry *mount_single(struct file_system_type *fs_type, extern struct dentry *mount_nodev(struct file_system_type *fs_type, int flags, void *data, int (*fill_super)(struct super_block *, void *, int)); +extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path); void generic_shutdown_super(struct super_block *sb); void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); -- cgit From 832dd3c17f7829fe8e4c257531d6c5c9e19bd7ac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 19:34:06 -0700 Subject: drm/i915: Move common PCH_PP_CONTROL setup to ironlake_get_pp_control Every usage of PCH_PP_CONTROL sets the PANEL_UNLOCK_REGS value to ensure that writes will be respected, move this to a common function to make the driver cleaner. No functional changes. Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7259034b33d1..efe5f9e0de9e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -906,6 +906,19 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp) msleep(delay); } +/* Read the current pp_control value, unlocking the register if it + * is locked + */ + +static u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv) +{ + u32 control = I915_READ(PCH_PP_CONTROL); + + control &= ~PANEL_UNLOCK_MASK; + control |= PANEL_UNLOCK_REGS; + return control; +} + static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp->base.base.dev; @@ -926,9 +939,7 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) } ironlake_wait_panel_off(intel_dp); - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); pp |= EDP_FORCE_VDD; I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -951,9 +962,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) u32 pp; if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); pp &= ~EDP_FORCE_VDD; I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -1012,9 +1021,7 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp) return; ironlake_wait_panel_off(intel_dp); - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); if (IS_GEN5(dev)) { /* ILK workaround: disable reset around power sequence */ @@ -1049,9 +1056,7 @@ static void ironlake_edp_panel_off(struct drm_encoder *encoder) if (!is_edp(intel_dp)) return; - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); if (IS_GEN5(dev)) { /* ILK workaround: disable reset around power sequence */ @@ -1098,9 +1103,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp) * allowing it to appear. */ msleep(intel_dp->backlight_on_delay); - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); pp |= EDP_BLC_ENABLE; I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -1116,9 +1119,7 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp) return; DRM_DEBUG_KMS("\n"); - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~PANEL_UNLOCK_MASK; - pp |= PANEL_UNLOCK_REGS; + pp = ironlake_get_pp_control(dev_priv); pp &= ~EDP_BLC_ENABLE; I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); -- cgit From 93f62dad5ffe0962d83772fd16c0c1a9dd69767d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 19:45:03 -0700 Subject: drm/i915: Remove link_status field from intel_dp structure No persistent data was ever stored here, so link_status is instead allocated on the stack as needed. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_dp.c | 65 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index efe5f9e0de9e..2c0c482222e1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -58,7 +58,6 @@ struct intel_dp { struct i2c_algo_dp_aux_data algo; bool is_pch_edp; uint8_t train_set[4]; - uint8_t link_status[DP_LINK_STATUS_SIZE]; int panel_power_up_delay; int panel_power_down_delay; int panel_power_cycle_delay; @@ -1285,11 +1284,11 @@ intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address, * link status information */ static bool -intel_dp_get_link_status(struct intel_dp *intel_dp) +intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { return intel_dp_aux_native_read_retry(intel_dp, DP_LANE0_1_STATUS, - intel_dp->link_status, + link_status, DP_LINK_STATUS_SIZE); } @@ -1301,27 +1300,25 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], } static uint8_t -intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], +intel_get_adjust_request_voltage(uint8_t adjust_request[2], int lane) { - int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); int s = ((lane & 1) ? DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); - uint8_t l = intel_dp_link_status(link_status, i); + uint8_t l = adjust_request[lane>>1]; return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; } static uint8_t -intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], +intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2], int lane) { - int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); int s = ((lane & 1) ? DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); - uint8_t l = intel_dp_link_status(link_status, i); + uint8_t l = adjust_request[lane>>1]; return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; } @@ -1362,15 +1359,18 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing) } static void -intel_get_adjust_train(struct intel_dp *intel_dp) +intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { + struct drm_device *dev = intel_dp->base.base.dev; uint8_t v = 0; uint8_t p = 0; int lane; + uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS); + int voltage_max; for (lane = 0; lane < intel_dp->lane_count; lane++) { - uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane); - uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); + uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane); + uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane); if (this_v > v) v = this_v; @@ -1389,7 +1389,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp) } static uint32_t -intel_dp_signal_levels(uint8_t train_set, int lane_count) +intel_dp_signal_levels(uint8_t train_set) { uint32_t signal_levels = 0; @@ -1458,9 +1458,8 @@ static uint8_t intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) { - int i = DP_LANE0_1_STATUS + (lane >> 1); int s = (lane & 1) * 4; - uint8_t l = intel_dp_link_status(link_status, i); + uint8_t l = link_status[lane>>1]; return (l >> s) & 0xf; } @@ -1485,18 +1484,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count DP_LANE_CHANNEL_EQ_DONE|\ DP_LANE_SYMBOL_LOCKED) static bool -intel_channel_eq_ok(struct intel_dp *intel_dp) +intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { uint8_t lane_align; uint8_t lane_status; int lane; - lane_align = intel_dp_link_status(intel_dp->link_status, + lane_align = intel_dp_link_status(link_status, DP_LANE_ALIGN_STATUS_UPDATED); if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) return false; for (lane = 0; lane < intel_dp->lane_count; lane++) { - lane_status = intel_get_lane_status(intel_dp->link_status, lane); + lane_status = intel_get_lane_status(link_status, lane); if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) return false; } @@ -1569,12 +1568,14 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) clock_recovery = false; for (;;) { /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + uint8_t link_status[DP_LINK_STATUS_SIZE]; uint32_t signal_levels; if (IS_GEN6(dev) && is_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { - signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); + signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); + DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels); DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } @@ -1590,10 +1591,13 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) /* Set training pattern 1 */ udelay(100); - if (!intel_dp_get_link_status(intel_dp)) + if (!intel_dp_get_link_status(intel_dp, link_status)) { + DRM_ERROR("failed to get link status\n"); break; + } - if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { + DRM_DEBUG_KMS("clock recovery OK\n"); clock_recovery = true; break; } @@ -1615,7 +1619,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new intel_dp->train_set as requested by target */ - intel_get_adjust_train(intel_dp); + intel_get_adjust_train(intel_dp, link_status); } intel_dp->DP = DP; @@ -1638,6 +1642,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) for (;;) { /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ uint32_t signal_levels; + uint8_t link_status[DP_LINK_STATUS_SIZE]; if (cr_tries > 5) { DRM_ERROR("failed to train DP, aborting\n"); @@ -1649,7 +1654,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { - signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); + signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); + DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels); DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } @@ -1665,17 +1671,17 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) break; udelay(400); - if (!intel_dp_get_link_status(intel_dp)) + if (!intel_dp_get_link_status(intel_dp, link_status)) break; /* Make sure clock is still ok */ - if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { intel_dp_start_link_train(intel_dp); cr_tries++; continue; } - if (intel_channel_eq_ok(intel_dp)) { + if (intel_channel_eq_ok(intel_dp, link_status)) { channel_eq = true; break; } @@ -1690,7 +1696,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) } /* Compute new intel_dp->train_set as requested by target */ - intel_get_adjust_train(intel_dp); + intel_get_adjust_train(intel_dp, link_status); ++tries; } @@ -1822,6 +1828,7 @@ static void intel_dp_check_link_status(struct intel_dp *intel_dp) { u8 sink_irq_vector; + u8 link_status[DP_LINK_STATUS_SIZE]; if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) return; @@ -1830,7 +1837,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) return; /* Try to read receiver status if the link appears to be up */ - if (!intel_dp_get_link_status(intel_dp)) { + if (!intel_dp_get_link_status(intel_dp, link_status)) { intel_dp_link_down(intel_dp); return; } @@ -1855,7 +1862,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - if (!intel_channel_eq_ok(intel_dp)) { + if (!intel_channel_eq_ok(intel_dp, link_status)) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", drm_get_encoder_name(&intel_dp->base.base)); intel_dp_start_link_train(intel_dp); -- cgit From 417e822deee1d2bcd8a8a60660c40a0903713f2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 19:54:11 -0700 Subject: drm/i915: Treat PCH eDP like DP in most places PCH eDP has many of the same needs as regular PCH DP connections, including the DP_CTl bit settings, the TRANS_DP_CTL register. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_dp.c | 103 ++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 591eb0ed3110..e77a863a3833 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2933,7 +2933,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) /* For PCH DP, enable TRANS_DP_CTL */ if (HAS_PCH_CPT(dev) && - intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5; reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2c0c482222e1..d1eabd4165c4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -766,10 +766,10 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, continue; intel_dp = enc_to_intel_dp(encoder); - if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) { + if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || is_pch_edp(intel_dp)) { lane_count = intel_dp->lane_count; break; - } else if (is_edp(intel_dp)) { + } else if (is_cpu_edp(intel_dp)) { lane_count = dev_priv->edp.lanes; break; } @@ -808,6 +808,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_crtc *crtc = intel_dp->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -820,18 +821,31 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ironlake_edp_pll_off(encoder); } - intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; - intel_dp->DP |= intel_dp->color_range; + /* + * There are three kinds of DP registers: + * + * IBX PCH + * CPU + * CPT PCH + * + * IBX PCH and CPU are the same for almost everything, + * except that the CPU DP PLL is configured in this + * register + * + * CPT PCH is quite different, having many bits moved + * to the TRANS_DP_CTL register instead. That + * configuration happens (oddly) in ironlake_pch_enable + */ - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - intel_dp->DP |= DP_SYNC_HS_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - intel_dp->DP |= DP_SYNC_VS_HIGH; + /* Preserve the BIOS-computed detected bit. This is + * supposed to be read-only. + */ + intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED; + intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) - intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - else - intel_dp->DP |= DP_LINK_TRAIN_OFF; + /* Handle DP bits in common between all three register formats */ + + intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; switch (intel_dp->lane_count) { case 1: @@ -850,32 +864,45 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; intel_write_eld(encoder, adjusted_mode); } - memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); intel_dp->link_configuration[0] = intel_dp->link_bw; intel_dp->link_configuration[1] = intel_dp->lane_count; intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; - /* * Check for DPCD version > 1.1 and enhanced framing support */ if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - intel_dp->DP |= DP_ENHANCED_FRAMING; } - /* CPT DP's pipe select is decided in TRANS_DP_CTL */ - if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev)) - intel_dp->DP |= DP_PIPEB_SELECT; + /* Split out the IBX/CPU vs CPT settings */ - if (is_cpu_edp(intel_dp)) { - /* don't miss out required setting for eDP */ - intel_dp->DP |= DP_PLL_ENABLE; - if (adjusted_mode->clock < 200000) - intel_dp->DP |= DP_PLL_FREQ_160MHZ; - else - intel_dp->DP |= DP_PLL_FREQ_270MHZ; + if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { + intel_dp->DP |= intel_dp->color_range; + + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + intel_dp->DP |= DP_SYNC_HS_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + intel_dp->DP |= DP_SYNC_VS_HIGH; + intel_dp->DP |= DP_LINK_TRAIN_OFF; + + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + intel_dp->DP |= DP_ENHANCED_FRAMING; + + if (intel_crtc->pipe == 1) + intel_dp->DP |= DP_PIPEB_SELECT; + + if (is_cpu_edp(intel_dp)) { + /* don't miss out required setting for eDP */ + intel_dp->DP |= DP_PLL_ENABLE; + if (adjusted_mode->clock < 200000) + intel_dp->DP |= DP_PLL_FREQ_160MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + } + } else { + intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; } } @@ -1341,6 +1368,7 @@ static char *link_train_names[] = { * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB */ #define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 +#define I830_DP_VOLTAGE_MAX_CPT DP_TRAIN_VOLTAGE_SWING_1200 static uint8_t intel_dp_pre_emphasis_max(uint8_t voltage_swing) @@ -1378,8 +1406,12 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST p = this_p; } - if (v >= I830_DP_VOLTAGE_MAX) - v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; + if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + voltage_max = I830_DP_VOLTAGE_MAX_CPT; + else + voltage_max = I830_DP_VOLTAGE_MAX; + if (v >= voltage_max) + v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; if (p >= intel_dp_pre_emphasis_max(v)) p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; @@ -1570,7 +1602,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ uint8_t link_status[DP_LINK_STATUS_SIZE]; uint32_t signal_levels; - if (IS_GEN6(dev) && is_edp(intel_dp)) { + + if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { @@ -1650,12 +1683,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) break; } - if (IS_GEN6(dev) && is_edp(intel_dp)) { + if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); - DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels); DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } @@ -1741,8 +1773,12 @@ intel_dp_link_down(struct intel_dp *intel_dp) msleep(17); - if (is_edp(intel_dp)) - DP |= DP_LINK_TRAIN_OFF; + if (is_edp(intel_dp)) { + if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + DP |= DP_LINK_TRAIN_OFF_CPT; + else + DP |= DP_LINK_TRAIN_OFF; + } if (!HAS_PCH_CPT(dev) && I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { @@ -2186,7 +2222,8 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc) continue; intel_dp = enc_to_intel_dp(encoder); - if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) + if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || + intel_dp->base.type == INTEL_OUTPUT_EDP) return intel_dp->output_reg; } -- cgit From 99ea7127a30bda29354e1ed3a75d80d5f9cfc2a7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 19:57:50 -0700 Subject: drm/i915: Let panel power sequencing hardware do its job The panel power sequencing hardware tracks the stages of panel power sequencing and signals when the panel is completely on or off. Instead of blindly assuming the panel timings will work, poll the panel power status register until it shows the correct values. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_reg.h | 17 +++-- drivers/gpu/drm/i915/intel_dp.c | 137 +++++++++++++++++++++------------------- 2 files changed, 85 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a34e86630f26..b080cc824001 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1553,12 +1553,21 @@ */ #define PP_READY (1 << 30) #define PP_SEQUENCE_NONE (0 << 28) -#define PP_SEQUENCE_ON (1 << 28) -#define PP_SEQUENCE_OFF (2 << 28) -#define PP_SEQUENCE_MASK 0x30000000 +#define PP_SEQUENCE_POWER_UP (1 << 28) +#define PP_SEQUENCE_POWER_DOWN (2 << 28) +#define PP_SEQUENCE_MASK (3 << 28) +#define PP_SEQUENCE_SHIFT 28 #define PP_CYCLE_DELAY_ACTIVE (1 << 27) -#define PP_SEQUENCE_STATE_ON_IDLE (1 << 3) #define PP_SEQUENCE_STATE_MASK 0x0000000f +#define PP_SEQUENCE_STATE_OFF_IDLE (0x0 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_1 (0x1 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_2 (0x2 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_3 (0x3 << 0) +#define PP_SEQUENCE_STATE_ON_IDLE (0x8 << 0) +#define PP_SEQUENCE_STATE_ON_S1_0 (0x9 << 0) +#define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0) +#define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0) +#define PP_SEQUENCE_STATE_RESET (0xf << 0) #define PP_CONTROL 0x61204 #define POWER_TARGET_ON (1 << 0) #define PP_ON_DELAYS 0x61208 diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d1eabd4165c4..56106101d3f8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -66,7 +66,6 @@ struct intel_dp { struct drm_display_mode *panel_fixed_mode; /* for eDP */ struct delayed_work panel_vdd_work; bool want_panel_vdd; - unsigned long panel_off_jiffies; }; /** @@ -906,32 +905,53 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } } -static void ironlake_wait_panel_off(struct intel_dp *intel_dp) +#define IDLE_ON_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) +#define IDLE_ON_VALUE (PP_ON | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) + +#define IDLE_OFF_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) +#define IDLE_OFF_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE) + +#define IDLE_CYCLE_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK) +#define IDLE_CYCLE_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE) + +static void ironlake_wait_panel_status(struct intel_dp *intel_dp, + u32 mask, + u32 value) { - unsigned long off_time; - unsigned long delay; + struct drm_device *dev = intel_dp->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; - DRM_DEBUG_KMS("Wait for panel power off time\n"); + DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n", + mask, value, + I915_READ(PCH_PP_STATUS), + I915_READ(PCH_PP_CONTROL)); - if (ironlake_edp_have_panel_power(intel_dp) || - ironlake_edp_have_panel_vdd(intel_dp)) - { - DRM_DEBUG_KMS("Panel still on, no delay needed\n"); - return; + if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) { + DRM_ERROR("Panel status timeout: status %08x control %08x\n", + I915_READ(PCH_PP_STATUS), + I915_READ(PCH_PP_CONTROL)); } +} - off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay); - if (time_after(jiffies, off_time)) { - DRM_DEBUG_KMS("Time already passed"); - return; - } - delay = jiffies_to_msecs(off_time - jiffies); - if (delay > intel_dp->panel_power_down_delay) - delay = intel_dp->panel_power_down_delay; - DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay); - msleep(delay); +static void ironlake_wait_panel_on(struct intel_dp *intel_dp) +{ + DRM_DEBUG_KMS("Wait for panel power on\n"); + ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE); } +static void ironlake_wait_panel_off(struct intel_dp *intel_dp) +{ + DRM_DEBUG_KMS("Wait for panel power off time\n"); + ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE); +} + +static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp) +{ + DRM_DEBUG_KMS("Wait for panel power cycle\n"); + ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE); +} + + /* Read the current pp_control value, unlocking the register if it * is locked */ @@ -959,12 +979,15 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) "eDP VDD already requested on\n"); intel_dp->want_panel_vdd = true; + if (ironlake_edp_have_panel_vdd(intel_dp)) { DRM_DEBUG_KMS("eDP VDD already on\n"); return; } - ironlake_wait_panel_off(intel_dp); + if (!ironlake_edp_have_panel_power(intel_dp)) + ironlake_wait_panel_power_cycle(intel_dp); + pp = ironlake_get_pp_control(dev_priv); pp |= EDP_FORCE_VDD; I915_WRITE(PCH_PP_CONTROL, pp); @@ -996,7 +1019,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) /* Make sure sequencer is idle before allowing subsequent activity */ DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n", I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); - intel_dp->panel_off_jiffies = jiffies; + + msleep(intel_dp->panel_power_down_delay); } } @@ -1034,21 +1058,25 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) } } -/* Returns true if the panel was already on when called */ static void ironlake_edp_panel_on(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; + u32 pp; if (!is_edp(intel_dp)) return; - if (ironlake_edp_have_panel_power(intel_dp)) + + DRM_DEBUG_KMS("Turn eDP power on\n"); + + if (ironlake_edp_have_panel_power(intel_dp)) { + DRM_DEBUG_KMS("eDP power already on\n"); return; + } - ironlake_wait_panel_off(intel_dp); - pp = ironlake_get_pp_control(dev_priv); + ironlake_wait_panel_power_cycle(intel_dp); + pp = ironlake_get_pp_control(dev_priv); if (IS_GEN5(dev)) { /* ILK workaround: disable reset around power sequence */ pp &= ~PANEL_POWER_RESET; @@ -1057,13 +1085,13 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp) } pp |= POWER_TARGET_ON; + if (!IS_GEN5(dev)) + pp |= PANEL_POWER_RESET; + I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); - if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, - 5000)) - DRM_ERROR("panel on wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); + ironlake_wait_panel_on(intel_dp); if (IS_GEN5(dev)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ @@ -1072,44 +1100,25 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp) } } -static void ironlake_edp_panel_off(struct drm_encoder *encoder) +static void ironlake_edp_panel_off(struct intel_dp *intel_dp) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_device *dev = encoder->dev; + struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | - PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; + u32 pp; if (!is_edp(intel_dp)) return; - pp = ironlake_get_pp_control(dev_priv); - if (IS_GEN5(dev)) { - /* ILK workaround: disable reset around power sequence */ - pp &= ~PANEL_POWER_RESET; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - } - - intel_dp->panel_off_jiffies = jiffies; + DRM_DEBUG_KMS("Turn eDP power off\n"); - if (IS_GEN5(dev)) { - pp &= ~POWER_TARGET_ON; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - pp &= ~POWER_TARGET_ON; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - msleep(intel_dp->panel_power_cycle_delay); + WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); - if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) - DRM_ERROR("panel off wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); + pp = ironlake_get_pp_control(dev_priv); + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); - pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - } + ironlake_wait_panel_off(intel_dp); } static void ironlake_edp_backlight_on(struct intel_dp *intel_dp) @@ -1223,7 +1232,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder) */ ironlake_edp_backlight_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_off(encoder); + ironlake_edp_panel_off(intel_dp); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1237,7 +1246,6 @@ static void intel_dp_commit(struct drm_encoder *encoder) intel_dp_start_link_train(intel_dp); ironlake_edp_panel_on(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, true); - intel_dp_complete_link_train(intel_dp); ironlake_edp_backlight_on(intel_dp); @@ -1261,7 +1269,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ironlake_edp_backlight_off(intel_dp); intel_dp_sink_dpms(intel_dp, mode); intel_dp_link_down(intel_dp); - ironlake_edp_panel_off(encoder); + ironlake_edp_panel_off(intel_dp); if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) ironlake_edp_pll_off(encoder); ironlake_edp_panel_vdd_off(intel_dp, false); @@ -2398,11 +2406,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay; - ironlake_edp_panel_vdd_on(intel_dp); ret = intel_dp_get_dpcd(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, false); + if (ret) { if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) dev_priv->no_aux_handshake = -- cgit From 21264c638b4f9179655a39436d0340bd0d4ab1de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 20:25:21 -0700 Subject: drm/i915: Make DP prepare/commit consistent with DP dpms Make sure the sequence of operations in all three functions makes sense: 1) The backlight must be off unless the screen is running 2) The link must be running to turn the eDP panel on/off 3) The CPU eDP PLL must be running until everything is off Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_dp.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 56106101d3f8..8e37fdd1fa2f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1222,17 +1222,18 @@ static void intel_dp_prepare(struct drm_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + ironlake_edp_backlight_off(intel_dp); + ironlake_edp_panel_off(intel_dp); + /* Wake up the sink first */ ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + intel_dp_link_down(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, false); /* Make sure the panel is off before trying to * change the mode */ - ironlake_edp_backlight_off(intel_dp); - intel_dp_link_down(intel_dp); - ironlake_edp_panel_off(intel_dp); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1264,16 +1265,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (mode != DRM_MODE_DPMS_ON) { + ironlake_edp_backlight_off(intel_dp); + ironlake_edp_panel_off(intel_dp); + ironlake_edp_panel_vdd_on(intel_dp); - if (is_edp(intel_dp)) - ironlake_edp_backlight_off(intel_dp); intel_dp_sink_dpms(intel_dp, mode); intel_dp_link_down(intel_dp); - ironlake_edp_panel_off(intel_dp); - if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) - ironlake_edp_pll_off(encoder); ironlake_edp_panel_vdd_off(intel_dp, false); + + if (is_cpu_edp(intel_dp)) + ironlake_edp_pll_off(encoder); } else { + if (is_cpu_edp(intel_dp)) + ironlake_edp_pll_on(encoder); + ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, mode); if (!(dp_reg & DP_PORT_EN)) { @@ -1281,7 +1286,6 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ironlake_edp_panel_on(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, true); intel_dp_complete_link_train(intel_dp); - ironlake_edp_backlight_on(intel_dp); } else ironlake_edp_panel_vdd_off(intel_dp, false); ironlake_edp_backlight_on(intel_dp); -- cgit From cdb0e95bf571dccc1f75fef9bdad21b167ef0b37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 20:00:06 -0700 Subject: drm/i915: Try harder during dp pattern 1 link training Instead of going through the sequence just once, run through the whole set up to 5 times to see if something can work. This isn't part of the DP spec, but the BIOS seems to do it, and given that link training failure is so bad, it seems reasonable to follow suit. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_dp.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8e37fdd1fa2f..7101b8b4f8b4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1581,7 +1581,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) int i; uint8_t voltage; bool clock_recovery = false; - int tries; + int voltage_tries, loop_tries; u32 reg; uint32_t DP = intel_dp->DP; @@ -1608,7 +1608,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP &= ~DP_LINK_TRAIN_MASK; memset(intel_dp->train_set, 0, 4); voltage = 0xff; - tries = 0; + voltage_tries = 0; + loop_tries = 0; clock_recovery = false; for (;;) { /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ @@ -1651,16 +1652,26 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) for (i = 0; i < intel_dp->lane_count; i++) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; - if (i == intel_dp->lane_count) - break; + if (i == intel_dp->lane_count) { + ++loop_tries; + if (loop_tries == 5) { + DRM_DEBUG_KMS("too many full retries, give up\n"); + break; + } + memset(intel_dp->train_set, 0, 4); + voltage_tries = 0; + continue; + } /* Check to see if we've tried the same voltage 5 times */ if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { - ++tries; - if (tries == 5) + ++voltage_tries; + if (voltage_tries == 5) { + DRM_DEBUG_KMS("too many voltage retries, give up\n"); break; + } } else - tries = 0; + voltage_tries = 0; voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new intel_dp->train_set as requested by target */ -- cgit From f2e8b18af95358cf5407bf263cba04fc4c379123 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Nov 2011 20:01:35 -0700 Subject: drm/i915: Remove trailing white space Found a couple of bare tabs in intel_dp.c Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7101b8b4f8b4..7bdf77e79798 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1042,7 +1042,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); - + intel_dp->want_panel_vdd = false; if (sync) { @@ -2388,7 +2388,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> PANEL_LIGHT_ON_DELAY_SHIFT; - + cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> PANEL_LIGHT_OFF_DELAY_SHIFT; -- cgit From b34f1f0931575bf1e1483472a5202b8247fa9b10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Nov 2011 10:17:59 -0700 Subject: drm/i915: Initiate DP link training only on the lanes we'll be using Limit the link training setting command to the lanes needed for the current mode. It seems vaguely possible that a monitor will try to train the other lanes and fail in some way, so this seems like the safer plan. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_dp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7bdf77e79798..8c3819b02a7f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1564,8 +1564,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_LANE0_SET, - intel_dp->train_set, 4); - if (ret != 4) + intel_dp->train_set, + intel_dp->lane_count); + if (ret != intel_dp->lane_count) return false; return true; -- cgit From 9a10f401a401ca69c6537641c8fc0d6b57b5aee8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Nov 2011 13:03:47 -0700 Subject: drm/i915: Use DPCD value for max DP lanes. The BIOS VBT value for an eDP panel has been shown to be incorrect on one machine, and we haven't found any machines where the DPCD value was wrong, so we'll use the DPCD value everywhere. Signed-off-by: Keith Packard Reviewed-by: Adam Jackson Reviewed-by: Jesse Barnes --- drivers/gpu/drm/i915/intel_dp.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8c3819b02a7f..ec28aebf5147 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -154,16 +154,12 @@ intel_edp_link_config(struct intel_encoder *intel_encoder, static int intel_dp_max_lane_count(struct intel_dp *intel_dp) { - int max_lane_count = 4; - - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { - max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; - switch (max_lane_count) { - case 1: case 2: case 4: - break; - default: - max_lane_count = 4; - } + int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; + switch (max_lane_count) { + case 1: case 2: case 4: + break; + default: + max_lane_count = 4; } return max_lane_count; } @@ -765,12 +761,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, continue; intel_dp = enc_to_intel_dp(encoder); - if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || is_pch_edp(intel_dp)) { + if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || + intel_dp->base.type == INTEL_OUTPUT_EDP) + { lane_count = intel_dp->lane_count; break; - } else if (is_cpu_edp(intel_dp)) { - lane_count = dev_priv->edp.lanes; - break; } } -- cgit From ba28c9aae26ef7f3651eef6835fae30a979f88ba Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 6 Oct 2011 02:53:38 +0000 Subject: powerpc: Revert show_regs() define for readability We had an existing ifdef for 4xx & BOOKE processors that got changed to CONFIG_PPC_ADV_DEBUG_REGS. The define has nothing to do with CONFIG_PPC_ADV_DEBUG_REGS. The define really should be: #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) and not #ifdef CONFIG_PPC_ADV_DEBUG_REGS Signed-off-by: Kumar Gala Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 9054ca9ab4f9..ad3612af0a04 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -657,7 +657,7 @@ void show_regs(struct pt_regs * regs) if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR)) printk("CFAR: "REG"\n", regs->orig_gpr3); if (trap == 0x300 || trap == 0x600) -#ifdef CONFIG_PPC_ADV_DEBUG_REGS +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); #else printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr); -- cgit From b95bc2191412f5ecf2781c966110a13fa82a80d3 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 6 Oct 2011 02:53:39 +0000 Subject: powerpc: Remove extraneous CONFIG_PPC_ADV_DEBUG_REGS define All of DebugException is already protected by CONFIG_PPC_ADV_DEBUG_REGS there is no need to have another such ifdef inside the function. Signed-off-by: Kumar Gala Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/traps.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 4e5908264d1a..5459d148a0f6 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -1298,14 +1298,12 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) if (user_mode(regs)) { current->thread.dbcr0 &= ~DBCR0_IC; -#ifdef CONFIG_PPC_ADV_DEBUG_REGS if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1)) regs->msr |= MSR_DE; else /* Make sure the IDM bit is off */ current->thread.dbcr0 &= ~DBCR0_IDM; -#endif } _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); -- cgit From 187b9f2aa769198daa7cf8054abb65a08b8d8b47 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 6 Oct 2011 02:53:40 +0000 Subject: powerpc/book3e-64: Fix debug support for userspace With the introduction of CONFIG_PPC_ADV_DEBUG_REGS user space debug is broken on Book-E 64-bit parts that support delayed debug events. When switch_booke_debug_regs() sets DBCR0 we'll start getting debug events as MSR_DE is also set and we aren't able to handle debug events from kernel space. We can remove the hack that always enables MSR_DE and loads up DBCR0 and just utilize switch_booke_debug_regs() to get user space debug working again. We still need to handle critical/debug exception stacks & proper save/restore of state for those exception levles to support debug events from kernel space like we have on 32-bit. Signed-off-by: Kumar Gala Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/reg_booke.h | 2 +- arch/powerpc/kernel/process.c | 22 ---------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 28cdbd9f399c..03c48e819c8e 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -31,7 +31,7 @@ #define MSR_ MSR_ME | MSR_CE #define MSR_KERNEL MSR_ | MSR_64BIT -#define MSR_USER32 MSR_ | MSR_PR | MSR_EE | MSR_DE +#define MSR_USER32 MSR_ | MSR_PR | MSR_EE #define MSR_USER64 MSR_USER32 | MSR_64BIT #elif defined (CONFIG_40x) #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ad3612af0a04..6457574c0b2f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -486,28 +486,6 @@ struct task_struct *__switch_to(struct task_struct *prev, new_thread = &new->thread; old_thread = ¤t->thread; -#if defined(CONFIG_PPC_BOOK3E_64) - /* XXX Current Book3E code doesn't deal with kernel side DBCR0, - * we always hold the user values, so we set it now. - * - * However, we ensure the kernel MSR:DE is appropriately cleared too - * to avoid spurrious single step exceptions in the kernel. - * - * This will have to change to merge with the ppc32 code at some point, - * but I don't like much what ppc32 is doing today so there's some - * thinking needed there - */ - if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) { - u32 dbcr0; - - mtmsr(mfmsr() & ~MSR_DE); - isync(); - dbcr0 = mfspr(SPRN_DBCR0); - dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0; - mtspr(SPRN_DBCR0, dbcr0); - } -#endif /* CONFIG_PPC64_BOOK3E */ - #ifdef CONFIG_PPC64 /* * Collect processor utilization data per process -- cgit From a9a8f77ac72d6dd3c92ea268291678836f77681c Mon Sep 17 00:00:00 2001 From: Kyle Moffett Date: Mon, 7 Nov 2011 13:30:43 +0000 Subject: powerpc: Remove buggy 9-year-old test for binutils < 2.12.1 Recent binutils refuses to assemble AltiVec opcodes when in e500/SPE mode, as some of those opcodes alias the "SPE" instructions. This triggers an ancient binutils version check even when building a kernel with CONFIG_ALTIVEC disabled. In theory, the check could be conditionalized on CONFIG_ALTIVEC, but in practice it has long outlived its utility. It is virtually impossible to find binutils older than 2.12.1 (released 2002) in the wild anymore. Even ancient RedHat Enterprise Linux 4 has binutils-2.14. To fix the kernel build when done natively on e500 systems with this new binutils, the test is simply removed. Signed-off-by: Kyle Moffett Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 57af16edc192..70ba0c0a1223 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -255,12 +255,6 @@ checkbin: echo 'disable kernel modules' ; \ false ; \ fi - @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \ - echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \ - echo 'correctly with old versions of binutils.' ; \ - echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \ - false ; \ - fi CLEAN_FILES += $(TOUT) -- cgit From b97021f85517552ea8a0d2c1680c1ee4beab6d14 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 15 Nov 2011 17:11:27 +0000 Subject: powerpc: Fix atomic_xxx_return barrier semantics The Documentation/memory-barriers.txt document requires that atomic operations that return a value act as a memory barrier both before and after the actual atomic operation. Our current implementation doesn't guarantee this. More specifically, while a load following the isync can not be issued before stwcx. has completed, that completion doesn't architecturally means that the result of stwcx. is visible to other processors (or any previous stores for that matter) (typically, the other processors L1 caches can still hold the old value). This has caused an actual crash in RCU torture testing on Power 7 This fixes it by changing those atomic ops to use new macros instead of RELEASE/ACQUIRE barriers, called ATOMIC_ENTRY and ATMOIC_EXIT barriers, which are then defined respectively to lwsync and sync. I haven't had a chance to measure the performance impact (or rather what I measured with kernel compiles is in the noise, I yet have to find a more precise benchmark) Signed-off-by: Benjamin Herrenschmidt Acked-by: Paul E. McKenney --- arch/powerpc/include/asm/atomic.h | 48 +++++++++++++++++++-------------------- arch/powerpc/include/asm/bitops.h | 12 +++++----- arch/powerpc/include/asm/futex.h | 7 +++--- arch/powerpc/include/asm/synch.h | 8 +++++-- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index e2a4c26ad377..02e41b53488d 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -49,13 +49,13 @@ static __inline__ int atomic_add_return(int a, atomic_t *v) int t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%2 # atomic_add_return\n\ add %0,%1,%0\n" PPC405_ERR77(0,%2) " stwcx. %0,0,%2 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (a), "r" (&v->counter) : "cc", "memory"); @@ -85,13 +85,13 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v) int t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%2 # atomic_sub_return\n\ subf %0,%1,%0\n" PPC405_ERR77(0,%2) " stwcx. %0,0,%2 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (a), "r" (&v->counter) : "cc", "memory"); @@ -119,13 +119,13 @@ static __inline__ int atomic_inc_return(atomic_t *v) int t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%1 # atomic_inc_return\n\ addic %0,%0,1\n" PPC405_ERR77(0,%1) " stwcx. %0,0,%1 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (&v->counter) : "cc", "xer", "memory"); @@ -163,13 +163,13 @@ static __inline__ int atomic_dec_return(atomic_t *v) int t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%1 # atomic_dec_return\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) " stwcx. %0,0,%1\n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (&v->counter) : "cc", "xer", "memory"); @@ -194,7 +194,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) int t; __asm__ __volatile__ ( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%1 # __atomic_add_unless\n\ cmpw 0,%0,%3 \n\ beq- 2f \n\ @@ -202,7 +202,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) PPC405_ERR77(0,%2) " stwcx. %0,0,%1 \n\ bne- 1b \n" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER " subf %0,%2,%0 \n\ 2:" : "=&r" (t) @@ -226,7 +226,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) int t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ cmpwi %0,1\n\ addi %0,%0,-1\n\ @@ -234,7 +234,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) PPC405_ERR77(0,%1) " stwcx. %0,0,%1\n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER "\n\ 2:" : "=&b" (t) : "r" (&v->counter) @@ -285,12 +285,12 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%2 # atomic64_add_return\n\ add %0,%1,%0\n\ stdcx. %0,0,%2 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (a), "r" (&v->counter) : "cc", "memory"); @@ -319,12 +319,12 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%2 # atomic64_sub_return\n\ subf %0,%1,%0\n\ stdcx. %0,0,%2 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (a), "r" (&v->counter) : "cc", "memory"); @@ -351,12 +351,12 @@ static __inline__ long atomic64_inc_return(atomic64_t *v) long t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%1 # atomic64_inc_return\n\ addic %0,%0,1\n\ stdcx. %0,0,%1 \n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (&v->counter) : "cc", "xer", "memory"); @@ -393,12 +393,12 @@ static __inline__ long atomic64_dec_return(atomic64_t *v) long t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%1 # atomic64_dec_return\n\ addic %0,%0,-1\n\ stdcx. %0,0,%1\n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER : "=&r" (t) : "r" (&v->counter) : "cc", "xer", "memory"); @@ -418,13 +418,13 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) long t; __asm__ __volatile__( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ addic. %0,%0,-1\n\ blt- 2f\n\ stdcx. %0,0,%1\n\ bne- 1b" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER "\n\ 2:" : "=&r" (t) : "r" (&v->counter) @@ -450,14 +450,14 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) long t; __asm__ __volatile__ ( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: ldarx %0,0,%1 # __atomic_add_unless\n\ cmpd 0,%0,%3 \n\ beq- 2f \n\ add %0,%2,%0 \n" " stdcx. %0,0,%1 \n\ bne- 1b \n" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER " subf %0,%2,%0 \n\ 2:" : "=&r" (t) diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index e137afcc10fa..efdc92618b38 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -124,14 +124,14 @@ static __inline__ unsigned long fn( \ return (old & mask); \ } -DEFINE_TESTOP(test_and_set_bits, or, PPC_RELEASE_BARRIER, - PPC_ACQUIRE_BARRIER, 0) +DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER, + PPC_ATOMIC_EXIT_BARRIER, 0) DEFINE_TESTOP(test_and_set_bits_lock, or, "", PPC_ACQUIRE_BARRIER, 1) -DEFINE_TESTOP(test_and_clear_bits, andc, PPC_RELEASE_BARRIER, - PPC_ACQUIRE_BARRIER, 0) -DEFINE_TESTOP(test_and_change_bits, xor, PPC_RELEASE_BARRIER, - PPC_ACQUIRE_BARRIER, 0) +DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER, + PPC_ATOMIC_EXIT_BARRIER, 0) +DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER, + PPC_ATOMIC_EXIT_BARRIER, 0) static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h index c94e4a3fe2ef..2a9cf845473b 100644 --- a/arch/powerpc/include/asm/futex.h +++ b/arch/powerpc/include/asm/futex.h @@ -11,12 +11,13 @@ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ __asm__ __volatile ( \ - PPC_RELEASE_BARRIER \ + PPC_ATOMIC_ENTRY_BARRIER \ "1: lwarx %0,0,%2\n" \ insn \ PPC405_ERR77(0, %2) \ "2: stwcx. %1,0,%2\n" \ "bne- 1b\n" \ + PPC_ATOMIC_EXIT_BARRIER \ "li %1,0\n" \ "3: .section .fixup,\"ax\"\n" \ "4: li %1,%3\n" \ @@ -92,14 +93,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; __asm__ __volatile__ ( - PPC_RELEASE_BARRIER + PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\ cmpw 0,%1,%4\n\ bne- 3f\n" PPC405_ERR77(0,%3) "2: stwcx. %5,0,%3\n\ bne- 1b\n" - PPC_ACQUIRE_BARRIER + PPC_ATOMIC_EXIT_BARRIER "3: .section .fixup,\"ax\"\n\ 4: li %0,%6\n\ b 3b\n\ diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/asm/synch.h index 87878c68d1c2..e682a7143edb 100644 --- a/arch/powerpc/include/asm/synch.h +++ b/arch/powerpc/include/asm/synch.h @@ -42,11 +42,15 @@ static inline void isync(void) START_LWSYNC_SECTION(97); \ isync; \ MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup); -#define PPC_ACQUIRE_BARRIER "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER) -#define PPC_RELEASE_BARRIER stringify_in_c(LWSYNC) "\n" +#define PPC_ACQUIRE_BARRIER "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER) +#define PPC_RELEASE_BARRIER stringify_in_c(LWSYNC) "\n" +#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n" +#define PPC_ATOMIC_EXIT_BARRIER "\n" stringify_in_c(sync) "\n" #else #define PPC_ACQUIRE_BARRIER #define PPC_RELEASE_BARRIER +#define PPC_ATOMIC_ENTRY_BARRIER +#define PPC_ATOMIC_EXIT_BARRIER #endif #endif /* __KERNEL__ */ -- cgit From a313f4c55d4952f2105fe33a4957ed858e998359 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 8 Nov 2011 04:51:19 +0000 Subject: powerpc/signal32: Fix sigset_t conversion when copying to user On PPC64, put_sigset_t converts a sigset_t to a compat_sigset_t before copying it to userspace. There is a typo in the case that we have 4 words to copy, meaning that we corrupt the compat_sigset_t. It appears that _NSIG_WORDS can't be greater than 2 at the moment so this code is probably always optimised away anyway. Signed-off-by: Will Deacon Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/signal_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 78b76dc54dfb..836a5a19eb2c 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -97,7 +97,7 @@ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) compat_sigset_t cset; switch (_NSIG_WORDS) { - case 4: cset.sig[5] = set->sig[3] & 0xffffffffull; + case 4: cset.sig[6] = set->sig[3] & 0xffffffffull; cset.sig[7] = set->sig[3] >> 32; case 3: cset.sig[4] = set->sig[2] & 0xffffffffull; cset.sig[5] = set->sig[2] >> 32; -- cgit From ff956135008bca99b5e38f48f0d10a2c04fef2d6 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 15 Nov 2011 21:00:56 -0600 Subject: [libata] ahci_platform: fix DT probing The change in commit 904c04feaf13ed "ahci_platform: Add the board_ids..." doesn't work for the DT probing case as platform_get_device_id returns NULL. Pick the default ahci_port_info in this case. Signed-off-by: Rob Herring Acked-by: Anton Vorontsov Cc: Richard Zhu Cc: linux-ide@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/ahci_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index ec555951176e..43b875810d1b 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -67,7 +67,7 @@ static int __init ahci_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ahci_platform_data *pdata = dev_get_platdata(dev); const struct platform_device_id *id = platform_get_device_id(pdev); - struct ata_port_info pi = ahci_port_info[id->driver_data]; + struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct ahci_host_priv *hpriv; struct ata_host *host; -- cgit From aab9440453d19c1885fa391d4aafd7705f316247 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sun, 13 Nov 2011 01:30:56 +0400 Subject: libata: fix build without BMDMA fix these errors: drivers/ata/libata-sff.c:2538:3: error: implicit declaration of function 'ata_pci_bmdma_prepare_host' drivers/ata/libata-sff.c:2549:40: error: 'ata_bmdma_interrupt' undeclared (first use in this function) Signed-off-by: Alexander Beregalov Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 63d53277d6a9..4cadfa28f940 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2533,10 +2533,12 @@ static int ata_pci_init_one(struct pci_dev *pdev, if (rc) goto out; +#ifdef CONFIG_ATA_BMDMA if (bmdma) /* prepare and activate BMDMA host */ rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); else +#endif /* prepare and activate SFF host */ rc = ata_pci_sff_prepare_host(pdev, ppi, &host); if (rc) @@ -2544,10 +2546,12 @@ static int ata_pci_init_one(struct pci_dev *pdev, host->private_data = host_priv; host->flags |= hflags; +#ifdef CONFIG_ATA_BMDMA if (bmdma) { pci_set_master(pdev); rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); } else +#endif rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); out: if (rc == 0) -- cgit From bbc1754639f771cd2b515fed39b977549b373034 Mon Sep 17 00:00:00 2001 From: Francesco Virlinzi Date: Wed, 16 Nov 2011 21:57:58 +0000 Subject: stmmac: use mdelay on timeout of sw reset This patch uses an mdelay to manage the timeout on sw reset to be independant of cpu_clk. Signed-off-by: Francesco Virlinzi Reviewed-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index da66ac511c4c..4d5402a1d262 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -39,10 +39,11 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, /* DMA SW reset */ value |= DMA_BUS_MODE_SFT_RESET; writel(value, ioaddr + DMA_BUS_MODE); - limit = 15000; + limit = 10; while (limit--) { if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) break; + mdelay(10); } if (limit < 0) return -EBUSY; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 627f656b0f3c..bc17fd08b55d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -41,10 +41,11 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx, /* DMA SW reset */ value |= DMA_BUS_MODE_SFT_RESET; writel(value, ioaddr + DMA_BUS_MODE); - limit = 15000; + limit = 10; while (limit--) { if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) break; + mdelay(10); } if (limit < 0) return -EBUSY; -- cgit From c5b9b4e4b9076089fe7f9d4f5d1f2bba776646d2 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 16 Nov 2011 21:57:59 +0000 Subject: stmmac: fix advertising 1000Base capabilties for non GMII iface This patch fixes the way to stop the 1000Base advertising capabilties for non GMII interfaces. Signed-off-by: Srinivas Kandagatla Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 20546bbbb8db..e079762a796e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -321,12 +321,10 @@ static int stmmac_init_phy(struct net_device *dev) } /* Stop Advertising 1000BASE Capability if interface is not GMII */ - if ((interface) && ((interface == PHY_INTERFACE_MODE_MII) || - (interface == PHY_INTERFACE_MODE_RMII))) { - phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | - SUPPORTED_Asym_Pause); - phydev->advertising = phydev->supported; - } + if ((interface == PHY_INTERFACE_MODE_MII) || + (interface == PHY_INTERFACE_MODE_RMII)) + phydev->advertising &= ~(SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); /* * Broken HW is sometimes missing the pull-up resistor on the -- cgit From 19e30c14371f7afd38d1d35a693b96423a4db144 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 16 Nov 2011 21:58:00 +0000 Subject: stmmac: parameters auto-tuning through HW cap reg New GMAC devices (newer than the databook 3.50a) have the HW capability register that provides which features are actually supported by the hardware. On old devices many information have to be passed through the platform, for example: enhanced descriptor structure, TX COE etc. These are mandatory to properly configure the driver. This remains still valid because the driver has to support old Synopsys devices but now it's also able to override them using the values from the HW capability register if supported. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 93 +++++++++++++++------- 3 files changed, 72 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 9bafa6cf9e8b..a140a8fbf051 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -72,7 +72,6 @@ struct stmmac_priv { spinlock_t lock; spinlock_t tx_lock; int wolopts; - int wolenabled; int wol_irq; #ifdef CONFIG_STMMAC_TIMER struct stmmac_timer *tm; @@ -80,6 +79,7 @@ struct stmmac_priv { struct plat_stmmacenet_data *plat; struct stmmac_counters mmc; struct dma_features dma_cap; + int hw_cap_support; }; extern int stmmac_mdio_unregister(struct net_device *ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index e8eff09bbbd7..0395f9eba801 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -430,6 +430,12 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct stmmac_priv *priv = netdev_priv(dev); u32 support = WAKE_MAGIC | WAKE_UCAST; + /* By default almost all GMAC devices support the WoL via + * magic frame but we can disable it if the HW capability + * register shows no support for pmt_magic_frame. */ + if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame)) + wol->wolopts &= ~WAKE_MAGIC; + if (!device_can_wakeup(priv->device)) return -EINVAL; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e079762a796e..7f3ffd3742d8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -805,8 +805,29 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) return 0; } -/* New GMAC chips support a new register to indicate the - * presence of the optional feature/functions. +/** + * stmmac_selec_desc_mode + * @dev : device pointer + * Description: select the Enhanced/Alternate or Normal descriptors */ +static void stmmac_selec_desc_mode(struct stmmac_priv *priv) +{ + if (priv->plat->enh_desc) { + pr_info(" Enhanced/Alternate descriptors\n"); + priv->hw->desc = &enh_desc_ops; + } else { + pr_info(" Normal descriptors\n"); + priv->hw->desc = &ndesc_ops; + } +} + +/** + * stmmac_get_hw_features + * @priv : private device pointer + * Description: + * new GMAC chip generations have a new register to indicate the + * presence of the optional feature/functions. + * This can be also used to override the value passed through the + * platform and necessary for old MAC10/100 and GMAC chips. */ static int stmmac_get_hw_features(struct stmmac_priv *priv) { @@ -827,7 +848,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv) (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; priv->dma_cap.pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; - /*MMC*/ + /* MMC */ priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; /* IEEE 1588-2002*/ priv->dma_cap.time_stamp = @@ -855,8 +876,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv) priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; - } else - pr_debug("\tNo HW DMA feature register supported"); + } return hw_cap; } @@ -911,6 +931,44 @@ static int stmmac_open(struct net_device *dev) goto open_error; } + stmmac_get_synopsys_id(priv); + + priv->hw_cap_support = stmmac_get_hw_features(priv); + + if (priv->hw_cap_support) { + pr_info(" Support DMA HW capability register"); + + /* We can override some gmac/dma configuration fields: e.g. + * enh_desc, tx_coe (e.g. that are passed through the + * platform) with the values from the HW capability + * register (if supported). + */ + priv->plat->enh_desc = priv->dma_cap.enh_desc; + priv->plat->tx_coe = priv->dma_cap.tx_coe; + priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; + + /* By default disable wol on magic frame if not supported */ + if (!priv->dma_cap.pmt_magic_frame) + priv->wolopts &= ~WAKE_MAGIC; + + } else + pr_info(" No HW DMA feature register supported"); + + /* Select the enhnaced/normal descriptor structures */ + stmmac_selec_desc_mode(priv); + + /* PMT module is not integrated in all the MAC devices. */ + if (priv->plat->pmt) { + pr_info(" Remote wake-up capable\n"); + device_set_wakeup_capable(priv->device, 1); + } + + priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); + if (priv->rx_coe) + pr_info(" Checksum Offload Engine supported\n"); + if (priv->plat->tx_coe) + pr_info(" Checksum insertion supported\n"); + /* Create and initialize the TX/RX descriptors chains. */ priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); @@ -933,15 +991,6 @@ static int stmmac_open(struct net_device *dev) /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->ioaddr); - stmmac_get_synopsys_id(priv); - - stmmac_get_hw_features(priv); - - priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); - if (priv->rx_coe) - pr_info("stmmac: Rx Checksum Offload Engine supported\n"); - if (priv->plat->tx_coe) - pr_info("\tTX Checksum insertion supported\n"); netdev_update_features(dev); /* Request the IRQ lines */ @@ -1556,7 +1605,7 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) struct net_device *dev = seq->private; struct stmmac_priv *priv = netdev_priv(dev); - if (!stmmac_get_hw_features(priv)) { + if (!priv->hw_cap_support) { seq_printf(seq, "DMA HW features not supported\n"); return 0; } @@ -1764,12 +1813,6 @@ static int stmmac_mac_device_setup(struct net_device *dev) if (!device) return -ENOMEM; - if (priv->plat->enh_desc) { - device->desc = &enh_desc_ops; - pr_info("\tEnhanced descriptor structure\n"); - } else - device->desc = &ndesc_ops; - priv->hw = device; priv->hw->ring = &ring_mode_ops; @@ -1843,11 +1886,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev) priv->ioaddr = addr; - /* PMT module is not integrated in all the MAC devices. */ - if (plat_dat->pmt) { - pr_info("\tPMT module supported\n"); - device_set_wakeup_capable(&pdev->dev, 1); - } /* * On some platforms e.g. SPEAr the wake up irq differs from the mac irq * The external wake up irq can be passed through the platform code @@ -1860,7 +1898,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev) if (priv->wol_irq == -ENXIO) priv->wol_irq = ndev->irq; - platform_set_drvdata(pdev, ndev); /* Set the I/O base addr */ @@ -1873,7 +1910,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) goto out_free_ndev; } - /* MAC HW revice detection */ + /* MAC HW device detection */ ret = stmmac_mac_device_setup(ndev); if (ret < 0) goto out_plat_exit; -- cgit From 989508ba60da6dce79f8aaee1be6c092fd4c67f8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 16 Nov 2011 21:58:01 +0000 Subject: stmmac: remove spin_lock in stmmac_ioctl. This patch removes un-needed spin_lock in stmmac_ioctl while reading and writing mdio registers. While holding spin_lock the code must be atomic, which is not true in this case as both mdiobus_read and writes have mutex locks. Without this patch reading mdio registers via mii-tool results in below BUG: mii-tool -vvv eth0" Using SIOCGMIIPHY=0x8947 BUG: sleeping function called from invalid context at kernel/mutex.c:287 in_atomic(): 1, irqs_disabled(): 0, pid: 614, name: mii-tool 2 locks held by mii-tool/614: #0: (rtnl_mutex){......}, at: [] dev_ioctl+0x550/0x674 #1: (&priv->lock){......}, at: [] stmmac_ioctl+0x4c/0x78 [] (unwind_backtrace+0x0/0xcc) from [] (mutex_lock_nested+0x24/0x35c) [] (mutex_lock_nested+0x24/0x35c) from [] (mdiobus_read+0x44/0x70) [] (mdiobus_read+0x44/0x70) from [] (phy_mii_ioctl+0x4c/0x138) [] (phy_mii_ioctl+0x4c/0x138) from [] (stmmac_ioctl+0x5c/0x78) [] (stmmac_ioctl+0x5c/0x78) from [] (dev_ifsioc+0x2a4/0x2c8) [] (dev_ifsioc+0x2a4/0x2c8) from [] (dev_ioctl+0x560/0x674) [] (dev_ioctl+0x560/0x674) from [] (vfs_ioctl+0x2c/0x8c) [] (vfs_ioctl+0x2c/0x8c) from [] (do_vfs_ioctl+0x530/0x578) [] (do_vfs_ioctl+0x530/0x578) from [] (sys_ioctl+0x34/0x54) [] (sys_ioctl+0x34/0x54) from [] (ret_fast_syscall+0x0/0x2c) Signed-off-by: Srinivas Kandagatla Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7f3ffd3742d8..29dd87c675dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1536,9 +1536,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!priv->phydev) return -EINVAL; - spin_lock(&priv->lock); ret = phy_mii_ioctl(priv->phydev, rq, cmd); - spin_unlock(&priv->lock); return ret; } -- cgit From 102463b18d922dd55c29fbfa222e0355ecf3e42f Mon Sep 17 00:00:00 2001 From: Francesco Virlinzi Date: Wed, 16 Nov 2011 21:58:02 +0000 Subject: stmmac: fix pm functions avoiding sleep on spinlock This patch fixes the pm functions to avoid the system sleeps while a spinlock is taken. Signed-off-by: Francesco Virlinzi Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 29dd87c675dc..8ea770a89f25 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2011,12 +2011,13 @@ static int stmmac_suspend(struct device *dev) if (!ndev || !netif_running(ndev)) return 0; + if (priv->phydev) + phy_stop(priv->phydev); + spin_lock(&priv->lock); netif_device_detach(ndev); netif_stop_queue(ndev); - if (priv->phydev) - phy_stop(priv->phydev); #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_stop(); @@ -2074,12 +2075,13 @@ static int stmmac_resume(struct device *dev) #endif napi_enable(&priv->napi); - if (priv->phydev) - phy_start(priv->phydev); - netif_start_queue(ndev); spin_unlock(&priv->lock); + + if (priv->phydev) + phy_start(priv->phydev); + return 0; } -- cgit From fc9f899483435935c1cd7005df29681929d1c99b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 9 Jul 2011 18:04:39 +0200 Subject: fs/ocfs2/dlm/dlmlock.c: free kmem_cache_zalloc'd data using kmem_cache_free Memory allocated using kmem_cache_zalloc should be freed using kmem_cache_free, not kfree. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,e,e1,e2; @@ x = kmem_cache_zalloc(e1,e2) ... when != x = e ?-kfree(x) +kmem_cache_free(e1,x) // Signed-off-by: Julia Lawall Signed-off-by: Joel Becker --- fs/ocfs2/dlm/dlmlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index f32fcba04923..975810b98492 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -438,7 +438,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie, /* zero memory only if kernel-allocated */ lksb = kzalloc(sizeof(*lksb), GFP_NOFS); if (!lksb) { - kfree(lock); + kmem_cache_free(dlm_lock_cache, lock); return NULL; } kernel_allocated = 1; -- cgit From 8298524803339a9a8df053ebdfebc2975ec55be9 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Tue, 12 Jul 2011 16:43:14 +0800 Subject: ocfs2: make direntry invalid when deleting it When we deleting a direntry from a directory, if it's the first in a block we invalid it by setting inode to 0; otherwise, we merge the deleted one to the prior and contiguous direntry. And we don't truncate directories. There is a problem for the later case since inode is not set to 0. This problem happens when the caller passes a file position as parameter to ocfs2_dir_foreach_blk(). If the position happens to point to a stale(not the first, deleted in betweens of ocfs2_dir_foreach_blk()s) direntry, we are not able to recognize its staleness. So that we treat it as a live one wrongly. The fix is to set inode to 0 in both cases indicating the direntry is stale. This won't introduce additional IOs. Signed-off-by: Wengang Wang Signed-off-by: Joel Becker --- fs/ocfs2/dir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8582e3f4f120..3302088e1f04 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -1184,8 +1184,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, if (pde) le16_add_cpu(&pde->rec_len, le16_to_cpu(de->rec_len)); - else - de->inode = 0; + de->inode = 0; dir->i_version++; ocfs2_journal_dirty(handle, bh); goto bail; -- cgit From b8a0ae579fb8d9b21008ac386be08b9428902455 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Wed, 12 Oct 2011 15:22:15 +0800 Subject: ocfs2: Commit transactions in error cases -v2 There are three cases found that in error cases, journal transactions are not committed nor aborted. We should take care of these case by committing the transactions. Otherwise, there would left a journal handle which will lead to , in same process context, the comming ocfs2_start_trans() gets wrong credits. Signed-off-by: Wengang Wang Signed-off-by: Joel Becker --- fs/ocfs2/alloc.c | 2 +- fs/ocfs2/ioctl.c | 3 ++- fs/ocfs2/xattr.c | 10 ++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index ed553c60de82..3165aebb43c8 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -5699,7 +5699,7 @@ int ocfs2_remove_btree_range(struct inode *inode, OCFS2_JOURNAL_ACCESS_WRITE); if (ret) { mlog_errno(ret); - goto out; + goto out_commit; } dquot_free_space_nodirty(inode, diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index d9a6ce779266..726ff265b296 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -122,7 +122,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { if (!capable(CAP_LINUX_IMMUTABLE)) - goto bail_unlock; + goto bail_commit; } ocfs2_inode->ip_attr = flags; @@ -132,6 +132,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, if (status < 0) mlog_errno(status); +bail_commit: ocfs2_commit_trans(osb, handle); bail_unlock: ocfs2_inode_unlock(inode, 1); diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 81ecf9c0bf0a..93d6c80b3922 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -2376,16 +2376,18 @@ static int ocfs2_remove_value_outside(struct inode*inode, } ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt); - if (ret < 0) { - mlog_errno(ret); - break; - } ocfs2_commit_trans(osb, ctxt.handle); if (ctxt.meta_ac) { ocfs2_free_alloc_context(ctxt.meta_ac); ctxt.meta_ac = NULL; } + + if (ret < 0) { + mlog_errno(ret); + break; + } + } if (ctxt.meta_ac) -- cgit From e41d33af7c037a6f7350f8410b45ce83b50d1b80 Mon Sep 17 00:00:00 2001 From: Dan Magenheimer Date: Mon, 17 Oct 2011 16:47:17 -0700 Subject: ocfs2: send correct UUID to cleancache initialization ocfs2: Fix cleancache initialization call to correctly pass uuid As reported by Steven Whitehouse in https://lkml.org/lkml/2011/5/27/221 the ocfs2 volume UUID is incorrectly passed to cleancache. As a result, shared-ephemeral tmem pools will not actually be created; instead they will be private (unshared) which misses out on a major benefit of tmem. Reported-by: Steven Whitehouse Signed-off-by: Dan Magenheimer Signed-off-by: Joel Becker --- fs/ocfs2/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 938e2b2b0c9c..4994f8b0e604 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -2360,7 +2360,7 @@ static int ocfs2_initialize_super(struct super_block *sb, mlog_errno(status); goto bail; } - cleancache_init_shared_fs((char *)&uuid_net_key, sb); + cleancache_init_shared_fs((char *)&di->id2.i_super.s_uuid, sb); bail: return status; -- cgit From 0393afea31874947b1d149b82d17b7dccac4f210 Mon Sep 17 00:00:00 2001 From: "Xiaowei.Hu" Date: Wed, 19 Oct 2011 09:34:19 +0800 Subject: ocfs2: Add a missing journal credit in ocfs2_link_credits() -v2 With indexed_dir enabled, ocfs2 maintains a list of dirblocks having space. The credit calculation in ocfs2_link_credits() did not correctly account for adding an entry that exactly fills a dirblock that triggers removing that dirblock by changing the pointer in the previous block in the list. The credit calculation did not account for that previous block. To expose, do: mkfs.ocfs2 -b 512 -M local /dev/sdX mount /dev/sdX /ocfs2 mkdir /ocfs2/linkdir touch /ocfs2/linkdir/file1 for i in `seq 1 29` ; do link /ocfs2/linkdir/file1 /ocfs2/linkdir/linklinklinklinklinklink$i; done rm -f /ocfs2/linkdir/linklinklinklinklinklink10 sleep 8 link /ocfs2/linkdir/file1 /ocfs2/linkdir/linklinklinklinklinklinkaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Note: The link names have been crafted for a 512 byte blocksize. Reproducing with a larger blocksize will require longer (or more) links. The sleep is important. We want jbd2 to commit the transaction so that the missing block does not piggy back on account of the previous transaction. Signed-off-by: XiaoweiHu Reviewed-by: WengangWang Reviewed-by: Sunil.Mushran Signed-off-by: Joel Becker --- fs/ocfs2/journal.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 68cf2f6d3c6a..a3385b63ff5e 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -441,10 +441,11 @@ static inline int ocfs2_mknod_credits(struct super_block *sb, int is_dir, #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2) /* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota - * update on dir + index leaf + dx root update for free list */ + * update on dir + index leaf + dx root update for free list + + * previous dirblock update in the free list */ static inline int ocfs2_link_credits(struct super_block *sb) { - return 2*OCFS2_INODE_UPDATE_CREDITS + 3 + + return 2*OCFS2_INODE_UPDATE_CREDITS + 4 + ocfs2_quota_trans_credits(sb); } -- cgit From df295d4a4b3c98af1a2445a82aef169e7e5d96b8 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 16 Nov 2011 12:03:10 -0800 Subject: ocfs2: honor O_(D)SYNC flag in fallocate We need to sync the transaction which updates i_size if the file is marked as needing sync semantics. Signed-off-by: Mark Fasheh Signed-off-by: Joel Becker --- fs/ocfs2/file.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 5c4a74e04ab4..09e3de57cdee 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1950,6 +1950,9 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, if (ret < 0) mlog_errno(ret); + if (file->f_flags & O_SYNC) + handle->h_sync = 1; + ocfs2_commit_trans(osb, handle); out_inode_unlock: -- cgit From 249ec93c01db8898058899a80ffb537c8d27f86f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 8 Nov 2011 00:20:39 +0100 Subject: ocfs2: Use filemap_write_and_wait() instead of write_inode_now() Since ocfs2 has no ->write_inode method, there's no point in calling write_inode_now() from ocfs2_cleanup_delete_inode(). Use filemap_write_and_wait() instead. This helps us to cleanup inode writing interfaces... Signed-off-by: Jan Kara Signed-off-by: Joel Becker --- fs/ocfs2/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index b4c8bb6b8d28..c4bf6ac4a0bb 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -951,7 +951,7 @@ static void ocfs2_cleanup_delete_inode(struct inode *inode, trace_ocfs2_cleanup_delete_inode( (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data); if (sync_data) - write_inode_now(inode, 1); + filemap_write_and_wait(inode->i_mapping); truncate_inode_pages(&inode->i_data, 0); } -- cgit From 3627902377c4fbdeef4c689fb43b47a86a3ec859 Mon Sep 17 00:00:00 2001 From: Donggeun Kim Date: Thu, 17 Nov 2011 05:33:05 -0500 Subject: hwmon: (exynos4_tmu) Fix Kconfig dependency Rename dependency of EXYNOS4_TMU in Kconfig to the existing one. Signed-off-by: Donggeun Kim Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9ec854ae118b..91be41f60809 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -315,7 +315,7 @@ config SENSORS_DS1621 config SENSORS_EXYNOS4_TMU tristate "Temperature sensor on Samsung EXYNOS4" - depends on EXYNOS4_DEV_TMU + depends on ARCH_EXYNOS4 help If you say yes here you get support for TMU (Thermal Managment Unit) on SAMSUNG EXYNOS4 series of SoC. -- cgit From f475058f48d3acb3c3979311c9532f3113839468 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Thu, 17 Nov 2011 18:54:29 +0800 Subject: ARM: imx6q: move clock register map to machine_desc.map_io map_io is the only place to call iotable_init. Signed-off-by: Richard Zhao [shawn.guo: rename imx_clock_map_io() to imx6q_clock_map_io()] Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clock-imx6q.c | 7 +++++-- arch/arm/mach-imx/mach-imx6q.c | 1 + arch/arm/plat-mxc/include/mach/common.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c index 613a1b993bff..039a7abb165a 100644 --- a/arch/arm/mach-imx/clock-imx6q.c +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -1953,14 +1953,17 @@ static struct map_desc imx6q_clock_desc[] = { imx_map_entry(MX6Q, ANATOP, MT_DEVICE), }; +void __init imx6q_clock_map_io(void) +{ + iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc)); +} + int __init mx6q_clocks_init(void) { struct device_node *np; void __iomem *base; int i, irq; - iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc)); - /* retrieve the freqency of fixed clocks from device tree */ for_each_compatible_node(np, NULL, "fixed-clock") { u32 rate; diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 8bf5fa349484..9cd860a27af5 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -34,6 +34,7 @@ static void __init imx6q_map_io(void) { imx_lluart_map_io(); imx_scu_map_io(); + imx6q_clock_map_io(); } static void __init imx6q_gpio_add_irq_domain(struct device_node *np, diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 83b745a5e1b7..7a5b6afc0982 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -133,4 +133,5 @@ extern void imx53_qsb_common_init(void); extern void imx53_smd_common_init(void); extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); extern void imx6q_pm_init(void); +extern void imx6q_clock_map_io(void); #endif -- cgit From d29387e8de8bdf64374874112b2b1540d3ada674 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 Nov 2011 18:17:03 -0800 Subject: media/staging: fix allyesconfig build error Fix x86 allyesconfig builds. Builds fail due to a non-static variable named 'debug' in drivers/staging/media/as102: arch/x86/built-in.o:arch/x86/kernel/entry_32.S:1296: first defined here ld: Warning: size of symbol `debug' changed from 90 in arch/x86/built-in.o to 4 in drivers/built-in.o Thou shalt have no non-static identifiers that are named 'debug'. Signed-off-by: Randy Dunlap Cc: Pierrick Hascoet Signed-off-by: Linus Torvalds --- drivers/staging/media/as102/as102_drv.c | 4 ++-- drivers/staging/media/as102/as102_drv.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index d335c7d6fa0f..828526d4c289 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -32,8 +32,8 @@ #include "as102_fw.h" #include "dvbdev.h" -int debug; -module_param_named(debug, debug, int, 0644); +int as102_debug; +module_param_named(debug, as102_debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)"); int dual_tuner; diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index bcda635b5a99..fd33f5a12dcc 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -37,7 +37,8 @@ extern struct spi_driver as102_spi_driver; #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver" #define DRIVER_NAME "as10x_usb" -extern int debug; +extern int as102_debug; +#define debug as102_debug #define dprintk(debug, args...) \ do { if (debug) { \ -- cgit From 869f8dfa52295e75e043af618e47305e4b109bc1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 Nov 2011 18:20:51 -0800 Subject: platform/x86: fix dell-laptop function prototypes Fix build warnings: drivers/platform/x86/dell-laptop.c:592:13: warning: function declaration isn't a prototype drivers/platform/x86/dell-laptop.c:599:13: warning: function declaration isn't a prototype Signed-off-by: Randy Dunlap Cc: Matthew Garrett Signed-off-by: Linus Torvalds --- drivers/platform/x86/dell-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index a43cfd906c6d..d93e962f2610 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -589,14 +589,14 @@ static const struct backlight_ops dell_ops = { .update_status = dell_send_intensity, }; -static void touchpad_led_on() +static void touchpad_led_on(void) { int command = 0x97; char data = 1; i8042_command(&data, command | 1 << 12); } -static void touchpad_led_off() +static void touchpad_led_off(void) { int command = 0x97; char data = 2; -- cgit From 1df647197c5b8aacaeb58592cba9a1df322c9000 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sun, 13 Nov 2011 19:47:32 -0600 Subject: writeback: hard throttle 1000+ dd on a slow USB stick The sleep based balance_dirty_pages() can pause at most MAX_PAUSE=200ms on every 1 4KB-page, which means it cannot throttle a task under 4KB/200ms=20KB/s. So when there are more than 512 dd writing to a 10MB/s USB stick, its bdi dirty pages could grow out of control. Even if we can increase MAX_PAUSE, the minimal (task_ratelimit = 1) means a limit of 4KB/s. They can eventually be safeguarded by the global limit check (nr_dirty < dirty_thresh). However if someone is also writing to an HDD at the same time, it'll get poor HDD write performance. We at least want to maintain good write performance for other devices when one device is attacked by some "massive parallel" workload, or suffers from slow write bandwidth, or somehow get stalled due to some error condition (eg. NFS server not responding). For a stalled device, we need to completely block its dirtiers, too, before its bdi dirty pages grow all the way up to the global limit and leave no space for the other functional devices. So change the loop exit condition to /* * Always enforce global dirty limit; also enforce bdi dirty limit * if the normal max_pause sleeps cannot keep things under control. */ if (nr_dirty < dirty_thresh && (bdi_dirty < bdi_thresh || bdi->dirty_ratelimit > 1)) break; which can be further simplified to if (task_ratelimit) break; Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 79c34419fadd..e7cb5ff6e53d 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1136,14 +1136,11 @@ pause: __set_current_state(TASK_KILLABLE); io_schedule_timeout(pause); - dirty_thresh = hard_dirty_limit(dirty_thresh); /* - * max-pause area. If dirty exceeded but still within this - * area, no need to sleep for more than 200ms: (a) 8 pages per - * 200ms is typically more than enough to curb heavy dirtiers; - * (b) the pause time limit makes the dirtiers more responsive. + * This is typically equal to (nr_dirty < dirty_thresh) and can + * also keep "1000+ dd on a slow USB stick" under control. */ - if (nr_dirty < dirty_thresh) + if (task_ratelimit) break; if (fatal_signal_pending(current)) -- cgit From 468e6a20afaccb67e2a7d7f60d301f90e1c6f301 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 7 Sep 2011 10:41:32 -0600 Subject: writeback: remove vm_dirties and task->dirties They are not used any more. Signed-off-by: Wu Fengguang --- include/linux/init_task.h | 1 - include/linux/sched.h | 1 - kernel/fork.c | 5 ----- mm/page-writeback.c | 9 --------- 4 files changed, 16 deletions(-) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 08ffab01e76c..94b1e356c02a 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -184,7 +184,6 @@ extern struct cred init_cred; [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ }, \ .thread_group = LIST_HEAD_INIT(tsk.thread_group), \ - .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ INIT_IDS \ INIT_PERF_EVENTS(tsk) \ INIT_TRACE_IRQFLAGS \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 68daf4f27e2c..1c4f3e9b9bc5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1521,7 +1521,6 @@ struct task_struct { #ifdef CONFIG_FAULT_INJECTION int make_it_fail; #endif - struct prop_local_single dirties; /* * when (nr_dirtied >= nr_dirtied_pause), it's time to call * balance_dirty_pages() for some dirty throttling pause diff --git a/kernel/fork.c b/kernel/fork.c index ba0d17261329..da4a6a10d088 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -162,7 +162,6 @@ static void account_kernel_stack(struct thread_info *ti, int account) void free_task(struct task_struct *tsk) { - prop_local_destroy_single(&tsk->dirties); account_kernel_stack(tsk->stack, -1); free_thread_info(tsk->stack); rt_mutex_debug_task_free(tsk); @@ -274,10 +273,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) tsk->stack = ti; - err = prop_local_init_single(&tsk->dirties); - if (err) - goto out; - setup_thread_stack(tsk, orig); clear_user_return_notifier(tsk); clear_tsk_need_resched(tsk); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index e7cb5ff6e53d..71252486bc6f 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -128,7 +128,6 @@ unsigned long global_dirty_limit; * */ static struct prop_descriptor vm_completions; -static struct prop_descriptor vm_dirties; /* * couple the period to the dirty_ratio: @@ -154,7 +153,6 @@ static void update_completion_period(void) { int shift = calc_period_shift(); prop_change_shift(&vm_completions, shift); - prop_change_shift(&vm_dirties, shift); writeback_set_ratelimit(); } @@ -235,11 +233,6 @@ void bdi_writeout_inc(struct backing_dev_info *bdi) } EXPORT_SYMBOL_GPL(bdi_writeout_inc); -void task_dirty_inc(struct task_struct *tsk) -{ - prop_inc_single(&vm_dirties, &tsk->dirties); -} - /* * Obtain an accurate fraction of the BDI's portion. */ @@ -1395,7 +1388,6 @@ void __init page_writeback_init(void) shift = calc_period_shift(); prop_descriptor_init(&vm_completions, shift); - prop_descriptor_init(&vm_dirties, shift); } /** @@ -1724,7 +1716,6 @@ void account_page_dirtied(struct page *page, struct address_space *mapping) __inc_zone_page_state(page, NR_DIRTIED); __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); __inc_bdi_stat(mapping->backing_dev_info, BDI_DIRTIED); - task_dirty_inc(current); task_io_account_write(PAGE_CACHE_SIZE); } } -- cgit From bd29e568a4cb6465f6e5ec7c1c1f3ae7d99cbec1 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Wed, 16 Nov 2011 10:50:56 -0800 Subject: fix typo/thinko in get_random_bytes() If there is an architecture-specific random number generator we use it to acquire randomness one "long" at a time. We should put these random words into consecutive words in the result buffer - not just overwrite the first word again and again. Signed-off-by: Tony Luck Acked-by: H. Peter Anvin Acked-by: Thomas Gleixner Signed-off-by: Linus Torvalds --- drivers/char/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 63e19ba56bbe..6035ab8d5ef7 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes) if (!arch_get_random_long(&v)) break; - memcpy(buf, &v, chunk); + memcpy(p, &v, chunk); p += chunk; nbytes -= chunk; } -- cgit From 9e6dabeffd1d0ec2aa19aa076c4886067238d442 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 17 Nov 2011 11:00:41 +0100 Subject: KVM: s390: Fix RUNNING flag misinterpretation CPUSTAT_RUNNING was implemented signifying that a vcpu is not stopped. This is not, however, what the architecture says: RUNNING should be set when the host is acting on the behalf of the guest operating system. CPUSTAT_RUNNING has been changed to be set in kvm_arch_vcpu_load() and to be unset in kvm_arch_vcpu_put(). For signifying stopped state of a vcpu, a host-controlled bit has been used and is set/unset basically on the reverse as the old CPUSTAT_RUNNING bit (including pushing it down into stop handling proper in handle_stop()). Cc: stable@kernel.org Signed-off-by: Cornelia Huck Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity --- arch/s390/include/asm/kvm_host.h | 2 +- arch/s390/kvm/diag.c | 2 +- arch/s390/kvm/intercept.c | 3 ++- arch/s390/kvm/interrupt.c | 1 + arch/s390/kvm/kvm-s390.c | 10 +++++++--- arch/s390/kvm/sigp.c | 6 +++--- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 24e18473d926..20f9068cd6b5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -47,7 +47,7 @@ struct sca_block { #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) -#define CPUSTAT_HOST 0x80000000 +#define CPUSTAT_STOPPED 0x80000000 #define CPUSTAT_WAIT 0x10000000 #define CPUSTAT_ECALL_PEND 0x08000000 #define CPUSTAT_STOP_INT 0x04000000 diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 87cedd61be04..8943e82cd4d9 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -70,7 +70,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu) return -EOPNOTSUPP; } - atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); + atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index c7c51898984e..02434543eabb 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu) int rc = 0; vcpu->stat.exit_stop_request++; - atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); spin_lock_bh(&vcpu->arch.local_int.lock); if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) { vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP; @@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu) } if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) { + atomic_set_mask(CPUSTAT_STOPPED, + &vcpu->arch.sie_block->cpuflags); vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP; VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); rc = -EOPNOTSUPP; diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 87c16705b381..278ee009ce65 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -252,6 +252,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, offsetof(struct _lowcore, restart_psw), sizeof(psw_t)); if (rc == -EFAULT) exception = 1; + atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); break; case KVM_S390_PROGRAM_INT: diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0bd3bea1e4cd..630ab65b488b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -270,10 +270,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) restore_fp_regs(&vcpu->arch.guest_fpregs); restore_access_regs(vcpu->arch.guest_acrs); gmap_enable(vcpu->arch.gmap); + atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { + atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); gmap_disable(vcpu->arch.gmap); save_fp_regs(&vcpu->arch.guest_fpregs); save_access_regs(vcpu->arch.guest_acrs); @@ -301,7 +303,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) { - atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM); + atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | + CPUSTAT_SM | + CPUSTAT_STOPPED); vcpu->arch.sie_block->ecb = 6; vcpu->arch.sie_block->eca = 0xC1002001U; vcpu->arch.sie_block->fac = (int) (long) facilities; @@ -428,7 +432,7 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw) { int rc = 0; - if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING) + if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED)) rc = -EBUSY; else { vcpu->run->psw_mask = psw.mask; @@ -501,7 +505,7 @@ rerun_vcpu: if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); - atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); + atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL); diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index f815118835f3..4a488a98d7f8 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -57,8 +57,8 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, spin_lock(&fi->lock); if (fi->local_int[cpu_addr] == NULL) rc = 3; /* not operational */ - else if (atomic_read(fi->local_int[cpu_addr]->cpuflags) - & CPUSTAT_RUNNING) { + else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags) + & CPUSTAT_STOPPED)) { *reg &= 0xffffffff00000000UL; rc = 1; /* status stored */ } else { @@ -251,7 +251,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, spin_lock_bh(&li->lock); /* cpu must be in stopped state */ - if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) { + if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { rc = 1; /* incorrect state */ *reg &= SIGP_STAT_INCORRECT_STATE; kfree(inti); -- cgit From bd59d3a4444e5f941c863db1a7715edf7289e29a Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 17 Nov 2011 11:00:42 +0100 Subject: KVM: s390: handle SIGP sense running intercepts SIGP sense running may cause an intercept on higher level virtualization, so handle it by checking the CPUSTAT_RUNNING flag. Signed-off-by: Cornelia Huck Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity --- arch/s390/include/asm/kvm_host.h | 1 + arch/s390/kvm/kvm-s390.c | 1 + arch/s390/kvm/sigp.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 20f9068cd6b5..b0c235cb6ad5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -139,6 +139,7 @@ struct kvm_vcpu_stat { u32 instruction_stfl; u32 instruction_tprot; u32 instruction_sigp_sense; + u32 instruction_sigp_sense_running; u32 instruction_sigp_external_call; u32 instruction_sigp_emergency; u32 instruction_sigp_stop; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 630ab65b488b..0891926ea953 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -65,6 +65,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "instruction_stfl", VCPU_STAT(instruction_stfl) }, { "instruction_tprot", VCPU_STAT(instruction_tprot) }, { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, + { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) }, { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) }, { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) }, diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 4a488a98d7f8..0a7941d74bc6 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -31,9 +31,11 @@ #define SIGP_SET_PREFIX 0x0d #define SIGP_STORE_STATUS_ADDR 0x0e #define SIGP_SET_ARCH 0x12 +#define SIGP_SENSE_RUNNING 0x15 /* cpu status bits */ #define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL +#define SIGP_STAT_NOT_RUNNING 0x00000400UL #define SIGP_STAT_INCORRECT_STATE 0x00000200UL #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL #define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL @@ -275,6 +277,38 @@ out_fi: return rc; } +static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, + unsigned long *reg) +{ + int rc; + struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; + + if (cpu_addr >= KVM_MAX_VCPUS) + return 3; /* not operational */ + + spin_lock(&fi->lock); + if (fi->local_int[cpu_addr] == NULL) + rc = 3; /* not operational */ + else { + if (atomic_read(fi->local_int[cpu_addr]->cpuflags) + & CPUSTAT_RUNNING) { + /* running */ + rc = 1; + } else { + /* not running */ + *reg &= 0xffffffff00000000UL; + *reg |= SIGP_STAT_NOT_RUNNING; + rc = 0; + } + } + spin_unlock(&fi->lock); + + VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr, + rc); + + return rc; +} + int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) { int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; @@ -331,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, &vcpu->arch.guest_gprs[r1]); break; + case SIGP_SENSE_RUNNING: + vcpu->stat.instruction_sigp_sense_running++; + rc = __sigp_sense_running(vcpu, cpu_addr, + &vcpu->arch.guest_gprs[r1]); + break; case SIGP_RESTART: vcpu->stat.instruction_sigp_restart++; /* user space must know about restart */ -- cgit From 1eddb85f889a5a9fe59ec184e06844716a00aded Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 17 Nov 2011 11:00:43 +0100 Subject: KVM: s390: Fix tprot locking There is a potential host deadlock in the tprot intercept handling. We must not hold the mmap semaphore while resolving the guest address. If userspace is remapping, then the memory detection in the guest is broken anyway so we can safely separate the address translation from walking the vmas. Signed-off-by: Christian Borntraeger Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity --- arch/s390/kvm/priv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 391626361084..d02638959922 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -336,6 +336,7 @@ static int handle_tprot(struct kvm_vcpu *vcpu) u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0; u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0; struct vm_area_struct *vma; + unsigned long user_address; vcpu->stat.instruction_tprot++; @@ -349,9 +350,14 @@ static int handle_tprot(struct kvm_vcpu *vcpu) return -EOPNOTSUPP; + /* we must resolve the address without holding the mmap semaphore. + * This is ok since the userspace hypervisor is not supposed to change + * the mapping while the guest queries the memory. Otherwise the guest + * might crash or get wrong info anyway. */ + user_address = (unsigned long) __guestaddr_to_user(vcpu, address1); + down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, - (unsigned long) __guestaddr_to_user(vcpu, address1)); + vma = find_vma(current->mm, user_address); if (!vma) { up_read(¤t->mm->mmap_sem); return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); -- cgit From 52e16b185fdd0aeb0522c203e944873e38ac1575 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 17 Nov 2011 11:00:44 +0100 Subject: KVM: s390: announce SYNC_MMU KVM on s390 always had a sync mmu. Any mapping change in userspace mapping was always reflected immediately in the guest mapping. - In older code the guest mapping was just an offset - In newer code the last level page table is shared Signed-off-by: Christian Borntraeger Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity --- arch/s390/kvm/kvm-s390.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0891926ea953..d1c445732451 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -128,6 +128,7 @@ int kvm_dev_ioctl_check_extension(long ext) switch (ext) { case KVM_CAP_S390_PSW: case KVM_CAP_S390_GMAP: + case KVM_CAP_SYNC_MMU: r = 1; break; default: -- cgit From 8bf00a529967dafbbb210b377c38a15834d1e979 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 5 Oct 2011 14:01:22 +0200 Subject: KVM: VMX: add support for switching of PERF_GLOBAL_CTRL Some cpus have special support for switching PERF_GLOBAL_CTRL msr. Add logic to detect if such support exists and works properly and extend msr switching code to use it if available. Also extend number of generic msr switching entries to 8. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a0d6bd9ad442..55e849b52d9e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -118,7 +118,7 @@ module_param(ple_gap, int, S_IRUGO); static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW; module_param(ple_window, int, S_IRUGO); -#define NR_AUTOLOAD_MSRS 1 +#define NR_AUTOLOAD_MSRS 8 #define VMCS02_POOL_SIZE 1 struct vmcs { @@ -622,6 +622,7 @@ static unsigned long *vmx_msr_bitmap_legacy; static unsigned long *vmx_msr_bitmap_longmode; static bool cpu_has_load_ia32_efer; +static bool cpu_has_load_perf_global_ctrl; static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS); static DEFINE_SPINLOCK(vmx_vpid_lock); @@ -1191,15 +1192,34 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) vmcs_write32(EXCEPTION_BITMAP, eb); } +static void clear_atomic_switch_msr_special(unsigned long entry, + unsigned long exit) +{ + vmcs_clear_bits(VM_ENTRY_CONTROLS, entry); + vmcs_clear_bits(VM_EXIT_CONTROLS, exit); +} + static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr) { unsigned i; struct msr_autoload *m = &vmx->msr_autoload; - if (msr == MSR_EFER && cpu_has_load_ia32_efer) { - vmcs_clear_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER); - vmcs_clear_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER); - return; + switch (msr) { + case MSR_EFER: + if (cpu_has_load_ia32_efer) { + clear_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER, + VM_EXIT_LOAD_IA32_EFER); + return; + } + break; + case MSR_CORE_PERF_GLOBAL_CTRL: + if (cpu_has_load_perf_global_ctrl) { + clear_atomic_switch_msr_special( + VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, + VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL); + return; + } + break; } for (i = 0; i < m->nr; ++i) @@ -1215,18 +1235,44 @@ static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr) vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); } +static void add_atomic_switch_msr_special(unsigned long entry, + unsigned long exit, unsigned long guest_val_vmcs, + unsigned long host_val_vmcs, u64 guest_val, u64 host_val) +{ + vmcs_write64(guest_val_vmcs, guest_val); + vmcs_write64(host_val_vmcs, host_val); + vmcs_set_bits(VM_ENTRY_CONTROLS, entry); + vmcs_set_bits(VM_EXIT_CONTROLS, exit); +} + static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, u64 guest_val, u64 host_val) { unsigned i; struct msr_autoload *m = &vmx->msr_autoload; - if (msr == MSR_EFER && cpu_has_load_ia32_efer) { - vmcs_write64(GUEST_IA32_EFER, guest_val); - vmcs_write64(HOST_IA32_EFER, host_val); - vmcs_set_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER); - vmcs_set_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER); - return; + switch (msr) { + case MSR_EFER: + if (cpu_has_load_ia32_efer) { + add_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER, + VM_EXIT_LOAD_IA32_EFER, + GUEST_IA32_EFER, + HOST_IA32_EFER, + guest_val, host_val); + return; + } + break; + case MSR_CORE_PERF_GLOBAL_CTRL: + if (cpu_has_load_perf_global_ctrl) { + add_atomic_switch_msr_special( + VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, + VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL, + GUEST_IA32_PERF_GLOBAL_CTRL, + HOST_IA32_PERF_GLOBAL_CTRL, + guest_val, host_val); + return; + } + break; } for (i = 0; i < m->nr; ++i) @@ -2455,6 +2501,42 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_LOAD_IA32_EFER); + cpu_has_load_perf_global_ctrl = + allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS, + VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) + && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS, + VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL); + + /* + * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL + * but due to arrata below it can't be used. Workaround is to use + * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL. + * + * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32] + * + * AAK155 (model 26) + * AAP115 (model 30) + * AAT100 (model 37) + * BC86,AAY89,BD102 (model 44) + * BA97 (model 46) + * + */ + if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) { + switch (boot_cpu_data.x86_model) { + case 26: + case 30: + case 37: + case 44: + case 46: + cpu_has_load_perf_global_ctrl = false; + printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL " + "does not work properly. Using workaround\n"); + break; + default: + break; + } + } + return 0; } -- cgit From d7cd97964ba6d70c558348bd2c87290dce885583 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 5 Oct 2011 14:01:23 +0200 Subject: KVM: VMX: Add support for guest/host-only profiling Support guest/host-only profiling by switch perf msrs on a guest entry if needed. Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 55e849b52d9e..98f4b0bcc660 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "trace.h" @@ -6050,6 +6051,24 @@ static void vmx_cancel_injection(struct kvm_vcpu *vcpu) vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); } +static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx) +{ + int i, nr_msrs; + struct perf_guest_switch_msr *msrs; + + msrs = perf_guest_get_msrs(&nr_msrs); + + if (!msrs) + return; + + for (i = 0; i < nr_msrs; i++) + if (msrs[i].host == msrs[i].guest) + clear_atomic_switch_msr(vmx, msrs[i].msr); + else + add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest, + msrs[i].host); +} + #ifdef CONFIG_X86_64 #define R "r" #define Q "q" @@ -6099,6 +6118,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) vmx_set_interrupt_shadow(vcpu, 0); + atomic_switch_perf_msrs(vmx); + vmx->__launched = vmx->loaded_vmcs->launched; asm( /* Store host registers */ -- cgit From e7fc6f93b4242b2b566f0070709e27257d6da8a2 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Wed, 5 Oct 2011 14:01:24 +0200 Subject: KVM: VMX: Check for automatic switch msr table overflow Signed-off-by: Gleb Natapov Signed-off-by: Avi Kivity --- arch/x86/kvm/vmx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 98f4b0bcc660..579a0b51696a 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1280,7 +1280,11 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, if (m->guest[i].index == msr) break; - if (i == m->nr) { + if (i == NR_AUTOLOAD_MSRS) { + printk_once(KERN_WARNING"Not enough mst switch entries. " + "Can't add msr %x\n", msr); + return; + } else if (i == m->nr) { ++m->nr; vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr); vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); -- cgit From bb75c627fb0dfb8c0ab75d3033709ff928896e16 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 Nov 2011 15:26:35 +0100 Subject: Revert "KVM: PPC: Add support for explicit HIOR setting" This reverts commit a15bd354f083f20f257db450488db52ac27df439. It exceeded the padding on the SREGS struct, rendering the ABI backwards-incompatible. Conflicts: arch/powerpc/kvm/powerpc.c include/linux/kvm.h Signed-off-by: Avi Kivity --- arch/powerpc/include/asm/kvm.h | 8 -------- arch/powerpc/include/asm/kvm_book3s.h | 2 -- arch/powerpc/kvm/book3s_pr.c | 14 ++------------ arch/powerpc/kvm/powerpc.c | 1 - include/linux/kvm.h | 1 - 5 files changed, 2 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index 08fe69edcd10..0ad432bc81d6 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h @@ -148,12 +148,6 @@ struct kvm_regs { #define KVM_SREGS_E_UPDATE_DEC (1 << 2) #define KVM_SREGS_E_UPDATE_DBSR (1 << 3) -/* - * Book3S special bits to indicate contents in the struct by maintaining - * backwards compatibility with older structs. If adding a new field, - * please make sure to add a flag for that new field */ -#define KVM_SREGS_S_HIOR (1 << 0) - /* * In KVM_SET_SREGS, reserved/pad fields must be left untouched from a * previous KVM_GET_REGS. @@ -179,8 +173,6 @@ struct kvm_sregs { __u64 ibat[8]; __u64 dbat[8]; } ppc32; - __u64 flags; /* KVM_SREGS_S_ */ - __u64 hior; } s; struct { union { diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index a384ffdf33de..d4df013ad779 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -90,8 +90,6 @@ struct kvmppc_vcpu_book3s { #endif int context_id[SID_CONTEXTS]; - bool hior_sregs; /* HIOR is set by SREGS, not PVR */ - struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE]; struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index bc4d50dec78b..3c791e1eb675 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -151,16 +151,14 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) #ifdef CONFIG_PPC_BOOK3S_64 if ((pvr >= 0x330000) && (pvr < 0x70330000)) { kvmppc_mmu_book3s_64_init(vcpu); - if (!to_book3s(vcpu)->hior_sregs) - to_book3s(vcpu)->hior = 0xfff00000; + to_book3s(vcpu)->hior = 0xfff00000; to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL; vcpu->arch.cpu_type = KVM_CPU_3S_64; } else #endif { kvmppc_mmu_book3s_32_init(vcpu); - if (!to_book3s(vcpu)->hior_sregs) - to_book3s(vcpu)->hior = 0; + to_book3s(vcpu)->hior = 0; to_book3s(vcpu)->msr_mask = 0xffffffffULL; vcpu->arch.cpu_type = KVM_CPU_3S_32; } @@ -797,9 +795,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, } } - if (sregs->u.s.flags & KVM_SREGS_S_HIOR) - sregs->u.s.hior = to_book3s(vcpu)->hior; - return 0; } @@ -836,11 +831,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, /* Flush the MMU after messing with the segments */ kvmppc_mmu_pte_flush(vcpu, 0, 0); - if (sregs->u.s.flags & KVM_SREGS_S_HIOR) { - to_book3s(vcpu)->hior_sregs = true; - to_book3s(vcpu)->hior = sregs->u.s.hior; - } - return 0; } diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index efbf9ad87203..607fbdf24b84 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -208,7 +208,6 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_PPC_BOOKE_SREGS: #else case KVM_CAP_PPC_SEGSTATE: - case KVM_CAP_PPC_HIOR: case KVM_CAP_PPC_PAPR: #endif case KVM_CAP_PPC_UNSET_IRQ: diff --git a/include/linux/kvm.h b/include/linux/kvm.h index f47fcd30273d..c3892fc1d538 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -555,7 +555,6 @@ struct kvm_ppc_pvinfo { #define KVM_CAP_PPC_SMT 64 #define KVM_CAP_PPC_RMA 65 #define KVM_CAP_MAX_VCPUS 66 /* returns max vcpus per vm */ -#define KVM_CAP_PPC_HIOR 67 #define KVM_CAP_PPC_PAPR 68 #define KVM_CAP_S390_GMAP 71 -- cgit From bce34d14428d35d9a06ddc10cd46ecef311764c9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 17 Nov 2011 15:05:14 +0000 Subject: ARM: perf: initialise used_mask for fake PMU during validation When validating an event group, we call pmu->get_event_idx for each group member in order to check that the group can be scheduled as a unit on an empty PMU. As a result of 3fc2c830 ("ARM: perf: remove event limit from pmu_hw_events"), the used_mask member of struct cpu_hw_events must be setup explicitly, something which we don't do for the fake cpu_hw_events used for validation. This patch sets up an empty used_mask for the fake validation cpu_hw_events, preventing NULL deferences when trying to get the event index. Reported-by: Pawel Moll Signed-off-by: Will Deacon --- arch/arm/kernel/perf_event.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 24e2347be6b1..e508066d3d64 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -343,8 +343,14 @@ validate_group(struct perf_event *event) { struct perf_event *sibling, *leader = event->group_leader; struct pmu_hw_events fake_pmu; + DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS); - memset(&fake_pmu, 0, sizeof(fake_pmu)); + /* + * Initialise the fake PMU. We only need to populate the + * used_mask for the purposes of validation. + */ + memset(fake_used_mask, 0, sizeof(fake_used_mask)); + fake_pmu.used_mask = fake_used_mask; if (!validate_event(&fake_pmu, leader)) return -ENOSPC; -- cgit From 2ed0e645f358c26f4f4a7aed56a9488db0020ad1 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 16 Nov 2011 12:27:39 +0000 Subject: genirq: Don't allow per cpu interrupts to be suspended The power management functions related to interrupts do not know (yet) about per-cpu interrupts and end up calling the wrong low-level methods to enable/disable interrupts. This leads to all kind of interesting issues (action taken on one CPU only, updating a refcount which is not used otherwise...). The workaround for the time being is simply to flag these interrupts with IRQF_NO_SUSPEND. At least on ARM, these interrupts are actually dealt with at the architecture level. Reported-by: Santosh Shilimkar Tested-by: Santosh Shilimkar Signed-off-by: Marc Zyngier Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1321446459-31409-1-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- kernel/irq/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 67ce837ae52c..0e2b179bc7b3 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1596,7 +1596,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler, return -ENOMEM; action->handler = handler; - action->flags = IRQF_PERCPU; + action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND; action->name = devname; action->percpu_dev_id = dev_id; -- cgit From 2391a0e06789a3f1718dee30b282562f7ed28c87 Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors Date: Thu, 17 Nov 2011 02:52:50 +0200 Subject: ASoC: wm8753: Skip noop reconfiguration of DAI mode This patch makes it possible to set DAI mode to its currently applied value even if codec is active. This is necessary to allow aplay -t raw -r 44100 -f S16_LE -c 2 < /dev/urandom & alsactl store -f backup.state alsactl restore -f backup.state to work without returning errors. This patch is based on a patch sent by Klaus Kurzmann . Signed-off-by: Timo Juhani Lindfors Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8753.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a9504710bb69..3a629d0d690e 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -190,6 +190,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); u16 ioctl; + if (wm8753->dai_func == ucontrol->value.integer.value[0]) + return 0; + if (codec->active) return -EBUSY; -- cgit From e5489847d6fc0ff176048b6e1cf5034507bf703a Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 17 Nov 2011 16:58:00 +0000 Subject: ARM: wire up process_vm_writev and process_vm_readv syscalls These two syscalls were introduced during the last merge window. Add the entries into the ARM call tables for them. Signed-off-by: Russell King --- arch/arm/include/asm/unistd.h | 2 ++ arch/arm/kernel/calls.S | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index c60a2944f95b..4a1123783806 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -402,6 +402,8 @@ #define __NR_syncfs (__NR_SYSCALL_BASE+373) #define __NR_sendmmsg (__NR_SYSCALL_BASE+374) #define __NR_setns (__NR_SYSCALL_BASE+375) +#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) +#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) /* * The following SWIs are ARM private. diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 9943e9e74a1b..463ff4a0ec8a 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -385,6 +385,8 @@ CALL(sys_syncfs) CALL(sys_sendmmsg) /* 375 */ CALL(sys_setns) + CALL(sys_process_vm_readv) + CALL(sys_process_vm_writev) #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls #define syscalls_counted -- cgit From df92d0561de364de53c42abc5d43e04ab6f326a5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 16 Nov 2011 16:27:07 +0100 Subject: TTY: ldisc, allow waiting for ldisc arbitrarily long To fix a nasty bug in ldisc hup vs. reinit we need to wait infinitely long for ldisc to be gone. So here we add a parameter to tty_ldisc_wait_idle to allow that. This is only a preparation for the real fix which is done in the following patches. Signed-off-by: Jiri Slaby Cc: Dave Young Cc: Dave Jones Cc: Ben Hutchings Cc: Dmitriy Matrosov Cc: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 512c49f98e85..534d176a78ed 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -547,15 +547,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) /** * tty_ldisc_wait_idle - wait for the ldisc to become idle * @tty: tty to wait for + * @timeout: for how long to wait at most * * Wait for the line discipline to become idle. The discipline must * have been halted for this to guarantee it remains idle. */ -static int tty_ldisc_wait_idle(struct tty_struct *tty) +static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) { - int ret; + long ret; ret = wait_event_timeout(tty_ldisc_idle, - atomic_read(&tty->ldisc->users) == 1, 5 * HZ); + atomic_read(&tty->ldisc->users) == 1, timeout); if (ret < 0) return ret; return ret > 0 ? 0 : -EBUSY; @@ -665,7 +666,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_ldisc_flush_works(tty); - retval = tty_ldisc_wait_idle(tty); + retval = tty_ldisc_wait_idle(tty, 5 * HZ); tty_lock(); mutex_lock(&tty->ldisc_mutex); @@ -762,7 +763,7 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) if (IS_ERR(ld)) return -1; - WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); + WARN_ON_ONCE(tty_ldisc_wait_idle(tty, 5 * HZ)); tty_ldisc_close(tty, tty->ldisc); tty_ldisc_put(tty->ldisc); -- cgit From 300420722e0734a4254f3b634e0f82664495d210 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 16 Nov 2011 16:27:08 +0100 Subject: TTY: ldisc, move wait idle to caller It is the only place where reinit is called from. And we really need to wait for the old ldisc to go once. Actually this is the place where the waiting originally was (before removed and re-added later). This will make the fix in the following patch easier to implement. Signed-off-by: Jiri Slaby Cc: Dave Young Cc: Dave Jones Cc: Ben Hutchings Cc: Dmitriy Matrosov Cc: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 534d176a78ed..a69a755035b6 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -763,8 +763,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) if (IS_ERR(ld)) return -1; - WARN_ON_ONCE(tty_ldisc_wait_idle(tty, 5 * HZ)); - tty_ldisc_close(tty, tty->ldisc); tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; @@ -848,6 +846,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) it means auditing a lot of other paths so this is a FIXME */ if (tty->ldisc) { /* Not yet closed */ + WARN_ON_ONCE(tty_ldisc_wait_idle(tty, 5 * HZ)); + if (reset == 0) { if (!tty_ldisc_reinit(tty, tty->termios->c_line)) -- cgit From 0c73c08ec73dbe080b9ec56696ee21d32754d918 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 16 Nov 2011 16:27:09 +0100 Subject: TTY: ldisc, wait for ldisc infinitely in hangup For /dev/console case, we do not kill all ldisc users. It's due to redirected_tty_write test in __tty_hangup. In that case there still might be a process waiting e.g. in n_tty_read for input. We wait for such processes to disappear. The problem is that we use a timeout. After this timeout, we continue closing the ldisc and start freeing tty resources. It obviously leads to crashes when the other process is woken. So to fix this, we wait infinitely before reiniting the ldisc. (The tiocsetd remains untouched -- times out after 5s.) This is nicely reproducible with this run from shell: exec 0<>/dev/console 1<>/dev/console 2<>/dev/console and stopping a getty like: systemctl stop serial-getty@ttyS0.service The crash proper may be produced only under load or with constified timing the same as for 92f6fa09b. Signed-off-by: Jiri Slaby Cc: Dave Young Cc: Dave Jones Cc: Ben Hutchings Cc: Dmitriy Matrosov Cc: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index a69a755035b6..8e0924f55446 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -36,6 +36,7 @@ #include #include +#include /* * This guards the refcounted line discipline lists. The lock @@ -837,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) tty_unlock(); cancel_work_sync(&tty->buf.work); mutex_unlock(&tty->ldisc_mutex); - +retry: tty_lock(); mutex_lock(&tty->ldisc_mutex); @@ -846,7 +847,21 @@ void tty_ldisc_hangup(struct tty_struct *tty) it means auditing a lot of other paths so this is a FIXME */ if (tty->ldisc) { /* Not yet closed */ - WARN_ON_ONCE(tty_ldisc_wait_idle(tty, 5 * HZ)); + if (atomic_read(&tty->ldisc->users) != 1) { + char cur_n[TASK_COMM_LEN], tty_n[64]; + long timeout = 3 * HZ; + tty_unlock(); + + while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { + timeout = MAX_SCHEDULE_TIMEOUT; + printk_ratelimited(KERN_WARNING + "%s: waiting (%s) for %s took too long, but we keep waiting...\n", + __func__, get_task_comm(cur_n, current), + tty_name(tty, tty_n)); + } + mutex_unlock(&tty->ldisc_mutex); + goto retry; + } if (reset == 0) { -- cgit From 4ba7d9997869d25bd223dea7536fc1ce9fab3b3b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 16 Nov 2011 11:09:17 +0100 Subject: rt2800pci: handle spurious interrupts Some devices may generate spurious interrupts, we have to handle them otherwise interrupt line will be disabled with below message and driver will not work: [ 2052.114334] irq 17: nobody cared (try booting with the "irqpoll" option) [ 2052.114339] Pid: 0, comm: swapper Tainted: P 2.6.35.6-48.fc14.x86_64 #1 [ 2052.114341] Call Trace: [ 2052.114342] [] __report_bad_irq.clone.1+0x3d/0x8b [ 2052.114349] [] note_interrupt+0x11a/0x17f [ 2052.114352] [] handle_fasteoi_irq+0xa8/0xce [ 2052.114355] [] handle_irq+0x88/0x90 [ 2052.114357] [] do_IRQ+0x5c/0xb4 [ 2052.114360] [] ret_from_intr+0x0/0x11 [ 2052.114361] [] ? native_safe_halt+0xb/0xd [ 2052.114366] [] ? need_resched+0x23/0x2d [ 2052.114367] [] default_idle+0x34/0x4f [ 2052.114370] [] cpu_idle+0xaa/0xcc [ 2052.114373] [] start_secondary+0x24d/0x28e [ 2052.114374] handlers: [ 2052.114375] [] (usb_hcd_irq+0x0/0x7c) [ 2052.114378] [] (rt2800pci_interrupt+0x0/0x18d [rt2800pci]) [ 2052.114384] Disabling IRQ #17 Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=658451 Reported-and-tested-by: Amir Hedayaty Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index da48c8ac27bd..4dc2d0f840d4 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -880,8 +880,13 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + /* + * Some devices can generate interrupts with empty CSR register, we + * "handle" such irq's to prevent interrupt controller treat them as + * spurious interrupts and disable irq line. + */ if (!reg) - return IRQ_NONE; + return IRQ_HANDLED; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; -- cgit From 23085d5796561625db4143a671f1de081f66ef08 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 16 Nov 2011 13:58:42 +0100 Subject: rt2x00: handle spurious pci interrupts We have documented case of very bad performance issue on rt2800pci device, because it generate spurious interrupt, what cause irq line is disabled: https://bugzilla.redhat.com/show_bug.cgi?id=658451 We already address that problem in separate patch by returning IRQ_HANDLED from interrupt handler. We think similar fix is needed for other rt2x00 PCI devices, because users report performance problems on these devices too. Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3a6b40239bc1..676c7657f5f5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1380,7 +1380,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, CSR7, reg); if (!reg) - return IRQ_NONE; + return IRQ_HANDLED; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index dcc0e1fcca77..d0b627c6c217 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1512,7 +1512,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, CSR7, reg); if (!reg) - return IRQ_NONE; + return IRQ_HANDLED; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index bf55b4a311e3..9d83e70f3e62 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2337,7 +2337,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg && !reg_mcu) - return IRQ_NONE; + return IRQ_HANDLED; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; -- cgit From 68fa64ef606bcee688fce46d07aa68f175070156 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 16 Nov 2011 23:16:15 +0100 Subject: rt2x00: Fix efuse EEPROM reading on PPC32. Fix __le32 to __le16 conversion of the first word of an 8-word block of EEPROM read via the efuse method. Reported-and-tested-by: Ingvar Hagelund Signed-off-by: Gertjan van Wingerde CC: Acked-by: Helmut Schaa Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3f183a15186e..1ba079dffb11 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3771,7 +3771,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) /* Apparently the data is read from end to start */ rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); /* The returned value is in CPU order, but eeprom is le */ - rt2x00dev->eeprom[i] = cpu_to_le32(reg); + *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, ®); *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); -- cgit From 32d3a3922d617a5a685a5e2d24b20d0e88f192a9 Mon Sep 17 00:00:00 2001 From: Michael Büsch Date: Wed, 16 Nov 2011 23:48:31 +0100 Subject: p54spi: Add missing spin_lock_init The tx_lock is not initialized properly. Add spin_lock_init(). Signed-off-by: Michael Buesch Cc: Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index f18df82eeb92..dda97c54d28f 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -656,6 +656,7 @@ static int __devinit p54spi_probe(struct spi_device *spi) init_completion(&priv->fw_comp); INIT_LIST_HEAD(&priv->tx_pending); mutex_init(&priv->mutex); + spin_lock_init(&priv->tx_lock); SET_IEEE80211_DEV(hw, &spi->dev); priv->common.open = p54spi_op_start; priv->common.stop = p54spi_op_stop; -- cgit From 2d1618170eb493d18f66f2ac03775409a6fb97c6 Mon Sep 17 00:00:00 2001 From: Michael Büsch Date: Wed, 16 Nov 2011 23:55:46 +0100 Subject: p54spi: Fix workqueue deadlock priv->work must not be synced while priv->mutex is locked, because the mutex is taken in the work handler. Move cancel_work_sync down to after the device shutdown code. This is safe, because the work handler checks fw_state and bails out early in case of a race. Signed-off-by: Michael Buesch Cc: Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index dda97c54d28f..78d0d6988553 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -588,8 +588,6 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) WARN_ON(priv->fw_state != FW_STATE_READY); - cancel_work_sync(&priv->work); - p54spi_power_off(priv); spin_lock_irqsave(&priv->tx_lock, flags); INIT_LIST_HEAD(&priv->tx_pending); @@ -597,6 +595,8 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) priv->fw_state = FW_STATE_OFF; mutex_unlock(&priv->mutex); + + cancel_work_sync(&priv->work); } static int __devinit p54spi_probe(struct spi_device *spi) -- cgit From 8b258cc8ac229aa7d5dcb7cc34cb35d9124498ac Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 17 Nov 2011 21:39:33 +0100 Subject: PM Sleep: Do not extend wakeup paths to devices with ignore_children set Commit 4ca46ff3e0d8c234cb40ebb6457653b59584426c (PM / Sleep: Mark devices involved in wakeup signaling during suspend) introduced the power.wakeup_path field in struct dev_pm_info to mark devices whose children are enabled to wake up the system from sleep states, so that power domains containing the parents that provide their children with wakeup power and/or relay their wakeup signals are not turned off. Unfortunately, that introduced a PM regression on SH7372 whose power consumption in the system "memory sleep" state increased as a result of it, because it prevented the power domain containing the I2C controller from being turned off when some children of that controller were enabled to wake up the system, although the controller was not necessary for them to signal wakeup. To fix this issue use the observation that devices whose power.ignore_children flag is set for runtime PM should be treated analogously during system suspend. Namely, they shouldn't be included in wakeup paths going through their children. Since the SH7372 I2C controller's power.ignore_children flag is set, doing so will restore the previous behavior of that SOC. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 3 ++- include/linux/device.h | 5 +++++ include/linux/pm.h | 2 +- include/linux/pm_runtime.h | 6 ------ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7fa098464dae..c3d2dfcf438d 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -920,7 +920,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) End: if (!error) { dev->power.is_suspended = true; - if (dev->power.wakeup_path && dev->parent) + if (dev->power.wakeup_path + && dev->parent && !dev->parent->power.ignore_children) dev->parent->power.wakeup_path = true; } diff --git a/include/linux/device.h b/include/linux/device.h index ffbcf95cd97d..52b3a4111df9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -682,6 +682,11 @@ static inline bool device_async_suspend_enabled(struct device *dev) return !!dev->power.async_suspend; } +static inline void pm_suspend_ignore_children(struct device *dev, bool enable) +{ + dev->power.ignore_children = enable; +} + static inline void device_lock(struct device *dev) { mutex_lock(&dev->mutex); diff --git a/include/linux/pm.h b/include/linux/pm.h index f15acb646813..5c4c8b18c8b7 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -447,6 +447,7 @@ struct dev_pm_info { unsigned int async_suspend:1; bool is_prepared:1; /* Owned by the PM core */ bool is_suspended:1; /* Ditto */ + bool ignore_children:1; spinlock_t lock; #ifdef CONFIG_PM_SLEEP struct list_head entry; @@ -464,7 +465,6 @@ struct dev_pm_info { atomic_t usage_count; atomic_t child_count; unsigned int disable_depth:3; - unsigned int ignore_children:1; unsigned int idle_notification:1; unsigned int request_pending:1; unsigned int deferred_resume:1; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index d8d903619642..d3085e72a0ee 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -52,11 +52,6 @@ static inline bool pm_children_suspended(struct device *dev) || !atomic_read(&dev->power.child_count); } -static inline void pm_suspend_ignore_children(struct device *dev, bool enable) -{ - dev->power.ignore_children = enable; -} - static inline void pm_runtime_get_noresume(struct device *dev) { atomic_inc(&dev->power.usage_count); @@ -130,7 +125,6 @@ static inline void pm_runtime_allow(struct device *dev) {} static inline void pm_runtime_forbid(struct device *dev) {} static inline bool pm_children_suspended(struct device *dev) { return false; } -static inline void pm_suspend_ignore_children(struct device *dev, bool en) {} static inline void pm_runtime_get_noresume(struct device *dev) {} static inline void pm_runtime_put_noidle(struct device *dev) {} static inline bool device_run_wake(struct device *dev) { return false; } -- cgit From 88995e809f8a8115f30db24696c9137aad93d570 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 17 Nov 2011 21:39:55 +0100 Subject: PM / shmobile: Fix build of sh7372_pm_init() for CONFIG_PM unset Fix build regression introduced by commit 056879d2f244001b2888cdc8cf (ARM: mach-shmobile: sh7372 A3SP no_suspend_console fix) by moving the intialization of the A3SP domain to a separate function and providing an empty definition of it for CONFIG_PM unset. Reported-and-tested-by: Guennadi Liakhovetski Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pm-sh7372.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 1ec35ebe2376..f15f07e15856 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -232,11 +232,23 @@ struct sh7372_pm_domain sh7372_a3sp = { .no_debug = true, }; +static void sh7372_a3sp_init(void) +{ + /* serial consoles make use of SCIF hardware located in A3SP, + * keep such power domain on if "no_console_suspend" is set. + */ + sh7372_a3sp.stay_on = !console_suspend_enabled; +} + struct sh7372_pm_domain sh7372_a3sg = { .bit_shift = 13, }; -#endif /* CONFIG_PM */ +#else /* !CONFIG_PM */ + +static inline void sh7372_a3sp_init(void) {} + +#endif /* !CONFIG_PM */ #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) static int sh7372_do_idle_core_standby(unsigned long unused) @@ -474,10 +486,7 @@ void __init sh7372_pm_init(void) /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ __raw_writel(0, PDNSEL); - /* serial consoles make use of SCIF hardware located in A3SP, - * keep such power domain on if "no_console_suspend" is set. - */ - sh7372_a3sp.stay_on = !console_suspend_enabled; + sh7372_a3sp_init(); sh7372_suspend_init(); sh7372_cpuidle_init(); -- cgit From 457eafce618cf89125da9d79751d81241bd3fa34 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Wed, 16 Nov 2011 00:49:28 +0600 Subject: drm, i915: Fix memory leak in i915_gem_busy_ioctl(). A call to i915_add_request() has been made in function i915_gem_busy_ioctl(). i915_add_request can fail, so in it's exit path previously allocated memory needs to be freed. Signed-off-by: Rakib Mullick Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ed0b68fdb970..8359dc777041 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3512,9 +3512,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * so emit a request to do so. */ request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request) + if (request) { ret = i915_add_request(obj->ring, NULL, request); - else + if (ret) + kfree(request); + } else ret = -ENOMEM; } -- cgit From f6f8285132907757ef84ef8dae0a1244b8cde6ac Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 17 Nov 2011 12:58:07 -0800 Subject: pstore: pass allocated memory region back to caller The buf_lock cannot be held while populating the inodes, so make the backend pass forward an allocated and filled buffer instead. This solves the following backtrace. The effect is that "buf" is only ever used to notify the backends that something was written to it, and shouldn't be used in the read path. To replace the buf_lock during the read path, isolate the open/read/close loop with a separate mutex to maintain serialized access to the backend. Note that is is up to the pstore backend to cope if the (*write)() path is called in the middle of the read path. [ 59.691019] BUG: sleeping function called from invalid context at .../mm/slub.c:847 [ 59.691019] in_atomic(): 0, irqs_disabled(): 1, pid: 1819, name: mount [ 59.691019] Pid: 1819, comm: mount Not tainted 3.0.8 #1 [ 59.691019] Call Trace: [ 59.691019] [<810252d5>] __might_sleep+0xc3/0xca [ 59.691019] [<810a26e6>] kmem_cache_alloc+0x32/0xf3 [ 59.691019] [<810b53ac>] ? __d_lookup_rcu+0x6f/0xf4 [ 59.691019] [<810b68b1>] alloc_inode+0x2a/0x64 [ 59.691019] [<810b6903>] new_inode+0x18/0x43 [ 59.691019] [<81142447>] pstore_get_inode.isra.1+0x11/0x98 [ 59.691019] [<81142623>] pstore_mkfile+0xae/0x26f [ 59.691019] [<810a2a66>] ? kmem_cache_free+0x19/0xb1 [ 59.691019] [<8116c821>] ? ida_get_new_above+0x140/0x158 [ 59.691019] [<811708ea>] ? __init_rwsem+0x1e/0x2c [ 59.691019] [<810b67e8>] ? inode_init_always+0x111/0x1b0 [ 59.691019] [<8102127e>] ? should_resched+0xd/0x27 [ 59.691019] [<8137977f>] ? _cond_resched+0xd/0x21 [ 59.691019] [<81142abf>] pstore_get_records+0x52/0xa7 [ 59.691019] [<8114254b>] pstore_fill_super+0x7d/0x91 [ 59.691019] [<810a7ff5>] mount_single+0x46/0x82 [ 59.691019] [<8114231a>] pstore_mount+0x15/0x17 [ 59.691019] [<811424ce>] ? pstore_get_inode.isra.1+0x98/0x98 [ 59.691019] [<810a8199>] mount_fs+0x5a/0x12d [ 59.691019] [<810b9174>] ? alloc_vfsmnt+0xa4/0x14a [ 59.691019] [<810b9474>] vfs_kern_mount+0x4f/0x7d [ 59.691019] [<810b9d7e>] do_kern_mount+0x34/0xb2 [ 59.691019] [<810bb15f>] do_mount+0x5fc/0x64a [ 59.691019] [<810912fb>] ? strndup_user+0x2e/0x3f [ 59.691019] [<810bb3cb>] sys_mount+0x66/0x99 [ 59.691019] [<8137b537>] sysenter_do_call+0x12/0x26 Signed-off-by: Kees Cook Signed-off-by: Tony Luck --- drivers/acpi/apei/erst.c | 31 ++++++++++++++++++++++--------- drivers/firmware/efivars.c | 9 +++++++-- fs/pstore/platform.c | 13 ++++++++----- include/linux/pstore.h | 4 +++- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 127408069ca7..631b9477b99c 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -932,7 +932,8 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) static int erst_open_pstore(struct pstore_info *psi); static int erst_close_pstore(struct pstore_info *psi); static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, - struct timespec *time, struct pstore_info *psi); + struct timespec *time, char **buf, + struct pstore_info *psi); static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part, size_t size, struct pstore_info *psi); static int erst_clearer(enum pstore_type_id type, u64 id, @@ -986,17 +987,23 @@ static int erst_close_pstore(struct pstore_info *psi) } static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, - struct timespec *time, struct pstore_info *psi) + struct timespec *time, char **buf, + struct pstore_info *psi) { int rc; ssize_t len = 0; u64 record_id; - struct cper_pstore_record *rcd = (struct cper_pstore_record *) - (erst_info.buf - sizeof(*rcd)); + struct cper_pstore_record *rcd; + size_t rcd_len = sizeof(*rcd) + erst_info.bufsize; if (erst_disable) return -ENODEV; + rcd = kmalloc(rcd_len, GFP_KERNEL); + if (!rcd) { + rc = -ENOMEM; + goto out; + } skip: rc = erst_get_record_id_next(&reader_pos, &record_id); if (rc) @@ -1004,22 +1011,27 @@ skip: /* no more record */ if (record_id == APEI_ERST_INVALID_RECORD_ID) { - rc = -1; + rc = -EINVAL; goto out; } - len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + - erst_info.bufsize); + len = erst_read(record_id, &rcd->hdr, rcd_len); /* The record may be cleared by others, try read next record */ if (len == -ENOENT) goto skip; - else if (len < 0) { - rc = -1; + else if (len < sizeof(*rcd)) { + rc = -EIO; goto out; } if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) goto skip; + *buf = kmalloc(len, GFP_KERNEL); + if (*buf == NULL) { + rc = -ENOMEM; + goto out; + } + memcpy(*buf, rcd->data, len - sizeof(*rcd)); *id = record_id; if (uuid_le_cmp(rcd->sec_hdr.section_type, CPER_SECTION_TYPE_DMESG) == 0) @@ -1037,6 +1049,7 @@ skip: time->tv_nsec = 0; out: + kfree(rcd); return (rc < 0) ? rc : (len - sizeof(*rcd)); } diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 8370f72d87ff..a54a6b972ced 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -457,7 +457,8 @@ static int efi_pstore_close(struct pstore_info *psi) } static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, - struct timespec *timespec, struct pstore_info *psi) + struct timespec *timespec, + char **buf, struct pstore_info *psi) { efi_guid_t vendor = LINUX_EFI_CRASH_GUID; struct efivars *efivars = psi->data; @@ -478,7 +479,11 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, timespec->tv_nsec = 0; get_var_data_locked(efivars, &efivars->walk_entry->var); size = efivars->walk_entry->var.DataSize; - memcpy(psi->buf, efivars->walk_entry->var.Data, size); + *buf = kmalloc(size, GFP_KERNEL); + if (*buf == NULL) + return -ENOMEM; + memcpy(*buf, efivars->walk_entry->var.Data, + size); efivars->walk_entry = list_entry(efivars->walk_entry->list.next, struct efivar_entry, list); return size; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 2bd620f0d796..57bbf9078ac8 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -167,6 +167,7 @@ int pstore_register(struct pstore_info *psi) } psinfo = psi; + mutex_init(&psinfo->read_mutex); spin_unlock(&pstore_lock); if (owner && !try_module_get(owner)) { @@ -195,30 +196,32 @@ EXPORT_SYMBOL_GPL(pstore_register); void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; + char *buf = NULL; ssize_t size; u64 id; enum pstore_type_id type; struct timespec time; int failed = 0, rc; - unsigned long flags; if (!psi) return; - spin_lock_irqsave(&psinfo->buf_lock, flags); + mutex_lock(&psi->read_mutex); rc = psi->open(psi); if (rc) goto out; - while ((size = psi->read(&id, &type, &time, psi)) > 0) { - rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, + while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) { + rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size, time, psi); + kfree(buf); + buf = NULL; if (rc && (rc != -EEXIST || !quiet)) failed++; } psi->close(psi); out: - spin_unlock_irqrestore(&psinfo->buf_lock, flags); + mutex_unlock(&psi->read_mutex); if (failed) printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n", diff --git a/include/linux/pstore.h b/include/linux/pstore.h index ea567321ae3c..2ca8cde5459d 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -35,10 +35,12 @@ struct pstore_info { spinlock_t buf_lock; /* serialize access to 'buf' */ char *buf; size_t bufsize; + struct mutex read_mutex; /* serialize open/read/close */ int (*open)(struct pstore_info *psi); int (*close)(struct pstore_info *psi); ssize_t (*read)(u64 *id, enum pstore_type_id *type, - struct timespec *time, struct pstore_info *psi); + struct timespec *time, char **buf, + struct pstore_info *psi); int (*write)(enum pstore_type_id type, u64 *id, unsigned int part, size_t size, struct pstore_info *psi); int (*erase)(enum pstore_type_id type, u64 id, -- cgit From 04b38670cf46c096705f24e92a8747d1ab89e53c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 10:58:03 +0100 Subject: drm/i915: Fix inconsistent backlight level during disabled When the brightness property is inquired while the backlight is disabled, the driver returns a wrong value (zero) because it probes the value after the backlight was turned off. This caused a black screen even after the backlight is enabled again. It should return the internal backlight_level instead, so that it won't be influenced by the backlight-enable state. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=41926 BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/872652 Tested-by: Kamal Mostafa Cc: Alex Davis Cc: Signed-off-by: Takashi Iwai Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 499d4c0dbeeb..21f60b7d69a3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -326,7 +326,8 @@ static int intel_panel_update_status(struct backlight_device *bd) static int intel_panel_get_brightness(struct backlight_device *bd) { struct drm_device *dev = bl_get_data(bd); - return intel_panel_get_backlight(dev); + struct drm_i915_private *dev_priv = dev->dev_private; + return dev_priv->backlight_level; } static const struct backlight_ops intel_panel_bl_ops = { -- cgit From 38ff1edb52f737d490126728e3d5ba2b8d2f3ba0 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Thu, 17 Nov 2011 02:58:55 +0000 Subject: f_phonet: fix page offset of first received fragment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We pull one byte (the MAC header) from the first fragment before the fragment is actually appended. So the socket buffer length is 1, not 0. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- drivers/usb/gadget/f_phonet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 349077033338..16a509ae517b 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -346,7 +346,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req) } skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, - skb->len == 0, req->actual); + skb->len <= 1, req->actual); page = NULL; if (req->actual < req->length) { /* Last fragment */ -- cgit From d004e024058a0eaca097513ce62cbcf978913e0a Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 14 Nov 2011 11:15:25 +0100 Subject: timekeeping: add arch_offset hook to ktime_get functions ktime_get and ktime_get_ts were calling timekeeping_get_ns() but later they were not calling arch_gettimeoffset() so architectures using this mechanism returned 0 ns when calling these functions. This happened for example when running Busybox's ping which calls syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts) which eventually calls ktime_get. As a result the returned ping travel time was zero. CC: stable@kernel.org Signed-off-by: Hector Palacios Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index e9f60d311436..237841378c03 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -249,6 +249,8 @@ ktime_t ktime_get(void) secs = xtime.tv_sec + wall_to_monotonic.tv_sec; nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec; nsecs += timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); } while (read_seqretry(&xtime_lock, seq)); /* @@ -280,6 +282,8 @@ void ktime_get_ts(struct timespec *ts) *ts = xtime; tomono = wall_to_monotonic; nsecs = timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); } while (read_seqretry(&xtime_lock, seq)); -- cgit From 4a8bb7e27fbb68da888b55f26defd2855225b2d5 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Tue, 15 Nov 2011 06:44:42 +0000 Subject: bonding: Don't allow mode change via sysfs with slaves present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When changing mode via bonding's sysfs, the slaves are not initialized correctly. Forbid to change modes with slaves present to ensure that every slave is initialized correctly via bond_enslave(). Signed-off-by: Veaceslav Falico Signed-off-by: Andy Gospodarek Acked-by: Nicolas de Pesloüan Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 5a20804fdece..4ef7e2fd9fe6 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -319,6 +319,13 @@ static ssize_t bonding_store_mode(struct device *d, goto out; } + if (bond->slave_cnt > 0) { + pr_err("unable to update mode of %s because it has slaves.\n", + bond->dev->name); + ret = -EPERM; + goto out; + } + new_value = bond_parse_parm(buf, bond_mode_tbl); if (new_value < 0) { pr_err("%s: Ignoring invalid mode value %.*s.\n", -- cgit From 3e37fd3153ac95088a74f5e7c569f7567e9f993a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 17 Nov 2011 18:17:59 -0800 Subject: sparc: Kill custom io_remap_pfn_range(). To handle the large physical addresses, just make a simple wrapper around remap_pfn_range() like MIPS does. Signed-off-by: David S. Miller --- arch/sparc/include/asm/pgtable_32.h | 20 ++++- arch/sparc/include/asm/pgtable_64.h | 20 ++++- arch/sparc/mm/Makefile | 1 - arch/sparc/mm/generic_32.c | 99 ---------------------- arch/sparc/mm/generic_64.c | 165 ------------------------------------ 5 files changed, 32 insertions(+), 273 deletions(-) delete mode 100644 arch/sparc/mm/generic_32.c delete mode 100644 arch/sparc/mm/generic_64.c diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 5b31a8e89823..a790cc657476 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_bitmap; #define kern_addr_valid(addr) \ (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap)) -extern int io_remap_pfn_range(struct vm_area_struct *vma, - unsigned long from, unsigned long pfn, - unsigned long size, pgprot_t prot); - /* * For sparc32&64, the pfn in io_remap_pfn_range() carries in * its high 4 bits. These macros/functions put it there or get it from there. @@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) #define GET_PFN(pfn) (pfn & 0x0fffffffUL) +extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, + unsigned long, pgprot_t); + +static inline int io_remap_pfn_range(struct vm_area_struct *vma, + unsigned long from, unsigned long pfn, + unsigned long size, pgprot_t prot) +{ + unsigned long long offset, space, phys_base; + + offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT; + space = GET_IOSPACE(pfn); + phys_base = offset | (space << 32ULL); + + return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); +} + #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ ({ \ diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index adf89329af59..38ebb2c60137 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsigned long addr) extern int page_in_phys_avail(unsigned long paddr); -extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long pfn, - unsigned long size, pgprot_t prot); - /* * For sparc32&64, the pfn in io_remap_pfn_range() carries in * its high 4 bits. These macros/functions put it there or get it from there. @@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) #define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL) +extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, + unsigned long, pgprot_t); + +static inline int io_remap_pfn_range(struct vm_area_struct *vma, + unsigned long from, unsigned long pfn, + unsigned long size, pgprot_t prot) +{ + unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; + int space = GET_IOSPACE(pfn); + unsigned long phys_base; + + phys_base = offset | (((unsigned long) space) << 32UL); + + return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); +} + #include /* We provide our own get_unmapped_area to cope with VA holes and diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index e3cda21b5ee9..301421c11291 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o obj-y += fault_$(BITS).o obj-y += init_$(BITS).o obj-$(CONFIG_SPARC32) += loadmmu.o -obj-y += generic_$(BITS).o obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o obj-$(CONFIG_SPARC_LEON)+= leon_mm.o diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c deleted file mode 100644 index 6ca39a60a196..000000000000 --- a/arch/sparc/mm/generic_32.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * generic.c: Generic Sparc mm routines that are not dependent upon - * MMU type but are Sparc specific. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* Remap IO memory, the same way as remap_pfn_range(), but use - * the obio memory space. - * - * They use a pgprot that sets PAGE_IO and does not check the - * mem_map table as this is independent of normal memory. - */ -static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space)); - address += PAGE_SIZE; - offset += PAGE_SIZE; - pte++; - } while (address < end); -} - -static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - offset -= address; - do { - pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); - if (!pte) - return -ENOMEM; - io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return 0; -} - -int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long pfn, unsigned long size, pgprot_t prot) -{ - int error = 0; - pgd_t * dir; - unsigned long beg = from; - unsigned long end = from + size; - struct mm_struct *mm = vma->vm_mm; - int space = GET_IOSPACE(pfn); - unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; - - /* See comment in mm/memory.c remap_pfn_range */ - vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; - vma->vm_pgoff = (offset >> PAGE_SHIFT) | - ((unsigned long)space << 28UL); - - offset -= from; - dir = pgd_offset(mm, from); - flush_cache_range(vma, beg, end); - - while (from < end) { - pmd_t *pmd = pmd_alloc(mm, dir, from); - error = -ENOMEM; - if (!pmd) - break; - error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space); - if (error) - break; - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - - flush_tlb_range(vma, beg, end); - return error; -} -EXPORT_SYMBOL(io_remap_pfn_range); diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c deleted file mode 100644 index 9b357ddae39d..000000000000 --- a/arch/sparc/mm/generic_64.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * generic.c: Generic Sparc mm routines that are not dependent upon - * MMU type but are Sparc specific. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Remap IO memory, the same way as remap_pfn_range(), but use - * the obio memory space. - * - * They use a pgprot that sets PAGE_IO and does not check the - * mem_map table as this is independent of normal memory. - */ -static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, - unsigned long address, - unsigned long size, - unsigned long offset, pgprot_t prot, - int space) -{ - unsigned long end; - - /* clear hack bit that was used as a write_combine side-effect flag */ - offset &= ~0x1UL; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t entry; - unsigned long curend = address + PAGE_SIZE; - - entry = mk_pte_io(offset, prot, space, PAGE_SIZE); - if (!(address & 0xffff)) { - if (PAGE_SIZE < (4 * 1024 * 1024) && - !(address & 0x3fffff) && - !(offset & 0x3ffffe) && - end >= address + 0x400000) { - entry = mk_pte_io(offset, prot, space, - 4 * 1024 * 1024); - curend = address + 0x400000; - offset += 0x400000; - } else if (PAGE_SIZE < (512 * 1024) && - !(address & 0x7ffff) && - !(offset & 0x7fffe) && - end >= address + 0x80000) { - entry = mk_pte_io(offset, prot, space, - 512 * 1024 * 1024); - curend = address + 0x80000; - offset += 0x80000; - } else if (PAGE_SIZE < (64 * 1024) && - !(offset & 0xfffe) && - end >= address + 0x10000) { - entry = mk_pte_io(offset, prot, space, - 64 * 1024); - curend = address + 0x10000; - offset += 0x10000; - } else - offset += PAGE_SIZE; - } else - offset += PAGE_SIZE; - - if (pte_write(entry)) - entry = pte_mkdirty(entry); - do { - BUG_ON(!pte_none(*pte)); - set_pte_at(mm, address, pte, entry); - address += PAGE_SIZE; - pte_val(entry) += PAGE_SIZE; - pte++; - } while (address < curend); - } while (address < end); -} - -static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - offset -= address; - do { - pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); - if (!pte) - return -ENOMEM; - io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); - pte_unmap(pte); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return 0; -} - -static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size, - unsigned long offset, pgprot_t prot, int space) -{ - unsigned long end; - - address &= ~PUD_MASK; - end = address + size; - if (end > PUD_SIZE) - end = PUD_SIZE; - offset -= address; - do { - pmd_t *pmd = pmd_alloc(mm, pud, address); - if (!pud) - return -ENOMEM; - io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space); - address = (address + PUD_SIZE) & PUD_MASK; - pud++; - } while (address < end); - return 0; -} - -int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, - unsigned long pfn, unsigned long size, pgprot_t prot) -{ - int error = 0; - pgd_t * dir; - unsigned long beg = from; - unsigned long end = from + size; - struct mm_struct *mm = vma->vm_mm; - int space = GET_IOSPACE(pfn); - unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; - unsigned long phys_base; - - phys_base = offset | (((unsigned long) space) << 32UL); - - /* See comment in mm/memory.c remap_pfn_range */ - vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; - vma->vm_pgoff = phys_base >> PAGE_SHIFT; - - offset -= from; - dir = pgd_offset(mm, from); - flush_cache_range(vma, beg, end); - - while (from < end) { - pud_t *pud = pud_alloc(mm, dir, from); - error = -ENOMEM; - if (!pud) - break; - error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space); - if (error) - break; - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - - flush_tlb_range(vma, beg, end); - return error; -} -EXPORT_SYMBOL(io_remap_pfn_range); -- cgit From 738a849c8eef4787a526d95763f985b8c1cb68e4 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 17 Nov 2011 14:37:23 +0000 Subject: sky2: enforce minimum ring size The hardware has a restriction that the minimum ring size possible is 128. The number of elements used is controlled by tx_pending and the overall number of elements in the ring tx_ring_size, therefore it is okay to limit the number of elements in use to a small value (63) but still provide a bigger ring. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 539de09cffc9..d99687177704 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4088,6 +4088,16 @@ static int sky2_set_coalesce(struct net_device *dev, return 0; } +/* + * Hardware is limited to min of 128 and max of 2048 for ring size + * and rounded up to next power of two + * to avoid division in modulus calclation + */ +static unsigned long roundup_ring_size(unsigned long pending) +{ + return max(128ul, roundup_pow_of_two(pending+1)); +} + static void sky2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { @@ -4115,7 +4125,7 @@ static int sky2_set_ringparam(struct net_device *dev, sky2->rx_pending = ering->rx_pending; sky2->tx_pending = ering->tx_pending; - sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1); + sky2->tx_ring_size = roundup_ring_size(sky2->tx_pending); return sky2_reattach(dev); } @@ -4709,7 +4719,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; - sky2->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1); + sky2->tx_ring_size = roundup_ring_size(TX_DEF_PENDING); sky2->rx_pending = RX_DEF_PENDING; hw->dev[port] = dev; -- cgit From 282edcece39e08d02c22492d593e4b9b94a65dff Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 17 Nov 2011 14:37:35 +0000 Subject: sky2: fix hang in napi_disable If IRQ was never initialized, then calling napi_disable() would hang. Add more bookkeeping to track whether IRQ was ever initialized. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 17 ++++++++++------- drivers/net/ethernet/marvell/sky2.h | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index d99687177704..7803efa46eb2 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1723,6 +1723,8 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name) if (err) dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); else { + hw->flags |= SKY2_HW_IRQ_SETUP; + napi_enable(&hw->napi); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); sky2_read32(hw, B0_IMSK); @@ -2120,6 +2122,7 @@ static int sky2_close(struct net_device *dev) napi_disable(&hw->napi); free_irq(hw->pdev->irq, hw); + hw->flags &= ~SKY2_HW_IRQ_SETUP; } else { u32 imask; @@ -3423,12 +3426,13 @@ static void sky2_all_down(struct sky2_hw *hw) { int i; - sky2_read32(hw, B0_IMSK); - sky2_write32(hw, B0_IMSK, 0); + if (hw->flags & SKY2_HW_IRQ_SETUP) { + sky2_read32(hw, B0_IMSK); + sky2_write32(hw, B0_IMSK, 0); - if (hw->ports > 1 || netif_running(hw->dev[0])) synchronize_irq(hw->pdev->irq); - napi_disable(&hw->napi); + napi_disable(&hw->napi); + } for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; @@ -3445,7 +3449,7 @@ static void sky2_all_down(struct sky2_hw *hw) static void sky2_all_up(struct sky2_hw *hw) { - u32 imask = 0; + u32 imask = Y2_IS_BASE; int i; for (i = 0; i < hw->ports; i++) { @@ -3461,8 +3465,7 @@ static void sky2_all_up(struct sky2_hw *hw) netif_wake_queue(dev); } - if (imask || hw->ports > 1) { - imask |= Y2_IS_BASE; + if (hw->flags & SKY2_HW_IRQ_SETUP) { sky2_write32(hw, B0_IMSK, imask); sky2_read32(hw, B0_IMSK); sky2_read32(hw, B0_Y2_SP_LISR); diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h index 0af31b8b5f10..ff6f58bf822a 100644 --- a/drivers/net/ethernet/marvell/sky2.h +++ b/drivers/net/ethernet/marvell/sky2.h @@ -2287,6 +2287,7 @@ struct sky2_hw { #define SKY2_HW_RSS_BROKEN 0x00000100 #define SKY2_HW_VLAN_BROKEN 0x00000200 #define SKY2_HW_RSS_CHKSUM 0x00000400 /* RSS requires chksum */ +#define SKY2_HW_IRQ_SETUP 0x00000800 u8 chip_id; u8 chip_rev; -- cgit From 0b64120cceb86e93cb1bda0dc055f13016646907 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 17 Nov 2011 22:44:58 -0800 Subject: sparc64: Patch sun4v code sequences properly on module load. Some of the sun4v code patching occurs in inline functions visible to, and usable by, modules. Therefore we have to patch them up during module load. Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.h | 7 +++++++ arch/sparc/kernel/module.c | 27 +++++++++++++++++++++++++ arch/sparc/kernel/setup_64.c | 48 ++++++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index e27f8ea8656e..0c218e4c0881 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, extern void fpload(unsigned long *fpregs, unsigned long *fsr); #else /* CONFIG_SPARC32 */ + +#include + struct popc_3insn_patch_entry { unsigned int addr; unsigned int insns[3]; @@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __popc_6insn_patch, __popc_6insn_patch_end; extern void __init per_cpu_patch(void); +extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, + struct sun4v_1insn_patch_entry *); +extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, + struct sun4v_2insn_patch_entry *); extern void __init sun4v_patch(void); extern void __init boot_cpu_id_too_large(int cpu); extern unsigned int dcache_parity_tl1_occurred; diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index da0c6c70ccb2..e5519870c3d9 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c @@ -17,6 +17,8 @@ #include #include +#include "entry.h" + #ifdef CONFIG_SPARC64 #include @@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs, } #ifdef CONFIG_SPARC64 +static void do_patch_sections(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs) +{ + const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL; + char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { + if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name)) + sun4v_1insn = s; + if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name)) + sun4v_2insn = s; + } + + if (sun4v_1insn && tlb_type == hypervisor) { + void *p = (void *) sun4v_1insn->sh_addr; + sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size); + } + if (sun4v_2insn && tlb_type == hypervisor) { + void *p = (void *) sun4v_2insn->sh_addr; + sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size); + } +} + int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) @@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr, /* make jump label nops */ jump_label_apply_nops(me); + do_patch_sections(hdr, sechdrs); + /* Cheetah's I-cache is fully coherent. */ if (tlb_type == spitfire) { unsigned long va; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index c965595aa7e9..a854a1c240ff 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -234,40 +234,50 @@ void __init per_cpu_patch(void) } } -void __init sun4v_patch(void) +void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start, + struct sun4v_1insn_patch_entry *end) { - extern void sun4v_hvapi_init(void); - struct sun4v_1insn_patch_entry *p1; - struct sun4v_2insn_patch_entry *p2; - - if (tlb_type != hypervisor) - return; + while (start < end) { + unsigned long addr = start->addr; - p1 = &__sun4v_1insn_patch; - while (p1 < &__sun4v_1insn_patch_end) { - unsigned long addr = p1->addr; - - *(unsigned int *) (addr + 0) = p1->insn; + *(unsigned int *) (addr + 0) = start->insn; wmb(); __asm__ __volatile__("flush %0" : : "r" (addr + 0)); - p1++; + start++; } +} - p2 = &__sun4v_2insn_patch; - while (p2 < &__sun4v_2insn_patch_end) { - unsigned long addr = p2->addr; +void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start, + struct sun4v_2insn_patch_entry *end) +{ + while (start < end) { + unsigned long addr = start->addr; - *(unsigned int *) (addr + 0) = p2->insns[0]; + *(unsigned int *) (addr + 0) = start->insns[0]; wmb(); __asm__ __volatile__("flush %0" : : "r" (addr + 0)); - *(unsigned int *) (addr + 4) = p2->insns[1]; + *(unsigned int *) (addr + 4) = start->insns[1]; wmb(); __asm__ __volatile__("flush %0" : : "r" (addr + 4)); - p2++; + start++; } +} + +void __init sun4v_patch(void) +{ + extern void sun4v_hvapi_init(void); + + if (tlb_type != hypervisor) + return; + + sun4v_patch_1insn_range(&__sun4v_1insn_patch, + &__sun4v_1insn_patch_end); + + sun4v_patch_2insn_range(&__sun4v_2insn_patch, + &__sun4v_2insn_patch_end); sun4v_hvapi_init(); } -- cgit From 19d7ca2998e095086869318dd2ad966952f5ac82 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 18 Nov 2011 16:32:34 +0900 Subject: sh: fix build warning in board-sh7757lcr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixed the following build warnings: CC arch/sh/boards/board-sh7757lcr.o arch/sh/boards/board-sh7757lcr.c:77: warning: initialization from incompatible pointer type arch/sh/boards/board-sh7757lcr.c:106: warning: initialization from incompatible pointer type arch/sh/boards/board-sh7757lcr.c:151: warning: initialization from incompatible pointer type arch/sh/boards/board-sh7757lcr.c:181: warning: initialization from incompatible pointer type arch/sh/boards/board-sh7757lcr.c:213: warning: missing braces around initializer arch/sh/boards/board-sh7757lcr.c:213: warning: (near initialization for ‘sh7757lcr_mmcif_dma.chan_priv_tx’) Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/boards/board-sh7757lcr.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index ec8c84c14b17..895e337c79b6 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -50,9 +50,9 @@ static struct platform_device heartbeat_device = { #define GBECONT 0xffc10100 #define GBECONT_RMII1 BIT(17) #define GBECONT_RMII0 BIT(16) -static void sh7757_eth_set_mdio_gate(unsigned long addr) +static void sh7757_eth_set_mdio_gate(void *addr) { - if ((addr & 0x00000fff) < 0x0800) + if (((unsigned long)addr & 0x00000fff) < 0x0800) writel(readl(GBECONT) | GBECONT_RMII0, GBECONT); else writel(readl(GBECONT) | GBECONT_RMII1, GBECONT); @@ -116,9 +116,9 @@ static struct platform_device sh7757_eth1_device = { }, }; -static void sh7757_eth_giga_set_mdio_gate(unsigned long addr) +static void sh7757_eth_giga_set_mdio_gate(void *addr) { - if ((addr & 0x00000fff) < 0x0800) { + if (((unsigned long)addr & 0x00000fff) < 0x0800) { gpio_set_value(GPIO_PTT4, 1); writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT); } else { @@ -210,8 +210,12 @@ static struct resource sh_mmcif_resources[] = { }; static struct sh_mmcif_dma sh7757lcr_mmcif_dma = { - .chan_priv_tx = SHDMA_SLAVE_MMCIF_TX, - .chan_priv_rx = SHDMA_SLAVE_MMCIF_RX, + .chan_priv_tx = { + .slave_id = SHDMA_SLAVE_MMCIF_TX, + }, + .chan_priv_rx = { + .slave_id = SHDMA_SLAVE_MMCIF_RX, + } }; static struct sh_mmcif_plat_data sh_mmcif_plat = { -- cgit From ef319c6e095676e0247fd24ef8ff7f085c19744f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 20 Oct 2011 13:36:59 +0300 Subject: OMAPDSS: HDMI: fix returned HDMI pixel clock hdmi_get_pixel_clock() returns the pixel clock in Hz, but the pck is stored as kHz. This means the return value has to be multiplied by 1000, not by 10000 as the code did. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 3262f0f1fa35..c56378c555b0 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -269,7 +269,7 @@ static void update_hdmi_timings(struct hdmi_config *cfg, unsigned long hdmi_get_pixel_clock(void) { /* HDMI Pixel Clock in Mhz */ - return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000; + return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000; } static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, -- cgit From 1c6bc899723ca8c0d58044c3661f13ac2369e55f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Nov 2011 09:54:50 +0200 Subject: OMAPFB: fix compilation warnings due to missing include Fix warnings similar to this by including module.h: drivers/video/omap/dispc.c:276:1: warning: data definition has no type or storage class drivers/video/omap/dispc.c:276:1: warning: type defaults to 'int' in declaration of 'EXPORT_SYMBOL' Signed-off-by: Tomi Valkeinen --- drivers/video/omap/dispc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 0ccd7adf47bb..6f61e781f15a 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -19,6 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include #include -- cgit From f95cb5ebd834117ff4829a460656095a0ae63921 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 1 Nov 2011 10:50:45 +0200 Subject: OMAPDSS: DISPC: skip scaling calculations when not scaling Current code calculates scaling factors for video overlays even when the overlays are not scaled. Change the code to skip calculations when not scaling. This optimizes the code a bit, but also fixes a problem when configuring an overlay for a disabled display: if the display is disabled we don't necessarily know the pixel clock used when the display is enabled, and in some cases (like HDMI) the pixel clock is set to zero until a proper video mode is set later. A wrong pixel clock will mess up the scaling calculations, causing an error like: omapdss DISPC error: failed to set up scaling, required fclk rate = 0 Hz, current fclk rate = 170666666 Hz A proper fix would be to check later whether the clocks are enough for the scaling, at the point when the overlay or display is actually enabled, but this patch removes the problem for now. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 3532782551cb..5c81533eacaa 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1720,12 +1720,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); unsigned long fclk = 0; - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { - if (width != out_width || height != out_height) - return -EINVAL; - else - return 0; - } + if (width == out_width && height == out_height) + return 0; + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) + return -EINVAL; if (out_width < width / maxdownscale || out_width > width * 8) -- cgit From f9dfb65b055c56678afa03e13e942761459ea53d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 18 Nov 2011 17:05:30 +0530 Subject: ktest: Check parent options for iterated tests Let's say we have "OUTPUT_DIR = build/${TEST_NAME}", and we're iterating a test. In the second iteration of a test, the TEST_NAME of the test we're repeating is not used. Instead, ${TEST_NAME} appears literally: touch /home/rabin/kernel/test/build/${TEST_NAME}/.config ... SUCCESS Fix this by making __eval_option() check the parent test options for a repeated test. Link: http://lkml.kernel.org/r/1321616131-21352-2-git-send-email-rabin@rab.in Signed-off-by: Rabin Vincent Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 30e2befd6f2a..8b4c2535b266 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -747,6 +747,18 @@ sub __eval_option { # Add space to evaluate the character before $ $option = " $option"; my $retval = ""; + my $repeated = 0; + my $parent = 0; + + foreach my $test (keys %repeat_tests) { + if ($i >= $test && + $i < $test + $repeat_tests{$test}) { + + $repeated = 1; + $parent = $test; + last; + } + } while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { my $start = $1; @@ -760,10 +772,14 @@ sub __eval_option { # otherwise see if the default OPT (without [$i]) exists. my $o = "$var\[$i\]"; + my $parento = "$var\[$parent\]"; if (defined($opt{$o})) { $o = $opt{$o}; $retval = "$retval$o"; + } elsif ($repeated && defined($opt{$parento})) { + $o = $opt{$parento}; + $retval = "$retval$o"; } elsif (defined($opt{$var})) { $o = $opt{$var}; $retval = "$retval$o"; -- cgit From 91a13c281d7d4648c0b32dede11a0144c4e7984c Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Thu, 17 Nov 2011 11:08:32 +0100 Subject: drivers/base/node.c: fix compilation error with older versions of gcc Patch to fix the error message "directives may not be used inside a macro argument" which appears when the kernel is compiled for the cris architecture. Signed-off-by: Claudio Scordino Acked-by: David Rientjes Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/base/node.c b/drivers/base/node.c index 793f796c4da3..5693ecee9a40 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -127,12 +127,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev, nid, K(node_page_state(nid, NR_WRITEBACK)), nid, K(node_page_state(nid, NR_FILE_PAGES)), nid, K(node_page_state(nid, NR_FILE_MAPPED)), - nid, K(node_page_state(nid, NR_ANON_PAGES) #ifdef CONFIG_TRANSPARENT_HUGEPAGE + nid, K(node_page_state(nid, NR_ANON_PAGES) + node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * - HPAGE_PMD_NR + HPAGE_PMD_NR), +#else + nid, K(node_page_state(nid, NR_ANON_PAGES)), #endif - ), nid, K(node_page_state(nid, NR_SHMEM)), nid, node_page_state(nid, NR_KERNEL_STACK) * THREAD_SIZE / 1024, @@ -143,13 +144,14 @@ static ssize_t node_read_meminfo(struct sys_device * dev, nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) + node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)), - nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)) #ifdef CONFIG_TRANSPARENT_HUGEPAGE + nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)) , nid, K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * - HPAGE_PMD_NR) + HPAGE_PMD_NR)); +#else + nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))); #endif - ); n += hugetlb_report_node_meminfo(nid, buf + n); return n; } -- cgit From 6ac2afb3f4601d74778a6ef76c50813a5b85b133 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 18 Nov 2011 11:05:10 +0100 Subject: misc: ad525x_dpot: Fix AD8400 spi transfer size. AD8400 type devices require 16-bit command transfers. Signed-off-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ad525x_dpot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h index a662f5987b68..82b2cb77ae19 100644 --- a/drivers/misc/ad525x_dpot.h +++ b/drivers/misc/ad525x_dpot.h @@ -100,7 +100,7 @@ enum dpot_devid { AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, BRDAC0, 7, 28), - AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, + AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT, BRDAC0, 8, 29), AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT, BRDAC0 | BRDAC1, 8, 30), -- cgit From e253dec31b3ffc2bf19aa8c29865ab7254e90c29 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 18 Nov 2011 12:12:41 +0530 Subject: usb: Netlogic: Fix HC_LENGTH call in ehci-xls.c Fix compile error, HC_LENGTH now takes two parameters and ehci needs to be passed as the first parameter. Signed-off-by: Jayachandran C Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-xls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c index fe74bd676018..b4fb511d24bc 100644 --- a/drivers/usb/host/ehci-xls.c +++ b/drivers/usb/host/ehci-xls.c @@ -19,7 +19,7 @@ static int ehci_xls_setup(struct usb_hcd *hcd) ehci->caps = hcd->regs; ehci->regs = hcd->regs + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); -- cgit From 46b5a277ed90317a4d17e936c16037e76011b219 Mon Sep 17 00:00:00 2001 From: "zheng.zhijian@zte.com.cn" Date: Thu, 17 Nov 2011 19:23:25 +0800 Subject: USB: option: release new PID for ZTE 3G modem This patch adds new PIDs for ZTE 3G modem, after we confirm it and tested. Thanks for Dan's work at kernel option devier. Signed-off-by: Alvin.Zheng Signed-off-by: wsalvin Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b8da93b3615c..d59e37571d99 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -316,6 +316,9 @@ static void option_instat_callback(struct urb *urb); #define ZTE_PRODUCT_AC8710 0xfff1 #define ZTE_PRODUCT_AC2726 0xfff5 #define ZTE_PRODUCT_AC8710T 0xffff +#define ZTE_PRODUCT_MC2718 0xffe8 +#define ZTE_PRODUCT_AD3812 0xffeb +#define ZTE_PRODUCT_MC2716 0xffed #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -504,6 +507,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = { .reserved = BIT(4), }; +static const struct option_blacklist_info zte_ad3812_z_blacklist = { + .sendsetup = BIT(0) | BIT(1) | BIT(2), +}; + +static const struct option_blacklist_info zte_mc2718_z_blacklist = { + .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4), +}; + +static const struct option_blacklist_info zte_mc2716_z_blacklist = { + .sendsetup = BIT(1) | BIT(2) | BIT(3), +}; + static const struct option_blacklist_info huawei_cdc12_blacklist = { .reserved = BIT(1) | BIT(2), }; @@ -1047,6 +1062,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ -- cgit From c61875977458637226ab093a35d200f2d5789787 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 17 Nov 2011 16:41:45 -0500 Subject: OHCI: final fix for NVIDIA problems (I hope) Problems with NVIDIA's OHCI host controllers persist. After looking carefully through the spec, I finally realized that when a controller is reset it then automatically goes into a SUSPEND state in which it is completely quiescent (no DMA and no IRQs) and from which it will not awaken until the system puts it into the OPERATIONAL state. Therefore there's no need to worry about controllers being in the RESET state for extended periods, or remaining in the OPERATIONAL state during system shutdown. The proper action for device initialization is to put the controller into the RESET state (if it's not there already) and then to issue a software reset. Similarly, the proper action for device shutdown is simply to do a software reset. This patch (as1499) implements such an approach. It simplifies initialization and shutdown, and allows the NVIDIA shutdown-quirk code to be removed. Signed-off-by: Alan Stern Tested-by: Andre "Osku" Schmidt Tested-by: Arno Augustin Cc: stable [after tested in 3.2 for a while] Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 15 ++++++------- drivers/usb/host/ohci-pci.c | 26 ---------------------- drivers/usb/host/ohci.h | 1 - drivers/usb/host/pci-quirks.c | 50 +++++++++++++++++++------------------------ 4 files changed, 28 insertions(+), 64 deletions(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 34efd479e068..b2639191549e 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd) struct ohci_hcd *ohci; ohci = hcd_to_ohci (hcd); - ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable); - /* If the SHUTDOWN quirk is set, don't put the controller in RESET */ - ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ? - OHCI_CTRL_RWC | OHCI_CTRL_HCFS : - OHCI_CTRL_RWC); - ohci_writel(ohci, ohci->hc_control, &ohci->regs->control); + /* Software reset, after which the controller goes into SUSPEND */ + ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus); + ohci_readl(ohci, &ohci->regs->cmdstatus); /* flush the writes */ + udelay(10); - /* flush the writes */ - (void) ohci_readl (ohci, &ohci->regs->control); + ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval); } static int check_ed(struct ohci_hcd *ohci, struct ed *ed) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index ad8166c681e2..bc01b064585a 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } -/* nVidia controllers continue to drive Reset signalling on the bus - * even after system shutdown, wasting power. This flag tells the - * shutdown routine to leave the controller OPERATIONAL instead of RESET. - */ -static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) -{ - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - /* Evidently nVidia fixed their later hardware; this is a guess at - * the changeover point. - */ -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d - - if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) { - ohci->flags |= OHCI_QUIRK_SHUTDOWN; - ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); - } - - return 0; -} - static void sb800_prefetch(struct ohci_hcd *ohci, int on) { struct pci_dev *pdev; @@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, - { - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), - .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, - }, /* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them. diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 35e5fd640ce7..0795b934d00c 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -403,7 +403,6 @@ struct ohci_hcd { #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ -#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */ // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index c7fd6ce11904..caf87428ca43 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -37,6 +37,7 @@ #define OHCI_INTRENABLE 0x10 #define OHCI_INTRDISABLE 0x14 #define OHCI_FMINTERVAL 0x34 +#define OHCI_HCFS (3 << 6) /* hc functional state */ #define OHCI_HCR (1 << 0) /* host controller reset */ #define OHCI_OCR (1 << 3) /* ownership change request */ #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ @@ -466,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) { void __iomem *base; u32 control; + u32 fminterval; + int cnt; if (!mmio_resource_enabled(pdev, 0)) return; @@ -498,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) } #endif - /* reset controller, preserving RWC (and possibly IR) */ - writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); - readl(base + OHCI_CONTROL); + /* disable interrupts */ + writel((u32) ~0, base + OHCI_INTRDISABLE); - /* Some NVIDIA controllers stop working if kept in RESET for too long */ - if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { - u32 fminterval; - int cnt; + /* Reset the USB bus, if the controller isn't already in RESET */ + if (control & OHCI_HCFS) { + /* Go into RESET, preserving RWC (and possibly IR) */ + writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); + readl(base + OHCI_CONTROL); - /* drive reset for at least 50 ms (7.1.7.5) */ + /* drive bus reset for at least 50 ms (7.1.7.5) */ msleep(50); + } - /* software reset of the controller, preserving HcFmInterval */ - fminterval = readl(base + OHCI_FMINTERVAL); - writel(OHCI_HCR, base + OHCI_CMDSTATUS); + /* software reset of the controller, preserving HcFmInterval */ + fminterval = readl(base + OHCI_FMINTERVAL); + writel(OHCI_HCR, base + OHCI_CMDSTATUS); - /* reset requires max 10 us delay */ - for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ - if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) - break; - udelay(1); - } - writel(fminterval, base + OHCI_FMINTERVAL); - - /* Now we're in the SUSPEND state with all devices reset - * and wakeups and interrupts disabled - */ + /* reset requires max 10 us delay */ + for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ + if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) + break; + udelay(1); } + writel(fminterval, base + OHCI_FMINTERVAL); - /* - * disable interrupts - */ - writel(~(u32)0, base + OHCI_INTRDISABLE); - writel(~(u32)0, base + OHCI_INTRSTATUS); - + /* Now the controller is safely in SUSPEND and nothing can wake it up */ iounmap(base); } -- cgit From 4aa3648c719265bac9c2742c9ebb043e6dbdd790 Mon Sep 17 00:00:00 2001 From: Ferenc Wagner Date: Thu, 17 Nov 2011 16:44:58 +0100 Subject: USB: option: add PID of Huawei E173s 3G modem Signed-off-by: Ferenc Wagner Cc: stable 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 d59e37571d99..d865878c9f97 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -156,6 +156,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_K4511 0x14CC #define HUAWEI_PRODUCT_ETS1220 0x1803 #define HUAWEI_PRODUCT_E353 0x1506 +#define HUAWEI_PRODUCT_E173S 0x1C05 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -641,6 +642,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), -- cgit From b1ffb4c851f185e9051ba837c16d9b84ef688d26 Mon Sep 17 00:00:00 2001 From: Andrew Worsley Date: Fri, 18 Nov 2011 23:13:33 +1100 Subject: USB: Fix Corruption issue in USB ftdi driver ftdi_sio.c Fix for ftdi_set_termios() glitching output ftdi_set_termios() is constantly setting the baud rate, data bits and parity unnecessarily on every call, . When called while characters are being transmitted can cause the FTDI chip to corrupt the serial port bit stream output by stalling the output half a bit during the output of a character. Simple fix by skipping this setting if the baud rate/data bits/parity are unchanged. Signed-off-by: Andrew Worsley Cc: stable ---- I had a brief run with strace on the getty and it was doing ioctl()s on each call but it didn't look relavant to the problem. I think the issue is that XON/XOFF flow control was being implmented via hardware - for the ixoff to allow the user to use XON/XOFF to control output. Unfortunately it would send 3 Control URBs updating all of the settings after each piece of input I am trying to work around the issue of gmail messing with the tab/spacing by submitting via SMTP via gmail which I believe should fix the issue. The patch is against v3.2-rc2 and compiles - but no additional testing in this kernel has been done. Thanks Andrew Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8fe034d2d3e7..bd4298bb6750 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2104,13 +2104,19 @@ static void ftdi_set_termios(struct tty_struct *tty, cflag = termios->c_cflag; - /* FIXME -For this cut I don't care if the line is really changing or - not - so just do the change regardless - should be able to - compare old_termios and tty->termios */ + if (old_termios->c_cflag == termios->c_cflag + && old_termios->c_ispeed == termios->c_ispeed + && old_termios->c_ospeed == termios->c_ospeed) + goto no_c_cflag_changes; + /* NOTE These routines can get interrupted by ftdi_sio_read_bulk_callback - need to examine what this means - don't see any problems yet */ + if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) == + (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB))) + goto no_data_parity_stop_changes; + /* Set number of data bits, parity, stop bits */ urb_value = 0; @@ -2151,6 +2157,7 @@ static void ftdi_set_termios(struct tty_struct *tty, } /* Now do the baudrate */ +no_data_parity_stop_changes: if ((cflag & CBAUD) == B0) { /* Disable flow control */ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2178,6 +2185,7 @@ static void ftdi_set_termios(struct tty_struct *tty, /* Set flow control */ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ +no_c_cflag_changes: if (cflag & CRTSCTS) { dbg("%s Setting to CRTSCTS flow control", __func__); if (usb_control_msg(dev, -- cgit From fb120c0a2775b0d2d095a99ea8432bfb5d444ab2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 17 Nov 2011 04:40:20 +0000 Subject: ping: dont increment ICMP_MIB_INERRORS ping module incorrectly increments ICMP_MIB_INERRORS if feeded with a frame not belonging to its own sockets. RFC 2011 states that ICMP_MIB_INERRORS should count "the number of ICMP messages which the entiry received but determined as having ICMP-specific errors (bad ICMP checksums, bad length, etc.)." Signed-off-by: Eric Dumazet CC: Vasiliy Kulikov Acked-by: Flavio Leitner Acked-by: Vasiliy Kulikov Signed-off-by: David S. Miller --- net/ipv4/ping.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index a06f73fdb3c0..43d4c3b22369 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -339,7 +339,6 @@ void ping_err(struct sk_buff *skb, u32 info) sk = ping_v4_lookup(net, iph->daddr, iph->saddr, ntohs(icmph->un.echo.id), skb->dev->ifindex); if (sk == NULL) { - ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); pr_debug("no socket, dropping\n"); return; /* No socket for error */ } @@ -679,7 +678,6 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", inet_sk(sk), inet_sk(sk)->inet_num, skb); if (sock_queue_rcv_skb(sk, skb) < 0) { - ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS); kfree_skb(skb); pr_debug("ping_queue_rcv_skb -> failed\n"); return -1; -- cgit From c8891329131f791e0ddc422eaf6fc86e9a8cf8f5 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 18 Nov 2011 17:21:05 +0000 Subject: MAINTAINERS: update XFS maintainer entry I will no longer be maintaining XFS for SGI. Ben Myers (bpm@sgi.com) has agreed to be the primary maintainer for XFS in my place. I will continue to be able to push commits to the SGI XFS tree if required. As such I will continue to be a designated XFS maintainer, but plan to serve in more of a backup role. Signed-off-by: Alex Elder Signed-off-by: Ben Myers --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4808256446f2..227cd7ccf816 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7425,7 +7425,8 @@ F: drivers/xen/*swiotlb* XFS FILESYSTEM P: Silicon Graphics Inc -M: Alex Elder +M: Ben Myers +M: Alex Elder M: xfs-masters@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs -- cgit From 9cc20b268a5a14f5e57b8ad405a83513ab0d78dc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 18 Nov 2011 15:24:32 -0500 Subject: ipv4: fix redirect handling commit f39925dbde77 (ipv4: Cache learned redirect information in inetpeer.) introduced a regression in ICMP redirect handling. It assumed ipv4_dst_check() would be called because all possible routes were attached to the inetpeer we modify in ip_rt_redirect(), but thats not true. commit 7cc9150ebe (route: fix ICMP redirect validation) tried to fix this but solution was not complete. (It fixed only one route) So we must lookup existing routes (including different TOS values) and call check_peer_redir() on them. Reported-by: Ivan Zahariev Signed-off-by: Eric Dumazet CC: Flavio Leitner Signed-off-by: David S. Miller --- net/ipv4/route.c | 110 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 511f4a75149c..0c74da8a0473 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1304,16 +1304,42 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } +static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +{ + struct rtable *rt = (struct rtable *) dst; + __be32 orig_gw = rt->rt_gateway; + struct neighbour *n, *old_n; + + dst_confirm(&rt->dst); + + rt->rt_gateway = peer->redirect_learned.a4; + + n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); + if (IS_ERR(n)) + return PTR_ERR(n); + old_n = xchg(&rt->dst._neighbour, n); + if (old_n) + neigh_release(old_n); + if (!n || !(n->nud_state & NUD_VALID)) { + if (n) + neigh_event_send(n, NULL); + rt->rt_gateway = orig_gw; + return -EAGAIN; + } else { + rt->rt_flags |= RTCF_REDIRECTED; + call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); + } + return 0; +} + /* called in rcu_read_lock() section */ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, __be32 saddr, struct net_device *dev) { int s, i; struct in_device *in_dev = __in_dev_get_rcu(dev); - struct rtable *rt; __be32 skeys[2] = { saddr, 0 }; int ikeys[2] = { dev->ifindex, 0 }; - struct flowi4 fl4; struct inet_peer *peer; struct net *net; @@ -1336,33 +1362,42 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, goto reject_redirect; } - memset(&fl4, 0, sizeof(fl4)); - fl4.daddr = daddr; for (s = 0; s < 2; s++) { for (i = 0; i < 2; i++) { - fl4.flowi4_oif = ikeys[i]; - fl4.saddr = skeys[s]; - rt = __ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) - continue; - - if (rt->dst.error || rt->dst.dev != dev || - rt->rt_gateway != old_gw) { - ip_rt_put(rt); - continue; - } + unsigned int hash; + struct rtable __rcu **rthp; + struct rtable *rt; + + hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net)); + + rthp = &rt_hash_table[hash].chain; + + while ((rt = rcu_dereference(*rthp)) != NULL) { + rthp = &rt->dst.rt_next; + + if (rt->rt_key_dst != daddr || + rt->rt_key_src != skeys[s] || + rt->rt_oif != ikeys[i] || + rt_is_input_route(rt) || + rt_is_expired(rt) || + !net_eq(dev_net(rt->dst.dev), net) || + rt->dst.error || + rt->dst.dev != dev || + rt->rt_gateway != old_gw) + continue; - if (!rt->peer) - rt_bind_peer(rt, rt->rt_dst, 1); + if (!rt->peer) + rt_bind_peer(rt, rt->rt_dst, 1); - peer = rt->peer; - if (peer) { - peer->redirect_learned.a4 = new_gw; - atomic_inc(&__rt_peer_genid); + peer = rt->peer; + if (peer) { + if (peer->redirect_learned.a4 != new_gw) { + peer->redirect_learned.a4 = new_gw; + atomic_inc(&__rt_peer_genid); + } + check_peer_redir(&rt->dst, peer); + } } - - ip_rt_put(rt); - return; } } return; @@ -1649,33 +1684,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } } -static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) -{ - struct rtable *rt = (struct rtable *) dst; - __be32 orig_gw = rt->rt_gateway; - struct neighbour *n, *old_n; - - dst_confirm(&rt->dst); - - rt->rt_gateway = peer->redirect_learned.a4; - - n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); - if (IS_ERR(n)) - return PTR_ERR(n); - old_n = xchg(&rt->dst._neighbour, n); - if (old_n) - neigh_release(old_n); - if (!n || !(n->nud_state & NUD_VALID)) { - if (n) - neigh_event_send(n, NULL); - rt->rt_gateway = orig_gw; - return -EAGAIN; - } else { - rt->rt_flags |= RTCF_REDIRECTED; - call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); - } - return 0; -} static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) { -- cgit From aa9a7b11821e883a7b93ecce190881e0ea48648b Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Fri, 18 Nov 2011 23:02:42 +0100 Subject: PM / Hibernate: Fix the early termination of test modes Commit 2aede851ddf08666f68ffc17be446420e9d2a056 (PM / Hibernate: Freeze kernel threads after preallocating memory) postponed the freezing of kernel threads to after preallocating memory for hibernation. But while doing that, the hibernation test TEST_FREEZER and the test mode HIBERNATION_TESTPROC were not moved accordingly. As a result, when using these test modes, it only goes upto the freezing of userspace and exits, when in fact it should go till the complete end of task freezing stage, namely the freezing of kernel threads as well. So, move these points of exit to appropriate places so that freezing of kernel threads is also tested while using these test harnesses. Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- kernel/power/hibernate.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b4511b6d3ef9..196c01268ebd 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -55,6 +55,8 @@ enum { static int hibernation_mode = HIBERNATION_SHUTDOWN; +static bool freezer_test_done; + static const struct platform_hibernation_ops *hibernation_ops; /** @@ -347,6 +349,17 @@ int hibernation_snapshot(int platform_mode) if (error) goto Close; + if (hibernation_test(TEST_FREEZER) || + hibernation_testmode(HIBERNATION_TESTPROC)) { + + /* + * Indicate to the caller that we are returning due to a + * successful freezer test. + */ + freezer_test_done = true; + goto Close; + } + error = dpm_prepare(PMSG_FREEZE); if (error) goto Complete_devices; @@ -641,15 +654,13 @@ int hibernate(void) if (error) goto Finish; - if (hibernation_test(TEST_FREEZER)) - goto Thaw; - - if (hibernation_testmode(HIBERNATION_TESTPROC)) - goto Thaw; - error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); if (error) goto Thaw; + if (freezer_test_done) { + freezer_test_done = false; + goto Thaw; + } if (in_suspend) { unsigned int flags = 0; -- cgit From 860ca0e6f72d21ded33ce14be9a53eb103f88441 Mon Sep 17 00:00:00 2001 From: Paul Menage Date: Fri, 18 Nov 2011 14:22:09 -0800 Subject: cgroup: Replace Paul Menage with Tejun Heo as cgroups maintainer As is probably painfully obvious, I don't have time to be a cgroups maintainer. Rather than have me continue to hope that I'll magically find more spare time, instead Tejun has kindly agreed to take over the role, along with Li Zefan. -tj: added cgroup tree URL to MAINTAINERS file Signed-off-by: Paul Menage Acked-by: Li Zefan Signed-off-by: Tejun Heo LKML-Reference: <1321320612-57855-1-git-send-email-paul@paulmenage.org> --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7f6bc290d455..78751bbfa91a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1927,10 +1927,11 @@ S: Maintained F: drivers/connector/ CONTROL GROUPS (CGROUPS) -M: Paul Menage +M: Tejun Heo M: Li Zefan L: containers@lists.linux-foundation.org L: cgroups@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git S: Maintained F: include/linux/cgroup* F: kernel/cgroup* -- cgit From 2e9ff8d917af622785b5b9f46d849b7eee43b29c Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Fri, 4 Nov 2011 17:58:02 +0000 Subject: linux-next: et131x: Fix build error when CONFIG_PM_SLEEP not enabled Randy Dunlap reports that the ex131x driver doesn't build when CONFIG_PM_SLEEP is not enabled. This bug was introduced when moving code around to remove some forward declarations earlier, the #endif part of #ifdef CONFIG_PM_SLEEP was not moved at the same time. Now fixed by moving it to its proper place. Reported-by: Randy Dunlap Signed-off-by: Mark Einon Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index f5f44a02456f..0c1c6ca8c379 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4469,6 +4469,12 @@ static int et131x_resume(struct device *dev) return 0; } +static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume); +#define ET131X_PM_OPS (&et131x_pm_ops) +#else +#define ET131X_PM_OPS NULL +#endif + /* ISR functions */ /** @@ -5470,12 +5476,6 @@ err_out: return result; } -static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume); -#define ET131X_PM_OPS (&et131x_pm_ops) -#else -#define ET131X_PM_OPS NULL -#endif - static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = { { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_GIG), 0UL}, { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_FAST), 0UL}, -- cgit From 07de7a5ecbd241507bf1d521e56692842a3e70d4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 1 Nov 2011 14:43:09 -0700 Subject: staging: slicoss depends on NET The slicoss driver uses network interfaces so it should depend on NET. Fixes the following build errors: ERROR: "eth_change_mtu" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "eth_validate_addr" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "register_netdev" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "alloc_etherdev_mqs" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "__netif_schedule" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "netif_rx" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "eth_type_trans" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "skb_put" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "skb_pull" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "__alloc_skb" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "free_netdev" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "unregister_netdev" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "consume_skb" [drivers/staging/slicoss/slicoss.ko] undefined! ERROR: "dev_kfree_skb_irq" [drivers/staging/slicoss/slicoss.ko] undefined! Signed-off-by: Randy Dunlap Cc: Lior Dotan Cc: Christopher Harrer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/slicoss/Kconfig b/drivers/staging/slicoss/Kconfig index 5cde96b2e6e1..5c2a15b42dfe 100644 --- a/drivers/staging/slicoss/Kconfig +++ b/drivers/staging/slicoss/Kconfig @@ -1,6 +1,6 @@ config SLICOSS tristate "Alacritech Gigabit IS-NIC support" - depends on PCI && X86 + depends on PCI && X86 && NET default n help This driver supports Alacritech's IS-NIC gigabit ethernet cards. -- cgit From 0337510f7cef9d569811b058a33306943c685ef6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 3 Nov 2011 14:24:00 -0700 Subject: staging: et131x depends on NET ET131X uses netdev interfaces so it should depend on NET. Fixes these build errors: ERROR: "ethtool_op_get_link" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "eth_validate_addr" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "register_netdev" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_connect" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_find_first" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_register" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_alloc" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "alloc_etherdev_mqs" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "netif_device_detach" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_stop" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "netif_device_attach" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_start" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "free_netdev" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_free" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_unregister" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "unregister_netdev" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "__netif_schedule" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_print_status" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "dev_kfree_skb_any" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "dev_alloc_skb" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "netif_rx" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "eth_type_trans" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "skb_put" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_ethtool_gset" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_ethtool_sset" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_mii_ioctl" [drivers/staging/et131x/et131x.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/et131x/Kconfig b/drivers/staging/et131x/Kconfig index 9e1864c6dfd0..98a165328e4e 100644 --- a/drivers/staging/et131x/Kconfig +++ b/drivers/staging/et131x/Kconfig @@ -1,6 +1,6 @@ config ET131X tristate "Agere ET-1310 Gigabit Ethernet support" - depends on PCI + depends on PCI && NET default n ---help--- This driver supports Agere ET-1310 ethernet adapters. -- cgit From c9fb041ff13c3b7b599fce6fb63cb903d69945d6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 15 Nov 2011 17:04:12 -0800 Subject: staging: fix more ET131X build errors ET131X is a network device, so it should depend on NETDEVICES. (This part won't be needed when the driver moves to drivers/net/.) It also uses PHYLIB interfaces, so it should select PHYLIB. Fixes these build errors: ERROR: "phy_connect" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_find_first" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_register" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_alloc" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_stop" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_start" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_free" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "mdiobus_unregister" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_print_status" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_ethtool_gset" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_ethtool_sset" [drivers/staging/et131x/et131x.ko] undefined! ERROR: "phy_mii_ioctl" [drivers/staging/et131x/et131x.ko] undefined! Signed-off-by: Randy Dunlap Acked-by: : Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/et131x/Kconfig b/drivers/staging/et131x/Kconfig index 98a165328e4e..8190f2aaf53b 100644 --- a/drivers/staging/et131x/Kconfig +++ b/drivers/staging/et131x/Kconfig @@ -1,6 +1,7 @@ config ET131X tristate "Agere ET-1310 Gigabit Ethernet support" - depends on PCI && NET + depends on PCI && NET && NETDEVICES + select PHYLIB default n ---help--- This driver supports Agere ET-1310 ethernet adapters. -- cgit From dbd1b5473ce8ae40fe7385eacc9294355eec0676 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 19 Nov 2011 11:41:30 +0100 Subject: ALSA: hda - Add pin fix for Alienware M17x R3 Reported-by: Albert Pool Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 470f6f286e81..f3658658548e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1641,6 +1641,8 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { "Alienware M17x", STAC_ALIENWARE_M17X), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; -- cgit From a5c86e986f0b2fe779f13cf53ce6e9f467b03950 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Sat, 19 Nov 2011 02:33:57 -0800 Subject: hugetlb: remove dummy definitions of HPAGE_MASK and HPAGE_SIZE Dummy, non-zero definitions for HPAGE_MASK and HPAGE_SIZE were added in 51c6f666fceb ("mm: ZAP_BLOCK causes redundant work") to avoid a divide by zero in generic kernel code. That code has since been removed, but probably should never have been added in the first place: we don't want HPAGE_SIZE to act like PAGE_SIZE for code that is working with hugepages, for example, when the dependency on CONFIG_HUGETLB_PAGE has not been fulfilled. Because hugepage size can differ from architecture to architecture, each is required to have their own definitions for both HPAGE_MASK and HPAGE_SIZE. This is always done in arch/*/include/asm/page.h. So, just remove the dummy and dangerous definitions since they are no longer needed and reveals the correct dependencies. Tested on architectures using the definitions with allyesconfig: x86 (even with thp), hppa, mips, powerpc, s390, sh3, sh4, sparc, and sparc64, and with defconfig on ia64. Signed-off-by: David Rientjes Signed-off-by: Linus Torvalds --- include/linux/hugetlb.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 19644e0016bd..d9d6c868b86b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -110,11 +110,6 @@ static inline void copy_huge_page(struct page *dst, struct page *src) #define hugetlb_change_protection(vma, address, end, newprot) -#ifndef HPAGE_MASK -#define HPAGE_MASK PAGE_MASK /* Keep the compiler happy */ -#define HPAGE_SIZE PAGE_SIZE -#endif - #endif /* !CONFIG_HUGETLB_PAGE */ #define HUGETLB_ANON_FILE "anon_hugepage" -- cgit From 27c9cd7e601632b3794e1c3344d37b86917ffb43 Mon Sep 17 00:00:00 2001 From: Jeff Ohlstein Date: Fri, 18 Nov 2011 15:47:10 -0800 Subject: hrtimer: Fix extra wakeups from __remove_hrtimer() __remove_hrtimer() attempts to reprogram the clockevent device when the timer being removed is the next to expire. However, __remove_hrtimer() reprograms the clockevent *before* removing the timer from the timerqueue and thus when hrtimer_force_reprogram() finds the next timer to expire it finds the timer we're trying to remove. This is especially noticeable when the system switches to NOHz mode and the system tick is removed. The timer tick is removed from the system but the clockevent is programmed to wakeup in another HZ anyway. Silence the extra wakeup by removing the timer from the timerqueue before calling hrtimer_force_reprogram() so that we actually program the clockevent for the next timer to expire. This was broken by 998adc3 "hrtimers: Convert hrtimers to use timerlist infrastructure". Signed-off-by: Jeff Ohlstein Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1321660030-8520-1-git-send-email-johlstei@codeaurora.org Signed-off-by: Thomas Gleixner --- kernel/hrtimer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index a9205e32a059..2043c08d36c8 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -885,10 +885,13 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, unsigned long newstate, int reprogram) { + struct timerqueue_node *next_timer; if (!(timer->state & HRTIMER_STATE_ENQUEUED)) goto out; - if (&timer->node == timerqueue_getnext(&base->active)) { + next_timer = timerqueue_getnext(&base->active); + timerqueue_del(&base->active, &timer->node); + if (&timer->node == next_timer) { #ifdef CONFIG_HIGH_RES_TIMERS /* Reprogram the clock event device. if enabled */ if (reprogram && hrtimer_hres_active()) { @@ -901,7 +904,6 @@ static void __remove_hrtimer(struct hrtimer *timer, } #endif } - timerqueue_del(&base->active, &timer->node); if (!timerqueue_getnext(&base->active)) base->cpu_base->active_bases &= ~(1 << base->index); out: -- cgit From d633180c20271d3b7c1fabbccbc7c5b30ad12be4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Fri, 18 Nov 2011 15:56:06 -0800 Subject: Xen: update MAINTAINER info No longer at Citrix, still interested in Xen. Signed-off-by: Jeremy Fitzhardinge Cc: Jeremy Fitzhardinge Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 48fe11cc2306..1e7cc42a69ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4950,7 +4950,7 @@ F: drivers/char/ppdev.c F: include/linux/ppdev.h PARAVIRT_OPS INTERFACE -M: Jeremy Fitzhardinge +M: Jeremy Fitzhardinge M: Chris Wright M: Alok Kataria M: Rusty Russell @@ -7402,8 +7402,8 @@ S: Maintained F: arch/x86/kernel/cpu/mcheck/* XEN HYPERVISOR INTERFACE -M: Jeremy Fitzhardinge M: Konrad Rzeszutek Wilk +M: Jeremy Fitzhardinge L: xen-devel@lists.xensource.com (moderated for non-subscribers) L: virtualization@lists.linux-foundation.org S: Supported -- cgit From 501a708f18ef911328ffd39f39738b8a7862aa8e Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Sat, 19 Nov 2011 14:37:57 +0100 Subject: PM / Suspend: Fix bug in suspend statistics update After commit 2a77c46de1e3dace73745015635ebbc648eca69c (PM / Suspend: Add statistics debugfs file for suspend to RAM) a missing pair of braces inside the state_store() function causes even invalid arguments to suspend to be wrongly treated as failed suspend attempts. Fix this. [rjw: Put the hash/subject of the buggy commit into the changelog.] Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- kernel/power/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 71f49fe4377e..36e0f0903c32 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -290,13 +290,14 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } - if (state < PM_SUSPEND_MAX && *s) + if (state < PM_SUSPEND_MAX && *s) { error = enter_state(state); if (error) { suspend_stats.fail++; dpm_save_failed_errno(error); } else suspend_stats.success++; + } #endif Exit: -- cgit From 016e8d44bc06dd3322f26712bdd3f3a6973592d0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 19 Aug 2011 14:50:26 -0400 Subject: fs/minix: Verify bitmap block counts before mounting Newer versions of MINIX can create filesystems that allocate an extra bitmap block. Mounting of this succeeds, but doing a statfs call will result in an oops in count_free because of a negative number being used for the bh index. Avoid this by verifying the number of allocated blocks at mount time, erroring out if there are not enough and make statfs ignore the extras if there are too many. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=18792 Signed-off-by: Josh Boyer Signed-off-by: Al Viro --- fs/minix/bitmap.c | 18 ++++++++++++------ fs/minix/inode.c | 25 +++++++++++++++++++++++-- fs/minix/minix.h | 9 +++++++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 3f32bcb0d9bd..7c82c29429d7 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -20,10 +20,11 @@ static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; static DEFINE_SPINLOCK(bitmap_lock); -static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) +static unsigned long count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits) { unsigned i, j, sum = 0; struct buffer_head *bh; + unsigned numblocks = minix_blocks_needed(numbits, blocksize); for (i=0; is_zmap, sbi->s_zmap_blocks, - sbi->s_nzones - sbi->s_firstdatazone + 1) + struct minix_sb_info *sbi = minix_sb(sb); + u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1); + + return (count_free(sbi->s_zmap, sb->s_blocksize, bits) << sbi->s_log_zone_size); } @@ -273,7 +276,10 @@ struct inode *minix_new_inode(const struct inode *dir, int mode, int *error) return inode; } -unsigned long minix_count_free_inodes(struct minix_sb_info *sbi) +unsigned long minix_count_free_inodes(struct super_block *sb) { - return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1); + struct minix_sb_info *sbi = minix_sb(sb); + u32 bits = sbi->s_ninodes + 1; + + return count_free(sbi->s_imap, sb->s_blocksize, bits); } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 64cdcd662ffc..1d9e33966db0 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -279,6 +279,27 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) else if (sbi->s_mount_state & MINIX_ERROR_FS) printk("MINIX-fs: mounting file system with errors, " "running fsck is recommended\n"); + + /* Apparently minix can create filesystems that allocate more blocks for + * the bitmaps than needed. We simply ignore that, but verify it didn't + * create one with not enough blocks and bail out if so. + */ + block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); + if (sbi->s_imap_blocks < block) { + printk("MINIX-fs: file system does not have enough " + "imap blocks allocated. Refusing to mount\n"); + goto out_iput; + } + + block = minix_blocks_needed( + (sbi->s_nzones - (sbi->s_firstdatazone + 1)), + s->s_blocksize); + if (sbi->s_zmap_blocks < block) { + printk("MINIX-fs: file system does not have enough " + "zmap blocks allocated. Refusing to mount.\n"); + goto out_iput; + } + return 0; out_iput: @@ -339,10 +360,10 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_type = sb->s_magic; buf->f_bsize = sb->s_blocksize; buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; - buf->f_bfree = minix_count_free_blocks(sbi); + buf->f_bfree = minix_count_free_blocks(sb); buf->f_bavail = buf->f_bfree; buf->f_files = sbi->s_ninodes; - buf->f_ffree = minix_count_free_inodes(sbi); + buf->f_ffree = minix_count_free_inodes(sb); buf->f_namelen = sbi->s_namelen; buf->f_fsid.val[0] = (u32)id; buf->f_fsid.val[1] = (u32)(id >> 32); diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 341e2122879a..6415fe0d2385 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -48,10 +48,10 @@ extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, stru extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **); extern struct inode * minix_new_inode(const struct inode *, int, int *); extern void minix_free_inode(struct inode * inode); -extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); +extern unsigned long minix_count_free_inodes(struct super_block *sb); extern int minix_new_block(struct inode * inode); extern void minix_free_block(struct inode *inode, unsigned long block); -extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); +extern unsigned long minix_count_free_blocks(struct super_block *sb); extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len); @@ -88,6 +88,11 @@ static inline struct minix_inode_info *minix_i(struct inode *inode) return list_entry(inode, struct minix_inode_info, vfs_inode); } +static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksize) +{ + return DIV_ROUND_UP(bits, blocksize * 8); +} + #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \ defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) -- cgit From f1fd306a91f875e65af0e04855b23adda6831ac9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 26 Aug 2011 22:38:50 -0400 Subject: minixfs: kill manual hweight(), simplify Signed-off-by: Al Viro --- fs/minix/bitmap.c | 41 ++++++++++++++--------------------------- fs/minix/minix.h | 2 +- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 7c82c29429d7..ef175cb8cfd8 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -16,39 +16,26 @@ #include #include -static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; - static DEFINE_SPINLOCK(bitmap_lock); -static unsigned long count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits) +/* + * bitmap consists of blocks filled with 16bit words + * bit set == busy, bit clear == free + * endianness is a mess, but for counting zero bits it really doesn't matter... + */ +static __u32 count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits) { - unsigned i, j, sum = 0; - struct buffer_head *bh; - unsigned numblocks = minix_blocks_needed(numbits, blocksize); - - for (i=0; ib_size; j++) - sum += nibblemap[bh->b_data[j] & 0xf] - + nibblemap[(bh->b_data[j]>>4) & 0xf]; - } + __u32 sum = 0; + unsigned blocks = DIV_ROUND_UP(numbits, blocksize * 8); - if (numblocks==0 || !(bh=map[numblocks-1])) - return(0); - i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; - for (j=0; jb_data[j] & 0xf] - + nibblemap[(bh->b_data[j]>>4) & 0xf]; + while (blocks--) { + unsigned words = blocksize / 2; + __u16 *p = (__u16 *)(*map++)->b_data; + while (words--) + sum += 16 - hweight16(*p++); } - i = numbits%16; - if (i!=0) { - i = *(__u16 *)(&bh->b_data[j]) | ~((1<>4) & 0xf]; - sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf]; - } - return(sum); + return sum; } void minix_free_block(struct inode *inode, unsigned long block) diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 6415fe0d2385..26bbd55e82ea 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -130,7 +130,7 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size) if (!size) return 0; - size = (size >> 4) + ((size & 15) > 0); + size >>= 4; while (*p++ == 0xffff) { if (--size == 0) return (p - addr) << 4; -- cgit From e70f224c1938af208b64b02c5cec27889fefcaec Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Tue, 25 Oct 2011 01:38:45 +0200 Subject: drm/radeon/kms: add a CS ioctl flag not to rewrite tiling flags in the CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a new optional chunk to the CS ioctl that specifies optional flags to the CS parser. Why this is useful is explained below. Note that some regs no longer need the NOP relocation packet if this feature is enabled. Tested on r300g and r600g with this flag disabled and enabled. Assume there are two contexts sharing the same mipmapped tiled texture. One context wants to render into the first mipmap and the other one wants to render into the last mipmap. As you probably know, the hardware has a MACRO_SWITCH feature, which turns off macro tiling for small mipmaps, but that only applies to samplers. (at least on r300-r500, though later hardware likely behaves the same) So we want to just re-set the tiling flags before rendering (writing packets), right? ... No. The contexts run in parallel, so they may set the tiling flags simultaneously and then fire their command streams also simultaneously. The last one setting the flags wins, the other one loses. Another problem is when one context wants to render into the first and the last mipmap in one CS. Impossible. It must flush before changing tiling flags and do the rendering into the smaller mipmaps in another CS. Yet another problem is that writing copy_blit in userspace would be a mess involving re-setting tiling flags to please the kernel, and causing races with other contexts at the same time. The only way out of this is to send tiling flags with each CS, ideally with each relocation. But we already do that through the registers. So let's just use what we have in the registers. Signed-off-by: Marek Olšák Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen_cs.c | 92 ++++++++++++++++++---------------- drivers/gpu/drm/radeon/r300.c | 94 +++++++++++++++++++---------------- drivers/gpu/drm/radeon/r600_cs.c | 26 ++++++---- drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_cs.c | 11 +++- drivers/gpu/drm/radeon/radeon_drv.c | 3 +- include/drm/radeon_drm.h | 4 ++ 7 files changed, 135 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 7fdfa8ea7570..38e1bda73d33 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -480,21 +480,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) } break; case DB_Z_INFO: - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - dev_warn(p->dev, "bad SET_CONTEXT_REG " - "0x%04X\n", reg); - return -EINVAL; - } track->db_z_info = radeon_get_ib_value(p, idx); - ib[idx] &= ~Z_ARRAY_MODE(0xf); - track->db_z_info &= ~Z_ARRAY_MODE(0xf); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else { - ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] &= ~Z_ARRAY_MODE(0xf); + track->db_z_info &= ~Z_ARRAY_MODE(0xf); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else { + ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } } break; case DB_STENCIL_INFO: @@ -607,40 +609,44 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR5_INFO: case CB_COLOR6_INFO: case CB_COLOR7_INFO: - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - dev_warn(p->dev, "bad SET_CONTEXT_REG " - "0x%04X\n", reg); - return -EINVAL; - } tmp = (reg - CB_COLOR0_INFO) / 0x3c; track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } } break; case CB_COLOR8_INFO: case CB_COLOR9_INFO: case CB_COLOR10_INFO: case CB_COLOR11_INFO: - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - dev_warn(p->dev, "bad SET_CONTEXT_REG " - "0x%04X\n", reg); - return -EINVAL; - } tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } } break; case CB_COLOR0_PITCH: @@ -1311,10 +1317,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } texture = reloc->robj; /* tex mip base */ r = evergreen_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 400b26df652a..c93bc64707e1 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -701,16 +701,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p, return r; } - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - tile_flags |= R300_TXO_MACRO_TILE; - if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - tile_flags |= R300_TXO_MICRO_TILE; - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) - tile_flags |= R300_TXO_MICRO_TILE_SQUARE; - - tmp = idx_value + ((u32)reloc->lobj.gpu_offset); - tmp |= tile_flags; - ib[idx] = tmp; + if (p->keep_tiling_flags) { + ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ + ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset); + } else { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_TXO_MACRO_TILE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_TXO_MICRO_TILE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_TXO_MICRO_TILE_SQUARE; + + tmp = idx_value + ((u32)reloc->lobj.gpu_offset); + tmp |= tile_flags; + ib[idx] = tmp; + } track->textures[i].robj = reloc->robj; track->tex_dirty = true; break; @@ -760,24 +765,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p, /* RB3D_COLORPITCH1 */ /* RB3D_COLORPITCH2 */ /* RB3D_COLORPITCH3 */ - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for ib[%d]=0x%04X\n", - idx, reg); - r100_cs_dump_packet(p, pkt); - return r; - } + if (!p->keep_tiling_flags) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - tile_flags |= R300_COLOR_TILE_ENABLE; - if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - tile_flags |= R300_COLOR_MICROTILE_ENABLE; - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) - tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_COLOR_MICROTILE_ENABLE; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; - tmp = idx_value & ~(0x7 << 16); - tmp |= tile_flags; - ib[idx] = tmp; + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } i = (reg - 0x4E38) >> 2; track->cb[i].pitch = idx_value & 0x3FFE; switch (((idx_value >> 21) & 0xF)) { @@ -843,25 +850,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p, break; case 0x4F24: /* ZB_DEPTHPITCH */ - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for ib[%d]=0x%04X\n", - idx, reg); - r100_cs_dump_packet(p, pkt); - return r; - } - - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - tile_flags |= R300_DEPTHMACROTILE_ENABLE; - if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - tile_flags |= R300_DEPTHMICROTILE_TILED; - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) - tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; + if (!p->keep_tiling_flags) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } - tmp = idx_value & ~(0x7 << 16); - tmp |= tile_flags; - ib[idx] = tmp; + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_DEPTHMACROTILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_DEPTHMICROTILE_TILED; + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) + tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; + tmp = idx_value & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + } track->zb.pitch = idx_value & 0x3FFC; track->zb_dirty = true; break; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0a2e023c1557..cb1acffd2430 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -941,7 +941,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) track->db_depth_control = radeon_get_ib_value(p, idx); break; case R_028010_DB_DEPTH_INFO: - if (r600_cs_packet_next_is_pkt3_nop(p)) { + if (!p->keep_tiling_flags && + r600_cs_packet_next_is_pkt3_nop(p)) { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_warn(p->dev, "bad SET_CONTEXT_REG " @@ -992,7 +993,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_0280B4_CB_COLOR5_INFO: case R_0280B8_CB_COLOR6_INFO: case R_0280BC_CB_COLOR7_INFO: - if (r600_cs_packet_next_is_pkt3_nop(p)) { + if (!p->keep_tiling_flags && + r600_cs_packet_next_is_pkt3_nop(p)) { r = r600_cs_packet_next_reloc(p, &reloc); if (r) { dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); @@ -1291,10 +1293,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, mip_offset <<= 8; word0 = radeon_get_ib_value(p, idx + 0); - if (tiling_flags & RADEON_TILING_MACRO) - word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); - else if (tiling_flags & RADEON_TILING_MICRO) - word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + if (tiling_flags & RADEON_TILING_MACRO) + word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (tiling_flags & RADEON_TILING_MICRO) + word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + } word1 = radeon_get_ib_value(p, idx + 1); w0 = G_038000_TEX_WIDTH(word0) + 1; h0 = G_038004_TEX_HEIGHT(word1) + 1; @@ -1621,10 +1625,12 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + if (!p->keep_tiling_flags) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); + } texture = reloc->robj; /* tex mip base */ r = r600_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fc5a1d642cb5..8227e76b5c70 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -611,7 +611,8 @@ struct radeon_cs_parser { struct radeon_ib *ib; void *track; unsigned family; - int parser_error; + int parser_error; + bool keep_tiling_flags; }; extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx); diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ccaa243c1442..29afd71e0840 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -93,7 +93,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; uint64_t *chunk_array_ptr; - unsigned size, i; + unsigned size, i, flags = 0; if (!cs->num_chunks) { return 0; @@ -140,6 +140,10 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) if (p->chunks[i].length_dw == 0) return -EINVAL; } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS && + !p->chunks[i].length_dw) { + return -EINVAL; + } p->chunks[i].length_dw = user_chunk.length_dw; p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data; @@ -155,6 +159,9 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunks[i].user_ptr, size)) { return -EFAULT; } + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { + flags = p->chunks[i].kdata[0]; + } } else { p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); @@ -174,6 +181,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunks[p->chunk_ib_idx].length_dw); return -EINVAL; } + + p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a0b35e909489..71499fc3daf5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -53,9 +53,10 @@ * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker + * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 11 +#define KMS_DRIVER_MINOR 12 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index b65be6054a18..be94be6d6f17 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -874,6 +874,10 @@ struct drm_radeon_gem_pwrite { #define RADEON_CHUNK_ID_RELOCS 0x01 #define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_FLAGS 0x03 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01 struct drm_radeon_cs_chunk { uint32_t chunk_id; -- cgit From 95ef1e52922cf75b1ea2eae54ef886f2cc47eecb Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 15 Nov 2011 14:59:07 +0200 Subject: KVM guest: prevent tracing recursion with kvmclock Prevent tracing of preempt_disable() in get_cpu_var() in kvm_clock_read(). When CONFIG_DEBUG_PREEMPT is enabled, preempt_disable/enable() are traced and this causes the function_graph tracer to go into an infinite recursion. By open coding the preempt_disable() around the get_cpu_var(), we can use the notrace version which prevents preempt_disable/enable() from being traced and prevents the recursion. Based on a similar patch for Xen from Jeremy Fitzhardinge. Tested-by: Gleb Natapov Acked-by: Steven Rostedt Signed-off-by: Avi Kivity --- arch/x86/kernel/kvmclock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index c1a0188e29ae..44842d756b29 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -74,9 +74,10 @@ static cycle_t kvm_clock_read(void) struct pvclock_vcpu_time_info *src; cycle_t ret; - src = &get_cpu_var(hv_clock); + preempt_disable_notrace(); + src = &__get_cpu_var(hv_clock); ret = pvclock_clocksource_read(src); - put_cpu_var(hv_clock); + preempt_enable_notrace(); return ret; } -- cgit From 387125fc722a8ed432066b85a552917343bdafca Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 18 Nov 2011 15:07:51 -0500 Subject: Btrfs: fix barrier flushes When btrfs is writing the super blocks, it send barrier flushes to make sure writeback caching drives get all the metadata on disk in the right order. But, we have two bugs in the way these are sent down. When doing full commits (not via the tree log), we are sending the barrier down before the last super when it should be going down before the first. In multi-device setups, we should be waiting for the barriers to complete on all devices before writing any of the supers. Both of these bugs can cause corruptions on power failures. We fix it with some new code to send down empty barriers to all devices before writing the first super. Alexandre Oliva found the multi-device bug. Arne Jansen did the async barrier loop. Signed-off-by: Chris Mason Reported-by: Alexandre Oliva --- fs/btrfs/disk-io.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++------- fs/btrfs/volumes.h | 6 +++ 2 files changed, 134 insertions(+), 17 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b6a5c0dd0dd8..48d30138237f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2573,22 +2573,10 @@ static int write_dev_supers(struct btrfs_device *device, int errors = 0; u32 crc; u64 bytenr; - int last_barrier = 0; if (max_mirrors == 0) max_mirrors = BTRFS_SUPER_MIRROR_MAX; - /* make sure only the last submit_bh does a barrier */ - if (do_barriers) { - for (i = 0; i < max_mirrors; i++) { - bytenr = btrfs_sb_offset(i); - if (bytenr + BTRFS_SUPER_INFO_SIZE >= - device->total_bytes) - break; - last_barrier = i; - } - } - for (i = 0; i < max_mirrors; i++) { bytenr = btrfs_sb_offset(i); if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes) @@ -2634,17 +2622,136 @@ static int write_dev_supers(struct btrfs_device *device, bh->b_end_io = btrfs_end_buffer_write_sync; } - if (i == last_barrier && do_barriers) - ret = submit_bh(WRITE_FLUSH_FUA, bh); - else - ret = submit_bh(WRITE_SYNC, bh); - + /* + * we fua the first super. The others we allow + * to go down lazy. + */ + ret = submit_bh(WRITE_FUA, bh); if (ret) errors++; } return errors < i ? 0 : -1; } +/* + * endio for the write_dev_flush, this will wake anyone waiting + * for the barrier when it is done + */ +static void btrfs_end_empty_barrier(struct bio *bio, int err) +{ + if (err) { + if (err == -EOPNOTSUPP) + set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); + clear_bit(BIO_UPTODATE, &bio->bi_flags); + } + if (bio->bi_private) + complete(bio->bi_private); + bio_put(bio); +} + +/* + * trigger flushes for one the devices. If you pass wait == 0, the flushes are + * sent down. With wait == 1, it waits for the previous flush. + * + * any device where the flush fails with eopnotsupp are flagged as not-barrier + * capable + */ +static int write_dev_flush(struct btrfs_device *device, int wait) +{ + struct bio *bio; + int ret = 0; + + if (device->nobarriers) + return 0; + + if (wait) { + bio = device->flush_bio; + if (!bio) + return 0; + + wait_for_completion(&device->flush_wait); + + if (bio_flagged(bio, BIO_EOPNOTSUPP)) { + printk("btrfs: disabling barriers on dev %s\n", + device->name); + device->nobarriers = 1; + } + if (!bio_flagged(bio, BIO_UPTODATE)) { + ret = -EIO; + } + + /* drop the reference from the wait == 0 run */ + bio_put(bio); + device->flush_bio = NULL; + + return ret; + } + + /* + * one reference for us, and we leave it for the + * caller + */ + device->flush_bio = NULL;; + bio = bio_alloc(GFP_NOFS, 0); + if (!bio) + return -ENOMEM; + + bio->bi_end_io = btrfs_end_empty_barrier; + bio->bi_bdev = device->bdev; + init_completion(&device->flush_wait); + bio->bi_private = &device->flush_wait; + device->flush_bio = bio; + + bio_get(bio); + submit_bio(WRITE_FLUSH, bio); + + return 0; +} + +/* + * send an empty flush down to each device in parallel, + * then wait for them + */ +static int barrier_all_devices(struct btrfs_fs_info *info) +{ + struct list_head *head; + struct btrfs_device *dev; + int errors = 0; + int ret; + + /* send down all the barriers */ + head = &info->fs_devices->devices; + list_for_each_entry_rcu(dev, head, dev_list) { + if (!dev->bdev) { + errors++; + continue; + } + if (!dev->in_fs_metadata || !dev->writeable) + continue; + + ret = write_dev_flush(dev, 0); + if (ret) + errors++; + } + + /* wait for all the barriers */ + list_for_each_entry_rcu(dev, head, dev_list) { + if (!dev->bdev) { + errors++; + continue; + } + if (!dev->in_fs_metadata || !dev->writeable) + continue; + + ret = write_dev_flush(dev, 1); + if (ret) + errors++; + } + if (errors) + return -EIO; + return 0; +} + int write_all_supers(struct btrfs_root *root, int max_mirrors) { struct list_head *head; @@ -2666,6 +2773,10 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) mutex_lock(&root->fs_info->fs_devices->device_list_mutex); head = &root->fs_info->fs_devices->devices; + + if (do_barriers) + barrier_all_devices(root->fs_info); + list_for_each_entry_rcu(dev, head, dev_list) { if (!dev->bdev) { total_errors++; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index ab5b1c49f352..78f2d4d4f37f 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -100,6 +100,12 @@ struct btrfs_device { struct reada_zone *reada_curr_zone; struct radix_tree_root reada_zones; struct radix_tree_root reada_extents; + + /* for sending down flush barriers */ + struct bio *flush_bio; + struct completion flush_wait; + int nobarriers; + }; struct btrfs_fs_devices { -- cgit From 745c4d8e160afaf6c75e887c27ea4b75c8142b26 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Sun, 20 Nov 2011 07:31:57 -0500 Subject: btrfs: Fix up 32/64-bit compatibility for new ioctls This patch casts to unsigned long before casting to a pointer and fixes the following warnings: fs/btrfs/extent_io.c:2289:20: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] fs/btrfs/ioctl.c:2933:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] fs/btrfs/ioctl.c:2937:21: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] fs/btrfs/ioctl.c:3020:21: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] fs/btrfs/scrub.c:275:4: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] fs/btrfs/backref.c:686:27: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Jeff Mahoney Signed-off-by: Chris Mason --- fs/btrfs/backref.c | 2 +- fs/btrfs/extent_io.c | 2 +- fs/btrfs/ioctl.c | 9 ++++++--- fs/btrfs/scrub.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 8855aad3929c..22c64fff1bd5 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -683,7 +683,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref, return PTR_ERR(fspath); if (fspath > fspath_min) { - ipath->fspath->val[i] = (u64)fspath; + ipath->fspath->val[i] = (u64)(unsigned long)fspath; ++ipath->fspath->elem_cnt; ipath->fspath->bytes_left = fspath - fspath_min; } else { diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 1f87c4d0e7a0..47fdba7853c3 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2286,7 +2286,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) } if (!uptodate) { u64 failed_mirror; - failed_mirror = (u64)bio->bi_bdev; + failed_mirror = (unsigned long)bio->bi_bdev; if (tree->ops && tree->ops->readpage_io_failed_hook) ret = tree->ops->readpage_io_failed_hook( bio, page, start, end, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4a34c472f126..bda53fcd1a09 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2930,11 +2930,13 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) goto out; for (i = 0; i < ipath->fspath->elem_cnt; ++i) { - rel_ptr = ipath->fspath->val[i] - (u64)ipath->fspath->val; + rel_ptr = ipath->fspath->val[i] - + (u64)(unsigned long)ipath->fspath->val; ipath->fspath->val[i] = rel_ptr; } - ret = copy_to_user((void *)ipa->fspath, (void *)ipath->fspath, size); + ret = copy_to_user((void *)(unsigned long)ipa->fspath, + (void *)(unsigned long)ipath->fspath, size); if (ret) { ret = -EFAULT; goto out; @@ -3017,7 +3019,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, if (ret < 0) goto out; - ret = copy_to_user((void *)loi->inodes, (void *)inodes, size); + ret = copy_to_user((void *)(unsigned long)loi->inodes, + (void *)(unsigned long)inodes, size); if (ret) ret = -EFAULT; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f4190f22edfb..fab420db5121 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -272,7 +272,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) swarn->logical, swarn->dev->name, (unsigned long long)swarn->sector, root, inum, offset, min(isize - offset, (u64)PAGE_SIZE), nlink, - (char *)ipath->fspath->val[i]); + (char *)(unsigned long)ipath->fspath->val[i]); free_ipath(ipath); return 0; -- cgit From 32240a913d9f3a5aad42175d7696590ea1bfdb08 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sun, 20 Nov 2011 07:33:38 -0500 Subject: btrfs: mirror_num should be int, not u64 My previous patch introduced some u64 for failed_mirror variables, this one makes it consistent again. Signed-off-by: Jan Schmidt Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 2 +- fs/btrfs/extent_io.c | 4 ++-- fs/btrfs/extent_io.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 48d30138237f..94abc25392f6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -620,7 +620,7 @@ out: static int btree_io_failed_hook(struct bio *failed_bio, struct page *page, u64 start, u64 end, - u64 mirror_num, struct extent_state *state) + int mirror_num, struct extent_state *state) { struct extent_io_tree *tree; unsigned long len; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 47fdba7853c3..a877b8b212eb 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2285,8 +2285,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err) clean_io_failure(start, page); } if (!uptodate) { - u64 failed_mirror; - failed_mirror = (unsigned long)bio->bi_bdev; + int failed_mirror; + failed_mirror = (int)(unsigned long)bio->bi_bdev; if (tree->ops && tree->ops->readpage_io_failed_hook) ret = tree->ops->readpage_io_failed_hook( bio, page, start, end, diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index feb9be0e23bc..7604c3001322 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -70,7 +70,7 @@ struct extent_io_ops { unsigned long bio_flags); int (*readpage_io_hook)(struct page *page, u64 start, u64 end); int (*readpage_io_failed_hook)(struct bio *bio, struct page *page, - u64 start, u64 end, u64 failed_mirror, + u64 start, u64 end, int failed_mirror, struct extent_state *state); int (*writepage_io_failed_hook)(struct bio *bio, struct page *page, u64 start, u64 end, -- cgit From 0f0fbf1d0e188d129756e9508090af4bdbfde00b Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Sun, 20 Nov 2011 07:33:38 -0500 Subject: Btrfs: fix to search one more bitmap for cluster setup Suppose there are two bitmaps [0, 256], [256, 512] and one extent [100, 120] in the free space cache, and we want to setup a cluster with offset=100, bytes=50. In this case, there will be only one bitmap [256, 512] in the temporary bitmaps list, and then setup_cluster_bitmap() won't search bitmap [0, 256]. The cause is, the list is constructed in setup_cluster_no_bitmap(), and only bitmaps with bitmap_entry->offset >= offset will be added into the list, and the very bitmap that convers offset has bitmap_entry->offset <= offset. Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 181760f9d2ab..8f792f41feab 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2453,10 +2453,22 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_space *entry; struct rb_node *node; int ret = -ENOSPC; + u64 bitmap_offset = offset_to_bitmap(ctl, offset); if (ctl->total_bitmaps == 0) return -ENOSPC; + /* + * The bitmap that covers offset won't be in the list unless offset + * is just its start offset. + */ + entry = list_first_entry(bitmaps, struct btrfs_free_space, list); + if (entry->offset != bitmap_offset) { + entry = tree_search_offset(ctl, bitmap_offset, 1, 0); + if (entry && list_empty(&entry->list)) + list_add(&entry->list, bitmaps); + } + /* * First check our cached list of bitmaps and see if there is an entry * here that will work. -- cgit From 52621cb6ed0e0e14358bb317bda7cd5fbd5c2a27 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Sun, 20 Nov 2011 07:33:38 -0500 Subject: Btrfs: avoid unnecessary bitmap search for cluster setup setup_cluster_no_bitmap() searches all the extents and bitmaps starting from offset. Therefore if it returns -ENOSPC, all the bitmaps starting from offset are in the bitmaps list, so it's sufficient to search from this list in setup_cluser_bitmap(). Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 42 ++++-------------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 8f792f41feab..8c32434da2cb 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2451,7 +2451,6 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *entry; - struct rb_node *node; int ret = -ENOSPC; u64 bitmap_offset = offset_to_bitmap(ctl, offset); @@ -2469,10 +2468,6 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, list_add(&entry->list, bitmaps); } - /* - * First check our cached list of bitmaps and see if there is an entry - * here that will work. - */ list_for_each_entry(entry, bitmaps, list) { if (entry->bytes < min_bytes) continue; @@ -2483,38 +2478,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, } /* - * If we do have entries on our list and we are here then we didn't find - * anything, so go ahead and get the next entry after the last entry in - * this list and start the search from there. + * The bitmaps list has all the bitmaps that record free space + * starting after offset, so no more search is required. */ - if (!list_empty(bitmaps)) { - entry = list_entry(bitmaps->prev, struct btrfs_free_space, - list); - node = rb_next(&entry->offset_index); - if (!node) - return -ENOSPC; - entry = rb_entry(node, struct btrfs_free_space, offset_index); - goto search; - } - - entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); - if (!entry) - return -ENOSPC; - -search: - node = &entry->offset_index; - do { - entry = rb_entry(node, struct btrfs_free_space, offset_index); - node = rb_next(&entry->offset_index); - if (!entry->bitmap) - continue; - if (entry->bytes < min_bytes) - continue; - ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, - bytes, min_bytes); - } while (ret && node); - - return ret; + return -ENOSPC; } /* @@ -2532,8 +2499,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, u64 offset, u64 bytes, u64 empty_size) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; - struct list_head bitmaps; struct btrfs_free_space *entry, *tmp; + LIST_HEAD(bitmaps); u64 min_bytes; int ret; @@ -2572,7 +2539,6 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, goto out; } - INIT_LIST_HEAD(&bitmaps); ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset, bytes, min_bytes); if (ret) -- cgit From fadc0d8be4dfca80f6c568bc5874931893c6709b Mon Sep 17 00:00:00 2001 From: David Sterba Date: Sun, 20 Nov 2011 07:33:38 -0500 Subject: btrfs: fix stat blocks accounting Round inode bytes and delalloc bytes up to real blocksize before converting to sector size. Otherwise eg. files smaller than 512 are reported with zero blocks due to incorrect rounding. Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e16215f480d0..8ad26b135a1c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6794,11 +6794,13 @@ static int btrfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = dentry->d_inode; + u32 blocksize = inode->i_sb->s_blocksize; + generic_fillattr(inode, stat); stat->dev = BTRFS_I(inode)->root->anon_dev; stat->blksize = PAGE_CACHE_SIZE; - stat->blocks = (inode_get_bytes(inode) + - BTRFS_I(inode)->delalloc_bytes) >> 9; + stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) + + ALIGN(BTRFS_I(inode)->delalloc_bytes, blocksize)) >> 9; return 0; } -- cgit From 5bb1468238e20b15921909e9f9601e945f03bac7 Mon Sep 17 00:00:00 2001 From: Arnd Hannemann Date: Sun, 20 Nov 2011 07:33:38 -0500 Subject: Btrfs: prefix resize related printks with btrfs: For the user it is confusing to find something like: [10197.627710] new size for /dev/mapper/vg0-usr_share is 3221225472 in kernel log, because it doesn't point directly to btrfs. This patch prefixes those messages with "btrfs:" like other btrfs related printks. Signed-off-by: Arnd Hannemann Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bda53fcd1a09..a90e749ed6d2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1216,12 +1216,12 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, *devstr = '\0'; devstr = vol_args->name; devid = simple_strtoull(devstr, &end, 10); - printk(KERN_INFO "resizing devid %llu\n", + printk(KERN_INFO "btrfs: resizing devid %llu\n", (unsigned long long)devid); } device = btrfs_find_device(root, devid, NULL, NULL); if (!device) { - printk(KERN_INFO "resizer unable to find device %llu\n", + printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", (unsigned long long)devid); ret = -EINVAL; goto out_unlock; @@ -1267,7 +1267,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, do_div(new_size, root->sectorsize); new_size *= root->sectorsize; - printk(KERN_INFO "new size for %s is %llu\n", + printk(KERN_INFO "btrfs: new size for %s is %llu\n", device->name, (unsigned long long)new_size); if (new_size > old_size) { -- cgit From 291c7d2f577428f896daa5002e784959328a80aa Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 14 Nov 2011 13:52:14 -0500 Subject: Btrfs: wait on caching if we're loading the free space cache We've been hitting panics when running xfstest 13 in a loop for long periods of time. And actually this problem has always existed so we've been hitting these things randomly for a while. Basically what happens is we get a thread coming into the allocator and reading the space cache off of disk and adding the entries to the free space cache as we go. Then we get another thread that comes in and tries to allocate from that block group. Since block_group->cached != BTRFS_CACHE_NO it goes ahead and tries to do the allocation. We do this because if we're doing the old slow way of caching we don't want to hold people up and wait for everything to finish. The problem with this is we could end up discarding the space cache at some arbitrary point in the future, which means we could very well end up allocating space that is either bad, or when the real caching happens it could end up thinking the space isn't in use when it really is and cause all sorts of other problems. The solution is to add a new flag to indicate we are loading the free space cache from disk, and always try to cache the block group if cache->cached != BTRFS_CACHE_FINISHED. That way if we are loading the space cache anybody else who tries to allocate from the block group will have to wait until it's finished to make sure it completes successfully. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 3 +- fs/btrfs/extent-tree.c | 119 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 81 insertions(+), 41 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b1cb3c052484..04a5dfcee5a1 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -848,7 +848,8 @@ struct btrfs_free_cluster { enum btrfs_caching_type { BTRFS_CACHE_NO = 0, BTRFS_CACHE_STARTED = 1, - BTRFS_CACHE_FINISHED = 2, + BTRFS_CACHE_FAST = 2, + BTRFS_CACHE_FINISHED = 3, }; enum btrfs_disk_cache_state { diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0f47b3e2010e..5d86877f10e1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -467,13 +467,59 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, struct btrfs_root *root, int load_cache_only) { + DEFINE_WAIT(wait); struct btrfs_fs_info *fs_info = cache->fs_info; struct btrfs_caching_control *caching_ctl; int ret = 0; - smp_mb(); - if (cache->cached != BTRFS_CACHE_NO) + caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); + BUG_ON(!caching_ctl); + + INIT_LIST_HEAD(&caching_ctl->list); + mutex_init(&caching_ctl->mutex); + init_waitqueue_head(&caching_ctl->wait); + caching_ctl->block_group = cache; + caching_ctl->progress = cache->key.objectid; + atomic_set(&caching_ctl->count, 1); + caching_ctl->work.func = caching_thread; + + spin_lock(&cache->lock); + /* + * This should be a rare occasion, but this could happen I think in the + * case where one thread starts to load the space cache info, and then + * some other thread starts a transaction commit which tries to do an + * allocation while the other thread is still loading the space cache + * info. The previous loop should have kept us from choosing this block + * group, but if we've moved to the state where we will wait on caching + * block groups we need to first check if we're doing a fast load here, + * so we can wait for it to finish, otherwise we could end up allocating + * from a block group who's cache gets evicted for one reason or + * another. + */ + while (cache->cached == BTRFS_CACHE_FAST) { + struct btrfs_caching_control *ctl; + + ctl = cache->caching_ctl; + atomic_inc(&ctl->count); + prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock(&cache->lock); + + schedule(); + + finish_wait(&ctl->wait, &wait); + put_caching_control(ctl); + spin_lock(&cache->lock); + } + + if (cache->cached != BTRFS_CACHE_NO) { + spin_unlock(&cache->lock); + kfree(caching_ctl); return 0; + } + WARN_ON(cache->caching_ctl); + cache->caching_ctl = caching_ctl; + cache->cached = BTRFS_CACHE_FAST; + spin_unlock(&cache->lock); /* * We can't do the read from on-disk cache during a commit since we need @@ -484,56 +530,51 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, if (trans && (!trans->transaction->in_commit) && (root && root != root->fs_info->tree_root) && btrfs_test_opt(root, SPACE_CACHE)) { - spin_lock(&cache->lock); - if (cache->cached != BTRFS_CACHE_NO) { - spin_unlock(&cache->lock); - return 0; - } - cache->cached = BTRFS_CACHE_STARTED; - spin_unlock(&cache->lock); - ret = load_free_space_cache(fs_info, cache); spin_lock(&cache->lock); if (ret == 1) { + cache->caching_ctl = NULL; cache->cached = BTRFS_CACHE_FINISHED; cache->last_byte_to_unpin = (u64)-1; } else { - cache->cached = BTRFS_CACHE_NO; + if (load_cache_only) { + cache->caching_ctl = NULL; + cache->cached = BTRFS_CACHE_NO; + } else { + cache->cached = BTRFS_CACHE_STARTED; + } } spin_unlock(&cache->lock); + wake_up(&caching_ctl->wait); if (ret == 1) { + put_caching_control(caching_ctl); free_excluded_extents(fs_info->extent_root, cache); return 0; } + } else { + /* + * We are not going to do the fast caching, set cached to the + * appropriate value and wakeup any waiters. + */ + spin_lock(&cache->lock); + if (load_cache_only) { + cache->caching_ctl = NULL; + cache->cached = BTRFS_CACHE_NO; + } else { + cache->cached = BTRFS_CACHE_STARTED; + } + spin_unlock(&cache->lock); + wake_up(&caching_ctl->wait); } - if (load_cache_only) - return 0; - - caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); - BUG_ON(!caching_ctl); - - INIT_LIST_HEAD(&caching_ctl->list); - mutex_init(&caching_ctl->mutex); - init_waitqueue_head(&caching_ctl->wait); - caching_ctl->block_group = cache; - caching_ctl->progress = cache->key.objectid; - /* one for caching kthread, one for caching block group list */ - atomic_set(&caching_ctl->count, 2); - caching_ctl->work.func = caching_thread; - - spin_lock(&cache->lock); - if (cache->cached != BTRFS_CACHE_NO) { - spin_unlock(&cache->lock); - kfree(caching_ctl); + if (load_cache_only) { + put_caching_control(caching_ctl); return 0; } - cache->caching_ctl = caching_ctl; - cache->cached = BTRFS_CACHE_STARTED; - spin_unlock(&cache->lock); down_write(&fs_info->extent_commit_sem); + atomic_inc(&caching_ctl->count); list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); up_write(&fs_info->extent_commit_sem); @@ -5177,13 +5218,15 @@ search: } have_block_group: - if (unlikely(block_group->cached == BTRFS_CACHE_NO)) { + cached = block_group_cache_done(block_group); + if (unlikely(!cached)) { u64 free_percent; + found_uncached_bg = true; ret = cache_block_group(block_group, trans, orig_root, 1); if (block_group->cached == BTRFS_CACHE_FINISHED) - goto have_block_group; + goto alloc; free_percent = btrfs_block_group_used(&block_group->item); free_percent *= 100; @@ -5205,7 +5248,6 @@ have_block_group: orig_root, 0); BUG_ON(ret); } - found_uncached_bg = true; /* * If loop is set for cached only, try the next block @@ -5215,10 +5257,7 @@ have_block_group: goto loop; } - cached = block_group_cache_done(block_group); - if (unlikely(!cached)) - found_uncached_bg = true; - +alloc: if (unlikely(block_group->ro)) goto loop; -- cgit From f7d61dcd6873c49bcc42be2caa2af1c2511aa915 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 15 Nov 2011 09:31:24 -0500 Subject: Btrfs: clear pages dirty for io and set them extent mapped When doing the io_ctl helpers to clean up the free space cache stuff I stopped using our normal prepare_pages stuff, which means I of course forgot to do things like set the pages extent mapped, which will cause us all sorts of wonderful propblems. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 8c32434da2cb..aedacdbf77e2 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -351,6 +351,11 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode, } } + for (i = 0; i < io_ctl->num_pages; i++) { + clear_page_dirty_for_io(io_ctl->pages[i]); + set_page_extent_mapped(io_ctl->pages[i]); + } + return 0; } -- cgit From 4d479cf010d56ec9c54f3099992d039918f1296b Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 17 Nov 2011 11:34:31 -0500 Subject: Btrfs: sectorsize align offsets in fiemap We've been hitting BUG()'s in btrfs_cont_expand and btrfs_fallocate and anywhere else that calls btrfs_get_extent while running xfstests 13 in a loop. This is because fiemap is calling btrfs_get_extent with non-sectorsize aligned offsets, which will end up adding mappings that are not sectorsize aligned, which will cause problems in some cases for subsequent calls to btrfs_get_extent for similar areas that are sectorsize aligned. With this patch I ran xfstests 13 in a loop for a couple of hours and didn't hit the problem that I could previously hit in at most 20 minutes. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent_io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index a877b8b212eb..9472d3de5e52 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3366,6 +3366,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, return -ENOMEM; path->leave_spinning = 1; + start = ALIGN(start, BTRFS_I(inode)->root->sectorsize); + len = ALIGN(len, BTRFS_I(inode)->root->sectorsize); + /* * lookup the last file extent. We're not using i_size here * because there might be preallocation past i_size @@ -3413,7 +3416,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0, &cached_state, GFP_NOFS); - em = get_extent_skip_holes(inode, off, last_for_get_extent, + em = get_extent_skip_holes(inode, start, last_for_get_extent, get_extent); if (!em) goto out; -- cgit From 0aed4a95ce3b39acfceb38ab7f93c7906b4a27f8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:10:27 +0100 Subject: ASoC: adau1373: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/adau1373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1ccf8dd47576..45c63028b40d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -245,7 +245,7 @@ static const char *adau1373_bass_hpf_cutoff_text[] = { }; static const unsigned int adau1373_bass_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(3), 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), -- cgit From a19ea0b8ec1f6892bf18f461d5023c9299e1417b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:11:54 +0100 Subject: ASoC: rt5631: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent the last entry from being omitted. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/rt5631.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 27a078cbb6eb..4646e808b90a 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -177,7 +177,7 @@ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ static unsigned int mic_bst_tlv[] = { - TLV_DB_RANGE_HEAD(6), + TLV_DB_RANGE_HEAD(7), 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), -- cgit From 740fb9d512d91b1d6192ea13c109efa05b101424 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:12:26 +0100 Subject: ASoC: sgtl5000: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d15695d1c273..bbcf921166f7 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -365,7 +365,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); /* tlv for mic gain, 0db 20db 30db 40db */ static const unsigned int mic_gain_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), }; -- cgit From 43e9dc7bce9f21355cd2aa493a99281eae03b156 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:13:27 +0100 Subject: ASoC: wm8962: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the arrays. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 91d3c6dbeba3..53edd9a8c758 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1973,7 +1973,7 @@ static int wm8962_reset(struct snd_soc_codec *codec) static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); static const unsigned int mixinpga_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(5), 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), @@ -1988,7 +1988,7 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); static const unsigned int classd_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From dac678f5c281fac55aadfa5f390c12a8d14bbc67 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:14:11 +0100 Subject: ASoC: wm8993: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm8993.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index eec8e1435116..d1a142f48b09 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -512,7 +512,7 @@ static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); static const unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), }; -- cgit From a1320fee27352b608a82020a47a59bb15e6e5db8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:14:55 +0100 Subject: ASoC: wm9090: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the arrays. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm9090.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2b5252c9e377..f94c06057c64 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -177,19 +177,19 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) } static const unsigned int in_tlv[] = { - TLV_DB_RANGE_HEAD(6), + TLV_DB_RANGE_HEAD(3), 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), 1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0), 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0), }; static const unsigned int mix_tlv[] = { - TLV_DB_RANGE_HEAD(4), + TLV_DB_RANGE_HEAD(2), 0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0), 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), }; static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From 028aa634e180107ac93b790c0fed7376c0402d1a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 20 Nov 2011 15:15:31 +0100 Subject: ASoC: wm_hubs: fix DB_RANGE size Give the correct number of entries to TLV_DB_RANGE_HEAD to prevent reading more data than actually is in the array. Signed-off-by: Clemens Ladisch --- sound/soc/codecs/wm_hubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 84f33d4ea2cd..48e61e912400 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -40,7 +40,7 @@ static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), + TLV_DB_RANGE_HEAD(2), 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), }; -- cgit From ef0cd47093a6c4b8a1f17d7be02a966f7805ff41 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 19 Nov 2011 14:41:07 +0800 Subject: ASoC: cs4271: Fix wrong mask parameter in some snd_soc_update_bits calls Signed-off-by: Axel Lin Acked-by: Alexander Sverdlin Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 23d1bd5dadda..69fde1506fe1 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -434,7 +434,8 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) { int ret; /* Set power-down bit */ - ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN); + ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, + CS4271_MODE2_PDN); if (ret < 0) return ret; return 0; @@ -501,8 +502,9 @@ static int cs4271_probe(struct snd_soc_codec *codec) return ret; } - ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, - CS4271_MODE2_PDN | CS4271_MODE2_CPEN); + ret = snd_soc_update_bits(codec, CS4271_MODE2, + CS4271_MODE2_PDN | CS4271_MODE2_CPEN, + CS4271_MODE2_PDN | CS4271_MODE2_CPEN); if (ret < 0) return ret; ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); -- cgit From dd179946db2493646955efc112d73c85b3cafcb1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 16 Aug 2011 15:31:30 +0100 Subject: VFS: Log the fact that we've given ELOOP rather than creating a loop To prevent an NFS server from being used to create a directory loop in an NFS superblock on the client, the following patch was committed: commit 1836750115f20b774e55c032a3893e8c5bdf41ed Author: Al Viro Date: Tue Jul 12 21:42:24 2011 -0400 Subject: fix loop checks in d_materialise_unique() This causes ELOOP to be reported to anyone trying to access the dentry that would otherwise cause the kernel to complete the loop. However, no indication is given to the caller as to why an operation that ought to work doesn't. The fault is with the kernel, which doesn't want to try and solve the problem as it gets horrendously messy if there's another mountpoint somewhere in the trees being spliced that can't be moved[*]. [*] The real problem is that we don't handle the excision of a subtree that gets moved _out_ of what we can see. This can happen on the server where a directory is merely moved between two other dirs on the same filesystem, but where destination dir is not accessible by the client. So, given the choice to return ELOOP rather than trying to reconfigure the dentry tree, we should give the caller some indication of why they aren't being allowed to make what should be a legitimate request and log a message. Signed-off-by: David Howells Acked-by: Sachin Prabhu Signed-off-by: Al Viro --- fs/dcache.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/dcache.c b/fs/dcache.c index a901c6901bce..10ba92def3f6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "internal.h" /* @@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) actual = __d_unalias(inode, dentry, alias); } write_sequnlock(&rename_lock); - if (IS_ERR(actual)) + if (IS_ERR(actual)) { + if (PTR_ERR(actual) == -ELOOP) + pr_warn_ratelimited( + "VFS: Lookup of '%s' in %s %s" + " would have caused loop\n", + dentry->d_name.name, + inode->i_sb->s_type->name, + inode->i_sb->s_id); dput(alias); + } goto out_nolock; } } -- cgit From 274252862f386b7868f35bf5ceaa5391a8ccfdf3 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 16 Nov 2011 18:28:01 +0100 Subject: crypto: mv_cesa - fix hashing of chunks > 1920 bytes This was broken by commit 7759995c75ae0cbd4c861582908449f6b6208e7a (yes, myself). The basic problem here is since the digest state is only saved after the last chunk, the state array is only valid when handling the first chunk of the next buffer. Broken since linux-3.0. Signed-off-by: Phil Sutter Cc: # 3.1.x Signed-off-by: Herbert Xu --- drivers/crypto/mv_cesa.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 3cf303ee3fe3..38a3297ae2be 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -342,11 +342,13 @@ static void mv_process_hash_current(int first_block) else op.config |= CFG_MID_FRAG; - writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A); - writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B); - writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C); - writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D); - writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E); + if (first_block) { + writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A); + writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B); + writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C); + writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D); + writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E); + } } memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config)); -- cgit From 91ec37cc1015220965e39bf342fb846810d19e79 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 17 Nov 2011 20:31:02 +0100 Subject: Fix comparison using wrong pointer variable in dma debug code cppcheck reported: [lib/dma-debug.c:248] -> [lib/dma-debug.c:248]: (style) Same expression on both sides of '=='. Signed-off-by: Thomas Jarosch Signed-off-by: Joerg Roedel --- lib/dma-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 74c6c7fce749..fea790a2b176 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -245,7 +245,7 @@ static void put_hash_bucket(struct hash_bucket *bucket, static bool exact_match(struct dma_debug_entry *a, struct dma_debug_entry *b) { - return ((a->dev_addr == a->dev_addr) && + return ((a->dev_addr == b->dev_addr) && (a->dev == b->dev)) ? true : false; } -- cgit From 27533df80e93dc164e39d47281bbbd608f9014a6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 20 Nov 2011 23:57:49 +0300 Subject: ALSA: cs5535 - Fix an endianness conversion desc->size is supposed to be a le16 type. On a big endian system the current code will set ->size to zero. We fixed a similar bug on the next line but missed this one. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/cs5535audio/cs5535audio_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index e083122ca55a..dbf94b189e75 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -148,7 +148,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, struct cs5535audio_dma_desc *desc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i]; desc->addr = cpu_to_le32(addr); - desc->size = cpu_to_le32(period_bytes); + desc->size = cpu_to_le16(period_bytes); desc->ctlreserved = cpu_to_le16(PRD_EOP); desc_addr += sizeof(struct cs5535audio_dma_desc); addr += period_bytes; -- cgit From 11ed0ba1754841316d4095478944300acf19acc3 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 14 Nov 2011 17:24:58 +0100 Subject: ARM: 7161/1: errata: no automatic store buffer drain This patch implements a workaround for PL310 erratum 769419. On revisions of the PL310 prior to r3p2, the Store Buffer does not automatically drain. This can cause normal, non-cacheable writes to be retained when the memory system is idle, leading to suboptimal I/O performance for drivers using coherent DMA. This patch adds an optional wmb() call to the cpu_idle loop. On systems with an outer cache, this causes an explicit flush of the store buffer. Cc: stable@vger.kernel.org Acked-by: Catalin Marinas Tested-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 12 ++++++++++++ arch/arm/kernel/process.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 44789eff983f..83aa746e71d6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1352,6 +1352,18 @@ config ARM_ERRATA_764369 relevant cache maintenance functions and sets a specific bit in the diagnostic control register of the SCU. +config PL310_ERRATA_769419 + bool "PL310 errata: no automatic Store Buffer drain" + depends on CACHE_L2X0 + help + On revisions of the PL310 prior to r3p2, the Store Buffer does + not automatically drain. This can cause normal, non-cacheable + writes to be retained when the memory system is idle, leading + to suboptimal I/O performance for drivers using coherent DMA. + This option adds a write barrier to the cpu_idle loop so that, + on systems with an outer cache, the store buffer is drained + explicitly. + endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 75316f0dd02a..3d0c6fb74ae4 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -192,6 +192,9 @@ void cpu_idle(void) #endif local_irq_disable(); +#ifdef CONFIG_PL310_ERRATA_769419 + wmb(); +#endif if (hlt_counter) { local_irq_enable(); cpu_relax(); -- cgit From fa0ce4035d4897b0642132866d896a906429f45e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 14 Nov 2011 17:24:57 +0100 Subject: ARM: 7162/1: errata: tidy up Kconfig options for PL310 errata workarounds The Kconfig options for the PL310 errata workarounds do not use a consistent naming scheme for either the config option or the bool description. This patch tidies up the options by ensuring that the bool descriptions are prefixed with "PL310 errata:" and the config options are prefixed with PL310_ERRATA_, making it much clearer in menuconfig as to what the workarounds are for. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 8 ++++---- arch/arm/mm/cache-l2x0.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 83aa746e71d6..e084b7e981e8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1231,7 +1231,7 @@ config ARM_ERRATA_742231 capabilities of the processor. config PL310_ERRATA_588369 - bool "Clean & Invalidate maintenance operations do not invalidate clean lines" + bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" depends on CACHE_L2X0 help The PL310 L2 cache controller implements three types of Clean & @@ -1256,7 +1256,7 @@ config ARM_ERRATA_720789 entries regardless of the ASID. config PL310_ERRATA_727915 - bool "Background Clean & Invalidate by Way operation can cause data corruption" + bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" depends on CACHE_L2X0 help PL310 implements the Clean & Invalidate by Way L2 cache maintenance @@ -1289,8 +1289,8 @@ config ARM_ERRATA_751472 operation is received by a CPU before the ICIALLUIS has completed, potentially leading to corrupted entries in the cache or TLB. -config ARM_ERRATA_753970 - bool "ARM errata: cache sync operation may be faulty" +config PL310_ERRATA_753970 + bool "PL310 errata: cache sync operation may be faulty" depends on CACHE_PL310 help This option enables the workaround for the 753970 PL310 (r3p0) erratum. diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 8ac9e9f84790..b1e192ba8c24 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -61,7 +61,7 @@ static inline void cache_sync(void) { void __iomem *base = l2x0_base; -#ifdef CONFIG_ARM_ERRATA_753970 +#ifdef CONFIG_PL310_ERRATA_753970 /* write to an unmmapped register */ writel_relaxed(0, base + L2X0_DUMMY_REG); #else -- cgit From 2674dd0b1c07d8b8dfb4872fc7b41841f05cb957 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Wed, 16 Nov 2011 12:21:24 +0100 Subject: ARM: 7163/2: PL330: Only register usable channels When the manager is running non-secure, the only channels that can issue interrupts are the ones that have a 1 in their corresponding bit in Configuration Register 3. The other ones will generate an abort when trying to signal the end of the transaction so they are useless in non-secure mode. Reference: <1320244259-10496-2-git-send-email-javi.merino@arm.com> Signed-off-by: Javi Merino Acked-by: Jassi Brar Signed-off-by: Russell King --- arch/arm/common/pl330.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index 7129cfbdacd6..f748a385693f 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -1623,6 +1623,11 @@ static inline int _alloc_event(struct pl330_thread *thrd) return -1; } +static bool _chan_ns(const struct pl330_info *pi, int i) +{ + return pi->pcfg.irq_ns & (1 << i); +} + /* Upon success, returns IdentityToken for the * allocated channel, NULL otherwise. */ @@ -1647,7 +1652,8 @@ void *pl330_request_channel(const struct pl330_info *pi) for (i = 0; i < chans; i++) { thrd = &pl330->channels[i]; - if (thrd->free) { + if ((thrd->free) && (!_manager_ns(thrd) || + _chan_ns(pi, i))) { thrd->ev = _alloc_event(thrd); if (thrd->ev >= 0) { thrd->free = false; -- cgit From 1c8a7c1fbfc7ae2362d26559df26b99c806b68b5 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Wed, 16 Nov 2011 12:45:39 +0100 Subject: ARM: 7165/2: PL330: Fix typo in _prepare_ccr() scctl should be shifted by CC_SRCCTRL_SHFT and dcctl by CC_DSTCCTRL_SHFT, not the other way round. Reference: <1320244259-10496-4-git-send-email-javi.merino@arm.com> Signed-off-by: Javi Merino Acked-by: Jassi Brar Signed-off-by: Russell King --- arch/arm/common/pl330.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c index f748a385693f..f407a6b35d3d 100644 --- a/arch/arm/common/pl330.c +++ b/arch/arm/common/pl330.c @@ -1211,8 +1211,8 @@ static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc) ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT); ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT); - ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT); - ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT); + ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT); + ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT); ccr |= (rqc->swap << CC_SWAP_SHFT); -- cgit From 53cbcbcf4362ef39e0a692b1d23c395999397fca Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 17 Nov 2011 13:11:21 +0100 Subject: ARM: 7166/1: Use PMD_SHIFT instead of PGDIR_SHIFT in dma-consistent.c Commit 99d1717d (ARM: Add init_consistent_dma_size()) introduces dynamic allocation of the consistent_pte array. The number of PTEs should be calculated based on the number of PMD entries rather than PGD, hence the PMD_SHIFT. Signed-off-by: Catalin Marinas Cc: Jon Medhurst Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index e4e7f6cba1ab..ab584569930e 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -168,7 +168,7 @@ static int __init consistent_init(void) pte_t *pte; int i = 0; unsigned long base = consistent_base; - unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT; + unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT; consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); if (!consistent_pte) { -- cgit From 2ac654f740b574c58ee02bac3816cf466a1bfb41 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 16 Nov 2011 20:40:42 -0800 Subject: Bluetooth: btmrvl: support Marvell Bluetooth device SD8797 The SD8797 firmware image is shared with mwifiex driver. Whoever gets loaded first will be responsible for firmware downloading. Signed-off-by: Bing Zhao Signed-off-by: Frank Huang Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/Kconfig | 6 +++--- drivers/bluetooth/btmrvl_sdio.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 11b41fd40c27..5ccf142ef0b8 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688/8787. + Marvell Bluetooth devices, such as 8688/8787/8797. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -201,8 +201,8 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently SD8688/SD8787 chipsets are - supported. + devices with SDIO interface. Currently SD8688/SD8787/SD8797 + chipsets are supported. Say Y here to compile support for Marvell BT-over-SDIO driver into the kernel or say M to compile it as module. diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index c827d737ccee..37b56398c8a6 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -64,7 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { .io_port_1 = 0x01, .io_port_2 = 0x02, }; -static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { +static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { .cfg = 0x00, .host_int_mask = 0x02, .host_intstatus = 0x03, @@ -91,7 +91,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .reg = &btmrvl_reg_8787, + .reg = &btmrvl_reg_87xx, + .sd_blksz_fw_dl = 256, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { + .helper = NULL, + .firmware = "mrvl/sd8797_uapsta.bin", + .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -102,6 +109,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8787 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, + /* Marvell SD8797 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), + .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, { } /* Terminating entry */ }; @@ -1075,3 +1085,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); -- cgit From 48b28b8db9a74cc5c43e76485dc397e22bea2984 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sat, 19 Nov 2011 13:23:32 +0100 Subject: Bluetooth: cmtp: Fix module reference We cannot call module_put(THIS_MODULE) if this is our last reference. Otherwise, this call may cleanup our module before it returns. Gladly, the kthread API provides a simple wrapper for us. So lets use module_put_and_exit() to avoid a race condition with the module cleanup code. Signed-off-by: David Herrmann Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 7d00ddf9e9dc..5a6e634f7fca 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -67,14 +67,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr) static void __cmtp_link_session(struct cmtp_session *session) { - __module_get(THIS_MODULE); list_add(&session->list, &cmtp_session_list); } static void __cmtp_unlink_session(struct cmtp_session *session) { list_del(&session->list); - module_put(THIS_MODULE); } static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) @@ -327,6 +325,7 @@ static int cmtp_session(void *arg) up_write(&cmtp_session_sem); kfree(session); + module_put_and_exit(0); return 0; } @@ -376,9 +375,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) __cmtp_link_session(session); + __module_get(THIS_MODULE); session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", session->num); if (IS_ERR(session->task)) { + module_put(THIS_MODULE); err = PTR_ERR(session->task); goto unlink; } -- cgit From 9b338c3dd12918f7f7df2b882f63f71e9efbcb41 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sat, 19 Nov 2011 13:23:33 +0100 Subject: Bluetooth: bnep: Fix module reference We cannot call module_put(THIS_MODULE) if this is our last reference. Otherwise, this call may cleanup our module before it returns. Gladly, the kthread API provides a simple wrapper for us. So lets use module_put_and_exit() to avoid a race condition with the module cleanup code. Signed-off-by: David Herrmann Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/bnep/core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 91bcd3a961ec..1eea8208b2cc 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -79,17 +79,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst) static void __bnep_link_session(struct bnep_session *s) { - /* It's safe to call __module_get() here because sessions are added - by the socket layer which has to hold the reference to this module. - */ - __module_get(THIS_MODULE); list_add(&s->list, &bnep_session_list); } static void __bnep_unlink_session(struct bnep_session *s) { list_del(&s->list); - module_put(THIS_MODULE); } static int bnep_send(struct bnep_session *s, void *data, size_t len) @@ -530,6 +525,7 @@ static int bnep_session(void *arg) up_write(&bnep_session_sem); free_netdev(dev); + module_put_and_exit(0); return 0; } @@ -616,9 +612,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) __bnep_link_session(s); + __module_get(THIS_MODULE); s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); if (IS_ERR(s->task)) { /* Session thread start failed, gotta cleanup. */ + module_put(THIS_MODULE); unregister_netdev(dev); __bnep_unlink_session(s); err = PTR_ERR(s->task); -- cgit From ed3e80c4c991a52f9fce3421536a78e331ae0949 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 11:55:41 +0000 Subject: ASoC: Ensure WM8731 register cache is synced when resuming from disabled Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8731.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 7e5ec03f6f8d..a7c9ae17fc7e 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -453,6 +453,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8731_PWR, 0xffff); regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); + codec->cache_sync = 1; break; } codec->dapm.bias_level = level; -- cgit From 6e58ad69efe9f4c91eb15f6bc365293414c397ce Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Mon, 21 Nov 2011 12:09:19 -0500 Subject: ext4: fix up a undefined error in ext4_free_blocks in debugging code sbi is not defined, so let ext4_free_blocks use EXT4_SB(sb) instead when EXT4FS_DEBUG is defined. Signed-off-by: Yongqiang Yang --- fs/ext4/balloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index f6dba4505f1c..12ccacda44e0 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -565,7 +565,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) brelse(bitmap_bh); printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu" ", computed = %llu, %llu\n", - EXT4_B2C(sbi, ext4_free_blocks_count(es)), + EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)), desc_count, bitmap_count); return bitmap_count; #else -- cgit From 648ae8e53d58ed1b667db173a2d4ff2132a3b529 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 9 Nov 2011 19:37:35 +0100 Subject: netfilter: ipset: suppress compile-time warnings in ip_set_hash_ipport*.c warning: 'ip_to' may be used uninitialized in this function Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_hash_ipport.c | 2 +- net/netfilter/ipset/ip_set_hash_ipportip.c | 2 +- net/netfilter/ipset/ip_set_hash_ipportnet.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 6ee10f5d59bd..37d667e3f6f8 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c @@ -158,7 +158,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; - u32 ip, ip_to, p = 0, port, port_to; + u32 ip, ip_to = 0, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index fb90e344e907..e69e2718fbe1 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -162,7 +162,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; - u32 ip, ip_to, p = 0, port, port_to; + u32 ip, ip_to = 0, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index deb3e3dfa5fc..64199b4e93c9 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -184,7 +184,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; - u32 ip, ip_to, p = 0, port, port_to; + u32 ip, ip_to = 0, p = 0, port, port_to; u32 ip2_from = 0, ip2_to, ip2_last, ip2; u32 timeout = h->timeout; bool with_ports = false; -- cgit From 5e2afba4ecd7931ea06e6fa116ab28e6943dbd42 Mon Sep 17 00:00:00 2001 From: Paul Guo Date: Mon, 14 Nov 2011 19:00:54 +0800 Subject: netfilter: possible unaligned packet header in ip_route_me_harder This patch tries to fix the following issue in netfilter: In ip_route_me_harder(), we invoke pskb_expand_head() that rellocates new header with additional head room which can break the alignment of the original packet header. In one of my NAT test case, the NIC port for internal hosts is configured with vlan and the port for external hosts is with general configuration. If we ping an external "unknown" hosts from an internal host, an icmp packet will be sent. We find that in icmp_send()->...->ip_route_me_harder()->pskb_expand_head(), hh_len=18 and current headroom (skb_headroom(skb)) of the packet is 16. After calling pskb_expand_head() the packet header becomes to be unaligned and then our system (arch/tile) panics immediately. Signed-off-by: Paul Guo Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 9899619ab9b8..4f47e064e262 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -64,7 +64,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) /* Change in oif may mean change in hh_len. */ hh_len = skb_dst(skb)->dev->hard_header_len; if (skb_headroom(skb) < hh_len && - pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) + pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)), + 0, GFP_ATOMIC)) return -1; return 0; -- cgit From 904603f9b78f94d5a5fe29cf2f9694ef7f6f4420 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 17 Nov 2011 14:53:36 -0800 Subject: mac80211: Fix AMSDU rate printout in debugfs. It was flipped. See section 7.3.2.56 of the 802.11n spec for details. Signed-off-by: Ben Greear Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c5f341798c16..3110cbdc501b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -274,9 +274,9 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); - PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " - "3839 bytes"); PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " + "3839 bytes"); + PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " "7935 bytes"); /* -- cgit From 9c8f2c42c93f415771d6d7b87a0881ba0bb72824 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Fri, 18 Nov 2011 17:02:16 +0100 Subject: mac80211: Fix endian bug in radiotap header generation I intoduced this bug in commit a2fe81667410723d941a688e1958a49d67ca3346 "mac80211: Build TX radiotap header dynamically" Signed-off-by: Helmut Schaa Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/status.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index df643cedf9b9..5533a74e9bb3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -259,7 +259,7 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_radiotap_header *rthdr; unsigned char *pos; - __le16 txflags; + u16 txflags; rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); @@ -289,13 +289,13 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band txflags = 0; if (!(info->flags & IEEE80211_TX_STAT_ACK) && !is_multicast_ether_addr(hdr->addr1)) - txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); + txflags |= IEEE80211_RADIOTAP_F_TX_FAIL; if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) - txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); + txflags |= IEEE80211_RADIOTAP_F_TX_CTS; else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); + txflags |= IEEE80211_RADIOTAP_F_TX_RTS; put_unaligned_le16(txflags, pos); pos += 2; -- cgit From de3584bd62d87b4c250129fbc46ca52c80330add Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 21 Nov 2011 10:44:00 +0100 Subject: cfg80211: fix regulatory NULL dereference By the time userspace returns with a response to the regulatory domain request, the wiphy causing the request might have gone away. If this is so, reject the update but mark the request as having been processed anyway. Cc: Luis R. Rodriguez Signed-off-by: Johannes Berg Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index bc1ec2c26fd0..186b7f2a27b6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2035,6 +2035,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); + if (!request_wiphy) { + reg_set_request_processed(); + return -ENODEV; + } if (!last_request->intersect) { int r; -- cgit From 40f9cd299a0e5e8dcdde9b5eb9bfda1cb9109f61 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 21 Nov 2011 17:47:13 +0300 Subject: prism54: potential memory corruption in prism54_get_essid() "dwrq->length" is the capped version of "essid->length". Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index d97a2caf582b..bc2ba80c47bb 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -778,7 +778,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, dwrq->flags = 0; dwrq->length = 0; } - essid->octets[essid->length] = '\0'; + essid->octets[dwrq->length] = '\0'; memcpy(extra, essid->octets, dwrq->length); kfree(essid); -- cgit From 404ba2b8f611bea3228daf031f03901d0c34ecd7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 17:57:25 +0000 Subject: gpio: pca953x: Staticise pca953x_get_altdata() It's not used outside of the driver so doesn't need to be exported, and sparse notices this and complains about it. Signed-off-by: Mark Brown --- drivers/gpio/gpio-pca953x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 147df8ae79db..d3f3e8f54561 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -546,7 +546,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) * Translate OpenFirmware node properties into platform_data * WARNING: This is DEPRECATED and will be removed eventually! */ -void +static void pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) { struct device_node *node; @@ -574,7 +574,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) *invert = *val; } #else -void +static void pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) { *gpio_base = -1; -- cgit From ba9bb431d3156a1c5d4d6f0b8c23b5792e9e9f4f Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 17 Nov 2011 10:33:52 +0000 Subject: iseries_veth: Fix wrong parameter given to sizeof call "remote_list" is of type struct dma_chunk remote_list[VETH_MAX_FRAMES_PER_MSG]; Probably a copy'n'paste error. Signed-off-by: Thomas Jarosch Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/iseries_veth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ibm/iseries_veth.c b/drivers/net/ethernet/ibm/iseries_veth.c index 4326681df382..acc31af6594a 100644 --- a/drivers/net/ethernet/ibm/iseries_veth.c +++ b/drivers/net/ethernet/ibm/iseries_veth.c @@ -1421,7 +1421,7 @@ static void veth_receive(struct veth_lpar_connection *cnx, /* FIXME: do we need this? */ memset(local_list, 0, sizeof(local_list)); - memset(remote_list, 0, sizeof(VETH_MAX_FRAMES_PER_MSG)); + memset(remote_list, 0, sizeof(remote_list)); /* a 0 address marks the end of the valid entries */ if (senddata->addr[startchunk] == 0) -- cgit From 24a70313969fc3fc440216b40babdb42564acff3 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 21 Nov 2011 09:39:11 -0500 Subject: Btrfs: remove free-space-cache.c WARN during log replay The log replay code only partially loads block groups, since the block group caching code is able to detect and deal with extents the logging code has pinned down. While the logging code is pinning down block groups, there is a bogus WARN_ON we're hitting if the code wasn't able to find an extent in the cache. This commit removes the warning because it can happen any time there isn't a valid free space cache for that block group. Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index aedacdbf77e2..6e5b7e463698 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1849,7 +1849,13 @@ again: info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!info) { - WARN_ON(1); + /* the tree logging code might be calling us before we + * have fully loaded the free space rbtree for this + * block group. So it is possible the entry won't + * be in the rbtree yet at all. The caching code + * will make sure not to put it in the rbtree if + * the logging code has pinned it. + */ goto out_lock; } } -- cgit From cc11f9edd919002d8b3a03601a181a449150defd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 Nov 2011 03:52:18 +0000 Subject: fix braino in um patchset (mea culpa) wrong register returned... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- arch/x86/um/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h index 118c143a9cb4..2c32df6fe231 100644 --- a/arch/x86/um/asm/processor.h +++ b/arch/x86/um/asm/processor.h @@ -11,7 +11,7 @@ #endif #define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP) -#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP) +#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP) #define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP) #define ARCH_IS_STACKGROW(address) \ -- cgit From 4f795b25eaf1109c77abfc3b57cef9b993f3aede Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Fri, 18 Nov 2011 05:00:20 +0000 Subject: stmmac: mask mmc interrupts We need to mask the MMC irq otherwise if we raise the mmc interrupts that are not handled the driver loops in the handler. In fact, by default all mmc counters (only used for stats) are managed in SW and registers are cleared on each READ. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 8ea770a89f25..72cd190b9c1a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -781,10 +781,15 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv) unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; - /* Do not manage MMC IRQ (FIXME) */ + /* Mask MMC irq, counters are managed in SW and registers + * are cleared on each READ eventually. */ dwmac_mmc_intr_all_mask(priv->ioaddr); - dwmac_mmc_ctrl(priv->ioaddr, mode); - memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); + + if (priv->dma_cap.rmon) { + dwmac_mmc_ctrl(priv->ioaddr, mode); + memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); + } else + pr_info(" No MAC Management Counters available"); } static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) @@ -1012,8 +1017,7 @@ static int stmmac_open(struct net_device *dev) memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); priv->xstats.threshold = tc; - if (priv->dma_cap.rmon) - stmmac_mmc_setup(priv); + stmmac_mmc_setup(priv); /* Start the ball rolling... */ DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); -- cgit From 5ccb3ea72097ee0c8ea1f200a2ade101caf08aa4 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 18 Nov 2011 05:42:05 +0000 Subject: xen-netback: use correct index for invalidation in xen_netbk_tx_check_gop() Signed-off-by: Jan Beulich Signed-off-by: Ian Campbell Cc: stable@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 0cb594c86090..1ae270eed51a 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1021,7 +1021,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, pending_idx = *((u16 *)skb->data); xen_netbk_idx_release(netbk, pending_idx); for (j = start; j < i; j++) { - pending_idx = frag_get_pending_idx(&shinfo->frags[i]); + pending_idx = frag_get_pending_idx(&shinfo->frags[j]); xen_netbk_idx_release(netbk, pending_idx); } -- cgit From fbe54e3b7a7ad7de92b65e8b10fae300eeec6ef3 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 20 Nov 2011 11:07:09 +0000 Subject: net, sja1000: Don't include version.h in peak_pci.c when not needed It was pointed out by "make versioncheck" that we do not need to include version.h in drivers/net/can/sja1000/peak_pci.c This patch removes the unneeded include. Signed-off-by: Jesper Juhl Acked-by: Marc Kleine-Budde Signed-off-by: David S. Miller --- drivers/net/can/sja1000/peak_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 905bce0b3a43..2c7f5036f570 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -20,7 +20,6 @@ */ #include -#include #include #include #include -- cgit From 525c6465d449cdec04b3c91733e46027a4d08422 Mon Sep 17 00:00:00 2001 From: "RongQing.Li" Date: Mon, 21 Nov 2011 16:45:26 -0500 Subject: dccp: fix error propagation in dccp_v4_connect The errcode is not updated when ip_route_newports() fails. Signed-off-by: RongQing.Li Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 90a919afbed7..3f4e5414c8e5 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -111,6 +111,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, inet->inet_sport, inet->inet_dport, sk); if (IS_ERR(rt)) { + err = PTR_ERR(rt); rt = NULL; goto failure; } -- cgit From f23aa62545c18728eb2b9434aa258be27e07dd49 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 21 Nov 2011 16:46:24 -0500 Subject: caif: fix endian conversion in cffrml_transmit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "tmp" variable here is used to store the result of cpu_to_le16() so it should be an __le16 instead of an int. We want the high bits set and the current code works on little endian systems but not on big endian systems. Signed-off-by: Dan Carpenter Acked-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cffrml.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index f39921171d0d..d3ca87bf23b7 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -136,20 +136,21 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) { - int tmp; u16 chks; u16 len; + __le16 data; + struct cffrml *this = container_obj(layr); if (this->dofcs) { chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); - tmp = cpu_to_le16(chks); - cfpkt_add_trail(pkt, &tmp, 2); + data = cpu_to_le16(chks); + cfpkt_add_trail(pkt, &data, 2); } else { cfpkt_pad_trail(pkt, 2); } len = cfpkt_getlen(pkt); - tmp = cpu_to_le16(len); - cfpkt_add_head(pkt, &tmp, 2); + data = cpu_to_le16(len); + cfpkt_add_head(pkt, &data, 2); cfpkt_info(pkt)->hdr_len += 2; if (cfpkt_erroneous(pkt)) { pr_err("Packet is erroneous!\n"); -- cgit From c332c10c01d8d31f2eba9abc04b0fc3d62610ed8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 Nov 2011 16:48:28 -0500 Subject: microblaze: bury asm/namei.h altroot support has been gone for years, along with arch/*/asm/namei.h; looks like a dummy survivor that sat it out in microblaze tree... Signed-off-by: Al Viro --- arch/microblaze/include/asm/namei.h | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 arch/microblaze/include/asm/namei.h diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h deleted file mode 100644 index 61d60b8a07d5..000000000000 --- a/arch/microblaze/include/asm/namei.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_NAMEI_H -#define _ASM_MICROBLAZE_NAMEI_H - -#ifdef __KERNEL__ - -/* This dummy routine maybe changed to something useful - * for /usr/gnemul/ emulation stuff. - * Look at asm-sparc/namei.h for details. - */ -#define __emul_prefix() NULL - -#endif /* __KERNEL__ */ - -#endif /* _ASM_MICROBLAZE_NAMEI_H */ -- cgit From b46413367961c2e8bd827e067a231be982aaeee2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 Nov 2011 17:25:37 -0500 Subject: iio: fix a leak due to improper use of anon_inode_getfd() it can fail and in that case ->release() will *not* be called... Signed-off-by: Al Viro --- drivers/staging/iio/industrialio-core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 326e967d54ef..26564094e33b 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -242,6 +242,8 @@ static const struct file_operations iio_event_chrdev_fileops = { static int iio_event_getfd(struct iio_dev *indio_dev) { + int fd; + if (indio_dev->event_interface == NULL) return -ENODEV; @@ -252,9 +254,15 @@ static int iio_event_getfd(struct iio_dev *indio_dev) return -EBUSY; } mutex_unlock(&indio_dev->event_interface->event_list_lock); - return anon_inode_getfd("iio:event", + fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops, indio_dev->event_interface, O_RDONLY); + if (fd < 0) { + mutex_lock(&indio_dev->event_interface->event_list_lock); + clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + mutex_unlock(&indio_dev->event_interface->event_list_lock); + } + return fd; } static int __init iio_init(void) -- cgit From 70e9942f17a6193e9172a804e6569a8806633d6b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 22 Nov 2011 00:16:51 +0100 Subject: netfilter: nf_conntrack: make event callback registration per-netns This patch fixes an oops that can be triggered following this recipe: 0) make sure nf_conntrack_netlink and nf_conntrack_ipv4 are loaded. 1) container is started. 2) connect to it via lxc-console. 3) generate some traffic with the container to create some conntrack entries in its table. 4) stop the container: you hit one oops because the conntrack table cleanup tries to report the destroy event to user-space but the per-netns nfnetlink socket has already gone (as the nfnetlink socket is per-netns but event callback registration is global). To fix this situation, we make the ctnl_notifier per-netns so the callback is registered/unregistered if the container is created/destroyed. Alex Bligh and Alexey Dobriyan originally proposed one small patch to check if the nfnetlink socket is gone in nfnetlink_has_listeners, but this is a very visited path for events, thus, it may reduce performance and it looks a bit hackish to check for the nfnetlink socket only to workaround this situation. As a result, I decided to follow the bigger path choice, which seems to look nicer to me. Cc: Alexey Dobriyan Reported-by: Alex Bligh Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_ecache.h | 19 ++++---- include/net/netns/conntrack.h | 2 + net/netfilter/nf_conntrack_ecache.c | 37 +++++++-------- net/netfilter/nf_conntrack_netlink.c | 73 ++++++++++++++++++++--------- 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 4283508b3e18..a88fb6939387 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -67,18 +67,18 @@ struct nf_ct_event_notifier { int (*fcn)(unsigned int events, struct nf_ct_event *item); }; -extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; -extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); -extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); +extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb); +extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb); extern void nf_ct_deliver_cached_events(struct nf_conn *ct); static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) { + struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *e; - if (nf_conntrack_event_cb == NULL) + if (net->ct.nf_conntrack_event_cb == NULL) return; e = nf_ct_ecache_find(ct); @@ -95,11 +95,12 @@ nf_conntrack_eventmask_report(unsigned int eventmask, int report) { int ret = 0; + struct net *net = nf_ct_net(ct); struct nf_ct_event_notifier *notify; struct nf_conntrack_ecache *e; rcu_read_lock(); - notify = rcu_dereference(nf_conntrack_event_cb); + notify = rcu_dereference(net->ct.nf_conntrack_event_cb); if (notify == NULL) goto out_unlock; @@ -164,9 +165,8 @@ struct nf_exp_event_notifier { int (*fcn)(unsigned int events, struct nf_exp_event *item); }; -extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb; -extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb); -extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb); +extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb); +extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb); static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, @@ -174,11 +174,12 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, u32 pid, int report) { + struct net *net = nf_ct_exp_net(exp); struct nf_exp_event_notifier *notify; struct nf_conntrack_ecache *e; rcu_read_lock(); - notify = rcu_dereference(nf_expect_event_cb); + notify = rcu_dereference(net->ct.nf_expect_event_cb); if (notify == NULL) goto out_unlock; diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 0249399e51a7..7a911eca0f18 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -18,6 +18,8 @@ struct netns_ct { struct hlist_nulls_head unconfirmed; struct hlist_nulls_head dying; struct ip_conntrack_stat __percpu *stat; + struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; + struct nf_exp_event_notifier __rcu *nf_expect_event_cb; int sysctl_events; unsigned int sysctl_events_retry_timeout; int sysctl_acct; diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 6b368be937c6..b62c4148b921 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -27,22 +27,17 @@ static DEFINE_MUTEX(nf_ct_ecache_mutex); -struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb __read_mostly; -EXPORT_SYMBOL_GPL(nf_conntrack_event_cb); - -struct nf_exp_event_notifier __rcu *nf_expect_event_cb __read_mostly; -EXPORT_SYMBOL_GPL(nf_expect_event_cb); - /* deliver cached events and clear cache entry - must be called with locally * disabled softirqs */ void nf_ct_deliver_cached_events(struct nf_conn *ct) { + struct net *net = nf_ct_net(ct); unsigned long events; struct nf_ct_event_notifier *notify; struct nf_conntrack_ecache *e; rcu_read_lock(); - notify = rcu_dereference(nf_conntrack_event_cb); + notify = rcu_dereference(net->ct.nf_conntrack_event_cb); if (notify == NULL) goto out_unlock; @@ -83,19 +78,20 @@ out_unlock: } EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); -int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new) +int nf_conntrack_register_notifier(struct net *net, + struct nf_ct_event_notifier *new) { int ret = 0; struct nf_ct_event_notifier *notify; mutex_lock(&nf_ct_ecache_mutex); - notify = rcu_dereference_protected(nf_conntrack_event_cb, + notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, lockdep_is_held(&nf_ct_ecache_mutex)); if (notify != NULL) { ret = -EBUSY; goto out_unlock; } - RCU_INIT_POINTER(nf_conntrack_event_cb, new); + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new); mutex_unlock(&nf_ct_ecache_mutex); return ret; @@ -105,32 +101,34 @@ out_unlock: } EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier); -void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new) +void nf_conntrack_unregister_notifier(struct net *net, + struct nf_ct_event_notifier *new) { struct nf_ct_event_notifier *notify; mutex_lock(&nf_ct_ecache_mutex); - notify = rcu_dereference_protected(nf_conntrack_event_cb, + notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, lockdep_is_held(&nf_ct_ecache_mutex)); BUG_ON(notify != new); - RCU_INIT_POINTER(nf_conntrack_event_cb, NULL); + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); -int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new) +int nf_ct_expect_register_notifier(struct net *net, + struct nf_exp_event_notifier *new) { int ret = 0; struct nf_exp_event_notifier *notify; mutex_lock(&nf_ct_ecache_mutex); - notify = rcu_dereference_protected(nf_expect_event_cb, + notify = rcu_dereference_protected(net->ct.nf_expect_event_cb, lockdep_is_held(&nf_ct_ecache_mutex)); if (notify != NULL) { ret = -EBUSY; goto out_unlock; } - RCU_INIT_POINTER(nf_expect_event_cb, new); + RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new); mutex_unlock(&nf_ct_ecache_mutex); return ret; @@ -140,15 +138,16 @@ out_unlock: } EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier); -void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new) +void nf_ct_expect_unregister_notifier(struct net *net, + struct nf_exp_event_notifier *new) { struct nf_exp_event_notifier *notify; mutex_lock(&nf_ct_ecache_mutex); - notify = rcu_dereference_protected(nf_expect_event_cb, + notify = rcu_dereference_protected(net->ct.nf_expect_event_cb, lockdep_is_held(&nf_ct_ecache_mutex)); BUG_ON(notify != new); - RCU_INIT_POINTER(nf_expect_event_cb, NULL); + RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); } EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e58aa9b1fe8a..ef21b221f036 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -4,7 +4,7 @@ * (C) 2001 by Jay Schulist * (C) 2002-2006 by Harald Welte * (C) 2003 by Patrick Mchardy - * (C) 2005-2008 by Pablo Neira Ayuso + * (C) 2005-2011 by Pablo Neira Ayuso * * Initial connection tracking via netlink development funded and * generally made possible by Network Robots, Inc. (www.networkrobots.com) @@ -2163,6 +2163,54 @@ MODULE_ALIAS("ip_conntrack_netlink"); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); +static int __net_init ctnetlink_net_init(struct net *net) +{ +#ifdef CONFIG_NF_CONNTRACK_EVENTS + int ret; + + ret = nf_conntrack_register_notifier(net, &ctnl_notifier); + if (ret < 0) { + pr_err("ctnetlink_init: cannot register notifier.\n"); + goto err_out; + } + + ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp); + if (ret < 0) { + pr_err("ctnetlink_init: cannot expect register notifier.\n"); + goto err_unreg_notifier; + } +#endif + return 0; + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +err_unreg_notifier: + nf_conntrack_unregister_notifier(net, &ctnl_notifier); +err_out: + return ret; +#endif +} + +static void ctnetlink_net_exit(struct net *net) +{ +#ifdef CONFIG_NF_CONNTRACK_EVENTS + nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp); + nf_conntrack_unregister_notifier(net, &ctnl_notifier); +#endif +} + +static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list) +{ + struct net *net; + + list_for_each_entry(net, net_exit_list, exit_list) + ctnetlink_net_exit(net); +} + +static struct pernet_operations ctnetlink_net_ops = { + .init = ctnetlink_net_init, + .exit_batch = ctnetlink_net_exit_batch, +}; + static int __init ctnetlink_init(void) { int ret; @@ -2180,28 +2228,15 @@ static int __init ctnetlink_init(void) goto err_unreg_subsys; } -#ifdef CONFIG_NF_CONNTRACK_EVENTS - ret = nf_conntrack_register_notifier(&ctnl_notifier); - if (ret < 0) { - pr_err("ctnetlink_init: cannot register notifier.\n"); + if (register_pernet_subsys(&ctnetlink_net_ops)) { + pr_err("ctnetlink_init: cannot register pernet operations\n"); goto err_unreg_exp_subsys; } - ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); - if (ret < 0) { - pr_err("ctnetlink_init: cannot expect register notifier.\n"); - goto err_unreg_notifier; - } -#endif - return 0; -#ifdef CONFIG_NF_CONNTRACK_EVENTS -err_unreg_notifier: - nf_conntrack_unregister_notifier(&ctnl_notifier); err_unreg_exp_subsys: nfnetlink_subsys_unregister(&ctnl_exp_subsys); -#endif err_unreg_subsys: nfnetlink_subsys_unregister(&ctnl_subsys); err_out: @@ -2213,11 +2248,7 @@ static void __exit ctnetlink_exit(void) pr_info("ctnetlink: unregistering from nfnetlink.\n"); nf_ct_remove_userspace_expectations(); -#ifdef CONFIG_NF_CONNTRACK_EVENTS - nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); - nf_conntrack_unregister_notifier(&ctnl_notifier); -#endif - + unregister_pernet_subsys(&ctnetlink_net_ops); nfnetlink_subsys_unregister(&ctnl_exp_subsys); nfnetlink_subsys_unregister(&ctnl_subsys); } -- cgit From 74a0efdef1df7f576116811234ebedd8a1255ebc Mon Sep 17 00:00:00 2001 From: "Manjunathappa, Prakash" Date: Tue, 15 Nov 2011 17:32:23 +0530 Subject: video:da8xx-fb: Disable and reset sequence on version2 of LCDC Patch follows the disable and software reset sequence specified in version2 to LCDC functional specification. Without this flicker is observed on re-enabling the LCDC. Signed-off-by: Manjunathappa, Prakash Signed-off-by: Florian Tobias Schandinat --- drivers/video/da8xx-fb.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 55f91d9ab00b..29577bf1f559 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -116,6 +116,7 @@ /* Clock registers available only on Version 2 */ #define LCD_CLK_ENABLE_REG 0x6c #define LCD_CLK_RESET_REG 0x70 +#define LCD_CLK_MAIN_RESET BIT(3) #define LCD_NUM_BUFFERS 2 @@ -244,6 +245,10 @@ static inline void lcd_enable_raster(void) { u32 reg; + /* Bring LCDC out of reset */ + if (lcd_revision == LCD_VERSION_2) + lcdc_write(0, LCD_CLK_RESET_REG); + reg = lcdc_read(LCD_RASTER_CTRL_REG); if (!(reg & LCD_RASTER_ENABLE)) lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); @@ -257,6 +262,10 @@ static inline void lcd_disable_raster(void) reg = lcdc_read(LCD_RASTER_CTRL_REG); if (reg & LCD_RASTER_ENABLE) lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); + + if (lcd_revision == LCD_VERSION_2) + /* Write 1 to reset LCDC */ + lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); } static void lcd_blit(int load_mode, struct da8xx_fb_par *par) @@ -584,8 +593,12 @@ static void lcd_reset(struct da8xx_fb_par *par) lcdc_write(0, LCD_DMA_CTRL_REG); lcdc_write(0, LCD_RASTER_CTRL_REG); - if (lcd_revision == LCD_VERSION_2) + if (lcd_revision == LCD_VERSION_2) { lcdc_write(0, LCD_INT_ENABLE_SET_REG); + /* Write 1 to reset */ + lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); + lcdc_write(0, LCD_CLK_RESET_REG); + } } static void lcd_calc_clk_divider(struct da8xx_fb_par *par) -- cgit From a32839696a8eef813a1aff604fbad9a32dff6c95 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 21 Nov 2011 15:05:56 +0000 Subject: viafb: correct sync polarity for OLPC DCON While the OLPC display appears to be able to handle either positive or negative sync, the Display Controller only recognises positive sync. This brings viafb (for XO-1.5) in line with lxfb (for XO-1) and fixes a recent regression where the XO-1.5 DCON could no longer be frozen. Thanks to Florian Tobias Schandinat for helping identify the fix. Test case: from a vt, echo 1 > /sys/devices/platform/dcon/freeze should cause the current screen contents to freeze, rather than garbage being displayed. Signed-off-by: Daniel Drake Signed-off-by: Florian Tobias Schandinat Cc: stable@kernel.org --- drivers/video/via/share.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 69d882cbe709..c01c1c162726 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -559,8 +559,8 @@ #define M1200X720_R60_VSP POSITIVE /* 1200x900@60 Sync Polarity (DCON) */ -#define M1200X900_R60_HSP NEGATIVE -#define M1200X900_R60_VSP NEGATIVE +#define M1200X900_R60_HSP POSITIVE +#define M1200X900_R60_VSP POSITIVE /* 1280x600@60 Sync Polarity (GTF Mode) */ #define M1280x600_R60_HSP NEGATIVE -- cgit From 05c7cc9ccab7d9229fdae68d7d6231edd2c93741 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Mon, 21 Nov 2011 16:15:36 +0100 Subject: ALSA: hdspm - Fix PCI ID for PCIe RME MADI cards Commit c09403dcc5698abf214329fbbf3cf8dbb5558bea has introduced a regression: PCIe versions of RME MADI were no longer detected, because the MADIface ID (0xd5) was used instead of the correct 0xd2. This commit fixes the problem. Signed-off-by: Adrian Knoth Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdspm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index e760adad9523..19ee2203cbb5 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6518,7 +6518,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, hdspm->io_type = AES32; hdspm->card_name = "RME AES32"; hdspm->midiPorts = 2; - } else if ((hdspm->firmware_rev == 0xd5) || + } else if ((hdspm->firmware_rev == 0xd2) || ((hdspm->firmware_rev >= 0xc8) && (hdspm->firmware_rev <= 0xcf))) { hdspm->io_type = MADI; -- cgit From e760b5260d39113794da17c64cbd6e6311155b66 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 21 Nov 2011 14:34:05 +0100 Subject: ARM: imx: drop 'ARCH_MX31' and 'ARCH_MX35' Commit 27ad4bf72a ("ARM: imx: move mx3 support to mach-imx") kept ARCH_MX31 and ARCH_MX35 'for compatibility'. Now that they aren't actually used anymore, they can be dropped entirely. Signed-off-by: Paul Bolle Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/Kconfig | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5f7f9c2a34ae..c44aa974e79c 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -10,11 +10,6 @@ config HAVE_IMX_MMDC config HAVE_IMX_SRC bool -# -# ARCH_MX31 and ARCH_MX35 are left for compatibility -# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2. -# To easily distinguish good and reviewed from unreviewed usages new (and IMHO -# more sensible) names are used: SOC_IMX31 and SOC_IMX35 config ARCH_MX1 bool @@ -27,12 +22,6 @@ config ARCH_MX25 config MACH_MX27 bool -config ARCH_MX31 - bool - -config ARCH_MX35 - bool - config SOC_IMX1 bool select ARCH_MX1 @@ -72,7 +61,6 @@ config SOC_IMX31 select CPU_V6 select IMX_HAVE_PLATFORM_MXC_RNGA select ARCH_MXC_AUDMUX_V2 - select ARCH_MX31 select MXC_AVIC select SMP_ON_UP if SMP @@ -82,7 +70,6 @@ config SOC_IMX35 select ARCH_MXC_IOMUX_V3 select ARCH_MXC_AUDMUX_V2 select HAVE_EPIT - select ARCH_MX35 select MXC_AVIC select SMP_ON_UP if SMP -- cgit From adf792928d1c57f31b92b7908a5ba383e9f05373 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 22 Nov 2011 10:04:46 +0100 Subject: MAINTAINERS: Add missing directory arch/arm/mach-imx/ is part of the i.MX support. Add it. Signed-off-by: Sascha Hauer --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 071a99674347..c9ae02a522b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -789,6 +789,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.pengutronix.de/git/imx/linux-2.6.git F: arch/arm/mach-mx*/ +F: arch/arm/mach-imx/ F: arch/arm/plat-mxc/ ARM/FREESCALE IMX51 -- cgit From ca06679d758933b726c2677b523a26bc581eadcf Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 21 Nov 2011 16:26:52 -0200 Subject: ARM: mx5: Fix checkpatch warnings in cpu-imx5.c Fix the following warnings reported by checkpatch: WARNING: Use #include instead of #19: FILE: arm/mach-imx/cpu-imx5.c:19: +#include WARNING: line over 80 characters #70: FILE: arm/mach-imx/cpu-imx5.c:70: + if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) { Signed-off-by: Fabio Estevam Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/cpu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c index 5c5328257dca..5e2e7a843860 100644 --- a/arch/arm/mach-mx5/cpu.c +++ b/arch/arm/mach-mx5/cpu.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include static int mx5_cpu_rev = -1; @@ -67,7 +67,8 @@ static int __init mx51_neon_fixup(void) if (!cpu_is_mx51()) return 0; - if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) { + if (mx51_revision() < IMX_CHIP_REVISION_3_0 && + (elf_hwcap & HWCAP_NEON)) { elf_hwcap &= ~HWCAP_NEON; pr_info("Turning off NEON support, detected broken NEON implementation\n"); } -- cgit From 87514fced7c347a7cdd8a7a346d935a168428ff7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 22 Nov 2011 10:07:26 +0100 Subject: ARM: imx/mm-imx3: conditionally compile i.MX31 and i.MX35 code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes building a kernel for only one of the two SOCs. Without this patch an i.MX31 only build fails with: arch/arm/mach-imx/built-in.o: In function `imx35_init_early': mach-bug.c:(.init.text+0x2c): undefined reference to `mxc_iomux_v3_init' arch/arm/mach-imx/built-in.o: In function `imx35_soc_init': mach-bug.c:(.init.text+0xe4): undefined reference to `mx35_revision' Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/mm-imx3.c | 58 ++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 9f0e82ec3398..72613c4b0e72 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -108,6 +108,7 @@ void imx3_init_l2x0(void) l2x0_init(l2x0_base, 0x00030024, 0x00000000); } +#ifdef CONFIG_SOC_IMX31 static struct map_desc mx31_io_desc[] __initdata = { imx_map_entry(MX31, X_MEMC, MT_DEVICE), imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED), @@ -126,19 +127,6 @@ void __init mx31_map_io(void) iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc)); } -static struct map_desc mx35_io_desc[] __initdata = { - imx_map_entry(MX35, X_MEMC, MT_DEVICE), - imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED), - imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED), - imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED), - imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED), -}; - -void __init mx35_map_io(void) -{ - iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc)); -} - void __init imx31_init_early(void) { mxc_set_cpu_type(MXC_CPU_MX31); @@ -147,25 +135,11 @@ void __init imx31_init_early(void) imx_ioremap = imx3_ioremap; } -void __init imx35_init_early(void) -{ - mxc_set_cpu_type(MXC_CPU_MX35); - mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR)); - imx_idle = imx3_idle; - imx_ioremap = imx3_ioremap; -} - void __init mx31_init_irq(void) { mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR)); } -void __init mx35_init_irq(void) -{ - mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR)); -} - static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = { .per_2_per_addr = 1677, }; @@ -199,6 +173,35 @@ void __init imx31_soc_init(void) imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata); } +#endif /* ifdef CONFIG_SOC_IMX31 */ + +#ifdef CONFIG_SOC_IMX35 +static struct map_desc mx35_io_desc[] __initdata = { + imx_map_entry(MX35, X_MEMC, MT_DEVICE), + imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED), + imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED), + imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED), + imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED), +}; + +void __init mx35_map_io(void) +{ + iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc)); +} + +void __init imx35_init_early(void) +{ + mxc_set_cpu_type(MXC_CPU_MX35); + mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR)); + imx_idle = imx3_idle; + imx_ioremap = imx3_ioremap; +} + +void __init mx35_init_irq(void) +{ + mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR)); +} static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = { .ap_2_ap_addr = 642, @@ -254,3 +257,4 @@ void __init imx35_soc_init(void) imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata); } +#endif /* ifdef CONFIG_SOC_IMX35 */ -- cgit From 807dfe7041fb1ff2b076b999800553440e61234d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 8 Oct 2011 17:16:49 +0200 Subject: ARM: imx: export imx_ioremap The arch_ioremap function on i.MX is now an indirect function pointer. In order to use it from any loadable module, the pointer itself has to be exported. ERROR: "imx_ioremap" [drivers/video/tmiofb.ko] undefined! ERROR: "imx_ioremap" [drivers/usb/host/sl811-hcd.ko] undefined! ERROR: "imx_ioremap" [drivers/usb/host/r8a66597-hcd.ko] undefined! ERROR: "imx_ioremap" [drivers/usb/host/oxu210hp-hcd.ko] undefined! ERROR: "imx_ioremap" [drivers/usb/gadget/r8a66597-udc.ko] undefined! Signed-off-by: Arnd Bergmann Acked-by: Shawn Guo Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/system.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c index 9dad8dcc2ea9..45e1b5f6be44 100644 --- a/arch/arm/plat-mxc/system.c +++ b/arch/arm/plat-mxc/system.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ void (*imx_idle)(void) = NULL; void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL; +EXPORT_SYMBOL_GPL(imx_ioremap); static void __iomem *wdog_base; -- cgit From c6e8453e7511001e453f8b20b9ceefd231946867 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 18 Nov 2011 16:59:32 -0600 Subject: ALSA: hda - repoll ELD content for multiple times Improve the one-shot ELD repoll to up to 6 retries. Up to now the 300ms looks sufficient for the test boxes. However I'm a bit worried about how well it can fit the wider user base. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 9850c5b481ea..c505fd5d338c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -69,6 +69,7 @@ struct hdmi_spec_per_pin { struct hda_codec *codec; struct hdmi_eld sink_eld; struct delayed_work work; + int repoll_count; }; struct hdmi_spec { @@ -748,7 +749,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, * Unsolicited events */ -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { @@ -766,7 +767,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) if (pin_idx < 0) return; - hdmi_present_sense(&spec->pins[pin_idx], true); + hdmi_present_sense(&spec->pins[pin_idx], 1); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -960,7 +961,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_codec *codec = per_pin->codec; struct hdmi_eld *eld = &per_pin->sink_eld; @@ -989,7 +990,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry) if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); - else if (retry) { + else if (repoll) { queue_delayed_work(codec->bus->workq, &per_pin->work, msecs_to_jiffies(300)); @@ -1004,7 +1005,10 @@ static void hdmi_repoll_eld(struct work_struct *work) struct hdmi_spec_per_pin *per_pin = container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); - hdmi_present_sense(per_pin, false); + if (per_pin->repoll_count++ > 6) + per_pin->repoll_count = 0; + + hdmi_present_sense(per_pin, per_pin->repoll_count); } static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) @@ -1235,7 +1239,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (err < 0) return err; - hdmi_present_sense(per_pin, false); + hdmi_present_sense(per_pin, 0); return 0; } -- cgit From afd00d7235c1989d06d75cf8ac3d7722fcf2f394 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 22 Nov 2011 11:15:44 +0100 Subject: ALSA: lx6464es - command buffer API cleanup the command buffer is only accessed from one file, so we can declare the specific functions as static in that file Signed-off-by: Tim Blechmann Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 7 ++++--- sound/pci/lx6464es/lx_core.h | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 5c8717e29eeb..ad52f4187e40 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -78,7 +78,8 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) return ioread32(address); } -void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len) +static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, + u32 len) { void __iomem *address = lx_dsp_register(chip, port); memcpy_fromio(data, address, len*sizeof(u32)); @@ -91,8 +92,8 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) iowrite32(data, address); } -void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, - u32 len) +static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, + const u32 *data, u32 len) { void __iomem *address = lx_dsp_register(chip, port); memcpy_toio(address, data, len*sizeof(u32)); diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h index 1dd562980b6c..4d7ff797a646 100644 --- a/sound/pci/lx6464es/lx_core.h +++ b/sound/pci/lx6464es/lx_core.h @@ -72,10 +72,7 @@ enum { }; unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port); -void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len); void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data); -void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, - u32 len); /* plx register access */ enum { -- cgit From a29878553a9a7b4c06f93c7e383527cf014d4ceb Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 22 Nov 2011 11:15:45 +0100 Subject: ALSA: lx6464es - fix device communication via command bus commit 6175ddf06b6172046a329e3abfd9c901a43efd2e optimized the mem*io functions that have been used to send commands to the device. these optimizations somehow corrupted the communication with the lx6464es, that resulted the device to be unusable with kernels after 2.6.33. this patch emulates the memcpy_*_io functions via a loop to avoid these problems. Signed-off-by: Tim Blechmann LKML-Reference: <4ECB5257.4040600@ladisch.de> Cc: Signed-off-by: Takashi Iwai --- sound/pci/lx6464es/lx_core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index ad52f4187e40..8c3e7fcefd99 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -81,8 +81,12 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_fromio(data, address, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_fromio */ + for (i = 0; i != len; ++i) + data[i] = ioread32(address + i); } @@ -95,8 +99,12 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_toio(address, data, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_to */ + for (i = 0; i != len; ++i) + iowrite32(data[i], address + i); } -- cgit From a370fc62b9ad3f73abe2a721de6c03cdcce95b54 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Tue, 22 Nov 2011 16:46:23 +0800 Subject: ALSA: hda - fail ELD reading early With the ELD repoll mechanism, we can (and should) fail the ELD reading immediately when find something obviously wrong and let the caller retry after some delay. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 7ae7578bdcc0..c1da422e085a 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -347,18 +347,28 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, for (i = 0; i < size; i++) { unsigned int val = hdmi_get_eld_data(codec, nid, i); + /* + * Graphics driver might be writing to ELD buffer right now. + * Just abort. The caller will repoll after a while. + */ if (!(val & AC_ELDD_ELD_VALID)) { - if (!i) { - snd_printd(KERN_INFO - "HDMI: invalid ELD data\n"); - ret = -EINVAL; - goto error; - } snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", i); - val = 0; - } else - val &= AC_ELDD_ELD_DATA; + ret = -EINVAL; + goto error; + } + val &= AC_ELDD_ELD_DATA; + /* + * The first byte cannot be zero. This can happen on some DVI + * connections. Some Intel chips may also need some 250ms delay + * to return non-zero ELD data, even when the graphics driver + * correctly writes ELD content before setting ELD_valid bit. + */ + if (!val && !i) { + snd_printdd(KERN_INFO "HDMI: 0 ELD data\n"); + ret = -EINVAL; + goto error; + } buf[i] = val; } -- cgit From 72531c9434fa884d20cb3c36fcec83752f32fdf4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 Nov 2011 09:46:51 +0800 Subject: ASoC: Fix wrong define for AD1836_ADC_WORD_OFFSET According to the datasheet: The BIT[5:4] of ADC Control Register 2 is to control the word width. 00 = 25 Bits 01 = 20 Bits 10 = 16 Bits 11 = Invalid Thus, the AD1836_ADC_WORD_OFFSET should be defined as 4. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/ad1836.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 444747f0db26..dd7be0dbbc58 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -34,7 +34,7 @@ #define AD1836_ADC_CTRL2 13 #define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_WORD_OFFSET 5 +#define AD1836_ADC_WORD_OFFSET 4 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) -- cgit From 5c4b2aa3fd1dc30af098de5dec766a817621ace2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 Nov 2011 14:47:44 +0800 Subject: ASoC: max9877: Update register if either val or val2 is changed In the case of ((max9877_regs[reg] >> shift) & mask) != val but ((max9877_regs[reg2] >> shift) & mask) == val2, current code does not update the registers. Fix the logic to update registers if either val or val2 is changed. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/max9877.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 9e7e964a5fa3..dcf6f2a1600a 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol, unsigned int mask = mc->max; unsigned int val = (ucontrol->value.integer.value[0] & mask); unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 1; + unsigned int change = 0; - if (((max9877_regs[reg] >> shift) & mask) == val) - change = 0; + if (((max9877_regs[reg] >> shift) & mask) != val) + change = 1; - if (((max9877_regs[reg2] >> shift) & mask) == val2) - change = 0; + if (((max9877_regs[reg2] >> shift) & mask) != val2) + change = 1; if (change) { max9877_regs[reg] &= ~(mask << shift); -- cgit From 90459ce06f410b983540be56209c0abcbce23944 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 4 Aug 2011 11:02:33 +0200 Subject: percpu: rename pcpu_mem_alloc to pcpu_mem_zalloc Currently pcpu_mem_alloc() is implemented always return zeroed memory. So rename it to make user like pcpu_get_pages_and_bitmap() know don't reinit it. Signed-off-by: Bob Liu Reviewed-by: Pekka Enberg Reviewed-by: Michal Hocko Signed-off-by: Tejun Heo --- mm/percpu-vm.c | 5 ++--- mm/percpu.c | 17 +++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c index ea534960a04b..29e3730d2ffd 100644 --- a/mm/percpu-vm.c +++ b/mm/percpu-vm.c @@ -50,14 +50,13 @@ static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk, if (!pages || !bitmap) { if (may_alloc && !pages) - pages = pcpu_mem_alloc(pages_size); + pages = pcpu_mem_zalloc(pages_size); if (may_alloc && !bitmap) - bitmap = pcpu_mem_alloc(bitmap_size); + bitmap = pcpu_mem_zalloc(bitmap_size); if (!pages || !bitmap) return NULL; } - memset(pages, 0, pages_size); bitmap_copy(bitmap, chunk->populated, pcpu_unit_pages); *bitmapp = bitmap; diff --git a/mm/percpu.c b/mm/percpu.c index bf80e55dbed7..28c37a2e2de2 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -273,11 +273,11 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk, (rs) = (re) + 1, pcpu_next_pop((chunk), &(rs), &(re), (end))) /** - * pcpu_mem_alloc - allocate memory + * pcpu_mem_zalloc - allocate memory * @size: bytes to allocate * * Allocate @size bytes. If @size is smaller than PAGE_SIZE, - * kzalloc() is used; otherwise, vmalloc() is used. The returned + * kzalloc() is used; otherwise, vzalloc() is used. The returned * memory is always zeroed. * * CONTEXT: @@ -286,7 +286,7 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk, * RETURNS: * Pointer to the allocated area on success, NULL on failure. */ -static void *pcpu_mem_alloc(size_t size) +static void *pcpu_mem_zalloc(size_t size) { if (WARN_ON_ONCE(!slab_is_available())) return NULL; @@ -302,7 +302,7 @@ static void *pcpu_mem_alloc(size_t size) * @ptr: memory to free * @size: size of the area * - * Free @ptr. @ptr should have been allocated using pcpu_mem_alloc(). + * Free @ptr. @ptr should have been allocated using pcpu_mem_zalloc(). */ static void pcpu_mem_free(void *ptr, size_t size) { @@ -384,7 +384,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc) size_t old_size = 0, new_size = new_alloc * sizeof(new[0]); unsigned long flags; - new = pcpu_mem_alloc(new_size); + new = pcpu_mem_zalloc(new_size); if (!new) return -ENOMEM; @@ -604,11 +604,12 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void) { struct pcpu_chunk *chunk; - chunk = pcpu_mem_alloc(pcpu_chunk_struct_size); + chunk = pcpu_mem_zalloc(pcpu_chunk_struct_size); if (!chunk) return NULL; - chunk->map = pcpu_mem_alloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); + chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC * + sizeof(chunk->map[0])); if (!chunk->map) { kfree(chunk); return NULL; @@ -1889,7 +1890,7 @@ void __init percpu_init_late(void) BUILD_BUG_ON(size > PAGE_SIZE); - map = pcpu_mem_alloc(size); + map = pcpu_mem_zalloc(size); BUG_ON(!map); spin_lock_irqsave(&pcpu_lock, flags); -- cgit From a855b84c3d8c73220d4d3cd392a7bee7c83de70e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 18 Nov 2011 10:55:35 -0800 Subject: percpu: fix chunk range calculation Percpu allocator recorded the cpus which map to the first and last units in pcpu_first/last_unit_cpu respectively and used them to determine the address range of a chunk - e.g. it assumed that the first unit has the lowest address in a chunk while the last unit has the highest address. This simply isn't true. Groups in a chunk can have arbitrary positive or negative offsets from the previous one and there is no guarantee that the first unit occupies the lowest offset while the last one the highest. Fix it by actually comparing unit offsets to determine cpus occupying the lowest and highest offsets. Also, rename pcu_first/last_unit_cpu to pcpu_low/high_unit_cpu to avoid confusion. The chunk address range is used to flush cache on vmalloc area map/unmap and decide whether a given address is in the first chunk by per_cpu_ptr_to_phys() and the bug was discovered by invalid per_cpu_ptr_to_phys() translation for crash_note. Kudos to Dave Young for tracking down the problem. Signed-off-by: Tejun Heo Reported-by: WANG Cong Reported-by: Dave Young Tested-by: Dave Young LKML-Reference: <4EC21F67.10905@redhat.com> Cc: stable @kernel.org --- mm/percpu-vm.c | 12 ++++++------ mm/percpu.c | 34 ++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c index 29e3730d2ffd..12a48a88c0d8 100644 --- a/mm/percpu-vm.c +++ b/mm/percpu-vm.c @@ -142,8 +142,8 @@ static void pcpu_pre_unmap_flush(struct pcpu_chunk *chunk, int page_start, int page_end) { flush_cache_vunmap( - pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), - pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); + pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), + pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); } static void __pcpu_unmap_pages(unsigned long addr, int nr_pages) @@ -205,8 +205,8 @@ static void pcpu_post_unmap_tlb_flush(struct pcpu_chunk *chunk, int page_start, int page_end) { flush_tlb_kernel_range( - pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), - pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); + pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), + pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); } static int __pcpu_map_pages(unsigned long addr, struct page **pages, @@ -283,8 +283,8 @@ static void pcpu_post_map_flush(struct pcpu_chunk *chunk, int page_start, int page_end) { flush_cache_vmap( - pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), - pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); + pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), + pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); } /** diff --git a/mm/percpu.c b/mm/percpu.c index 28c37a2e2de2..2473ff06dc76 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -116,9 +116,9 @@ static int pcpu_atom_size __read_mostly; static int pcpu_nr_slots __read_mostly; static size_t pcpu_chunk_struct_size __read_mostly; -/* cpus with the lowest and highest unit numbers */ -static unsigned int pcpu_first_unit_cpu __read_mostly; -static unsigned int pcpu_last_unit_cpu __read_mostly; +/* cpus with the lowest and highest unit addresses */ +static unsigned int pcpu_low_unit_cpu __read_mostly; +static unsigned int pcpu_high_unit_cpu __read_mostly; /* the address of the first chunk which starts with the kernel static area */ void *pcpu_base_addr __read_mostly; @@ -985,19 +985,19 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr) { void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); bool in_first_chunk = false; - unsigned long first_start, first_end; + unsigned long first_low, first_high; unsigned int cpu; /* - * The following test on first_start/end isn't strictly + * The following test on unit_low/high isn't strictly * necessary but will speed up lookups of addresses which * aren't in the first chunk. */ - first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); - first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, - pcpu_unit_pages); - if ((unsigned long)addr >= first_start && - (unsigned long)addr < first_end) { + first_low = pcpu_chunk_addr(pcpu_first_chunk, pcpu_low_unit_cpu, 0); + first_high = pcpu_chunk_addr(pcpu_first_chunk, pcpu_high_unit_cpu, + pcpu_unit_pages); + if ((unsigned long)addr >= first_low && + (unsigned long)addr < first_high) { for_each_possible_cpu(cpu) { void *start = per_cpu_ptr(base, cpu); @@ -1234,7 +1234,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, for (cpu = 0; cpu < nr_cpu_ids; cpu++) unit_map[cpu] = UINT_MAX; - pcpu_first_unit_cpu = NR_CPUS; + + pcpu_low_unit_cpu = NR_CPUS; + pcpu_high_unit_cpu = NR_CPUS; for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) { const struct pcpu_group_info *gi = &ai->groups[group]; @@ -1254,9 +1256,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, unit_map[cpu] = unit + i; unit_off[cpu] = gi->base_offset + i * ai->unit_size; - if (pcpu_first_unit_cpu == NR_CPUS) - pcpu_first_unit_cpu = cpu; - pcpu_last_unit_cpu = cpu; + /* determine low/high unit_cpu */ + if (pcpu_low_unit_cpu == NR_CPUS || + unit_off[cpu] < unit_off[pcpu_low_unit_cpu]) + pcpu_low_unit_cpu = cpu; + if (pcpu_high_unit_cpu == NR_CPUS || + unit_off[cpu] > unit_off[pcpu_high_unit_cpu]) + pcpu_high_unit_cpu = cpu; } } pcpu_nr_units = unit; -- cgit From d31da0f0ba3bc0a827a63879310818c22d9a95be Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 22 Nov 2011 12:31:21 -0500 Subject: mount_subtree() pointless use-after-free d'oh... we'd carefully pinned mnt->mnt_sb down, dropped mnt and attempt to grab s_umount on mnt->mnt_sb. The trouble is, *mnt might've been overwritten by now... Signed-off-by: Al Viro --- fs/namespace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 50ee30345b4f..6d3a1963879b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2493,6 +2493,7 @@ EXPORT_SYMBOL(create_mnt_ns); struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) { struct mnt_namespace *ns; + struct super_block *s; struct path path; int err; @@ -2509,10 +2510,11 @@ struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) return ERR_PTR(err); /* trade a vfsmount reference for active sb one */ - atomic_inc(&path.mnt->mnt_sb->s_active); + s = path.mnt->mnt_sb; + atomic_inc(&s->s_active); mntput(path.mnt); /* lock the sucker */ - down_write(&path.mnt->mnt_sb->s_umount); + down_write(&s->s_umount); /* ... and return the root of (sub)tree on it */ return path.dentry; } -- cgit From e5a21327644adba32816f74a415114d11c57f2e9 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 22 Nov 2011 18:01:46 +0000 Subject: ARM: perf: check that we have a platform device when reserving PMU Attempting to use a hardware counter on a platform with a supported PMU but where the platform_device (defining the interrupts) has not been registered results in a NULL pointer dereference. This patch fixes the problem by checking that we actually have a platform device registered before attempting to grab the interrupts. Reported-by: Pawel Moll Signed-off-by: Will Deacon --- arch/arm/kernel/perf_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index e508066d3d64..c475379199b1 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -402,6 +402,9 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) int i, err, irq, irqs; struct platform_device *pmu_device = armpmu->plat_device; + if (!pmu_device) + return -ENODEV; + err = reserve_pmu(armpmu->type); if (err) { pr_warning("unable to reserve pmu\n"); -- cgit From 3d94a2a53a3979c30620e3adea10f20bef8267b3 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Tue, 22 Nov 2011 11:03:22 +0900 Subject: ASoC: SAMSUNG: Fix build error This patch adds to fix following build errors. sound/soc/codecs/wm8994.c: In function 'wm8994_readable': sound/soc/codecs/wm8994.c:58: warning: unused variable 'wm8994' sound/soc/samsung/smdk_wm8994.c:176: error: expected declaration specifiers or '...' before string constant sound/soc/samsung/smdk_wm8994.c:176: warning: data definition has no type or storage class sound/soc/samsung/smdk_wm8994.c:176: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' sound/soc/samsung/smdk_wm8994.c:176: warning: function declaration isn't a prototype sound/soc/samsung/smdk_wm8994.c:177: error: expected declaration specifiers or '...' before string constant Signed-off-by: Boojin Kim Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index f75e43997d5b..ad9ac42522e2 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -9,6 +9,7 @@ #include "../codecs/wm8994.h" #include +#include /* * Default CFG switch settings to use this driver: -- cgit From 26cc40a83384178bfaefbcfb4786591498f3e190 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 21 Nov 2011 13:05:02 +0100 Subject: ttm: Don't return the bo reserved on error path An unlikely race could case a bo to be returned reserved on an error path. Signed-off-by: Thomas Hellstrom Reviewed-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 617b64678fc6..0bb0f5f713e6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -574,10 +574,16 @@ retry: return ret; spin_lock(&glob->lru_lock); + + if (unlikely(list_empty(&bo->ddestroy))) { + spin_unlock(&glob->lru_lock); + return 0; + } + ret = ttm_bo_reserve_locked(bo, interruptible, no_wait_reserve, false, 0); - if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) { + if (unlikely(ret != 0)) { spin_unlock(&glob->lru_lock); return ret; } -- cgit From d724502a9d7a46f4a56a1663b1f50d2dc9d1ef40 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 21 Nov 2011 12:10:14 -0500 Subject: drm/radeon/kms: fix up gpio i2c mask bits for r4xx for real Fixes i2c test failures when i2c_algo_bit.bit_test=1. The hw doesn't actually require a mask, so just set it to the default mask bits for r1xx-r4xx radeon ddc. I missed this part the first time through. Signed-off-by: Alex Deucher Cc: stable@kernel.org Cc: Jean Delvare Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fecd705a1a5f..933a2cd7bb55 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -181,6 +181,18 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) gpio = &i2c_info->asGPIO_Info[i]; i2c.valid = false; + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + /* some evergreen boards have bad data for this entry */ if (ASIC_IS_DCE4(rdev)) { if ((i == 7) && -- cgit From 21240f9bc1b0ac925cd18b74618327a110022332 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 21 Nov 2011 12:41:21 -0500 Subject: drm/radeon/kms/atom: unify i2c gpio table handling Split the quirks and i2c_rec assignment into separate functions used by both radeon_lookup_i2c_gpio() and radeon_atombios_i2c_init(). This avoids duplicating code and cases where quirks were only added to one of the functions. Signed-off-by: Alex Deucher Cc: Jean Delvare Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 214 +++++++++++++------------------ 1 file changed, 86 insertions(+), 128 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 933a2cd7bb55..d24baf30efcb 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -62,6 +62,87 @@ union atom_supported_devices { struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; }; +static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev, + ATOM_GPIO_I2C_ASSIGMENT *gpio, + u8 index) +{ + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((index == 7) && + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + + /* some DCE3 boards have bad data for this entry */ + if (ASIC_IS_DCE3(rdev)) { + if ((index == 4) && + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && + (gpio->sucI2cId.ucAccess == 0x94)) + gpio->sucI2cId.ucAccess = 0x14; + } +} + +static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio) +{ + struct radeon_i2c_bus_rec i2c; + + memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); + + i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; + i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; + i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; + i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; + i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; + i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; + i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; + i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; + i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); + i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); + i2c.en_clk_mask = (1 << gpio->ucClkEnShift); + i2c.en_data_mask = (1 << gpio->ucDataEnShift); + i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); + i2c.y_data_mask = (1 << gpio->ucDataY_Shift); + i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); + i2c.a_data_mask = (1 << gpio->ucDataA_Shift); + + if (gpio->sucI2cId.sbfAccess.bfHW_Capable) + i2c.hw_capable = true; + else + i2c.hw_capable = false; + + if (gpio->sucI2cId.ucAccess == 0xa0) + i2c.mm_i2c = true; + else + i2c.mm_i2c = false; + + i2c.i2c_id = gpio->sucI2cId.ucAccess; + + if (i2c.mask_clk_reg) + i2c.valid = true; + else + i2c.valid = false; + + return i2c; +} + static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, uint8_t id) { @@ -85,71 +166,10 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; - /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ - if ((rdev->family == CHIP_R420) || - (rdev->family == CHIP_R423) || - (rdev->family == CHIP_RV410)) { - if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { - gpio->ucClkMaskShift = 0x19; - gpio->ucDataMaskShift = 0x18; - } - } - - /* some evergreen boards have bad data for this entry */ - if (ASIC_IS_DCE4(rdev)) { - if ((i == 7) && - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && - (gpio->sucI2cId.ucAccess == 0)) { - gpio->sucI2cId.ucAccess = 0x97; - gpio->ucDataMaskShift = 8; - gpio->ucDataEnShift = 8; - gpio->ucDataY_Shift = 8; - gpio->ucDataA_Shift = 8; - } - } - - /* some DCE3 boards have bad data for this entry */ - if (ASIC_IS_DCE3(rdev)) { - if ((i == 4) && - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && - (gpio->sucI2cId.ucAccess == 0x94)) - gpio->sucI2cId.ucAccess = 0x14; - } + radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); if (gpio->sucI2cId.ucAccess == id) { - i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; - i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; - i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; - i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; - i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; - i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; - i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; - i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; - i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); - i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); - i2c.en_clk_mask = (1 << gpio->ucClkEnShift); - i2c.en_data_mask = (1 << gpio->ucDataEnShift); - i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); - i2c.y_data_mask = (1 << gpio->ucDataY_Shift); - i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); - i2c.a_data_mask = (1 << gpio->ucDataA_Shift); - - if (gpio->sucI2cId.sbfAccess.bfHW_Capable) - i2c.hw_capable = true; - else - i2c.hw_capable = false; - - if (gpio->sucI2cId.ucAccess == 0xa0) - i2c.mm_i2c = true; - else - i2c.mm_i2c = false; - - i2c.i2c_id = gpio->sucI2cId.ucAccess; - - if (i2c.mask_clk_reg) - i2c.valid = true; + i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); break; } } @@ -169,8 +189,6 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) int i, num_indices; char stmp[32]; - memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); - if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); @@ -179,72 +197,12 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; - i2c.valid = false; - - /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ - if ((rdev->family == CHIP_R420) || - (rdev->family == CHIP_R423) || - (rdev->family == CHIP_RV410)) { - if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { - gpio->ucClkMaskShift = 0x19; - gpio->ucDataMaskShift = 0x18; - } - } - - /* some evergreen boards have bad data for this entry */ - if (ASIC_IS_DCE4(rdev)) { - if ((i == 7) && - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && - (gpio->sucI2cId.ucAccess == 0)) { - gpio->sucI2cId.ucAccess = 0x97; - gpio->ucDataMaskShift = 8; - gpio->ucDataEnShift = 8; - gpio->ucDataY_Shift = 8; - gpio->ucDataA_Shift = 8; - } - } - - /* some DCE3 boards have bad data for this entry */ - if (ASIC_IS_DCE3(rdev)) { - if ((i == 4) && - (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && - (gpio->sucI2cId.ucAccess == 0x94)) - gpio->sucI2cId.ucAccess = 0x14; - } - i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; - i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; - i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; - i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; - i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; - i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; - i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; - i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; - i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); - i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); - i2c.en_clk_mask = (1 << gpio->ucClkEnShift); - i2c.en_data_mask = (1 << gpio->ucDataEnShift); - i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); - i2c.y_data_mask = (1 << gpio->ucDataY_Shift); - i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); - i2c.a_data_mask = (1 << gpio->ucDataA_Shift); - - if (gpio->sucI2cId.sbfAccess.bfHW_Capable) - i2c.hw_capable = true; - else - i2c.hw_capable = false; - - if (gpio->sucI2cId.ucAccess == 0xa0) - i2c.mm_i2c = true; - else - i2c.mm_i2c = false; + radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); - i2c.i2c_id = gpio->sucI2cId.ucAccess; + i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); - if (i2c.mask_clk_reg) { - i2c.valid = true; + if (i2c.valid) { sprintf(stmp, "0x%x", i2c.i2c_id); rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); } -- cgit From c916874d60d9daf2e2d5f4f622b185ef57deb6a4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 15 Nov 2011 14:53:11 -0800 Subject: drivers/gpu/vga/vgaarb.c: add missing kfree kbuf is a buffer that is local to this function, so all of the error paths leaving the function should release it. Signed-off-by: Julia Lawall Cc: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/gpu/vga/vgaarb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index bdde899af72e..111d956d8e7d 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -991,14 +991,20 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, uc = &priv->cards[i]; } - if (!uc) - return -EINVAL; + if (!uc) { + ret_val = -EINVAL; + goto done; + } - if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) - return -EINVAL; + if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) { + ret_val = -EINVAL; + goto done; + } - if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) - return -EINVAL; + if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) { + ret_val = -EINVAL; + goto done; + } vga_put(pdev, io_state); -- cgit From 717b6d83664646963c71d014c71babaa802333b9 Mon Sep 17 00:00:00 2001 From: Maciej Żenczykowski Date: Tue, 22 Nov 2011 16:03:10 -0500 Subject: net-netlink: fix diag to export IPv4 tos for dual-stack IPv6 sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maciej Żenczykowski Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 68e8ac514383..ccee270a9b65 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -108,9 +108,6 @@ static int inet_csk_diag_fill(struct sock *sk, icsk->icsk_ca_ops->name); } - if ((ext & (1 << (INET_DIAG_TOS - 1))) && (sk->sk_family != AF_INET6)) - RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos); - r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; @@ -125,16 +122,23 @@ static int inet_csk_diag_fill(struct sock *sk, r->id.idiag_src[0] = inet->inet_rcv_saddr; r->id.idiag_dst[0] = inet->inet_daddr; + /* IPv6 dual-stack sockets use inet->tos for IPv4 connections, + * hence this needs to be included regardless of socket family. + */ + if (ext & (1 << (INET_DIAG_TOS - 1))) + RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos); + #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { const struct ipv6_pinfo *np = inet6_sk(sk); + if (ext & (1 << (INET_DIAG_TCLASS - 1))) + RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass); + ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, &np->rcv_saddr); ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, &np->daddr); - if (ext & (1 << (INET_DIAG_TCLASS - 1))) - RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass); } #endif -- cgit From 20e994a05b33b186a22a3b9e922df4cce644daac Mon Sep 17 00:00:00 2001 From: Feng King Date: Mon, 21 Nov 2011 01:47:11 +0000 Subject: net: correct comments of skb_shift when skb_shift, we want to shift paged data from skb to tgt frag area. Original comments revert the shift order Signed-off-by: Feng King Signed-off-by: David S. Miller --- net/core/skbuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 18a3cebb753d..3c30ee4a5710 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2230,7 +2230,7 @@ static int skb_prepare_for_shift(struct sk_buff *skb) * @shiftlen: shift up to this many bytes * * Attempts to shift up to shiftlen worth of bytes, which may be less than - * the length of the skb, from tgt to skb. Returns number bytes shifted. + * the length of the skb, from skb to tgt. Returns number bytes shifted. * It's up to caller to free skb if everything was shifted. * * If @tgt runs out of frags, the whole operation is aborted. -- cgit From 6cccccafe9e8b88adb1800940ded6ad76c587e1b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 22 Nov 2011 16:36:35 -0500 Subject: Revert "rt2x00: handle spurious pci interrupts" This reverts commit 23085d5796561625db4143a671f1de081f66ef08. The original patch was a misguided attempt to improve performance on some hardware that is apparently prone to spurious interrupt generation. Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 676c7657f5f5..3a6b40239bc1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1380,7 +1380,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, CSR7, reg); if (!reg) - return IRQ_HANDLED; + return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d0b627c6c217..dcc0e1fcca77 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1512,7 +1512,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, CSR7, reg); if (!reg) - return IRQ_HANDLED; + return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 9d83e70f3e62..bf55b4a311e3 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2337,7 +2337,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg && !reg_mcu) - return IRQ_HANDLED; + return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; -- cgit From 5eccdf5e06eb67779716ae26142402a1ae9b012c Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 21 Nov 2011 06:53:46 +0000 Subject: tc: comment spelling fixes Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/pkt_sched.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index c5336705921f..7281d5acf2f9 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -30,7 +30,7 @@ */ struct tc_stats { - __u64 bytes; /* NUmber of enqueues bytes */ + __u64 bytes; /* Number of enqueued bytes */ __u32 packets; /* Number of enqueued packets */ __u32 drops; /* Packets dropped because of lack of resources */ __u32 overlimits; /* Number of throttle events when this @@ -297,7 +297,7 @@ struct tc_htb_glob { __u32 debug; /* debug flags */ /* stats */ - __u32 direct_pkts; /* count of non shapped packets */ + __u32 direct_pkts; /* count of non shaped packets */ }; enum { TCA_HTB_UNSPEC, @@ -503,7 +503,7 @@ enum { }; #define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) -/* State transition probablities for 4 state model */ +/* State transition probabilities for 4 state model */ struct tc_netem_gimodel { __u32 p13; __u32 p31; -- cgit From 82e5fc2a34fa9ffea38f00c4066b7e600a0ca5e6 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 22 Nov 2011 16:38:19 -0500 Subject: Revert "rt2800pci: handle spurious interrupts" This reverts commit 4ba7d9997869d25bd223dea7536fc1ce9fab3b3b. The original patch was a misguided attempt to improve performance on some hardware that is apparently prone to spurious interrupt generation. Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4dc2d0f840d4..da48c8ac27bd 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -880,13 +880,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - /* - * Some devices can generate interrupts with empty CSR register, we - * "handle" such irq's to prevent interrupt controller treat them as - * spurious interrupts and disable irq line. - */ if (!reg) - return IRQ_HANDLED; + return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; -- cgit From 24ca9a847791fd53d9b217330b15f3c285827a18 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 22 Nov 2011 14:44:28 +0200 Subject: SUNRPC: Ensure we return EAGAIN in xs_nospace if congestion is cleared By returning '0' instead of 'EAGAIN' when the tests in xs_nospace() fail to find evidence of socket congestion, we are making the RPC engine believe that the message was incorrectly sent and so it disconnects the socket instead of just retrying. The bug appears to have been introduced by commit 5e3771ce2d6a69e10fcc870cdf226d121d868491 (SUNRPC: Ensure that xs_nospace return values are propagated). Reported-by: Andrew Cooper Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 2.6.30] Tested-by: Andrew Cooper --- net/sunrpc/xprtsock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 2d78d95955ab..55472c48825e 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -496,7 +496,7 @@ static int xs_nospace(struct rpc_task *task) struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); - int ret = 0; + int ret = -EAGAIN; dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", task->tk_pid, req->rq_slen - req->rq_bytes_sent, @@ -508,7 +508,6 @@ static int xs_nospace(struct rpc_task *task) /* Don't race with disconnect */ if (xprt_connected(xprt)) { if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { - ret = -EAGAIN; /* * Notify TCP that we're limited by the application * window size -- cgit From d66b8537b30fbaf79e0f467fa6b7e1a2191cba83 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 22 Nov 2011 17:17:23 +0100 Subject: ASoC: cs4720: use snd_soc_cache_sync() Replace the manual register restore mechanism in cs4270.c and call the generic snd_soc_cache_sync() handler instead. This factors code out in favour of core facilities and also fixes a bus confusion that is most probably caused by intermixing i2c-regmap functions and i2c_smbus_* accessors. Signed-off-by: Daniel Mack Reported-and-tested-by: Sven Neumann Acked-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1f237ecec2a..73f46eb459f1 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -601,7 +601,6 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) static int cs4270_soc_resume(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c_client = to_i2c_client(codec->dev); int reg; regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), @@ -612,14 +611,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) ndelay(500); /* first restore the entire register cache ... */ - for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { - u8 val = snd_soc_read(codec, reg); - - if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { - dev_err(codec->dev, "i2c write failed\n"); - return -EIO; - } - } + snd_soc_cache_sync(codec); /* ... then disable the power-down bits */ reg = snd_soc_read(codec, CS4270_PWRCTL); -- cgit From 380c88303812951f6c838241366a66a03fb5c897 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 22 Nov 2011 14:38:59 -0600 Subject: ASoC: mpc8610: tell the CS4270 codec that it's the master Commit ac601555 ("ASoC: Return early with -EINVAL if invalid dai format is detected") requires the machine driver to tell the CS4270 codec driver whether the CS4270 should be configured for master or slave operation. Signed-off-by: Timur Tabi Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 31af405bda84..ae49f1c78c6d 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -392,7 +392,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } if (strcasecmp(sprop, "i2s-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_I2S; + machine_data->dai_format = + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; @@ -409,31 +410,38 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } machine_data->clk_frequency = be32_to_cpup(iprop); } else if (strcasecmp(sprop, "i2s-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_I2S; + machine_data->dai_format = + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "lj-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "lj-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "rj-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "rj-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; + machine_data->dai_format = + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "ac97-slave") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_AC97; + machine_data->dai_format = + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "ac97-master") == 0) { - machine_data->dai_format = SND_SOC_DAIFMT_AC97; + machine_data->dai_format = + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else { -- cgit From b4bbb02934e4511d9083f15c23e90703482e84ad Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 22 Nov 2011 15:09:20 -0800 Subject: Revert "of/irq: of_irq_find_parent: check for parent equal to child" This reverts commit dc9372808412edbc653a675a526c2ee6c0c14a91. As requested by Ben Herrenschmidt: "This breaks some powerpc platforms at least. The practice of having a node provide an explicit "interrupt-parent" property pointing to itself is an old trick that we've used in the past to allow a device-node to have interrupts routed to different controllers. In that case, the node also contains an interrupt-map, so the node is its own parent, the interrupt resolution hits the map, which then can route each individual interrupt to a different parent." Grant says: "Ah, nuts, yes that is broken then. Yes, please revert the commit and Rob & I will come up with a better solution. Rob, I think it can be done by explicitly checking for np == desc->interrupt_parent in of_irq_init() instead of relying on of_irq_find_parent() returning NULL." Requested-by: Benjamin Herrenschmidt Acked-by: Grant Likely Cc: Rob Herring Cc: devicetree-discuss@lists.ozlabs.org Cc: linuxppc-dev Cc: Tanmay Inamdar Signed-off-by: Linus Torvalds --- drivers/of/irq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 6d3dd3988d0f..791270b8bd1c 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -60,27 +60,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); */ struct device_node *of_irq_find_parent(struct device_node *child) { - struct device_node *p, *c = child; + struct device_node *p; const __be32 *parp; - if (!of_node_get(c)) + if (!of_node_get(child)) return NULL; do { - parp = of_get_property(c, "interrupt-parent", NULL); + parp = of_get_property(child, "interrupt-parent", NULL); if (parp == NULL) - p = of_get_parent(c); + p = of_get_parent(child); else { if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) p = of_node_get(of_irq_dflt_pic); else p = of_find_node_by_phandle(be32_to_cpup(parp)); } - of_node_put(c); - c = p; + of_node_put(child); + child = p; } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); - return (p == child) ? NULL : p; + return p; } /** -- cgit From 7c8f4247986bb5c5fb1d5b1fad35461989fe8310 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 23 Nov 2011 10:18:52 +1100 Subject: md/lock: ensure updates to page_attrs are properly locked. Page attributes are set using __set_bit rather than set_bit as it normally called under a spinlock so the extra atomicity is not needed. However there are two places where we might set or clear page attributes without holding the spinlock. So add the spinlock in those cases. This might be the cause of occasional reports that bits a aren't getting clear properly - theory is that BITMAP_PAGE_PENDING gets lost when BITMAP_PAGE_NEEDWRITE is set or cleared. This is an inconvenience, not a threat to data safety. Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7878712721bf..b6907118283a 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1106,10 +1106,12 @@ void bitmap_write_all(struct bitmap *bitmap) */ int i; + spin_lock_irq(&bitmap->lock); for (i = 0; i < bitmap->file_pages; i++) set_page_attr(bitmap, bitmap->filemap[i], BITMAP_PAGE_NEEDWRITE); bitmap->allclean = 0; + spin_unlock_irq(&bitmap->lock); } static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) @@ -1605,7 +1607,9 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) for (chunk = s; chunk <= e; chunk++) { sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap); bitmap_set_memory_bits(bitmap, sec, 1); + spin_lock_irq(&bitmap->lock); bitmap_file_set_bit(bitmap, sec); + spin_unlock_irq(&bitmap->lock); if (sec < bitmap->mddev->recovery_cp) /* We are asserting that the array is dirty, * so move the recovery_cp address back so -- cgit From c0afabd3d553c521e003779c127143ffde55a16f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 22 Nov 2011 11:03:14 +0100 Subject: rtc: Disable the alarm in the hardware Currently, the RTC code does not disable the alarm in the hardware. This means that after a sequence such as the one below (the files are in the RTC sysfs), the box will boot up after 2 minutes even though we've asked for the alarm to be turned off. # echo $((`cat since_epoch`)+120) > wakealarm # echo 0 > wakealarm # poweroff Fix this by disabling the alarm when there are no timers to run. Cc: stable@kernel.org Cc: John Stultz Signed-off-by: Rabin Vincent Signed-off-by: John Stultz --- drivers/rtc/interface.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3195dbd3ec34..e3cf2f54221f 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -318,6 +318,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_read_alarm); +static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +{ + int err; + + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->set_alarm) + err = -EINVAL; + else + err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + + return err; +} + static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { struct rtc_time tm; @@ -341,14 +355,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) * over right here, before we set the alarm. */ - if (!rtc->ops) - err = -ENODEV; - else if (!rtc->ops->set_alarm) - err = -EINVAL; - else - err = rtc->ops->set_alarm(rtc->dev.parent, alarm); - - return err; + return ___rtc_set_alarm(rtc, alarm); } int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -762,6 +769,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + struct rtc_wkalrm alarm; + struct rtc_time tm; + + __rtc_read_time(rtc, &tm); + + alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), + ktime_set(300, 0))); + alarm.enabled = 0; + + ___rtc_set_alarm(rtc, &alarm); +} + /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device @@ -783,8 +804,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) struct rtc_wkalrm alarm; int err; next = timerqueue_getnext(&rtc->timerqueue); - if (!next) + if (!next) { + rtc_alarm_disable(rtc); return; + } alarm.time = rtc_ktime_to_tm(next->expires); alarm.enabled = 1; err = __rtc_set_alarm(rtc, &alarm); @@ -846,7 +869,8 @@ again: err = __rtc_set_alarm(rtc, &alarm); if (err == -ETIME) goto again; - } + } else + rtc_alarm_disable(rtc); mutex_unlock(&rtc->ops_lock); } -- cgit From 6a8943d9ec2567572fca25cf69ad45844d0141a3 Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Tue, 22 Nov 2011 18:24:51 -0800 Subject: rtc: Fix some bugs that allowed accumulating time drift in suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code checks if abs(delta_delta.tv_sec) is greater or equal to two before it discards the old delta value, but this can trigger at close to -1 seconds since -1.000000001 seconds is stored as tv_sec -2 and tv_nsec 999999999 in a normalized timespec. rtc_resume had an early return check if the rtc value had not changed since rtc_suspend. This effectivly stops time for the duration of the short sleep. Check if sleep_time is positive after all the adjustments have been applied instead since this allows the old_system adjustment in rtc_suspend to have an effect even for short sleep cycles. CC: stable@kernel.org Signed-off-by: Arve Hjønnevåg Signed-off-by: John Stultz --- drivers/rtc/class.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01a7df5317c1..b82a1554cdc1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -66,7 +66,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) */ delta = timespec_sub(old_system, old_rtc); delta_delta = timespec_sub(delta, old_delta); - if (abs(delta_delta.tv_sec) >= 2) { + if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { /* * if delta_delta is too large, assume time correction * has occured and set old_delta to the current delta. @@ -100,9 +100,8 @@ static int rtc_resume(struct device *dev) rtc_tm_to_time(&tm, &new_rtc.tv_sec); new_rtc.tv_nsec = 0; - if (new_rtc.tv_sec <= old_rtc.tv_sec) { - if (new_rtc.tv_sec < old_rtc.tv_sec) - pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); + if (new_rtc.tv_sec < old_rtc.tv_sec) { + pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } @@ -119,7 +118,8 @@ static int rtc_resume(struct device *dev) sleep_time = timespec_sub(sleep_time, timespec_sub(new_system, old_system)); - timekeeping_inject_sleeptime(&sleep_time); + if (sleep_time.tv_sec >= 0) + timekeeping_inject_sleeptime(&sleep_time); return 0; } -- cgit From e2301a4de22c438f5a962c7cefc3e9cba736991c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 22 Nov 2011 19:58:56 +0100 Subject: ALSA: hda - Check subdevice mask in snd_hda_check_board_codec_sid_config() In snd_hda_check_board_codec_sid_config(), not only comparing with the exact value but allow the bit-mask comparison for vendor-only, etc. Tested-by: Linus Torvalds Tested-by: Dirk Hohndel Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e44b107fdc75..4562e9de6a1a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4046,9 +4046,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, /* Search for codec ID */ for (q = tbl; q->subvendor; q++) { - unsigned long vendorid = (q->subdevice) | (q->subvendor << 16); - - if (vendorid == codec->subsystem_id) + unsigned int mask = 0xffff0000 | q->subdevice_mask; + unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; + if ((codec->subsystem_id & mask) == id) break; } -- cgit From 6dfeb703e386369d9f1585d29482efe7b2b4401d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 22 Nov 2011 20:00:31 +0100 Subject: ALSA: hda - Fix invalid pin and GPIO for Apple laptops with CS codecs The PCI SSID 8086:7270 is commonly used for multiple Apple machines, thus we can't use it as identifier for a unique model. Because of this conflict, some machines show weird behavior. For example, MacBook Air shows Front and Surround speakers although only Surround works due to the wrongly overridden pin-configuration for imac27. This patch fixes two things: - Stop the wrong pin-config override of imac27 by removing PCI SSID entry for avoiding the wrong mappings, - Add the generic GPIO setup for Apple machines by checking the codec SSID vendor bits Tested-by: Linus Torvalds Tested-by: Dirk Hohndel Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2fbab8e29576..7bd2a52f2bac 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -58,6 +58,8 @@ struct cs_spec { unsigned int gpio_mask; unsigned int gpio_dir; unsigned int gpio_data; + unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */ + unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */ struct hda_pcm pcm_rec[2]; /* PCM information */ @@ -76,6 +78,7 @@ enum { CS420X_MBP53, CS420X_MBP55, CS420X_IMAC27, + CS420X_APPLE, CS420X_AUTO, CS420X_MODELS }; @@ -928,10 +931,9 @@ static void cs_automute(struct hda_codec *codec) spdif_present ? 0 : PIN_OUT); } } - if (spec->board_config == CS420X_MBP53 || - spec->board_config == CS420X_MBP55 || - spec->board_config == CS420X_IMAC27) { - unsigned int gpio = hp_present ? 0x02 : 0x08; + if (spec->gpio_eapd_hp) { + unsigned int gpio = hp_present ? + spec->gpio_eapd_hp : spec->gpio_eapd_speaker; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); } @@ -1276,6 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = { [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", + [CS420X_IMAC27] = "apple", [CS420X_AUTO] = "auto", }; @@ -1285,7 +1288,13 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), - SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), + /* this conflicts with too many other models */ + /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ + {} /* terminator */ +}; + +static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), {} /* terminator */ }; @@ -1367,6 +1376,10 @@ static int patch_cs420x(struct hda_codec *codec) spec->board_config = snd_hda_check_board_config(codec, CS420X_MODELS, cs420x_models, cs420x_cfg_tbl); + if (spec->board_config < 0) + spec->board_config = + snd_hda_check_board_codec_sid_config(codec, + CS420X_MODELS, NULL, cs420x_codec_cfg_tbl); if (spec->board_config >= 0) fix_pincfg(codec, spec->board_config, cs_pincfgs); @@ -1374,10 +1387,11 @@ static int patch_cs420x(struct hda_codec *codec) case CS420X_IMAC27: case CS420X_MBP53: case CS420X_MBP55: - /* GPIO1 = headphones */ - /* GPIO3 = speakers */ - spec->gpio_mask = 0x0a; - spec->gpio_dir = 0x0a; + case CS420X_APPLE: + spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ + spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ + spec->gpio_mask = spec->gpio_dir = + spec->gpio_eapd_hp | spec->gpio_eapd_speaker; break; } -- cgit From 6759dc323826c2c806c998cd93945c5476688dd2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Nov 2011 07:38:59 +0100 Subject: ALSA: hda/realtek - Fix missing inits of item indices for auto-mic When the imux entries are rebuilt in alc_rebuild_imux_for_auto_mic(), the initialization of index field is missing. It may work without it casually when the original imux was created by the auto-parser, but it's definitely broken in the case of static configs where no imux was parsed beforehand. Because of this, the auto-mic switching doesn't work properly on some model options. This patch adds the missing initialization of index field. Reported-by: Dmitry Nezhevenko Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 336d14eb72af..06c0c12d4fec 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1054,8 +1054,20 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) spec->imux_pins[2] = spec->dock_mic_pin; for (i = 0; i < 3; i++) { strcpy(imux->items[i].label, texts[i]); - if (spec->imux_pins[i]) + if (spec->imux_pins[i]) { + hda_nid_t pin = spec->imux_pins[i]; + int c; + for (c = 0; c < spec->num_adc_nids; c++) { + hda_nid_t cap = spec->capsrc_nids ? + spec->capsrc_nids[c] : spec->adc_nids[c]; + int idx = get_connection_index(codec, cap, pin); + if (idx >= 0) { + imux->items[i].index = idx; + break; + } + } imux->num_items = i + 1; + } } spec->num_mux_defs = 1; spec->input_mux = imux; -- cgit From 61071594f64ed12328046f94716d1d744bddc0a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Nov 2011 07:52:15 +0100 Subject: ALSA: hda/realtek - Minor cleanup Use an inline function for the common pattern for assigning a capsrc. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 06c0c12d4fec..cbde019d3d52 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -277,6 +277,12 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur) return false; } +static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) +{ + return spec->capsrc_nids ? + spec->capsrc_nids[idx] : spec->adc_nids[idx]; +} + /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, unsigned int idx, bool force) @@ -303,8 +309,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, adc_idx = spec->dyn_adc_idx[idx]; } - nid = spec->capsrc_nids ? - spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; + nid = get_capsrc(spec, adc_idx); /* no selection? */ num_conns = snd_hda_get_conn_list(codec, nid, NULL); @@ -1058,8 +1063,7 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) hda_nid_t pin = spec->imux_pins[i]; int c; for (c = 0; c < spec->num_adc_nids; c++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[c] : spec->adc_nids[c]; + hda_nid_t cap = get_capsrc(spec, c); int idx = get_connection_index(codec, cap, pin); if (idx >= 0) { imux->items[i].index = idx; @@ -1969,10 +1973,8 @@ static int alc_build_controls(struct hda_codec *codec) if (!kctl) kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); for (i = 0; kctl && i < kctl->count; i++) { - const hda_nid_t *nids = spec->capsrc_nids; - if (!nids) - nids = spec->adc_nids; - err = snd_hda_add_nid(codec, kctl, i, nids[i]); + err = snd_hda_add_nid(codec, kctl, i, + get_capsrc(spec, i)); if (err < 0) return err; } @@ -2759,8 +2761,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec) } for (c = 0; c < num_adcs; c++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[c] : spec->adc_nids[c]; + hda_nid_t cap = get_capsrc(spec, c); idx = get_connection_index(codec, cap, pin); if (idx >= 0) { spec->imux_pins[imux->num_items] = pin; @@ -3706,8 +3707,7 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) if (!pin) return 0; for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[i] : spec->adc_nids[i]; + hda_nid_t cap = get_capsrc(spec, i); int idx; idx = get_connection_index(codec, cap, pin); -- cgit From 4d65a2465f6f2694de67777a8aedb1272f473979 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Wed, 23 Nov 2011 03:51:54 -0500 Subject: ipv6: fix a bug in ndisc_send_redirect Release skb when transmit rate limit _not_ allow Signed-off-by: Li Wei Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 44e5b7f2a6c1..0cb78d7ddaf5 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1571,7 +1571,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, } if (!rt->rt6i_peer) rt6_bind_peer(rt, 1); - if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) + if (!inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) goto release; if (dev->addr_len) { -- cgit From a5cd335165e31db9dbab636fd29895d41da55dd2 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 23 Nov 2011 01:12:01 -0500 Subject: drm: integer overflow in drm_mode_dirtyfb_ioctl() There is a potential integer overflow in drm_mode_dirtyfb_ioctl() if userspace passes in a large num_clips. The call to kmalloc would allocate a small buffer, and the call to fb->funcs->dirty may result in a memory corruption. Reported-by: Haogang Chen Signed-off-by: Xi Wang Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 4 ++++ include/drm/drm_mode.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 405c63b9d539..8323fc389840 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1873,6 +1873,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, } if (num_clips && clips_ptr) { + if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { + ret = -EINVAL; + goto out_err1; + } clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); if (!clips) { ret = -ENOMEM; diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index d30bedfeb7ef..ddd46db65b57 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -235,6 +235,8 @@ struct drm_mode_fb_cmd { #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 #define DRM_MODE_FB_DIRTY_FLAGS 0x03 +#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 + /* * Mark a region of a framebuffer as dirty. * -- cgit From 5151412dd4338b273afdb107c3772528e9e67d92 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Wed, 23 Nov 2011 10:59:13 +0100 Subject: block: initialize request_queue's numa node during struct request_queue is allocated with __GFP_ZERO so its "node" field is zero before initialization. This causes an oops if node 0 is offline in the page allocator because its zonelists are not initialized. From Dave Young's dmesg: SRAT: Node 1 PXM 2 0-d0000000 SRAT: Node 1 PXM 2 100000000-330000000 SRAT: Node 0 PXM 1 330000000-630000000 Initmem setup node 1 0000000000000000-000000000affb000 ... Built 1 zonelists in Node order, mobility grouping on. ... BUG: unable to handle kernel paging request at 0000000000001c08 IP: [] __alloc_pages_nodemask+0xb5/0x870 and __alloc_pages_nodemask+0xb5 translates to a NULL pointer on zonelist->_zonerefs. The fix is to initialize q->node at the time of allocation so the correct node is passed to the slab allocator later. Since blk_init_allocated_queue_node() is no longer needed, merge it with blk_init_allocated_queue(). [rientjes@google.com: changelog, initializing q->node] Cc: stable@vger.kernel.org [2.6.37+] Reported-by: Dave Young Signed-off-by: Mike Snitzer Signed-off-by: David Rientjes Tested-by: Dave Young Signed-off-by: Jens Axboe --- block/blk-core.c | 14 +++----------- include/linux/blkdev.h | 3 --- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index ea70e6c80cd3..20d69f6beb6b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -467,6 +467,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) q->backing_dev_info.state = 0; q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY; q->backing_dev_info.name = "block"; + q->node = node_id; err = bdi_init(&q->backing_dev_info); if (err) { @@ -551,7 +552,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) if (!uninit_q) return NULL; - q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id); + q = blk_init_allocated_queue(uninit_q, rfn, lock); if (!q) blk_cleanup_queue(uninit_q); @@ -562,19 +563,10 @@ EXPORT_SYMBOL(blk_init_queue_node); struct request_queue * blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, spinlock_t *lock) -{ - return blk_init_allocated_queue_node(q, rfn, lock, -1); -} -EXPORT_SYMBOL(blk_init_allocated_queue); - -struct request_queue * -blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, - spinlock_t *lock, int node_id) { if (!q) return NULL; - q->node = node_id; if (blk_init_free_list(q)) return NULL; @@ -604,7 +596,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, return NULL; } -EXPORT_SYMBOL(blk_init_allocated_queue_node); +EXPORT_SYMBOL(blk_init_allocated_queue); int blk_get_queue(struct request_queue *q) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c7a6d3b5bc7b..94acd8172b5b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -805,9 +805,6 @@ extern void blk_unprep_request(struct request *); */ extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id); -extern struct request_queue *blk_init_allocated_queue_node(struct request_queue *, - request_fn_proc *, - spinlock_t *, int node_id); extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *); extern struct request_queue *blk_init_allocated_queue(struct request_queue *, request_fn_proc *, spinlock_t *); -- cgit From 4ca8af579c9748376db537575f7a811c179fe50a Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 23 Nov 2011 10:39:10 +0100 Subject: ASoC: drop support for PlayPaq with WM8510 SoC Audio support for PlayPaq with WM8510 got added in commit 9aaca9683b ("[ALSA] Revised AT32 ASoC Patch"). That support depends on BOARD_PLAYPAQ. That Kconfig symbol didn't exist when that support got added in v2.6.27. It still doesn't. It has never been possible to even build this driver. Drop it. Signed-off-by: Paul Bolle Signed-off-by: Mark Brown --- sound/soc/atmel/Kconfig | 21 +- sound/soc/atmel/Makefile | 4 - sound/soc/atmel/playpaq_wm8510.c | 473 --------------------------------------- 3 files changed, 1 insertion(+), 497 deletions(-) delete mode 100644 sound/soc/atmel/playpaq_wm8510.c diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index bee3c94f58b0..d1fcc816ce97 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -1,6 +1,6 @@ config SND_ATMEL_SOC tristate "SoC Audio for the Atmel System-on-Chip" - depends on ARCH_AT91 || AVR32 + depends on ARCH_AT91 help Say Y or M if you want to add support for codecs attached to the ATMEL SSC interface. You will also need @@ -24,25 +24,6 @@ config SND_AT91_SOC_SAM9G20_WM8731 Say Y if you want to add support for SoC audio on WM8731-based AT91sam9g20 evaluation board. -config SND_AT32_SOC_PLAYPAQ - tristate "SoC Audio support for PlayPaq with WM8510" - depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS - select SND_ATMEL_SOC_SSC - select SND_SOC_WM8510 - help - Say Y or M here if you want to add support for SoC audio - on the LRS PlayPaq. - -config SND_AT32_SOC_PLAYPAQ_SLAVE - bool "Run CODEC on PlayPaq in slave mode" - depends on SND_AT32_SOC_PLAYPAQ - default n - help - Say Y if you want to run with the AT32 SSC generating the BCLK - and FRAME signals on the PlayPaq. Unless you want to play - with the AT32 as the SSC master, you probably want to say N here, - as this will give you better sound quality. - config SND_AT91_SOC_AFEB9260 tristate "SoC Audio support for AFEB9260 board" depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index e7ea56bd5f82..a5c0bf19da78 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile @@ -8,9 +8,5 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o -# AT32 Machine Support -snd-soc-playpaq-objs := playpaq_wm8510.o - obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o -obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c deleted file mode 100644 index 73ae99ad4578..000000000000 --- a/sound/soc/atmel/playpaq_wm8510.c +++ /dev/null @@ -1,473 +0,0 @@ -/* sound/soc/at32/playpaq_wm8510.c - * ASoC machine driver for PlayPaq using WM8510 codec - * - * Copyright (C) 2008 Long Range Systems - * Geoffrey Wossum - * - * 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 code is largely inspired by sound/soc/at91/eti_b1_wm8731.c - * - * NOTE: If you don't have the AT32 enhanced portmux configured (which - * isn't currently in the mainline or Atmel patched kernel), you will - * need to set the MCLK pin (PA30) to peripheral A in your board initialization - * code. Something like: - * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); - * - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "../codecs/wm8510.h" -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - - -/*-------------------------------------------------------------------------*\ - * constants -\*-------------------------------------------------------------------------*/ -#define MCLK_PIN GPIO_PIN_PA(30) -#define MCLK_PERIPH GPIO_PERIPH_A - - -/*-------------------------------------------------------------------------*\ - * data types -\*-------------------------------------------------------------------------*/ -/* SSC clocking data */ -struct ssc_clock_data { - /* CMR div */ - unsigned int cmr_div; - - /* Frame period (as needed by xCMR.PERIOD) */ - unsigned int period; - - /* The SSC clock rate these settings where calculated for */ - unsigned long ssc_rate; -}; - - -/*-------------------------------------------------------------------------*\ - * module data -\*-------------------------------------------------------------------------*/ -static struct clk *_gclk0; -static struct clk *_pll0; - -#define CODEC_CLK (_gclk0) - - -/*-------------------------------------------------------------------------*\ - * Sound SOC operations -\*-------------------------------------------------------------------------*/ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); - struct ssc_device *ssc = ssc_p->ssc; - struct ssc_clock_data cd; - unsigned int rate, width_bits, channels; - unsigned int bitrate, ssc_div; - unsigned actual_rate; - - - /* - * Figure out required bitrate - */ - rate = params_rate(params); - channels = params_channels(params); - width_bits = snd_pcm_format_physical_width(params_format(params)); - bitrate = rate * width_bits * channels; - - - /* - * Figure out required SSC divider and period for required bitrate - */ - cd.ssc_rate = clk_get_rate(ssc->clk); - ssc_div = cd.ssc_rate / bitrate; - cd.cmr_div = ssc_div / 2; - if (ssc_div & 1) { - /* round cmr_div up */ - cd.cmr_div++; - } - cd.period = width_bits - 1; - - - /* - * Find actual rate, compare to requested rate - */ - actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); - pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n", - rate, actual_rate); - - - return cd; -} -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - -static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); - struct ssc_device *ssc = ssc_p->ssc; - unsigned int pll_out = 0, bclk = 0, mclk_div = 0; - int ret; - - - /* Due to difficulties with getting the correct clocks from the AT32's - * PLL0, we're going to let the CODEC be in charge of all the clocks - */ -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - const unsigned int fmt = (SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); -#else - struct ssc_clock_data cd; - const unsigned int fmt = (SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); -#endif - - if (ssc == NULL) { - pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n"); - return -EINVAL; - } - - - /* - * Figure out PLL and BCLK dividers for WM8510 - */ - switch (params_rate(params)) { - case 48000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_2; - bclk = WM8510_BCLKDIV_8; - break; - - case 44100: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_2; - bclk = WM8510_BCLKDIV_8; - break; - - case 22050: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_4; - bclk = WM8510_BCLKDIV_8; - break; - - case 16000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_6; - bclk = WM8510_BCLKDIV_8; - break; - - case 11025: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_8; - bclk = WM8510_BCLKDIV_8; - break; - - case 8000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_12; - bclk = WM8510_BCLKDIV_8; - break; - - default: - pr_warning("playpaq_wm8510: Unsupported sample rate %d\n", - params_rate(params)); - return -EINVAL; - } - - - /* - * set CPU and CODEC DAI configuration - */ - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CODEC DAI format (%d)\n", - ret); - return ret; - } - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CPU DAI format (%d)\n", - ret); - return ret; - } - - - /* - * Set CPU clock configuration - */ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai); - pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n", - cd.cmr_div, cd.period); - ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n", - ret); - return ret; - } - ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD, - cd.period); - if (ret < 0) { - pr_warning("playpaq_wm8510: " - "Failed to set CPU transmit period (%d)\n", - ret); - return ret; - } -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - /* - * Set CODEC clock configuration - */ - pr_debug("playpaq_wm8510: " - "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n", - clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div); - - -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk); - if (ret < 0) { - pr_warning - ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n", - ret); - return ret; - } -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - ret = snd_soc_dai_set_pll(codec_dai, 0, 0, - clk_get_rate(CODEC_CLK), pll_out); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", - ret); - return ret; - } - - - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div); - if (ret < 0) { - pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n", - ret); - return ret; - } - - - return 0; -} - - - -static struct snd_soc_ops playpaq_wm8510_ops = { - .hw_params = playpaq_wm8510_hw_params, -}; - - - -static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Int Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), -}; - - - -static const struct snd_soc_dapm_route intercon[] = { - /* speaker connected to SPKOUT */ - {"Ext Spk", NULL, "SPKOUTP"}, - {"Ext Spk", NULL, "SPKOUTN"}, - - {"Mic Bias", NULL, "Int Mic"}, - {"MICN", NULL, "Mic Bias"}, - {"MICP", NULL, "Mic Bias"}, -}; - - - -static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int i; - - /* - * Add DAPM widgets - */ - for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++) - snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]); - - - - /* - * Setup audio path interconnects - */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - - - /* always connected pins */ - snd_soc_dapm_enable_pin(dapm, "Int Mic"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - - - - /* Make CSB show PLL rate */ - snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, - WM8510_OPCLKDIV_1 | 4); - - return 0; -} - - - -static struct snd_soc_dai_link playpaq_wm8510_dai = { - .name = "WM8510", - .stream_name = "WM8510 PCM", - .cpu_dai_name= "atmel-ssc-dai.0", - .platform_name = "atmel-pcm-audio", - .codec_name = "wm8510-codec.0-0x1a", - .codec_dai_name = "wm8510-hifi", - .init = playpaq_wm8510_init, - .ops = &playpaq_wm8510_ops, -}; - - - -static struct snd_soc_card snd_soc_playpaq = { - .name = "LRS_PlayPaq_WM8510", - .dai_link = &playpaq_wm8510_dai, - .num_links = 1, -}; - -static struct platform_device *playpaq_snd_device; - - -static int __init playpaq_asoc_init(void) -{ - int ret = 0; - - /* - * Configure MCLK for WM8510 - */ - _gclk0 = clk_get(NULL, "gclk0"); - if (IS_ERR(_gclk0)) { - _gclk0 = NULL; - ret = PTR_ERR(_gclk0); - goto err_gclk0; - } - _pll0 = clk_get(NULL, "pll0"); - if (IS_ERR(_pll0)) { - _pll0 = NULL; - ret = PTR_ERR(_pll0); - goto err_pll0; - } - ret = clk_set_parent(_gclk0, _pll0); - if (ret) { - pr_warning("snd-soc-playpaq: " - "Failed to set PLL0 as parent for DAC clock\n"); - goto err_set_clk; - } - clk_set_rate(CODEC_CLK, 12000000); - clk_enable(CODEC_CLK); - -#if defined CONFIG_AT32_ENHANCED_PORTMUX - at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0); -#endif - - - /* - * Create and register platform device - */ - playpaq_snd_device = platform_device_alloc("soc-audio", 0); - if (playpaq_snd_device == NULL) { - ret = -ENOMEM; - goto err_device_alloc; - } - - platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); - - ret = platform_device_add(playpaq_snd_device); - if (ret) { - pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n", - ret); - goto err_device_add; - } - - return 0; - - -err_device_add: - if (playpaq_snd_device != NULL) { - platform_device_put(playpaq_snd_device); - playpaq_snd_device = NULL; - } -err_device_alloc: -err_set_clk: - if (_pll0 != NULL) { - clk_put(_pll0); - _pll0 = NULL; - } -err_pll0: - if (_gclk0 != NULL) { - clk_put(_gclk0); - _gclk0 = NULL; - } - return ret; -} - - -static void __exit playpaq_asoc_exit(void) -{ - if (_gclk0 != NULL) { - clk_put(_gclk0); - _gclk0 = NULL; - } - if (_pll0 != NULL) { - clk_put(_pll0); - _pll0 = NULL; - } - -#if defined CONFIG_AT32_ENHANCED_PORTMUX - at32_free_pin(MCLK_PIN); -#endif - - platform_device_unregister(playpaq_snd_device); - playpaq_snd_device = NULL; -} - -module_init(playpaq_asoc_init); -module_exit(playpaq_asoc_exit); - -MODULE_AUTHOR("Geoffrey Wossum "); -MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq"); -MODULE_LICENSE("GPL"); -- cgit From cc6bcf7d2ec2234e7b41770185e4dc826390185e Mon Sep 17 00:00:00 2001 From: "Jeffrey (Sheng-Hui) Chu" Date: Wed, 23 Nov 2011 11:33:07 +0100 Subject: i2c-algo-bit: Generate correct i2c address sequence for 10-bit target The wrong bits were put on the wire, fix that. This fixes kernel bug #42562. Signed-off-by: Sheng-Hui J. Chu Cc: stable@kernel.org Signed-off-by: Jean Delvare --- drivers/i2c/algos/i2c-algo-bit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 85584a547c25..525c7345fa0b 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -488,7 +488,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) if (flags & I2C_M_TEN) { /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x03); + addr = 0xf0 | ((msg->addr >> 7) & 0x06); bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr); /* try extended address code...*/ ret = try_address(i2c_adap, addr, retries); @@ -498,7 +498,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) return -ENXIO; } /* the remaining 8 bit address */ - ret = i2c_outb(i2c_adap, msg->addr & 0x7f); + ret = i2c_outb(i2c_adap, msg->addr & 0xff); if ((ret != 1) && !nak_ok) { /* the chip did not ack / xmission error occurred */ dev_err(&i2c_adap->dev, "died at 2nd address code\n"); -- cgit From cbb44514048a250647c6c6b3df27ff62cb71f7d5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 23 Nov 2011 11:33:07 +0100 Subject: i2c: Fix device name for 10-bit slave address 10-bit addresses overlap with traditional 7-bit addresses, leading in device name collisions. Add an arbitrary offset to 10-bit addresses to prevent this collision. The offset was chosen so that the address is still easily recognizable. Signed-off-by: Jean Delvare Acked-by: Wolfram Sang --- Documentation/i2c/ten-bit-addresses | 36 +++++++++++++++++++----------------- drivers/i2c/i2c-core.c | 4 +++- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Documentation/i2c/ten-bit-addresses b/Documentation/i2c/ten-bit-addresses index e9890709c508..cdfe13901b99 100644 --- a/Documentation/i2c/ten-bit-addresses +++ b/Documentation/i2c/ten-bit-addresses @@ -1,22 +1,24 @@ The I2C protocol knows about two kinds of device addresses: normal 7 bit addresses, and an extended set of 10 bit addresses. The sets of addresses do not intersect: the 7 bit address 0x10 is not the same as the 10 bit -address 0x10 (though a single device could respond to both of them). You -select a 10 bit address by adding an extra byte after the address -byte: - S Addr7 Rd/Wr .... -becomes - S 11110 Addr10 Rd/Wr -S is the start bit, Rd/Wr the read/write bit, and if you count the number -of bits, you will see the there are 8 after the S bit for 7 bit addresses, -and 16 after the S bit for 10 bit addresses. +address 0x10 (though a single device could respond to both of them). -WARNING! The current 10 bit address support is EXPERIMENTAL. There are -several places in the code that will cause SEVERE PROBLEMS with 10 bit -addresses, even though there is some basic handling and hooks. Also, -almost no supported adapter handles the 10 bit addresses correctly. +I2C messages to and from 10-bit address devices have a different format. +See the I2C specification for the details. -As soon as a real 10 bit address device is spotted 'in the wild', we -can and will add proper support. Right now, 10 bit address devices -are defined by the I2C protocol, but we have never seen a single device -which supports them. +The current 10 bit address support is minimal. It should work, however +you can expect some problems along the way: +* Not all bus drivers support 10-bit addresses. Some don't because the + hardware doesn't support them (SMBus doesn't require 10-bit address + support for example), some don't because nobody bothered adding the + code (or it's there but not working properly.) Software implementation + (i2c-algo-bit) is known to work. +* Some optional features do not support 10-bit addresses. This is the + case of automatic detection and instantiation of devices by their, + drivers, for example. +* Many user-space packages (for example i2c-tools) lack support for + 10-bit addresses. + +Note that 10-bit address devices are still pretty rare, so the limitations +listed above could stay for a long time, maybe even forever if nobody +needs them to be fixed. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 131079a3e292..1e5606185b4f 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -539,8 +539,10 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.type = &i2c_client_type; client->dev.of_node = info->of_node; + /* For 10-bit clients, add an arbitrary offset to avoid collisions */ dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), - client->addr); + client->addr | ((client->flags & I2C_CLIENT_TEN) + ? 0xa000 : 0)); status = device_register(&client->dev); if (status) goto out_err; -- cgit From 67820021dc9c8da37f773025190280f55f3626d4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 23 Nov 2011 11:33:07 +0100 Subject: i2c: Delete ANY_I2C_BUS Last piece of code using ANY_I2C_BUS was deleted almost 2 years ago, so ANY_I2C_BUS can go away as well. Signed-off-by: Jean Delvare --- include/linux/i2c.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/i2c.h b/include/linux/i2c.h index a81bf6d23b3e..07d103a06d64 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -432,9 +432,6 @@ void i2c_unlock_adapter(struct i2c_adapter *); /* Internal numbers to terminate lists */ #define I2C_CLIENT_END 0xfffeU -/* The numbers to use to set I2C bus address */ -#define ANY_I2C_BUS 0xffff - /* Construct an I2C_CLIENT_END-terminated array of i2c addresses */ #define I2C_ADDRS(addr, addrs...) \ ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END }) -- cgit From eff245c82f115059648cdce95dd68bb940f2b006 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Wed, 23 Nov 2011 11:33:07 +0100 Subject: i2c: Make i2cdev_notifier_call static The function i2cdev_notifier_call is used only in i2c-dev file making it static. Also removes the following sparse warning drivers/i2c/i2c-dev.c:582:5: warning: symbol 'i2cdev_notifier_call' was not declared. Should it be static? Signed-off-by: Shubhrajyoti D Signed-off-by: Jean Delvare --- drivers/i2c/i2c-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c90ce50b619f..57a45ce84b2d 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -579,7 +579,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy) return 0; } -int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, +static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; -- cgit From b284362b6b45150d171ff5bed92bc416b040aead Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 Nov 2011 12:46:11 +0800 Subject: ASoC: cs42l51: Fix off-by-one for reg_cache_size Just checking the code in cs42l51_fill_cache(): The cache pointer points to codec->reg_cache + 1. I think it is because CS42L51_FIRSTREG is 0x01, so codec->reg_cache[0] is not used here. Then we read CS42L51_NUMREGS bytes to cache. So we need reg_cache_size to be CS42L51_NUMREGS + 1. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 8c3c8205d19e..1ee66361f61b 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -555,7 +555,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS, + .reg_cache_size = CS42L51_NUMREGS + 1, .reg_word_size = sizeof(u8), }; -- cgit From b1807719f6acdf18cc4bde3b5400d05d77801494 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 16 Nov 2011 11:39:52 +0100 Subject: HID: Correct General touch PID Genera Touch told us that 0001 is their single point device and 0003 is the multitouch one. Apparently, we made the tests someone having a prototype, and not the final product. They said it should be safe to do the switch. This partially reverts 5572da0 ("HID: hid-mulitouch: add support for the 'Sensing Win7-TwoFinger'"). Signed-off-by: Benjamin Tissoires Cc: stable@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 +- drivers/hid/hid-ids.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 848a56c0279c..af353842f75f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1771,8 +1771,8 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 06ce996b8b65..4a441a6f9967 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -266,7 +266,7 @@ #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 -- cgit From 780dc9ba4eb682a89be48d5b814feae6722a19e0 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Tue, 8 Nov 2011 18:54:10 +0530 Subject: regulator: TPS65910: Fix VDD1/2 voltage selector count Count of selector voltage is required for regulator_set_voltage to work via set_voltage_sel. VDD1/2 currently have it as zero, so regulator_set_voltage won't work for VDD1/2. Update count (n_voltages) for VDD1/2. Output Voltage = (step value * 12.5 mV + 562.5 mV) * gain With above expr, number of voltages that can be selected is step value count * gain count constant for gain count will be called VDD1_2_NUM_VOLT_COARSE existing constant for step value count is VDD1_2_NUM_VOLTS, use VDD1_2_NUM_VOLT_FINE instead to make clear that step value is not the only component in deciding selectable voltage count Signed-off-by: Afzal Mohammed Signed-off-by: Mark Brown --- drivers/regulator/tps65910-regulator.c | 14 ++++++++------ include/linux/mfd/tps65910.h | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 66d2d60b436a..b552aae55b41 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -664,10 +664,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, switch (id) { case TPS65910_REG_VDD1: - dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; + dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; if (dcdc_mult == 1) dcdc_mult--; - vsel = (selector % VDD1_2_NUM_VOLTS) + 3; + vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; tps65910_modify_bits(pmic, TPS65910_VDD1, (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), @@ -675,10 +675,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); break; case TPS65910_REG_VDD2: - dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; + dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; if (dcdc_mult == 1) dcdc_mult--; - vsel = (selector % VDD1_2_NUM_VOLTS) + 3; + vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; tps65910_modify_bits(pmic, TPS65910_VDD2, (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), @@ -756,9 +756,9 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, switch (id) { case TPS65910_REG_VDD1: case TPS65910_REG_VDD2: - mult = (selector / VDD1_2_NUM_VOLTS) + 1; + mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; volt = VDD1_2_MIN_VOLT + - (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; + (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET; break; case TPS65911_REG_VDDCTRL: volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); @@ -947,6 +947,8 @@ static __devinit int tps65910_probe(struct platform_device *pdev) if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { pmic->desc[i].ops = &tps65910_ops_dcdc; + pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE * + VDD1_2_NUM_VOLT_COARSE; } else if (i == TPS65910_REG_VDD3) { if (tps65910_chip_id(tps65910) == TPS65910) pmic->desc[i].ops = &tps65910_ops_vdd3; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 82b4c8801a4f..8bf2cb9502dd 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -243,7 +243,8 @@ /*Registers VDD1, VDD2 voltage values definitions */ -#define VDD1_2_NUM_VOLTS 73 +#define VDD1_2_NUM_VOLT_FINE 73 +#define VDD1_2_NUM_VOLT_COARSE 3 #define VDD1_2_MIN_VOLT 6000 #define VDD1_2_OFFSET 125 -- cgit From 5ff1ddf22b2584d00d7e0ba5a8eab07b5338bd84 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 23 Nov 2011 22:37:00 +0800 Subject: ASoC: skip resume of soc-audio devices without codecs There are cases where there is no working codec on the soc-audio devices, and snd_soc_suspend() will skip such device when suspending. Yet its counterpart snd_soc_resume() does not check this, causing complaints about spinlock lockup: [ 176.726087] BUG: spinlock lockup on CPU#0, kworker/0:2/1067, d8ab82a8 [ 176.732539] [<80014a14>] (unwind_backtrace+0x0/0xec) from [<805b3fc8>] (dump_stack+0x20/0x24) [ 176.741082] [<805b3fc8>] (dump_stack+0x20/0x24) from [<80322208>] (do_raw_spin_lock+0x118/0x158) [ 176.749882] [<80322208>] (do_raw_spin_lock+0x118/0x158) from [<805b7874>] (_raw_spin_lock_irqsave+0x5c/0x68) [ 176.759723] [<805b7874>] (_raw_spin_lock_irqsave+0x5c/0x68) from [<8002a020>] (__wake_up+0x2c/0x5c) [ 176.768781] [<8002a020>] (__wake_up+0x2c/0x5c) from [<804a6de8>] (soc_resume_deferred+0x3c/0x2b0) [ 176.777666] [<804a6de8>] (soc_resume_deferred+0x3c/0x2b0) from [<8004ee20>] (process_one_work+0x2e8/0x50c) [ 176.787334] [<8004ee20>] (process_one_work+0x2e8/0x50c) from [<8004fd08>] (worker_thread+0x1c8/0x2e0) [ 176.796566] [<8004fd08>] (worker_thread+0x1c8/0x2e0) from [<80053ec8>] (kthread+0xa4/0xb0) [ 176.804843] [<80053ec8>] (kthread+0xa4/0xb0) from [<8000ea70>] (kernel_thread_exit+0x0/0x8) Signed-off-by: Eric Miao Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a5d3685a5d38..a25fa63ce9a2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -709,6 +709,12 @@ int snd_soc_resume(struct device *dev) struct snd_soc_card *card = dev_get_drvdata(dev); int i, ac97_control = 0; + /* If the initialization of this soc device failed, there is no codec + * associated with it. Just bail out in this case. + */ + if (list_empty(&card->codec_dev_list)) + return 0; + /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume -- cgit From 67589c71456b0346500629967292dea3802230b6 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 23 Nov 2011 08:20:53 -0800 Subject: percpu: explain why per_cpu_ptr_to_phys() is more complicated than necessary Add comments about current per_cpu_ptr_to_phys implementation to explain why the logic is more complicated than necessary. -tj: relocated comment into kerneldoc comment Signed-off-by: Dave Young Signed-off-by: Tejun Heo --- mm/percpu.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mm/percpu.c b/mm/percpu.c index 2473ff06dc76..3bb810a72006 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -978,6 +978,17 @@ bool is_kernel_percpu_address(unsigned long addr) * address. The caller is responsible for ensuring @addr stays valid * until this function finishes. * + * percpu allocator has special setup for the first chunk, which currently + * supports either embedding in linear address space or vmalloc mapping, + * and, from the second one, the backing allocator (currently either vm or + * km) provides translation. + * + * The addr can be tranlated simply without checking if it falls into the + * first chunk. But the current code reflects better how percpu allocator + * actually works, and the verification can discover both bugs in percpu + * allocator itself and per_cpu_ptr_to_phys() callers. So we keep current + * code. + * * RETURNS: * The physical address for @addr. */ -- cgit From c2735391fbc68feae10d6d14e60956c8106e725f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 10 Sep 2011 12:26:07 +0200 Subject: arm: mx28: fix bit operation in clock setting reg | (1 << clk->enable_shift) always evaluates to true. Switch it to & which makes much more sense. Same fix as 13be9f00 (ARM i.MX28: fix bit operation) at a different location. Signed-off-by: Wolfram Sang Cc: Sascha Hauer Cc: Shawn Guo Signed-off-by: Shawn Guo Cc: stable@kernel.org Signed-off-by: Arnd Bergmann --- arch/arm/mach-mxs/clock-mx28.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 229ae3494216..da6e4aad177c 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -404,7 +404,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg | (1 << clk->enable_shift)) { \ + if (reg & (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ -- cgit From bb58dd5d1ffad6c2d21c69698ba766dad4ae54e6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Nov 2011 23:08:10 +0100 Subject: PM / Hibernate: Do not leak memory in error/test code paths The hibernation core code forgets to release memory preallocated for hibernation if there's an error in its early stages or if test modes causing hibernation_snapshot() to return early are used. This causes the system to be hardly usable, because the amount of preallocated memory is usually huge. Fix this problem. Reported-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki Acked-by: Srivatsa S. Bhat --- kernel/power/hibernate.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 196c01268ebd..a6b0503574ee 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -347,7 +347,7 @@ int hibernation_snapshot(int platform_mode) error = freeze_kernel_threads(); if (error) - goto Close; + goto Cleanup; if (hibernation_test(TEST_FREEZER) || hibernation_testmode(HIBERNATION_TESTPROC)) { @@ -357,12 +357,14 @@ int hibernation_snapshot(int platform_mode) * successful freezer test. */ freezer_test_done = true; - goto Close; + goto Cleanup; } error = dpm_prepare(PMSG_FREEZE); - if (error) - goto Complete_devices; + if (error) { + dpm_complete(msg); + goto Cleanup; + } suspend_console(); pm_restrict_gfp_mask(); @@ -391,8 +393,6 @@ int hibernation_snapshot(int platform_mode) pm_restore_gfp_mask(); resume_console(); - - Complete_devices: dpm_complete(msg); Close: @@ -402,6 +402,10 @@ int hibernation_snapshot(int platform_mode) Recover_platform: platform_recover(platform_mode); goto Resume_devices; + + Cleanup: + swsusp_free(); + goto Close; } /** -- cgit From c16a98ed91597b40b22b540c6517103497ef8e74 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 23 Nov 2011 15:49:31 -0500 Subject: ipv6: tcp: fix panic in SYN processing commit 72a3effaf633bc ([NET]: Size listen hash tables using backlog hint) added a bug allowing inet6_synq_hash() to return an out of bound array index, because of u16 overflow. Bug can happen if system admins set net.core.somaxconn & net.ipv4.tcp_max_syn_backlog sysctls to values greater than 65536 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/inet6_connection_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index fee46d5a2f12..1567fb120392 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -85,7 +85,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, * request_sock (formerly open request) hash tables. */ static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, - const u32 rnd, const u16 synq_hsize) + const u32 rnd, const u32 synq_hsize) { u32 c; -- cgit From 46a246c4dff9f248913e791b69f2336cd8d4ec41 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 Nov 2011 16:07:00 -0500 Subject: netfilter: Remove NOTRACK/RAW dependency on NETFILTER_ADVANCED. Distributions are using this in their default scripts, so don't hide them behind the advanced setting. Reported-by: Linus Torvalds Signed-off-by: David S. Miller --- net/ipv4/netfilter/Kconfig | 1 - net/ipv6/netfilter/Kconfig | 1 - net/netfilter/Kconfig | 1 - 3 files changed, 3 deletions(-) diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 1dfc18a03fd4..f19f2182894c 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -325,7 +325,6 @@ config IP_NF_TARGET_TTL # raw + specific targets config IP_NF_RAW tristate 'raw table support (required for NOTRACK/TRACE)' - depends on NETFILTER_ADVANCED help This option adds a `raw' table to iptables. This table is the very first in the netfilter framework and hooks in at the PREROUTING diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 448464844a25..f792b34cbe9c 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -186,7 +186,6 @@ config IP6_NF_MANGLE config IP6_NF_RAW tristate 'raw table support (required for TRACE)' - depends on NETFILTER_ADVANCED help This option adds a `raw' table to ip6tables. This table is the very first in the netfilter framework and hooks in at the PREROUTING diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 8260b13d93c9..e8f379692294 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -542,7 +542,6 @@ config NETFILTER_XT_TARGET_NOTRACK tristate '"NOTRACK" target support' depends on IP_NF_RAW || IP6_NF_RAW depends on NF_CONNTRACK - depends on NETFILTER_ADVANCED help The NOTRACK target allows a select rule to specify which packets *not* to enter the conntrack/NAT -- cgit From 8d715f0024f64ad1b1be85d8c081cf577944c847 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Nov 2011 20:39:01 -0800 Subject: drm/i915: add multi-threaded forcewake support On IVB C0+ with newer BIOSes, the forcewake handshake has changed. There's now a bitfield for different driver components to keep the GT powered on. On Linux, we centralize forcewake handling in one place, so we still just need a single bit, but we need to use the new registers if MT forcewake is enabled. This needs testing on affected machines. Please reply with your tested-by if you had problems after a BIOS upgrade and this patch fixes them. v2: force MT mode. shift by 16 v3: set MT force wake bits then check ECOBUS Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=42923 Tested-by: Manoj Iyer Tested-by: Robert Hooker Tested-by: Keith Packard Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.c | 35 +++++++++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_drv.h | 13 +++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 15bfa9145d2b..28836fe72211 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -328,7 +328,7 @@ void intel_detect_pch(struct drm_device *dev) } } -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { int count; @@ -344,6 +344,22 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) udelay(10); } +void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1); + POSTING_READ(FORCEWAKE_MT); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) + udelay(10); +} + /* * Generally this is called implicitly by the register read function. However, * if some sequence requires the GT to not power down then this function should @@ -356,15 +372,21 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) /* Forcewake is atomic in case we get in here without the lock */ if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) - __gen6_gt_force_wake_get(dev_priv); + dev_priv->display.force_wake_get(dev_priv); } -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); POSTING_READ(FORCEWAKE); } +void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0); + POSTING_READ(FORCEWAKE_MT); +} + /* * see gen6_gt_force_wake_get() */ @@ -373,7 +395,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (atomic_dec_and_test(&dev_priv->forcewake_count)) - __gen6_gt_force_wake_put(dev_priv); + dev_priv->display.force_wake_put(dev_priv); } void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) @@ -903,8 +925,9 @@ MODULE_LICENSE("GPL and additional rights"); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE) && \ + ((reg) != ECOBUS)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4a9c1b979804..8ba88cfc36de 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -107,6 +107,7 @@ struct opregion_header; struct opregion_acpi; struct opregion_swsci; struct opregion_asle; +struct drm_i915_private; struct intel_opregion { struct opregion_header *header; @@ -221,6 +222,8 @@ struct drm_i915_display_funcs { struct drm_i915_gem_object *obj); int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y); + void (*force_wake_get)(struct drm_i915_private *dev_priv); + void (*force_wake_put)(struct drm_i915_private *dev_priv); /* clock updates for mode set */ /* cursor updates */ /* render clock increase/decrease */ @@ -1308,6 +1311,11 @@ extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); +extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); + /* overlay */ #ifdef CONFIG_DEBUG_FS extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); @@ -1352,8 +1360,9 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE) && \ + ((reg) != ECOBUS)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b080cc824001..8990057e384c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3449,6 +3449,10 @@ #define FORCEWAKE 0xA18C #define FORCEWAKE_ACK 0x130090 +#define FORCEWAKE_MT 0xa188 /* multi-threaded */ +#define FORCEWAKE_MT_ACK 0x130040 +#define ECOBUS 0xa180 +#define FORCEWAKE_MT_ENABLE (1<<5) #define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_NUM_RESERVED_ENTRIES 20 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e77a863a3833..633c69365388 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8491,6 +8491,28 @@ static void intel_init_display(struct drm_device *dev) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; + + /* IVB configs may use multi-threaded forcewake */ + if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + DRM_DEBUG_KMS("Using MT version of forcewake\n"); + dev_priv->display.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->display.force_wake_put = + __gen6_gt_force_wake_mt_put; + } + } + if (HAS_PCH_IBX(dev)) dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; else if (HAS_PCH_CPT(dev)) -- cgit From 1a2eb4604b85c5efb343da8a4dcf41288fcfca85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Nov 2011 16:26:07 -0800 Subject: drm/i915: Hook up Ivybridge eDP The Ivybridge eDP control register looks like a cross between a Cougarpoint PCH DP control register and a Sandybridge eDP control register. Where things trivially match, share the code. Where there are any tricky bits, just split things out into two obviously separate code paths. Signed-off-by: Keith Packard Tested-by: Fang Xun Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41991 --- drivers/gpu/drm/i915/i915_reg.h | 18 +++++ drivers/gpu/drm/i915/intel_dp.c | 149 +++++++++++++++++++++++++++++++--------- 2 files changed, 133 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8990057e384c..6ef68c74189d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3447,6 +3447,24 @@ #define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22) #define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) +/* IVB */ +#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 <<22) +#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a <<22) +#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f <<22) +#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22) +#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22) +#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22) +#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22) + +/* legacy values */ +#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22) +#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 <<22) +#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 <<22) +#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 <<22) +#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 <<22) + +#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22) + #define FORCEWAKE 0xA18C #define FORCEWAKE_ACK 0x130090 #define FORCEWAKE_MT 0xa188 /* multi-threaded */ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4d0358fad937..294f55788f0b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -362,8 +362,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, * clock divider. */ if (is_cpu_edp(intel_dp)) { - if (IS_GEN6(dev)) - aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ + if (IS_GEN6(dev) || IS_GEN7(dev)) + aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */ else aux_clock_divider = 225; /* eDP input clock at 450Mhz */ } else if (HAS_PCH_SPLIT(dev)) @@ -817,10 +817,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } /* - * There are three kinds of DP registers: + * There are four kinds of DP registers: * * IBX PCH - * CPU + * SNB CPU + * IVB CPU * CPT PCH * * IBX PCH and CPU are the same for almost everything, @@ -873,7 +874,25 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* Split out the IBX/CPU vs CPT settings */ - if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { + if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) { + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + intel_dp->DP |= DP_SYNC_HS_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + intel_dp->DP |= DP_SYNC_VS_HIGH; + intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; + + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + intel_dp->DP |= DP_ENHANCED_FRAMING; + + intel_dp->DP |= intel_crtc->pipe << 29; + + /* don't miss out required setting for eDP */ + intel_dp->DP |= DP_PLL_ENABLE; + if (adjusted_mode->clock < 200000) + intel_dp->DP |= DP_PLL_FREQ_160MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { intel_dp->DP |= intel_dp->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1375,34 +1394,59 @@ static char *link_train_names[] = { * These are source-specific values; current Intel hardware supports * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB */ -#define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 -#define I830_DP_VOLTAGE_MAX_CPT DP_TRAIN_VOLTAGE_SWING_1200 static uint8_t -intel_dp_pre_emphasis_max(uint8_t voltage_swing) +intel_dp_voltage_max(struct intel_dp *intel_dp) { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_400: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_600: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_800: - return DP_TRAIN_PRE_EMPHASIS_3_5; - case DP_TRAIN_VOLTAGE_SWING_1200: - default: - return DP_TRAIN_PRE_EMPHASIS_0; + struct drm_device *dev = intel_dp->base.base.dev; + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_800; + else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_1200; + else + return DP_TRAIN_VOLTAGE_SWING_800; +} + +static uint8_t +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) +{ + struct drm_device *dev = intel_dp->base.base.dev; + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } else { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } } } static void intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { - struct drm_device *dev = intel_dp->base.base.dev; uint8_t v = 0; uint8_t p = 0; int lane; uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS); - int voltage_max; + uint8_t voltage_max; + uint8_t preemph_max; for (lane = 0; lane < intel_dp->lane_count; lane++) { uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane); @@ -1414,15 +1458,13 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST p = this_p; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) - voltage_max = I830_DP_VOLTAGE_MAX_CPT; - else - voltage_max = I830_DP_VOLTAGE_MAX; + voltage_max = intel_dp_voltage_max(intel_dp); if (v >= voltage_max) v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; - if (p >= intel_dp_pre_emphasis_max(v)) - p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); + if (p >= preemph_max) + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; for (lane = 0; lane < 4; lane++) intel_dp->train_set[lane] = v | p; @@ -1494,6 +1536,37 @@ intel_gen6_edp_signal_levels(uint8_t train_set) } } +/* Gen7's DP voltage swing and pre-emphasis control */ +static uint32_t +intel_gen7_edp_signal_levels(uint8_t train_set) +{ + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_400MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_400MV_3_5DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: + return EDP_LINK_TRAIN_400MV_6DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_600MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_600MV_3_5DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_800MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_800MV_3_5DB_IVB; + + default: + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" + "0x%x\n", signal_levels); + return EDP_LINK_TRAIN_500MV_0DB_IVB; + } +} + static uint8_t intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) @@ -1599,7 +1672,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP_LINK_CONFIGURATION_SIZE); DP |= DP_PORT_EN; - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) DP &= ~DP_LINK_TRAIN_MASK_CPT; else DP &= ~DP_LINK_TRAIN_MASK; @@ -1613,7 +1687,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) uint8_t link_status[DP_LINK_STATUS_SIZE]; uint32_t signal_levels; - if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; + } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { @@ -1622,7 +1700,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_PAT_1_CPT; else reg = DP | DP_LINK_TRAIN_PAT_1; @@ -1703,7 +1781,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) break; } - if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; + } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { @@ -1711,7 +1792,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_PAT_2_CPT; else reg = DP | DP_LINK_TRAIN_PAT_2; @@ -1752,7 +1833,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ++tries; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_OFF_CPT; else reg = DP | DP_LINK_TRAIN_OFF; @@ -1782,7 +1863,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) udelay(100); } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) { + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { DP &= ~DP_LINK_TRAIN_MASK_CPT; I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); } else { @@ -1794,7 +1875,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) msleep(17); if (is_edp(intel_dp)) { - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) DP |= DP_LINK_TRAIN_OFF_CPT; else DP |= DP_LINK_TRAIN_OFF; -- cgit From ca88479c1c3b7b1a9f94320745f5331e1de77f80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Nov 2011 11:09:24 -0800 Subject: drm/i915: Treat pre-gen4 backlight duty cycle value consistently For i945 and earlier chips, the backlight frequency value had the low bit (of 16) fixed to zero. The Pineview code path handled this by just exposing the backlight range as 15 bits while other chips had the backlight range limited to 0 .. 0xfffe. This patch makes everyone take the pineview code path, providing 15 bits of backlight duty cycle range which seems more than sufficient to me. Daniel Mack reported that writing 1 to bit 0 of the duty cycle register was causing problems on his Samsung X20 notebook, even when the duty cycle value was less than the maximum backlight value. (He tried a value of 29749 with max_brightness of 29750). This patch never writes a '1' to that bit. Signed-off-by: Keith Packard Reviewed-by: Takashi Iwai Reported-and-tested-by: Daniel Mack Cc: stable@kernel.org --- drivers/gpu/drm/i915/intel_panel.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 21f60b7d69a3..04d79fd1dc9d 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -178,13 +178,10 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { max >>= 16; } else { - if (IS_PINEVIEW(dev)) { + if (INTEL_INFO(dev)->gen < 4) max >>= 17; - } else { + else max >>= 16; - if (INTEL_INFO(dev)->gen < 4) - max &= ~1; - } if (is_backlight_combination_mode(dev)) max *= 0xff; @@ -203,13 +200,12 @@ u32 intel_panel_get_backlight(struct drm_device *dev) val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (IS_PINEVIEW(dev)) + if (INTEL_INFO(dev)->gen < 4) val >>= 1; if (is_backlight_combination_mode(dev)) { u8 lbpc; - val &= ~1; pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); val *= lbpc; } @@ -246,11 +242,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level } tmp = I915_READ(BLC_PWM_CTL); - if (IS_PINEVIEW(dev)) { - tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); + if (INTEL_INFO(dev)->gen < 4) level <<= 1; - } else - tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; + tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; I915_WRITE(BLC_PWM_CTL, tmp | level); } -- cgit From b59db43ad4434519feb338eacb01d77eb50825c5 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 21 Nov 2011 17:31:02 -0600 Subject: eCryptfs: Prevent file create race condition The file creation path prematurely called d_instantiate() and unlock_new_inode() before the eCryptfs inode info was fully allocated and initialized and before the eCryptfs metadata was written to the lower file. This could result in race conditions in subsequent file and inode operations leading to unexpected error conditions or a null pointer dereference while attempting to use the unallocated memory. https://launchpad.net/bugs/813146 Signed-off-by: Tyler Hicks Cc: stable@kernel.org --- fs/ecryptfs/crypto.c | 22 +++++++++--------- fs/ecryptfs/ecryptfs_kernel.h | 5 +++-- fs/ecryptfs/inode.c | 52 ++++++++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 58609bde3b9f..203a1fdff666 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -967,7 +967,7 @@ static void ecryptfs_set_default_crypt_stat_vals( /** * ecryptfs_new_file_context - * @ecryptfs_dentry: The eCryptfs dentry + * @ecryptfs_inode: The eCryptfs inode * * If the crypto context for the file has not yet been established, * this is where we do that. Establishing a new crypto context @@ -984,13 +984,13 @@ static void ecryptfs_set_default_crypt_stat_vals( * * Returns zero on success; non-zero otherwise */ -int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) +int ecryptfs_new_file_context(struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; + ecryptfs_inode->i_sb)->mount_crypt_stat; int cipher_name_len; int rc = 0; @@ -1299,12 +1299,12 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max, } static int -ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry, +ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode, char *virt, size_t virt_len) { int rc; - rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, + rc = ecryptfs_write_lower(ecryptfs_inode, virt, 0, virt_len); if (rc < 0) printk(KERN_ERR "%s: Error attempting to write header " @@ -1338,7 +1338,8 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, /** * ecryptfs_write_metadata - * @ecryptfs_dentry: The eCryptfs dentry + * @ecryptfs_dentry: The eCryptfs dentry, which should be negative + * @ecryptfs_inode: The newly created eCryptfs inode * * Write the file headers out. This will likely involve a userspace * callout, in which the session key is encrypted with one or more @@ -1348,10 +1349,11 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, * * Returns zero on success; non-zero on error */ -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; unsigned int order; char *virt; size_t virt_len; @@ -1391,7 +1393,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt, size); else - rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt, + rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt, virt_len); if (rc) { printk(KERN_ERR "%s: Error writing metadata out to lower file; " diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 54481a3b2c79..a9f29b12fbf2 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -584,9 +584,10 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode); int ecryptfs_encrypt_page(struct page *page); int ecryptfs_decrypt_page(struct page *page); -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry); +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode); int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry); -int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); +int ecryptfs_new_file_context(struct inode *ecryptfs_inode); void ecryptfs_write_crypt_stat_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, size_t *written); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index a36d327f1521..32f90a3ae63e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -172,22 +172,23 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode, * it. It will also update the eCryptfs directory inode to mimic the * stat of the lower directory inode. * - * Returns zero on success; non-zero on error condition + * Returns the new eCryptfs inode on success; an ERR_PTR on error condition */ -static int +static struct inode * ecryptfs_do_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, int mode) { int rc; struct dentry *lower_dentry; struct dentry *lower_dir_dentry; + struct inode *inode; lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); lower_dir_dentry = lock_parent(lower_dentry); if (IS_ERR(lower_dir_dentry)) { ecryptfs_printk(KERN_ERR, "Error locking directory of " "dentry\n"); - rc = PTR_ERR(lower_dir_dentry); + inode = ERR_CAST(lower_dir_dentry); goto out; } rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode, @@ -195,20 +196,19 @@ ecryptfs_do_create(struct inode *directory_inode, if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc = [%d]\n", __func__, rc); + inode = ERR_PTR(rc); goto out_lock; } - rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, - directory_inode->i_sb); - if (rc) { - ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); + inode = __ecryptfs_get_inode(lower_dentry->d_inode, + directory_inode->i_sb); + if (IS_ERR(inode)) goto out_lock; - } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: unlock_dir(lower_dir_dentry); out: - return rc; + return inode; } /** @@ -219,26 +219,26 @@ out: * * Returns zero on success */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) +static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc = 0; - if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { + if (S_ISDIR(ecryptfs_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); - rc = ecryptfs_new_file_context(ecryptfs_dentry); + rc = ecryptfs_new_file_context(ecryptfs_inode); if (rc) { ecryptfs_printk(KERN_ERR, "Error creating new file " "context; rc = [%d]\n", rc); goto out; } - rc = ecryptfs_get_lower_file(ecryptfs_dentry, - ecryptfs_dentry->d_inode); + rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " "the lower file for the dentry with name " @@ -246,10 +246,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) ecryptfs_dentry->d_name.name, rc); goto out; } - rc = ecryptfs_write_metadata(ecryptfs_dentry); + rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode); if (rc) printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); - ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); + ecryptfs_put_lower_file(ecryptfs_inode); out: return rc; } @@ -269,18 +269,28 @@ static int ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, int mode, struct nameidata *nd) { + struct inode *ecryptfs_inode; int rc; - /* ecryptfs_do_create() calls ecryptfs_interpose() */ - rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode); - if (unlikely(rc)) { + ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry, + mode); + if (unlikely(IS_ERR(ecryptfs_inode))) { ecryptfs_printk(KERN_WARNING, "Failed to create file in" "lower filesystem\n"); + rc = PTR_ERR(ecryptfs_inode); goto out; } /* At this point, a file exists on "disk"; we need to make sure * that this on disk file is prepared to be an ecryptfs file */ - rc = ecryptfs_initialize_file(ecryptfs_dentry); + rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); + if (rc) { + drop_nlink(ecryptfs_inode); + unlock_new_inode(ecryptfs_inode); + iput(ecryptfs_inode); + goto out; + } + d_instantiate(ecryptfs_dentry, ecryptfs_inode); + unlock_new_inode(ecryptfs_inode); out: return rc; } -- cgit From 32001d6fe9ac6b0423e674a3093aa56740849f3b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 21 Nov 2011 17:31:29 -0600 Subject: eCryptfs: Flush file in vma close Dirty pages weren't being written back when an mmap'ed eCryptfs file was closed before the mapping was unmapped. Since f_ops->flush() is not called by the munmap() path, the lower file was simply being released. This patch flushes the eCryptfs file in the vm_ops->close() path. https://launchpad.net/bugs/870326 Signed-off-by: Tyler Hicks Cc: stable@kernel.org [2.6.39+] --- fs/ecryptfs/file.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c6ac98cf9baa..d3f95f941c47 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -139,6 +139,27 @@ out: return rc; } +static void ecryptfs_vma_close(struct vm_area_struct *vma) +{ + filemap_write_and_wait(vma->vm_file->f_mapping); +} + +static const struct vm_operations_struct ecryptfs_file_vm_ops = { + .close = ecryptfs_vma_close, + .fault = filemap_fault, +}; + +static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + int rc; + + rc = generic_file_mmap(file, vma); + if (!rc) + vma->vm_ops = &ecryptfs_file_vm_ops; + + return rc; +} + struct kmem_cache *ecryptfs_file_info_cache; /** @@ -349,7 +370,7 @@ const struct file_operations ecryptfs_main_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = ecryptfs_compat_ioctl, #endif - .mmap = generic_file_mmap, + .mmap = ecryptfs_file_mmap, .open = ecryptfs_open, .flush = ecryptfs_flush, .release = ecryptfs_release, -- cgit From 15ac2b08a2fd0f4aacbe8ae39788252fea6fbe63 Mon Sep 17 00:00:00 2001 From: Xander Hover Date: Wed, 23 Nov 2011 16:40:31 -0500 Subject: b44: Use dev_kfree_skb_irq() in b44_tx() Reported issues when using dev_kfree_skb() on UP systems and systems with low numbers of cores. dev_kfree_skb_irq() will properly save IRQ state before freeing the skb. Tested on 3.1.1 and 3.2_rc2 Example of reproducible trace of kernel 3.1.1 ------------[ cut here ]------------ WARNING: at kernel/softirq.c:159 local_bh_enable+0x32/0x79() ... Pid: 0, comm: swapper Not tainted 3.1.1-gentoo #1 Call Trace: [] warn_slowpath_common+0x65/0x7a [] ? local_bh_enable+0x32/0x79 [] warn_slowpath_null+0xf/0x13 [] local_bh_enable+0x32/0x79 [] destroy_conntrack+0x7c/0x9b [] nf_conntrack_destroy+0x1f/0x26 [] skb_release_head_state+0x74/0x83 [] __kfree_skb+0xb/0x6b [] consume_skb+0x24/0x26 [] b44_poll+0xaa/0x449 [] net_rx_action+0x3f/0xea [] __do_softirq+0x5f/0xd5 [] ? local_bh_enable+0x79/0x79 [] ? irq_exit+0x34/0x8d [] ? do_IRQ+0x74/0x87 [] ? common_interrupt+0x29/0x30 [] ? default_idle+0x29/0x3e [] ? cpu_idle+0x2f/0x5d [] ? rest_init+0x79/0x7b [] ? start_kernel+0x297/0x29c [] ? i386_start_kernel+0xb0/0xb7 ---[ end trace 583f33bb1aa207a9 ]--- Signed-off-by: Xander Hover Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/b44.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 4cf835dbc122..3fb66d09ece5 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp) skb->len, DMA_TO_DEVICE); rp->skb = NULL; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } bp->tx_cons = cons; -- cgit From 0f751e641a71157aa584c2a2e22fda52b52b8a56 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 23 Nov 2011 11:31:24 -0600 Subject: eCryptfs: Extend array bounds for all filename chars From mhalcrow's original commit message: Characters with ASCII values greater than the size of filename_rev_map[] are valid filename characters. ecryptfs_decode_from_filename() will access kernel memory beyond that array, and ecryptfs_parse_tag_70_packet() will then decrypt those characters. The attacker, using the FNEK of the crafted file, can then re-encrypt the characters to reveal the kernel memory past the end of the filename_rev_map[] array. I expect low security impact since this array is statically allocated in the text area, and the amount of memory past the array that is accessible is limited by the largest possible ASCII filename character. This patch solves the issue reported by mhalcrow but with an implementation suggested by Linus to simply extend the length of filename_rev_map[] to 256. Characters greater than 0x7A are mapped to 0x00, which is how invalid characters less than 0x7A were previously being handled. Signed-off-by: Tyler Hicks Reported-by: Michael Halcrow Cc: stable@kernel.org --- fs/ecryptfs/crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 203a1fdff666..2a834255c75d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1945,7 +1945,7 @@ static unsigned char *portable_filename_chars = ("-.0123456789ABCD" /* We could either offset on every reverse map or just pad some 0x00's * at the front here */ -static const unsigned char filename_rev_map[] = { +static const unsigned char filename_rev_map[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ @@ -1961,7 +1961,7 @@ static const unsigned char filename_rev_map[] = { 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */ 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */ - 0x3D, 0x3E, 0x3F + 0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */ }; /** -- cgit From 4d0fe50c75a547088e4304e5eb5f521514dfae46 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 23 Nov 2011 17:29:23 -0500 Subject: ipv6: tcp: fix tcp_v6_conn_request() Since linux 2.6.26 (commit c6aefafb7ec6 : Add IPv6 support to TCP SYN cookies), we can drop a SYN packet reusing a TIME_WAIT socket. (As a matter of fact we fail to send the SYNACK answer) As the client resends its SYN packet after a one second timeout, we accept it, because first packet removed the TIME_WAIT socket before being dropped. This probably explains why nobody ever noticed or complained. Reported-by: Jesse Young Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 36131d122a6f..2dea4bb7b54a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1255,6 +1255,13 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!want_cookie || tmp_opt.tstamp_ok) TCP_ECN_create_request(req, tcp_hdr(skb)); + treq->iif = sk->sk_bound_dev_if; + + /* So that link locals have meaning */ + if (!sk->sk_bound_dev_if && + ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) + treq->iif = inet6_iif(skb); + if (!isn) { struct inet_peer *peer = NULL; @@ -1264,12 +1271,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) atomic_inc(&skb->users); treq->pktopts = skb; } - treq->iif = sk->sk_bound_dev_if; - - /* So that link locals have meaning */ - if (!sk->sk_bound_dev_if && - ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) - treq->iif = inet6_iif(skb); if (want_cookie) { isn = cookie_v6_init_sequence(sk, skb, &req->mss); -- cgit From 685f94e6db8496399c881218018166515445a914 Mon Sep 17 00:00:00 2001 From: Jun Zhao Date: Tue, 22 Nov 2011 17:19:03 +0000 Subject: ipv4 : igmp : fix error handle in ip_mc_add_src() When add sources to interface failure, need to roll back the sfcount[MODE] to before state. We need to match it corresponding. Acked-by: David L Stevens Acked-by: Eric Dumazet Signed-off-by: Jun Zhao Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c7472eff2d51..b2ca095cb9da 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1716,7 +1716,8 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, if (err) { int j; - pmc->sfcount[sfmode]--; + if (!delta) + pmc->sfcount[sfmode]--; for (j=0; jsfcount[MCAST_EXCLUDE] != 0)) { -- cgit From cc1b0765da6078b906772b79ff211b88cc0ae958 Mon Sep 17 00:00:00 2001 From: sricharan Date: Wed, 23 Nov 2011 14:35:07 -0800 Subject: ARM: OMAP: hwmod: Fix the addr space, irq, dma count APIs The address spaces, irqs and dma reqs count APIs return the number of corresponding entries in a hwmod including a additional null value or a -1 terminator in the structure introduced recently. More information here: - 212738a4: omap_hwmod: use a terminator record with omap_hwmod_mpu_irqs arrays - 78183f3f: omap_hwmod: use a null structure record to terminate omap_hwmod_addr_space arrays - bc614958: omap_hwmod: use a terminator record with omap_hwmod_dma_info arrays The issue with irqs and dma info was originally reported by Benoit Cousson. The devices which have multiple hwmods and use device_build_ss are broken with this, as their resources are populated with a extra null value, subsequently the probe fails. So fix the API not to include the array terminator in the count. Reported-by: Benoit Cousson Signed-off-by: Santosh Shilimkar Signed-off-by: sricharan Signed-off-by: Benoit Cousson Cc: Paul Walmsley Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 6b3088db83b7..207a2ff9a8c4 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -749,7 +749,7 @@ static int _count_mpu_irqs(struct omap_hwmod *oh) ohii = &oh->mpu_irqs[i++]; } while (ohii->irq != -1); - return i; + return i-1; } /** @@ -772,7 +772,7 @@ static int _count_sdma_reqs(struct omap_hwmod *oh) ohdi = &oh->sdma_reqs[i++]; } while (ohdi->dma_req != -1); - return i; + return i-1; } /** @@ -795,7 +795,7 @@ static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os) mem = &os->addr[i++]; } while (mem->pa_start != mem->pa_end); - return i; + return i-1; } /** -- cgit From 46232a3622c6e33605906ee6690dfef372925f53 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 23 Nov 2011 14:43:01 -0800 Subject: ARM: OMAP: PM: only register TWL with voltage layer when device is present Current code registers voltage layer details for TWL PMIC even when a TWL has not been registered. Fix this to only register the TWL with voltage layer when the TWL PMIC is initialized by board-level code. Signed-off-by: Kevin Hilman Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pm.c | 6 ++---- arch/arm/mach-omap2/twl-common.c | 11 +++++++++++ arch/arm/mach-omap2/twl-common.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 1e79bdf313e3..00bff46ca48b 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -24,6 +24,7 @@ #include "powerdomain.h" #include "clockdomain.h" #include "pm.h" +#include "twl-common.h" static struct omap_device_pm_latency *pm_lats; @@ -226,11 +227,8 @@ postcore_initcall(omap2_common_pm_init); static int __init omap2_common_pm_late_init(void) { - /* Init the OMAP TWL parameters */ - omap3_twl_init(); - omap4_twl_init(); - /* Init the voltage layer */ + omap_pmic_late_init(); omap_voltage_late_init(); /* Initialize the voltages */ diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 522435772168..10b20c652e5d 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -30,6 +30,7 @@ #include #include "twl-common.h" +#include "pm.h" static struct i2c_board_info __initdata pmic_i2c_board_info = { .addr = 0x48, @@ -48,6 +49,16 @@ void __init omap_pmic_init(int bus, u32 clkrate, omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1); } +void __init omap_pmic_late_init(void) +{ + /* Init the OMAP TWL parameters (if PMIC has been registerd) */ + if (!pmic_i2c_board_info.irq) + return; + + omap3_twl_init(); + omap4_twl_init(); +} + #if defined(CONFIG_ARCH_OMAP3) static struct twl4030_usb_data omap3_usb_pdata = { .usb_mode = T2_USB_MODE_ULPI, diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h index 5e83a5bd37fb..275dde8cb27a 100644 --- a/arch/arm/mach-omap2/twl-common.h +++ b/arch/arm/mach-omap2/twl-common.h @@ -1,6 +1,8 @@ #ifndef __OMAP_PMIC_COMMON__ #define __OMAP_PMIC_COMMON__ +#include + #define TWL_COMMON_PDATA_USB (1 << 0) #define TWL_COMMON_PDATA_BCI (1 << 1) #define TWL_COMMON_PDATA_MADC (1 << 2) @@ -30,6 +32,7 @@ struct twl4030_platform_data; void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, struct twl4030_platform_data *pmic_data); +void omap_pmic_late_init(void); static inline void omap2_pmic_init(const char *pmic_type, struct twl4030_platform_data *pmic_data) -- cgit From 5a4f1844c2ba21f804d7729306d9b16eaeb724a8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 23 Nov 2011 14:43:37 -0800 Subject: ARM: OMAP: smartreflex: fix IRQ handling bug Fix a bug which has been on this driver since it was added by the original commit 984aa6db which would never clear IRQSTATUS bits. Signed-off-by: Felipe Balbi Signed-off-by: Kevin Hilman Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/smartreflex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 6a4f6839a7d9..cf246b39bac7 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -139,7 +139,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) sr_write_reg(sr_info, ERRCONFIG_V1, status); } else if (sr_info->ip_type == SR_TYPE_V2) { /* Read the status bits */ - sr_read_reg(sr_info, IRQSTATUS); + status = sr_read_reg(sr_info, IRQSTATUS); /* Clear them by writing back */ sr_write_reg(sr_info, IRQSTATUS, status); -- cgit From a8a6565c7615cab3608d75af95b5c8a3522cd7c4 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 23 Nov 2011 14:44:50 -0800 Subject: ARM: OMAP2: select ARM_AMBA if OMAP3_EMU is defined This patch selects ARM_AMBA if OMAP3_EMU is defined because OC_ETM depends on ARM_AMBA, so fix the link failure[1]. [1], arch/arm/kernel/built-in.o: In function `etm_remove': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:609: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etb_remove': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:409: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etm_init': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:640: undefined reference to `amba_driver_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:646: undefined reference to `amba_driver_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:648: undefined reference to `amba_driver_unregister' arch/arm/kernel/built-in.o: In function `etm_probe': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:545: undefined reference to `amba_request_regions' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:595: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etb_probe': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:347: undefined reference to `amba_request_regions' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:392: undefined reference to `amba_release_regions' arch/arm/mach-omap2/built-in.o: In function `emu_init': /home/tom/git/omap/linux-2.6-omap/arch/arm/mach-omap2/emu.c:62: undefined reference to `amba_device_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/mach-omap2/emu.c:63: undefined reference to `amba_device_register' make: *** [.tmp_vmlinux1] Error 1 making modules Signed-off-by: Ming Lei Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 503414718905..e1293aa513d3 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -334,6 +334,7 @@ config MACH_OMAP4_PANDA config OMAP3_EMU bool "OMAP3 debugging peripherals" depends on ARCH_OMAP3 + select ARM_AMBA select OC_ETM help Say Y here to enable debugging hardware of omap3 -- cgit From 52a2396249478018ea2e83d962a347d38d8cccbe Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Wed, 23 Nov 2011 14:45:22 -0800 Subject: ARM: OMAP2+: Remove empty io.h The file arch/arm/mach-omap2/io.h is empty, so we can remove it. Signed-off-by: Thomas Weber Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/io.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 arch/arm/mach-omap2/io.h diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h deleted file mode 100644 index e69de29bb2d1..000000000000 -- cgit From 8770b07c2dff3cec2c751b289ee690137c88ea54 Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Wed, 23 Nov 2011 14:45:37 -0800 Subject: ARM: OMAP2+: Fix Compilation error when omap_l3_noc built as module Fix below compilation failure on mainline kernel 3.2-rc1 when omap_l3_noc.c is built as module. arch/arm/mach-omap2/omap_l3_noc.c:240: error: expected ',' or ';' before 'MODULE_DEVICE_TABLE' Signed-off-by: Govindraj.R Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_l3_noc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c index 6a66aa5e2a5b..d15225ff5c49 100644 --- a/arch/arm/mach-omap2/omap_l3_noc.c +++ b/arch/arm/mach-omap2/omap_l3_noc.c @@ -237,7 +237,7 @@ static int __devexit omap4_l3_remove(struct platform_device *pdev) static const struct of_device_id l3_noc_match[] = { {.compatible = "ti,omap4-l3-noc", }, {}, -} +}; MODULE_DEVICE_TABLE(of, l3_noc_match); #else #define l3_noc_match NULL -- cgit From 1d125bd52e1e1b9810a2d5a32a76147912fa4133 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 23 Nov 2011 03:54:08 +0000 Subject: bnx2x: Fix 5461x LED Fix port identify test on 5461x PHY by driving LEDs through MDIO. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 39 +++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index bce203fa4b9e..882f48f0a03c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -10327,6 +10327,43 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy, return 0; } + +static void bnx2x_5461x_set_link_led(struct bnx2x_phy *phy, + struct link_params *params, u8 mode) +{ + struct bnx2x *bp = params->bp; + u16 temp; + + bnx2x_cl22_write(bp, phy, + MDIO_REG_GPHY_SHADOW, + MDIO_REG_GPHY_SHADOW_LED_SEL1); + bnx2x_cl22_read(bp, phy, + MDIO_REG_GPHY_SHADOW, + &temp); + temp &= 0xff00; + + DP(NETIF_MSG_LINK, "54618x set link led (mode=%x)\n", mode); + switch (mode) { + case LED_MODE_FRONT_PANEL_OFF: + case LED_MODE_OFF: + temp |= 0x00ee; + break; + case LED_MODE_OPER: + temp |= 0x0001; + break; + case LED_MODE_ON: + temp |= 0x00ff; + break; + default: + break; + } + bnx2x_cl22_write(bp, phy, + MDIO_REG_GPHY_SHADOW, + MDIO_REG_GPHY_SHADOW_WR_ENA | temp); + return; +} + + static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy, struct link_params *params) { @@ -11103,7 +11140,7 @@ static struct bnx2x_phy phy_54618se = { .config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback, .format_fw_ver = (format_fw_ver_t)NULL, .hw_reset = (hw_reset_t)NULL, - .set_link_led = (set_link_led_t)NULL, + .set_link_led = (set_link_led_t)bnx2x_5461x_set_link_led, .phy_specific_func = (phy_specific_func_t)NULL }; /*****************************************************************/ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index fc7bd0f23c0b..e58073ef33b4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -6990,6 +6990,7 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_REG_INTR_MASK 0x1b #define MDIO_REG_INTR_MASK_LINK_STATUS (0x1 << 1) #define MDIO_REG_GPHY_SHADOW 0x1c +#define MDIO_REG_GPHY_SHADOW_LED_SEL1 (0x0d << 10) #define MDIO_REG_GPHY_SHADOW_LED_SEL2 (0x0e << 10) #define MDIO_REG_GPHY_SHADOW_WR_ENA (0x1 << 15) #define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED (0x1e << 10) -- cgit From 782428535e0819b5b7c9825cd3faa2ad37032a70 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 23 Nov 2011 13:10:42 +0000 Subject: qlge: fix size of external list for TX address descriptors When transmiting a fragmented skb, qlge fills a descriptor with the fragment addresses, after DMA-mapping them. If there are more than eight fragments, it will use the eighth descriptor as a pointer to an external list. After mapping this external list, called OAL to a structure containing more descriptors, it fills it with the extra fragments. However, considering that systems with pages larger than 8KiB would have less than 8 fragments, which was true before commit a715dea3c8e, it defined a macro for the OAL size as 0 in those cases. Now, if a skb with more than 8 fragments (counting skb->data as one fragment), this would start overwriting the list of addresses already mapped and would make the driver fail to properly unmap the right addresses on architectures with pages larger than 8KiB. Besides that, the list of mappings was one size too small, since it must have a mapping for the maxinum number of skb fragments plus one for skb->data and another for the OAL. So, even on architectures with page sizes 4KiB and 8KiB, a skb with the maximum number of fragments would make the driver overwrite its counter for the number of mappings, which, again, would make it fail to unmap the mapped DMA addresses. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index 8731f79c9efc..b8478aab050e 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -58,10 +58,8 @@ #define TX_DESC_PER_IOCB 8 -/* The maximum number of frags we handle is based - * on PAGE_SIZE... - */ -#if (PAGE_SHIFT == 12) || (PAGE_SHIFT == 13) /* 4k & 8k pages */ + +#if ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2) > 0 #define TX_DESC_PER_OAL ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2) #else /* all other page sizes */ #define TX_DESC_PER_OAL 0 @@ -1353,7 +1351,7 @@ struct tx_ring_desc { struct ob_mac_iocb_req *queue_entry; u32 index; struct oal oal; - struct map_list map[MAX_SKB_FRAGS + 1]; + struct map_list map[MAX_SKB_FRAGS + 2]; int map_cnt; struct tx_ring_desc *next; }; -- cgit From aa9084a01a7893a9f4bed98aa29081f15d403a88 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 23 Nov 2011 00:13:02 +0000 Subject: ehea: Reduce memory usage in buffer pools Now that we enable multiqueue by default the ehea driver is using quite a lot of memory for its buffer pools. With 4 queues we consume 64MB in the jumbo packet ring, 16MB in the medium packet ring and 16MB in the tiny packet ring. We should only fill the jumbo ring once the MTU is increased but for now halve it's size so it consumes 32MB. Also reduce the tiny packet ring, with 4 queues we had 16k entries which is overkill. Signed-off-by: Anton Blanchard Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ehea/ehea.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/ehea/ehea.h b/drivers/net/ethernet/ibm/ehea/ehea.h index 410d6a1984ed..6650068c996c 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea.h +++ b/drivers/net/ethernet/ibm/ehea/ehea.h @@ -61,9 +61,9 @@ #ifdef EHEA_SMALL_QUEUES #define EHEA_MAX_CQE_COUNT 1023 #define EHEA_DEF_ENTRIES_SQ 1023 -#define EHEA_DEF_ENTRIES_RQ1 4095 +#define EHEA_DEF_ENTRIES_RQ1 1023 #define EHEA_DEF_ENTRIES_RQ2 1023 -#define EHEA_DEF_ENTRIES_RQ3 1023 +#define EHEA_DEF_ENTRIES_RQ3 511 #else #define EHEA_MAX_CQE_COUNT 4080 #define EHEA_DEF_ENTRIES_SQ 4080 -- cgit From 67c170a24fc6669f8f7c0864d75caadef0a8e5e6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 23 Nov 2011 00:13:54 +0000 Subject: ehea: Use round_jiffies_relative to align workqueue Use round_jiffies_relative to align the ehea workqueue and avoid extra wakeups. Signed-off-by: Anton Blanchard Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ehea/ehea_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 37b70f7052b6..bfeccbfde236 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -371,7 +371,8 @@ static void ehea_update_stats(struct work_struct *work) out_herr: free_page((unsigned long)cb2); resched: - schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000)); + schedule_delayed_work(&port->stats_work, + round_jiffies_relative(msecs_to_jiffies(1000))); } static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) @@ -2434,7 +2435,8 @@ static int ehea_open(struct net_device *dev) } mutex_unlock(&port->port_lock); - schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000)); + schedule_delayed_work(&port->stats_work, + round_jiffies_relative(msecs_to_jiffies(1000))); return ret; } -- cgit From ac8a48106be49c422575ddc7531b776f8eb49610 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Tue, 22 Nov 2011 23:33:10 +0000 Subject: ipv4: Save nexthop address of LSRR/SSRR option to IPCB. We can not update iph->daddr in ip_options_rcv_srr(), It is too early. When some exception ocurred later (eg. in ip_forward() when goto sr_failed) we need the ip header be identical to the original one as ICMP need it. Add a field 'nexthop' in struct ip_options to save nexthop of LSRR or SSRR option. Signed-off-by: Li Wei Signed-off-by: David S. Miller --- include/net/inet_sock.h | 2 ++ net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_options.c | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index b897d6e6d0a5..f941964a9931 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -31,6 +31,7 @@ /** struct ip_options - IP Options * * @faddr - Saved first hop address + * @nexthop - Saved nexthop address in LSRR and SSRR * @is_data - Options in __data, rather than skb * @is_strictroute - Strict source route * @srr_is_hit - Packet destination addr was our one @@ -41,6 +42,7 @@ */ struct ip_options { __be32 faddr; + __be32 nexthop; unsigned char optlen; unsigned char srr; unsigned char rr; diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 3b34d1c86270..29a07b6c7168 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb) rt = skb_rtable(skb); - if (opt->is_strictroute && ip_hdr(skb)->daddr != rt->rt_gateway) + if (opt->is_strictroute && opt->nexthop != rt->rt_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 05d20cca9d66..1e60f7679075 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -568,12 +568,13 @@ void ip_forward_options(struct sk_buff *skb) ) { if (srrptr + 3 > srrspace) break; - if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0) + if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0) break; } if (srrptr + 3 <= srrspace) { opt->is_changed = 1; ip_rt_get_source(&optptr[srrptr-1], skb, rt); + ip_hdr(skb)->daddr = opt->nexthop; optptr[2] = srrptr+4; } else if (net_ratelimit()) printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); @@ -640,7 +641,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) } if (srrptr <= srrspace) { opt->srr_is_hit = 1; - iph->daddr = nexthop; + opt->nexthop = nexthop; opt->is_changed = 1; } return 0; -- cgit From bd20817f733ceb0291e0449106307ffc939006ba Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 15 Nov 2011 10:13:24 +0100 Subject: virtio: add HAS_IOMEM dependency to MMIO platform bus driver Fix this compile error on s390: CC [M] drivers/virtio/virtio_mmio.o drivers/virtio/virtio_mmio.c: In function 'vm_get_features': drivers/virtio/virtio_mmio.c:107:2: error: implicit declaration of function 'writel' Cc: Christian Borntraeger Signed-off-by: Heiko Carstens Acked-by: Pawel Moll Signed-off-by: Rusty Russell --- drivers/virtio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 816ed08e7cf3..1a61939b85fc 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -37,7 +37,7 @@ config VIRTIO_BALLOON config VIRTIO_MMIO tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on HAS_IOMEM && EXPERIMENTAL select VIRTIO select VIRTIO_RING ---help--- -- cgit From fe1a7fe2c4456679b3402f04268bdfafca7b127a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 15 Nov 2011 16:17:18 +0200 Subject: virtio-mmio: Correct the name of the guest features selector Guest features selector spelling mistake. Cc: Pawel Moll Cc: Rusty Russell Cc: virtualization@lists.linux-foundation.org Signed-off-by: Sasha Levin Signed-off-by: Rusty Russell --- drivers/virtio/virtio_mmio.c | 2 +- include/linux/virtio_mmio.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index acc5e43c373e..7317dc2ec426 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -118,7 +118,7 @@ static void vm_finalize_features(struct virtio_device *vdev) vring_transport_features(vdev); for (i = 0; i < ARRAY_SIZE(vdev->features); i++) { - writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET); + writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL); writel(vdev->features[i], vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES); } diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h index 27c7edefbc86..5c7b6f0daef8 100644 --- a/include/linux/virtio_mmio.h +++ b/include/linux/virtio_mmio.h @@ -63,7 +63,7 @@ #define VIRTIO_MMIO_GUEST_FEATURES 0x020 /* Activated features set selector - Write Only */ -#define VIRTIO_MMIO_GUEST_FEATURES_SET 0x024 +#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 /* Guest's memory page size in bytes - Write Only */ #define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 -- cgit From e6af578c5305be693a1bc7f4dc7b51dd82d41425 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 17 Nov 2011 17:41:15 +0200 Subject: virtio-pci: make reset operation safer virtio pci device reset actually just does an I/O write, which in PCI is really posted, that is it can complete on CPU before the device has received it. Further, interrupts might have been pending on another CPU, so device callback might get invoked after reset. This conflicts with how drivers use reset, which is typically: reset unregister a callback running after reset completed can race with unregister, potentially leading to use after free bugs. Fix by flushing out the write, and flushing pending interrupts. This assumes that device is never reset from its vq/config callbacks, or in parallel with being added/removed, document this assumption. Signed-off-by: Michael S. Tsirkin Signed-off-by: Rusty Russell --- drivers/virtio/virtio_pci.c | 18 ++++++++++++++++++ include/linux/virtio_config.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 3d1bf41e8892..03d1984bd363 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -169,11 +169,29 @@ static void vp_set_status(struct virtio_device *vdev, u8 status) iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); } +/* wait for pending irq handlers */ +static void vp_synchronize_vectors(struct virtio_device *vdev) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + int i; + + if (vp_dev->intx_enabled) + synchronize_irq(vp_dev->pci_dev->irq); + + for (i = 0; i < vp_dev->msix_vectors; ++i) + synchronize_irq(vp_dev->msix_entries[i].vector); +} + static void vp_reset(struct virtio_device *vdev) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); /* 0 status means a reset. */ iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); + /* Flush out the status write, and flush in device writes, + * including MSi-X interrupts, if any. */ + ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); + /* Flush pending VQ/configuration callbacks. */ + vp_synchronize_vectors(vdev); } /* the notify function used when creating a virt queue */ diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index add4790b21fe..e9e72bda1b72 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -85,6 +85,8 @@ * @reset: reset the device * vdev: the virtio device * After this, status and feature negotiation must be done again + * Device must not be reset from its vq/config callbacks, or in + * parallel with being added/removed. * @find_vqs: find virtqueues and instantiate them. * vdev: the virtio_device * nvqs: the number of virtqueues to find -- cgit From caca6a03d365883564885f2c1da3e88dcf65d139 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 23 Nov 2011 20:20:28 -0800 Subject: Linux 3.2-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dab8610c4d6f..3a8f0640cda0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit From c3c3ced77fd1949af753be7731bfdadae88a226b Mon Sep 17 00:00:00 2001 From: Roy Zang Date: Mon, 7 Nov 2011 16:32:58 +0800 Subject: powerpc/p1023: set IRQ[4:6,11] to active-high level sensitive for PCIe P1023 external IRQ[4:6, 11] are not pin out, but the interrupts are utilized by the PCIe controllers. As they are not exposed as pins we need to set them as active-high (internal to the SoC these interrupts are pulled down). IRQs[0:3,7:10] are pulled up on the board so we have them set as active-low. Signed-off-by: Roy Zang Signed-off-by: Kumar Gala --- arch/powerpc/boot/dts/p1023rds.dts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/boot/dts/p1023rds.dts b/arch/powerpc/boot/dts/p1023rds.dts index d9b776740a67..d3b478242ea9 100644 --- a/arch/powerpc/boot/dts/p1023rds.dts +++ b/arch/powerpc/boot/dts/p1023rds.dts @@ -449,6 +449,7 @@ interrupt-parent = <&mpic>; interrupts = <16 2>; interrupt-map-mask = <0xf800 0 0 7>; + /* IRQ[0:3] are pulled up on board, set to active-low */ interrupt-map = < /* IDSEL 0x0 */ 0000 0 0 1 &mpic 0 1 @@ -488,11 +489,15 @@ interrupt-parent = <&mpic>; interrupts = <16 2>; interrupt-map-mask = <0xf800 0 0 7>; + /* + * IRQ[4:6] only for PCIe, set to active-high, + * IRQ[7] is pulled up on board, set to active-low + */ interrupt-map = < /* IDSEL 0x0 */ - 0000 0 0 1 &mpic 4 1 - 0000 0 0 2 &mpic 5 1 - 0000 0 0 3 &mpic 6 1 + 0000 0 0 1 &mpic 4 2 + 0000 0 0 2 &mpic 5 2 + 0000 0 0 3 &mpic 6 2 0000 0 0 4 &mpic 7 1 >; ranges = <0x2000000 0x0 0xa0000000 @@ -527,12 +532,16 @@ interrupt-parent = <&mpic>; interrupts = <16 2>; interrupt-map-mask = <0xf800 0 0 7>; + /* + * IRQ[8:10] are pulled up on board, set to active-low + * IRQ[11] only for PCIe, set to active-high, + */ interrupt-map = < /* IDSEL 0x0 */ 0000 0 0 1 &mpic 8 1 0000 0 0 2 &mpic 9 1 0000 0 0 3 &mpic 10 1 - 0000 0 0 4 &mpic 11 1 + 0000 0 0 4 &mpic 11 2 >; ranges = <0x2000000 0x0 0x80000000 0x2000000 0x0 0x80000000 -- cgit From a92282524aee149de0014eef10a0771d1d19821f Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Nov 2011 00:50:30 +0100 Subject: powerpc/p3060qds: Fix select of 'MPC8xxx_GPIO' The driver for the Freescale P3060 QDS got added by commit 96cc017c5b ("[...] Add support for P3060QDS board"). Its Kconfig entry selects MPC8xxx_GPIO. But at the time that driver got added MPC8xxx_GPIO was already renamed to GPIO_MPC8XXX, by commit c68308dd50c ("gpio: move mpc8xxx/512x gpio driver to drivers/gpio"). So make this driver select GPIO_MPC8XXX. Signed-off-by: Paul Bolle Acked-by: Wolfram Sang Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 45023e26aea3..d7946be298b6 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -203,7 +203,7 @@ config P3060_QDS select PPC_E500MC select PHYS_64BIT select SWIOTLB - select MPC8xxx_GPIO + select GPIO_MPC8XXX select HAS_RAPIDIO select PPC_EPAPR_HV_PIC help -- cgit From 05011f370a4f549da69f3841e319043728f65542 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sun, 20 Nov 2011 09:58:11 -0600 Subject: powerpc/85xx: Fix compile error on p3060_qds.c arch/powerpc/platforms/85xx/p3060_qds.c: In function '__machine_initcall_p3060_qds_declare_of_platform_devices': arch/powerpc/platforms/85xx/p3060_qds.c:73:1: error: implicit declaration of function 'declare_of_platform_devices' declare_of_platform_devices should have been corenet_ds_publish_devices. Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/p3060_qds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c index 01dcf44871e9..081cf4ac1881 100644 --- a/arch/powerpc/platforms/85xx/p3060_qds.c +++ b/arch/powerpc/platforms/85xx/p3060_qds.c @@ -70,7 +70,7 @@ define_machine(p3060_qds) { .power_save = e500_idle, }; -machine_device_initcall(p3060_qds, declare_of_platform_devices); +machine_device_initcall(p3060_qds, corenet_ds_publish_devices); #ifdef CONFIG_SWIOTLB machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier); -- cgit From 42d623a8cd08eb93ab221d22cee5a62618895bbf Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 23 Nov 2011 09:14:38 -0600 Subject: slub: use irqsafe_cpu_cmpxchg for put_cpu_partial The cmpxchg must be irq safe. The fallback for this_cpu_cmpxchg only disables preemption which results in per cpu partial page operation potentially failing on non x86 platforms. This patch fixes the following problem reported by Christian Kujau: I seem to hit it with heavy disk & cpu IO is in progress on this PowerBook G4. Full dmesg & .config: http://nerdbynature.de/bits/3.2.0-rc1/oops/ I've enabled some debug options and now it really points to slub.c:2166 http://nerdbynature.de/bits/3.2.0-rc1/oops/oops4m.jpg With debug options enabled I'm currently in the xmon debugger, not sure what to make of it yet, I'll try to get something useful out of it :) Reported-by: Christian Kujau Tested-by: Christian Kujau Acked-by: Eric Dumazet Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index 00efbb56a268..2a9cfd72a3d7 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1978,7 +1978,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) page->pobjects = pobjects; page->next = oldpage; - } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage); + } while (irqsafe_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage); stat(s, CPU_PARTIAL_FREE); return pobjects; } -- cgit From bc6697d8a506dedf09e8e9974ffa3a316183e608 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 22 Nov 2011 16:02:02 +0100 Subject: slub: avoid potential NULL dereference or corruption show_slab_objects() can trigger NULL dereferences or memory corruption. Another cpu can change its c->page to NULL or c->node to NUMA_NO_NODE while we use them. Use ACCESS_ONCE(c->page) and ACCESS_ONCE(c->node) to make sure this cannot happen. Acked-by: Christoph Lameter Acked-by: David Rientjes Signed-off-by: Eric Dumazet Signed-off-by: Pekka Enberg --- mm/slub.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 2a9cfd72a3d7..ed3334d9b6da 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4444,30 +4444,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, for_each_possible_cpu(cpu) { struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); + int node = ACCESS_ONCE(c->node); struct page *page; - if (!c || c->node < 0) + if (node < 0) continue; - - if (c->page) { - if (flags & SO_TOTAL) - x = c->page->objects; + page = ACCESS_ONCE(c->page); + if (page) { + if (flags & SO_TOTAL) + x = page->objects; else if (flags & SO_OBJECTS) - x = c->page->inuse; + x = page->inuse; else x = 1; total += x; - nodes[c->node] += x; + nodes[node] += x; } page = c->partial; if (page) { x = page->pobjects; - total += x; - nodes[c->node] += x; + total += x; + nodes[node] += x; } - per_cpu[c->node]++; + per_cpu[node]++; } } -- cgit From ae5f8c19827493e5a8d48c2c6a8a92201a94f08b Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Tue, 23 Aug 2011 14:30:05 +0200 Subject: powerpc/qe: Fixup QE_General4 errata QE_General4 should only round up the divisor iff divisor is > 3. Rounding up lower divisors makes the error too big, causing USB on MPC832x to fail. Signed-off-by: Joakim Tjernlund Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/qe_lib/qe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 3363fbc964f8..ceb09cbd2329 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -216,7 +216,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier) /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says that the BRG divisor must be even if you're not using divide-by-16 mode. */ - if (!div16 && (divisor & 1)) + if (!div16 && (divisor & 1) && (divisor > 3)) divisor++; tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | -- cgit From 86f9a4330580b4ed3d5f7d5b0989ae69518c90f5 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Tue, 15 Nov 2011 14:52:22 -0800 Subject: drivers/edac/mpc85xx_edac.c: fix memory controller compatible for edac compatible in dts has been changed, so the driver needs to be updated accordingly. Signed-off-by: Shaohui Xie Cc: Grant Likely Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Kumar Gala --- drivers/edac/mpc85xx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 8af8e864a9cf..73464a62adf7 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -1128,7 +1128,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = { { .compatible = "fsl,p1020-memory-controller", }, { .compatible = "fsl,p1021-memory-controller", }, { .compatible = "fsl,p2020-memory-controller", }, - { .compatible = "fsl,p4080-memory-controller", }, + { .compatible = "fsl,qoriq-memory-controller", }, {}, }; MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match); -- cgit From 7145cf12095265b8a292835d0f6da87f89fac1d1 Mon Sep 17 00:00:00 2001 From: Alexandre Rusev Date: Thu, 27 Oct 2011 18:18:37 +0400 Subject: powerpc/fsl-lbc: Fix for fsl_upm If Freescale LBC driver fails to initialise itself from device tree, then internal structure is freed only but not NULL-fied. As result functions fsl_lbc_find() after checking the structure is not NULL are trying to access device registers. Signed-off-by: Alexandre Rusev Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/fsl_lbc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index c4d96fa32ba5..d5c3c90ee698 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -328,6 +328,7 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) err: iounmap(fsl_lbc_ctrl_dev->regs); kfree(fsl_lbc_ctrl_dev); + fsl_lbc_ctrl_dev = NULL; return ret; } -- cgit From e3854b6e25d1b092c30c5f81a04fe6fc839b1e26 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 8 Aug 2011 13:18:02 +0200 Subject: arch/powerpc/sysdev/ehv_pic.c: add missing kfree At this point, ehv_pic has been allocated but not stored anywhere, so it should be freed before leaving the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @exists@ local idexpression x; statement S,S1; expression E; identifier fl; expression *ptr != NULL; @@ x = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...kfree(x)...+> } when any when != true x == NULL x->fl ...> ( if (x == NULL) S1 | if (...) { ... when != x when forall ( return \(0\|<+...x...+>\|ptr\); | * return ...; ) } ) // Signed-off-by: Julia Lawall Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- arch/powerpc/sysdev/ehv_pic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index af1a5df46b3e..b6731e4a6646 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c @@ -280,6 +280,7 @@ void __init ehv_pic_init(void) if (!ehv_pic->irqhost) { of_node_put(np); + kfree(ehv_pic); return; } -- cgit From 1b6cec8a6910ca08d727898453baad22b0122920 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Nov 2011 15:15:57 +0900 Subject: ARM: mach-shmobile: Kota2 PINT fix Support PINT on sh73a0 and Kota2 using INTC PINT macros. With this patch applied the Kota2 ethernet is handled through one of the chained sh73a0 PINT interrupt controllers. sh73a0 PINT support is included in 3.2-rc but the Kota2 board code does not make use of this shared code base without this patch. Without this patch kota2 on-board ethernet is broken. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-kota2.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index bd9a78424d6b..5e084b9a8404 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -56,7 +56,7 @@ static struct resource smsc9220_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gic_spi(33), /* PINTA2 @ PORT144 */ + .start = SH73A0_PINT0_IRQ(2), /* PINTA2 */ .flags = IORESOURCE_IRQ, }, }; @@ -317,18 +317,6 @@ static void __init kota2_map_io(void) shmobile_setup_console(); } -#define PINTER0A 0xe69000a0 -#define PINTCR0A 0xe69000b0 - -void __init kota2_init_irq(void) -{ - sh73a0_init_irq(); - - /* setup PINT: enable PINTA2 as active low */ - __raw_writel(1 << 29, PINTER0A); - __raw_writew(2 << 10, PINTCR0A); -} - static void __init kota2_init(void) { sh73a0_pinmux_init(); @@ -447,7 +435,7 @@ struct sys_timer kota2_timer = { MACHINE_START(KOTA2, "kota2") .map_io = kota2_map_io, - .init_irq = kota2_init_irq, + .init_irq = sh73a0_init_irq, .handle_irq = shmobile_handle_irq_gic, .init_machine = kota2_init, .timer = &kota2_timer, -- cgit From dcb4ea869877b00fd1c761662bfd9359d15a8c2a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Nov 2011 15:29:54 +0900 Subject: ARM: mach-shmobile: Kota2 GIC Sparse IRQ fix Fix IRQ support on the Kota2 board. The sh73a0 and the Kota2 board make use of the ARM GIC hardware block as main interrupt controller. The following commit changed the default behaviour for non-device tree platforms and broke Kota2 irq support: f37a53c ARM: gic: fix irq_alloc_descs handling for sparse irq Without this fix the following warning triggers at boot: NR_IRQS:1024 nr_irqs:1024 1024 ------------[ cut here ]------------ WARNING: at arch/arm/common/gic.c:607 gic_init+0x90/0x2e4() Cannot allocate irq_descs @ IRQ16, assuming pre-allocated [] (unwind_backtrace+0x0/0xe0) from [] (warn_slowpath_commo) [] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_) [] (warn_slowpath_fmt+0x2c/0x3c) from [] (gic_init+0x90/0x2) [] (gic_init+0x90/0x2e4) from [] (sh73a0_init_irq+0x30/0x18) [] (sh73a0_init_irq+0x30/0x184) from [] (init_IRQ+0x14/0x1c) [] (init_IRQ+0x14/0x1c) from [] (start_kernel+0x15c/0x2b8) [] (start_kernel+0x15c/0x2b8) from [<4000803c>] (0x4000803c) ---[ end trace 1b75b31a2719ed1c ]--- With this fix applied interrupts work as expected. Signed-off-by: Magnus Damm Acked-by: Rob Herring Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-kota2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index 5e084b9a8404..53e5e45521aa 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -435,6 +435,7 @@ struct sys_timer kota2_timer = { MACHINE_START(KOTA2, "kota2") .map_io = kota2_map_io, + .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, .handle_irq = shmobile_handle_irq_gic, .init_machine = kota2_init, -- cgit From 33661c9e2062865acde9d421c971f1c142cf99ca Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Nov 2011 15:44:58 +0900 Subject: ARM: mach-shmobile: Kota2 TPU LED platform data This patch updates the Kota2 board support code to use the recently merged TPU LED driver whenever possible. The sh73a0 SoC has 5 TPU hardware blocks each with 4 timer channels which in theory allows a total of 20 LEDs to be controlled by "leds-renesas-tpu" driver instances. The Kota2 board has 4 LEDs connected to GPIO pins that also come with TPU pin functions, so this patch ties up these 4 LEDS and leaves the remaining 3 LEDS for the GPIO based LED driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-kota2.c | 122 ++++++++++++++++++++++++++++++++-- arch/arm/mach-shmobile/clock-sh73a0.c | 16 +++++ 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index 53e5e45521aa..f44150b5ae46 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -157,10 +158,6 @@ static struct platform_device gpio_keys_device = { #define GPIO_LED(n, g) { .name = n, .gpio = g } static struct gpio_led gpio_leds[] = { - GPIO_LED("V2513", GPIO_PORT153), /* PORT153 [TPU1T02] -> V2513 */ - GPIO_LED("V2514", GPIO_PORT199), /* PORT199 [TPU4TO1] -> V2514 */ - GPIO_LED("V2515", GPIO_PORT197), /* PORT197 [TPU2TO1] -> V2515 */ - GPIO_LED("KEYLED", GPIO_PORT163), /* PORT163 [TPU3TO0] -> KEYLED */ GPIO_LED("G", GPIO_PORT20), /* PORT20 [GPO0] -> LED7 -> "G" */ GPIO_LED("H", GPIO_PORT21), /* PORT21 [GPO1] -> LED8 -> "H" */ GPIO_LED("J", GPIO_PORT22), /* PORT22 [GPO2] -> LED9 -> "J" */ @@ -179,6 +176,119 @@ static struct platform_device gpio_leds_device = { }, }; +/* TPU LED */ +static struct led_renesas_tpu_config led_renesas_tpu12_pdata = { + .name = "V2513", + .pin_gpio_fn = GPIO_FN_TPU1TO2, + .pin_gpio = GPIO_PORT153, + .channel_offset = 0x90, + .timer_bit = 2, + .max_brightness = 1000, +}; + +static struct resource tpu12_resources[] = { + [0] = { + .name = "TPU12", + .start = 0xe6610090, + .end = 0xe66100b5, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device leds_tpu12_device = { + .name = "leds-renesas-tpu", + .id = 12, + .dev = { + .platform_data = &led_renesas_tpu12_pdata, + }, + .num_resources = ARRAY_SIZE(tpu12_resources), + .resource = tpu12_resources, +}; + +static struct led_renesas_tpu_config led_renesas_tpu41_pdata = { + .name = "V2514", + .pin_gpio_fn = GPIO_FN_TPU4TO1, + .pin_gpio = GPIO_PORT199, + .channel_offset = 0x50, + .timer_bit = 1, + .max_brightness = 1000, +}; + +static struct resource tpu41_resources[] = { + [0] = { + .name = "TPU41", + .start = 0xe6640050, + .end = 0xe6640075, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device leds_tpu41_device = { + .name = "leds-renesas-tpu", + .id = 41, + .dev = { + .platform_data = &led_renesas_tpu41_pdata, + }, + .num_resources = ARRAY_SIZE(tpu41_resources), + .resource = tpu41_resources, +}; + +static struct led_renesas_tpu_config led_renesas_tpu21_pdata = { + .name = "V2515", + .pin_gpio_fn = GPIO_FN_TPU2TO1, + .pin_gpio = GPIO_PORT197, + .channel_offset = 0x50, + .timer_bit = 1, + .max_brightness = 1000, +}; + +static struct resource tpu21_resources[] = { + [0] = { + .name = "TPU21", + .start = 0xe6620050, + .end = 0xe6620075, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device leds_tpu21_device = { + .name = "leds-renesas-tpu", + .id = 21, + .dev = { + .platform_data = &led_renesas_tpu21_pdata, + }, + .num_resources = ARRAY_SIZE(tpu21_resources), + .resource = tpu21_resources, +}; + +static struct led_renesas_tpu_config led_renesas_tpu30_pdata = { + .name = "KEYLED", + .pin_gpio_fn = GPIO_FN_TPU3TO0, + .pin_gpio = GPIO_PORT163, + .channel_offset = 0x10, + .timer_bit = 0, + .max_brightness = 1000, +}; + +static struct resource tpu30_resources[] = { + [0] = { + .name = "TPU30", + .start = 0xe6630010, + .end = 0xe6630035, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device leds_tpu30_device = { + .name = "leds-renesas-tpu", + .id = 30, + .dev = { + .platform_data = &led_renesas_tpu30_pdata, + }, + .num_resources = ARRAY_SIZE(tpu30_resources), + .resource = tpu30_resources, +}; + /* MMCIF */ static struct resource mmcif_resources[] = { [0] = { @@ -291,6 +401,10 @@ static struct platform_device *kota2_devices[] __initdata = { &keysc_device, &gpio_keys_device, &gpio_leds_device, + &leds_tpu12_device, + &leds_tpu41_device, + &leds_tpu21_device, + &leds_tpu30_device, &mmcif_device, &sdhi0_device, &sdhi1_device, diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 61a846bb30f2..a56d6c63b71e 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -113,6 +113,12 @@ static struct clk main_clk = { .ops = &main_clk_ops, }; +/* Divide Main clock by two */ +static struct clk main_div2_clk = { + .ops = &div2_clk_ops, + .parent = &main_clk, +}; + /* PLL0, PLL1, PLL2, PLL3 */ static unsigned long pll_recalc(struct clk *clk) { @@ -181,6 +187,7 @@ static struct clk *main_clks[] = { &extal1_div2_clk, &extal2_div2_clk, &main_clk, + &main_div2_clk, &pll0_clk, &pll1_clk, &pll2_clk, @@ -268,6 +275,7 @@ enum { MSTP001, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, MSTP331, MSTP329, MSTP325, MSTP323, MSTP318, MSTP314, MSTP313, MSTP312, MSTP311, + MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, MSTP_NR }; @@ -301,6 +309,10 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ [MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */ + [MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */ + [MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */ + [MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */ + [MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */ [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ @@ -350,6 +362,10 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ + CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */ + CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */ + CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */ + CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ -- cgit From eded9143151a116753b1d8e893bc2d37f8687e0b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Nov 2011 15:31:40 +0900 Subject: ARM: mach-shmobile: AG5EVM GIC Sparse IRQ fix Fix IRQ support on the AG5EVM board. The sh73a0 and the AG5EVM board make use of the ARM GIC hardware block as main interrupt controller. The following commit changed the default behaviour for non-device tree platforms and broke AG5EVM irq support: f37a53c ARM: gic: fix irq_alloc_descs handling for sparse irq Without this fix the following warning triggers at boot: NR_IRQS:1024 nr_irqs:1024 1024 ------------[ cut here ]------------ WARNING: at arch/arm/common/gic.c:607 gic_init+0x90/0x2e4() Cannot allocate irq_descs @ IRQ16, assuming pre-allocated [] (unwind_backtrace+0x0/0xe0) from [] (warn_slowpath_commo) [] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_) [] (warn_slowpath_fmt+0x2c/0x3c) from [] (gic_init+0x90/0x2) [] (gic_init+0x90/0x2e4) from [] (sh73a0_init_irq+0x30/0x18) [] (sh73a0_init_irq+0x30/0x184) from [] (init_IRQ+0x14/0x1c) [] (init_IRQ+0x14/0x1c) from [] (start_kernel+0x15c/0x2b8) [] (start_kernel+0x15c/0x2b8) from [<4000803c>] (0x4000803c) ---[ end trace 1b75b31a2719ed1c ]--- With this fix applied interrupts work as expected. Signed-off-by: Magnus Damm Acked-by: Rob Herring Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ag5evm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index b862e9f81e3e..7119b87cbfa0 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -607,6 +607,7 @@ struct sys_timer ag5evm_timer = { MACHINE_START(AG5EVM, "ag5evm") .map_io = ag5evm_map_io, + .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, .handle_irq = shmobile_handle_irq_gic, .init_machine = ag5evm_init, -- cgit From 9bcc0a5d0de137b3a154dc951c5ff70dce815879 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Nov 2011 15:23:17 +0900 Subject: ARM: mach-shmobile: SH73A0 external Ethernet fix Keep the ZB clock enabled on sh73a0 to allow the BSC to access external peripherals hooked up to CS signals. This is needed to unbreak Ethernet support on sh73a0 boards such as AG5EVM and Kota2 together with the following patch: 794d78f drivers: sh: late disabling of clocks V2 Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/clock-sh73a0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 61a846bb30f2..84fd33c9f4ee 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -243,7 +243,7 @@ static struct clk div6_clks[DIV6_NR] = { [DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0), [DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0), [DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0), - [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, 0), + [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT), [DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0), [DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0), [DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0), -- cgit From 85d096db6764fd89cea232cf64b65a5f3b0f1ffc Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 16 Oct 2011 00:07:20 +0800 Subject: ARM: at91: rename defconfig files appropriately rename all Atmel reference board as soc defconfig Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Signed-off-by: Arnd Bergmann --- arch/arm/configs/at91cap9_defconfig | 115 +++++++++++++++++++++++++++++ arch/arm/configs/at91cap9adk_defconfig | 115 ----------------------------- arch/arm/configs/at91sam9260_defconfig | 83 +++++++++++++++++++++ arch/arm/configs/at91sam9260ek_defconfig | 83 --------------------- arch/arm/configs/at91sam9g20_defconfig | 123 +++++++++++++++++++++++++++++++ arch/arm/configs/at91sam9g20ek_defconfig | 123 ------------------------------- arch/arm/configs/at91sam9rl_defconfig | 84 +++++++++++++++++++++ arch/arm/configs/at91sam9rlek_defconfig | 84 --------------------- 8 files changed, 405 insertions(+), 405 deletions(-) create mode 100644 arch/arm/configs/at91cap9_defconfig delete mode 100644 arch/arm/configs/at91cap9adk_defconfig create mode 100644 arch/arm/configs/at91sam9260_defconfig delete mode 100644 arch/arm/configs/at91sam9260ek_defconfig create mode 100644 arch/arm/configs/at91sam9g20_defconfig delete mode 100644 arch/arm/configs/at91sam9g20ek_defconfig create mode 100644 arch/arm/configs/at91sam9rl_defconfig delete mode 100644 arch/arm/configs/at91sam9rlek_defconfig diff --git a/arch/arm/configs/at91cap9_defconfig b/arch/arm/configs/at91cap9_defconfig new file mode 100644 index 000000000000..ffb1edd93363 --- /dev/null +++ b/arch/arm/configs/at91cap9_defconfig @@ -0,0 +1,115 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_BLK_DEV_INITRD=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91CAP9=y +CONFIG_MACH_AT91CAP9ADK=y +CONFIG_MTD_AT91_DATAFLASH_CARD=y +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +# CONFIG_ARM_THUMB is not set +CONFIG_AEABI=y +CONFIG_LEDS=y +CONFIG_LEDS_CPU=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw" +CONFIG_FPE_NWFPE=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ATMEL=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_ATMEL_SSC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_NETDEVICES=y +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +# CONFIG_SERIO is not set +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_SPI=y +CONFIG_SPI_ATMEL=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +CONFIG_FB=y +CONFIG_FB_ATMEL=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_DEVICEFS=y +CONFIG_USB_MON=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_ETH=m +CONFIG_USB_FILE_STORAGE=m +CONFIG_MMC=y +CONFIG_MMC_AT91=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91SAM9=y +CONFIG_EXT2_FS=y +CONFIG_INOTIFY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_USER=y diff --git a/arch/arm/configs/at91cap9adk_defconfig b/arch/arm/configs/at91cap9adk_defconfig deleted file mode 100644 index ffb1edd93363..000000000000 --- a/arch/arm/configs/at91cap9adk_defconfig +++ /dev/null @@ -1,115 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_AT91=y -CONFIG_ARCH_AT91CAP9=y -CONFIG_MACH_AT91CAP9ADK=y -CONFIG_MTD_AT91_DATAFLASH_CARD=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y -# CONFIG_ARM_THUMB is not set -CONFIG_AEABI=y -CONFIG_LEDS=y -CONFIG_LEDS_CPU=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw" -CONFIG_FPE_NWFPE=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y -CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_MACB=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ADS7846=y -# CONFIG_SERIO is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_USB_HID is not set -CONFIG_USB=y -CONFIG_USB_DEVICEFS=y -CONFIG_USB_MON=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_ETH=m -CONFIG_USB_FILE_STORAGE=m -CONFIG_MMC=y -CONFIG_MMC_AT91=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT91SAM9=y -CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y -CONFIG_CRAMFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_USER=y diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig new file mode 100644 index 000000000000..f8a9226413bf --- /dev/null +++ b/arch/arm/configs/at91sam9260_defconfig @@ -0,0 +1,83 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_BLK_DEV_INITRD=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91SAM9260=y +CONFIG_MACH_AT91SAM9260EK=y +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +# CONFIG_ARM_THUMB is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +CONFIG_FPE_NWFPE=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_ATMEL_SSC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_NETDEVICES=y +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +CONFIG_AT91SAM9X_WATCHDOG=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_DEVICEFS=y +CONFIG_USB_MON=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_GADGET=y +CONFIG_USB_ZERO=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91SAM9=y +CONFIG_EXT2_FS=y +CONFIG_INOTIFY=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_CRAMFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig deleted file mode 100644 index f8a9226413bf..000000000000 --- a/arch/arm/configs/at91sam9260ek_defconfig +++ /dev/null @@ -1,83 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_AT91=y -CONFIG_ARCH_AT91SAM9260=y -CONFIG_MACH_AT91SAM9260EK=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y -# CONFIG_ARM_THUMB is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" -CONFIG_FPE_NWFPE=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y -CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_MACB=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_AT91SAM9X_WATCHDOG=y -# CONFIG_VGA_CONSOLE is not set -# CONFIG_USB_HID is not set -CONFIG_USB=y -CONFIG_USB_DEVICEFS=y -CONFIG_USB_MON=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DEBUG=y -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_FILE_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT91SAM9=y -CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CRAMFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_LL=y diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig new file mode 100644 index 000000000000..9e90e6d79297 --- /dev/null +++ b/arch/arm/configs/at91sam9g20_defconfig @@ -0,0 +1,123 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_BLK_DEV_INITRD=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_AT91SAM9G20EK=y +CONFIG_MACH_AT91SAM9G20EK_2MMC=y +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +# CONFIG_ARM_THUMB is not set +CONFIG_AEABI=y +CONFIG_LEDS=y +CONFIG_LEDS_CPU=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +CONFIG_FPE_NWFPE=y +CONFIG_PM=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ATMEL=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_ATMEL_SSC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_HW_RANDOM=y +CONFIG_SPI=y +CONFIG_SPI_ATMEL=y +CONFIG_SPI_SPIDEV=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_VERBOSE_PROCFS is not set +CONFIG_SND_AT73C213=y +CONFIG_USB=y +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_MON=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_ZERO=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_MMC=y +CONFIG_MMC_AT91=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91SAM9=y +CONFIG_EXT2_FS=y +CONFIG_INOTIFY=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig deleted file mode 100644 index 9e90e6d79297..000000000000 --- a/arch/arm/configs/at91sam9g20ek_defconfig +++ /dev/null @@ -1,123 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_AT91=y -CONFIG_ARCH_AT91SAM9G20=y -CONFIG_MACH_AT91SAM9G20EK=y -CONFIG_MACH_AT91SAM9G20EK_2MMC=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y -# CONFIG_ARM_THUMB is not set -CONFIG_AEABI=y -CONFIG_LEDS=y -CONFIG_LEDS_CPU=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" -CONFIG_FPE_NWFPE=y -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_MACB=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -CONFIG_LEGACY_PTY_COUNT=16 -CONFIG_HW_RANDOM=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -CONFIG_SPI_SPIDEV=y -# CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SEQUENCER=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SND_AT73C213=y -CONFIG_USB=y -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DEVICE_CLASS is not set -CONFIG_USB_MON=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_ZERO=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_FILE_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_MMC=y -CONFIG_MMC_AT91=m -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT91SAM9=y -CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_SUMMARY=y -CONFIG_CRAMFS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_ISO8859_15=y -CONFIG_NLS_UTF8=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig new file mode 100644 index 000000000000..75621e4d03fc --- /dev/null +++ b/arch/arm/configs/at91sam9rl_defconfig @@ -0,0 +1,84 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_BLK_DEV_INITRD=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91SAM9RL=y +CONFIG_MACH_AT91SAM9RLEK=y +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +# CONFIG_ARM_THUMB is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw" +CONFIG_FPE_NWFPE=y +CONFIG_NET=y +CONFIG_UNIX=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ATMEL=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=4 +CONFIG_BLK_DEV_RAM_SIZE=24576 +CONFIG_ATMEL_SSC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y +# CONFIG_SERIO is not set +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_ATMEL=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y +CONFIG_AT91SAM9X_WATCHDOG=y +CONFIG_FB=y +CONFIG_FB_ATMEL=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_MMC=y +CONFIG_MMC_AT91=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91SAM9=y +CONFIG_EXT2_FS=y +CONFIG_INOTIFY=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_CRAMFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig deleted file mode 100644 index 75621e4d03fc..000000000000 --- a/arch/arm/configs/at91sam9rlek_defconfig +++ /dev/null @@ -1,84 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_AT91=y -CONFIG_ARCH_AT91SAM9RL=y -CONFIG_MACH_AT91SAM9RLEK=y -CONFIG_AT91_PROGRAMMABLE_CLOCKS=y -# CONFIG_ARM_THUMB is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw" -CONFIG_FPE_NWFPE=y -CONFIG_NET=y -CONFIG_UNIX=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_DATAFLASH=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ATMEL=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=4 -CONFIG_BLK_DEV_RAM_SIZE=24576 -CONFIG_ATMEL_SSC=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y -# CONFIG_SERIO is not set -CONFIG_SERIAL_ATMEL=y -CONFIG_SERIAL_ATMEL_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -CONFIG_SPI=y -CONFIG_SPI_ATMEL=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_AT91SAM9X_WATCHDOG=y -CONFIG_FB=y -CONFIG_FB_ATMEL=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_MMC=y -CONFIG_MMC_AT91=m -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_AT91SAM9=y -CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CRAMFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_850=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_ISO8859_15=y -CONFIG_NLS_UTF8=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_LL=y -- cgit From 9f939adeb2d0bcc079a8b2684761b34709d65407 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 16 Oct 2011 00:07:20 +0800 Subject: ARM: at91: refresh soc defconfig files for 3.2 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Signed-off-by: Arnd Bergmann --- arch/arm/configs/at91cap9_defconfig | 7 ----- arch/arm/configs/at91rm9200_defconfig | 47 ++++++++++------------------------ arch/arm/configs/at91sam9260_defconfig | 4 --- arch/arm/configs/at91sam9g20_defconfig | 12 +-------- arch/arm/configs/at91sam9g45_defconfig | 6 +---- arch/arm/configs/at91sam9rl_defconfig | 5 ---- 6 files changed, 16 insertions(+), 65 deletions(-) diff --git a/arch/arm/configs/at91cap9_defconfig b/arch/arm/configs/at91cap9_defconfig index ffb1edd93363..8826eb218e73 100644 --- a/arch/arm/configs/at91cap9_defconfig +++ b/arch/arm/configs/at91cap9_defconfig @@ -38,7 +38,6 @@ CONFIG_IP_PNP_RARP=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -52,16 +51,12 @@ CONFIG_MTD_NAND_ATMEL=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_MACB=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_KEYBOARD is not set @@ -81,7 +76,6 @@ CONFIG_WATCHDOG=y CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_FB=y CONFIG_FB_ATMEL=y -# CONFIG_VGA_CONSOLE is not set CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_CLUT224 is not set @@ -99,7 +93,6 @@ CONFIG_MMC_AT91=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AT91SAM9=y CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig index 38cb7c985426..bbe4e1a1f5d8 100644 --- a/arch/arm/configs/at91rm9200_defconfig +++ b/arch/arm/configs/at91rm9200_defconfig @@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y @@ -56,7 +55,6 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m @@ -75,18 +73,8 @@ CONFIG_IPV6_TUNNEL=m CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_AFS_PARTS=y CONFIG_MTD_CHAR=y @@ -108,8 +96,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_TCLIB=y -CONFIG_EEPROM_LEGACY=m CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m @@ -119,14 +105,23 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y CONFIG_TUN=m +CONFIG_ARM_AT91_ETHER=y CONFIG_PHYLIB=y CONFIG_DAVICOM_PHY=y CONFIG_SMSC_PHY=y CONFIG_MICREL_PHY=y -CONFIG_NET_ETHERNET=y -CONFIG_ARM_AT91_ETHER=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPP_ASYNC=y +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m @@ -139,18 +134,6 @@ CONFIG_USB_NET_RNDIS_HOST=m CONFIG_USB_ALI_M5632=y CONFIG_USB_AN2720=y CONFIG_USB_EPSON2888=y -CONFIG_PPP=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 @@ -158,9 +141,9 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_LEGACY_PTY_COUNT=32 CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y -CONFIG_LEGACY_PTY_COUNT=32 CONFIG_HW_RANDOM=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y @@ -290,7 +273,6 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y -CONFIG_SMB_FS=m CONFIG_CIFS=m CONFIG_PARTITION_ADVANCED=y CONFIG_MAC_PARTITION=y @@ -335,7 +317,6 @@ CONFIG_NLS_UTF8=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_FTRACE is not set CONFIG_CRYPTO_PCBC=y CONFIG_CRYPTO_SHA1=y diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig index f8a9226413bf..8a4c22d7be61 100644 --- a/arch/arm/configs/at91sam9260_defconfig +++ b/arch/arm/configs/at91sam9260_defconfig @@ -33,12 +33,10 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_MACB=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set @@ -55,7 +53,6 @@ CONFIG_I2C_GPIO=y CONFIG_WATCHDOG=y CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_AT91SAM9X_WATCHDOG=y -# CONFIG_VGA_CONSOLE is not set # CONFIG_USB_HID is not set CONFIG_USB=y CONFIG_USB_DEVICEFS=y @@ -71,7 +68,6 @@ CONFIG_USB_G_SERIAL=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AT91SAM9=y CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_CRAMFS=y diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig index 9e90e6d79297..23966c699065 100644 --- a/arch/arm/configs/at91sam9g20_defconfig +++ b/arch/arm/configs/at91sam9g20_defconfig @@ -23,7 +23,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" CONFIG_FPE_NWFPE=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -37,8 +36,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -48,17 +45,13 @@ CONFIG_MTD_NAND_ATMEL=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_ATMEL_SSC=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_MACB=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 @@ -66,15 +59,14 @@ CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set +CONFIG_LEGACY_PTY_COUNT=16 CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y -CONFIG_LEGACY_PTY_COUNT=16 CONFIG_HW_RANDOM=y CONFIG_SPI=y CONFIG_SPI_ATMEL=y CONFIG_SPI_SPIDEV=y # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SEQUENCER=y @@ -82,7 +74,6 @@ CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SND_AT73C213=y CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_DEVICE_CLASS is not set @@ -105,7 +96,6 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AT91SAM9=y CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig index c5876d244f4b..7f8f99919d34 100644 --- a/arch/arm/configs/at91sam9g45_defconfig +++ b/arch/arm/configs/at91sam9g45_defconfig @@ -73,11 +73,8 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y CONFIG_MII=y -CONFIG_DAVICOM_PHY=y -CONFIG_NET_ETHERNET=y CONFIG_MACB=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set +CONFIG_DAVICOM_PHY=y CONFIG_LIBERTAS_THINFIRM=m CONFIG_LIBERTAS_THINFIRM_USB=m CONFIG_AT76C50X_USB=m @@ -131,7 +128,6 @@ CONFIG_I2C_GPIO=y CONFIG_SPI=y CONFIG_SPI_ATMEL=y # CONFIG_HWMON is not set -# CONFIG_MFD_SUPPORT is not set CONFIG_FB=y CONFIG_FB_ATMEL=y CONFIG_FB_UDL=m diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig index 75621e4d03fc..ad562ee64209 100644 --- a/arch/arm/configs/at91sam9rl_defconfig +++ b/arch/arm/configs/at91sam9rl_defconfig @@ -23,8 +23,6 @@ CONFIG_NET=y CONFIG_UNIX=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -35,7 +33,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=4 CONFIG_BLK_DEV_RAM_SIZE=24576 -CONFIG_ATMEL_SSC=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y @@ -62,13 +59,11 @@ CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_AT91SAM9X_WATCHDOG=y CONFIG_FB=y CONFIG_FB_ATMEL=y -# CONFIG_VGA_CONSOLE is not set CONFIG_MMC=y CONFIG_MMC_AT91=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_AT91SAM9=y CONFIG_EXT2_FS=y -CONFIG_INOTIFY=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y -- cgit From db5509f0c2b7e7c02e1294a10a4d4b04f2720c28 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 16 Oct 2011 00:03:17 +0800 Subject: ARM: at91: enable additional boards in existing soc defconfig files Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Nicolas Ferre Signed-off-by: Arnd Bergmann --- arch/arm/configs/at91sam9260_defconfig | 12 ++++++++++++ arch/arm/configs/at91sam9g20_defconfig | 11 +++++++++++ arch/arm/configs/at91sam9g45_defconfig | 1 + 3 files changed, 24 insertions(+) diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig index 8a4c22d7be61..505b3765f87e 100644 --- a/arch/arm/configs/at91sam9260_defconfig +++ b/arch/arm/configs/at91sam9260_defconfig @@ -12,11 +12,23 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9260=y +CONFIG_ARCH_AT91SAM9260_SAM9XE=y CONFIG_MACH_AT91SAM9260EK=y +CONFIG_MACH_CAM60=y +CONFIG_MACH_SAM9_L9260=y +CONFIG_MACH_AFEB9260=y +CONFIG_MACH_USB_A9260=y +CONFIG_MACH_QIL_A9260=y +CONFIG_MACH_CPU9260=y +CONFIG_MACH_FLEXIBITY=y +CONFIG_MACH_SNAPPER_9260=y +CONFIG_MACH_AT91SAM_DT=y CONFIG_AT91_PROGRAMMABLE_CLOCKS=y # CONFIG_ARM_THUMB is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" CONFIG_FPE_NWFPE=y CONFIG_NET=y diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig index 23966c699065..9123568d9a8d 100644 --- a/arch/arm/configs/at91sam9g20_defconfig +++ b/arch/arm/configs/at91sam9g20_defconfig @@ -14,6 +14,15 @@ CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9G20=y CONFIG_MACH_AT91SAM9G20EK=y CONFIG_MACH_AT91SAM9G20EK_2MMC=y +CONFIG_MACH_CPU9G20=y +CONFIG_MACH_ACMENETUSFOXG20=y +CONFIG_MACH_PORTUXG20=y +CONFIG_MACH_STAMP9G20=y +CONFIG_MACH_PCONTROL_G20=y +CONFIG_MACH_GSIA18S=y +CONFIG_MACH_USB_A9G20=y +CONFIG_MACH_SNAPPER_9260=y +CONFIG_MACH_AT91SAM_DT=y CONFIG_AT91_PROGRAMMABLE_CLOCKS=y # CONFIG_ARM_THUMB is not set CONFIG_AEABI=y @@ -21,6 +30,8 @@ CONFIG_LEDS=y CONFIG_LEDS_CPU=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" CONFIG_FPE_NWFPE=y CONFIG_NET=y diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig index 7f8f99919d34..606d48f3b8f8 100644 --- a/arch/arm/configs/at91sam9g45_defconfig +++ b/arch/arm/configs/at91sam9g45_defconfig @@ -18,6 +18,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9G45=y CONFIG_MACH_AT91SAM9M10G45EK=y +CONFIG_MACH_AT91SAM_DT=y CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_SLOW_CLOCK=y CONFIG_AEABI=y -- cgit From ff83bd82cb343d37b5ab8e402aaad9ef33d03f1e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 12 Nov 2011 22:33:30 -0300 Subject: [media] af9015: limit I2C access to keep FW happy AF9015 firmware does not like if it gets interrupted by I2C adapter request on some critical phases. During normal operation I2C adapter is used only 2nd demodulator and tuner on dual tuner devices. Override demodulator callbacks and use mutex for limit access to those "critical" paths to keep AF9015 happy. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 97 ++++++++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/af9015.h | 7 +++ 2 files changed, 104 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index c6c275bac08e..033aa8affd8e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1093,9 +1093,80 @@ error: return ret; } +/* override demod callbacks for resource locking */ +static int af9015_af9013_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->set_frontend[adap->id](fe, params); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_read_status(struct dvb_frontend *fe, + fe_status_t *status) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->read_status[adap->id](fe, status); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_init(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->init[adap->id](fe); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_sleep(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct af9015_state *priv = adap->dev->priv; + + if (mutex_lock_interruptible(&adap->dev->usb_mutex)) + return -EAGAIN; + + ret = priv->init[adap->id](fe); + + mutex_unlock(&adap->dev->usb_mutex); + + return ret; +} + static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) { int ret; + struct af9015_state *state = adap->dev->priv; if (adap->id == 1) { /* copy firmware to 2nd demodulator */ @@ -1116,6 +1187,32 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], &adap->dev->i2c_adap); + /* + * AF9015 firmware does not like if it gets interrupted by I2C adapter + * request on some critical phases. During normal operation I2C adapter + * is used only 2nd demodulator and tuner on dual tuner devices. + * Override demodulator callbacks and use mutex for limit access to + * those "critical" paths to keep AF9015 happy. + * Note: we abuse unused usb_mutex here. + */ + if (adap->fe_adap[0].fe) { + state->set_frontend[adap->id] = + adap->fe_adap[0].fe->ops.set_frontend; + adap->fe_adap[0].fe->ops.set_frontend = + af9015_af9013_set_frontend; + + state->read_status[adap->id] = + adap->fe_adap[0].fe->ops.read_status; + adap->fe_adap[0].fe->ops.read_status = + af9015_af9013_read_status; + + state->init[adap->id] = adap->fe_adap[0].fe->ops.init; + adap->fe_adap[0].fe->ops.init = af9015_af9013_init; + + state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep; + adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep; + } + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 6252ea6c1904..4a126177e101 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -102,6 +102,13 @@ struct af9015_state { u8 rc_repeat; u32 rc_keycode; u8 rc_last[4]; + + /* for demod callback override */ + int (*set_frontend[2]) (struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); + int (*init[2]) (struct dvb_frontend *fe); + int (*sleep[2]) (struct dvb_frontend *fe); }; struct af9015_config { -- cgit From d7d89dc85b9ec0e94f16e811d5f440106e2e77c0 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 00:22:33 -0300 Subject: [media] tda18218: fix 6 MHz default IF frequency Default IF for 6 MHz bandwidth is 3 MHz. Use that. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18218.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c index aacfe2387e28..4fc29730a12c 100644 --- a/drivers/media/common/tuners/tda18218.c +++ b/drivers/media/common/tuners/tda18218.c @@ -141,7 +141,7 @@ static int tda18218_set_params(struct dvb_frontend *fe, switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: LP_Fc = 0; - LO_Frac = params->frequency + 4000000; + LO_Frac = params->frequency + 3000000; break; case BANDWIDTH_7_MHZ: LP_Fc = 1; -- cgit From 576b849ea7af9ac05dca3ca92bc62c7528e8f0ef Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 9 Oct 2011 08:59:16 -0300 Subject: [media] mxl5007t: fix reg read Register to read should be written to register 0xfb and then perform I2C read to get reg value. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5007t.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 7eb1bf75cd07..5d02221e99dd 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -488,9 +488,10 @@ static int mxl5007t_write_regs(struct mxl5007t_state *state, static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val) { + u8 buf[2] = { 0xfb, reg }; struct i2c_msg msg[] = { { .addr = state->i2c_props.addr, .flags = 0, - .buf = ®, .len = 1 }, + .buf = buf, .len = 2 }, { .addr = state->i2c_props.addr, .flags = I2C_M_RD, .buf = val, .len = 1 }, }; -- cgit From 884a45d964dd395eda945842afff5e16bcaedf56 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 22 Nov 2011 07:44:47 -0800 Subject: cgroup_freezer: fix freezing groups with stopped tasks 2d3cbf8b (cgroup_freezer: update_freezer_state() does incorrect state transitions) removed is_task_frozen_enough and replaced it with a simple frozen call. This, however, breaks freezing for a group with stopped tasks because those cannot be frozen and so the group remains in CGROUP_FREEZING state (update_if_frozen doesn't count stopped tasks) and never reaches CGROUP_FROZEN. Let's add is_task_frozen_enough back and use it at the original locations (update_if_frozen and try_to_freeze_cgroup). Semantically we consider stopped tasks as frozen enough so we should consider both cases when testing frozen tasks. Testcase: mkdir /dev/freezer mount -t cgroup -o freezer none /dev/freezer mkdir /dev/freezer/foo sleep 1h & pid=$! kill -STOP $pid echo $pid > /dev/freezer/foo/tasks echo FROZEN > /dev/freezer/foo/freezer.state while true do cat /dev/freezer/foo/freezer.state [ "`cat /dev/freezer/foo/freezer.state`" = "FROZEN" ] && break sleep 1 done echo OK Signed-off-by: Michal Hocko Acked-by: Li Zefan Cc: Tomasz Buchert Cc: Paul Menage Cc: Andrew Morton Cc: stable@kernel.org Signed-off-by: Tejun Heo --- kernel/cgroup_freezer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 5e828a2ca8e6..213c0351dad8 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c @@ -153,6 +153,13 @@ static void freezer_destroy(struct cgroup_subsys *ss, kfree(cgroup_freezer(cgroup)); } +/* task is frozen or will freeze immediately when next it gets woken */ +static bool is_task_frozen_enough(struct task_struct *task) +{ + return frozen(task) || + (task_is_stopped_or_traced(task) && freezing(task)); +} + /* * The call to cgroup_lock() in the freezer.state write method prevents * a write to that file racing against an attach, and hence the @@ -231,7 +238,7 @@ static void update_if_frozen(struct cgroup *cgroup, cgroup_iter_start(cgroup, &it); while ((task = cgroup_iter_next(cgroup, &it))) { ntotal++; - if (frozen(task)) + if (is_task_frozen_enough(task)) nfrozen++; } @@ -284,7 +291,7 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) while ((task = cgroup_iter_next(cgroup, &it))) { if (!freeze_task(task, true)) continue; - if (frozen(task)) + if (is_task_frozen_enough(task)) continue; if (!freezing(task) && !freezer_should_skip(task)) num_cant_freeze_now++; -- cgit From ffe06198876a3cbda1cd642883adcec5304d9442 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Nov 2011 19:22:10 -0200 Subject: MAINTAINERS: Update media entries Now that we've created a /drivers/staging/media, put it together with /drivers/media. Also, added there a missing entry for the Media API spec. Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index e839b95b2723..273b0498e715 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4234,7 +4234,9 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: Documentation/dvb/ F: Documentation/video4linux/ +F: Documentation/DocBook/media/ F: drivers/media/ +F: drivers/staging/media/ F: include/media/ F: include/linux/dvb/ F: include/linux/videodev*.h -- cgit From e067d5abdd04cbf1bed466f95682c67e2496ba42 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 Nov 2011 22:17:03 -0300 Subject: [media] media/staging: fix allyesconfig build error Fix x86 allyesconfig builds. Builds fail due to a non-static variable named 'debug' in drivers/staging/media/as102/. Signed-off-by: Randy Dunlap Cc: Pierrick Hascoet Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/as102/as102_drv.c | 4 ++-- drivers/staging/media/as102/as102_drv.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index d335c7d6fa0f..828526d4c289 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -32,8 +32,8 @@ #include "as102_fw.h" #include "dvbdev.h" -int debug; -module_param_named(debug, debug, int, 0644); +int as102_debug; +module_param_named(debug, as102_debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)"); int dual_tuner; diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index bcda635b5a99..fd33f5a12dcc 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -37,7 +37,8 @@ extern struct spi_driver as102_spi_driver; #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver" #define DRIVER_NAME "as10x_usb" -extern int debug; +extern int as102_debug; +#define debug as102_debug #define dprintk(debug, args...) \ do { if (debug) { \ -- cgit From 7acde02a5bf4d3c32cd197eb7ce2257e6a0e17b7 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 13 Sep 2011 14:07:09 -0300 Subject: [media] s5p-fimc: Fix wrong pointer dereference when unregistering sensors After i2c_unregister_device() has been called the client object can already be freed and thus using the client pointer may lead to dereferencing freed memory. Avoid this by saving the adapter pointer for further use before i2c_unregister_device() call. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index cc337b1de913..d558ae79e320 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -220,6 +220,7 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, s_info->pdata->board_info, NULL); if (IS_ERR_OR_NULL(sd)) { + i2c_put_adapter(adapter); v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n"); return NULL; } @@ -234,12 +235,15 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, static void fimc_md_unregister_sensor(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct i2c_adapter *adapter; if (!client) return; v4l2_device_unregister_subdev(sd); + adapter = client->adapter; i2c_unregister_device(client); - i2c_put_adapter(client->adapter); + if (adapter) + i2c_put_adapter(adapter); } static int fimc_md_register_sensor_entities(struct fimc_md *fmd) -- cgit From 64c570f505a0eac4914402bb7832d019c44eabd8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 11 Sep 2011 10:36:13 -0300 Subject: [media] s5p-fimc: Fix error in the capture subdev deinitialization Make sure the subdev pointer is cleared when the subdev object has been freed. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index c8d91b0cd9bd..382dacd23133 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -1375,7 +1375,7 @@ static void fimc_destroy_capture_subdev(struct fimc_dev *fimc) media_entity_cleanup(&sd->entity); v4l2_device_unregister_subdev(sd); kfree(sd); - sd = NULL; + fimc->vid_cap.subdev = NULL; } /* Set default format at the sensor and host interface */ -- cgit From 7aa9f1844a3aac428ef7977a9f1da706718afe0d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 4 Nov 2011 09:59:52 -0300 Subject: [media] s5p-fimc: Fix initialization for proper system suspend support ST_LPM bit must not be initially set, so the first resume helper call properly quiesce the device's operation. Also fimc_runtime_suspend() at device remove is unneeded and leads to unbalanced clock disable so remove it. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 19ca6db38b2f..ef53528934f2 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -1615,7 +1615,6 @@ static int fimc_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; fimc->pdata = pdata; - set_bit(ST_LPM, &fimc->state); init_waitqueue_head(&fimc->irq_queue); spin_lock_init(&fimc->slock); @@ -1780,7 +1779,6 @@ static int __devexit fimc_remove(struct platform_device *pdev) struct fimc_dev *fimc = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); - fimc_runtime_suspend(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); -- cgit From 2c1bb62e217f4f2eb6fa9734dcb331bc09c7768e Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 5 Oct 2011 14:20:45 -0300 Subject: [media] s5p-fimc: Fix buffer dequeue order issue When requested more than 2 buffers the buffer dequeue order was wrong due to erroneous updating FIMC registers in every interrupt handler call. This also fixes regression of resetting the output DMA buffer pointer at wrong time, when some buffers are already queued in hardware. The hardware is reset in the start_streaming callback in order to align the H/W state with the software output buffer pointer (buf_index). Additionally a simple write to S5P_CISCCTRL register is replaced with a read/modification/write to make sure the scaler is not being disabled in fimc_hw_set_scaler(). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 9 ++++++--- drivers/media/video/s5p-fimc/fimc-core.c | 4 ---- drivers/media/video/s5p-fimc/fimc-reg.c | 15 ++++++++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 382dacd23133..70f741f7659f 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -98,6 +98,10 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } set_bit(ST_CAPT_SUSPENDED, &fimc->state); + + fimc_hw_reset(fimc); + cap->buf_index = 0; + spin_unlock_irqrestore(&fimc->slock, flags); if (streaming) @@ -137,7 +141,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) struct fimc_dev *fimc = ctx->fimc_dev; int ret; - if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) + if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) return 0; spin_lock(&ctx->slock); @@ -150,7 +154,7 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) fimc_hw_set_rotation(ctx); fimc_prepare_dma_offset(ctx, &ctx->d_frame); fimc_hw_set_out_dma(ctx); - set_bit(ST_CAPT_APPLY_CFG, &fimc->state); + clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); } spin_unlock(&ctx->slock); return ret; @@ -164,7 +168,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) int min_bufs; int ret; - fimc_hw_reset(fimc); vid_cap->frame_count = 0; ret = fimc_init_capture(fimc); diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index ef53528934f2..9c3a8c51da4f 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -1706,8 +1706,6 @@ static int fimc_runtime_resume(struct device *dev) /* Enable clocks and perform basic initalization */ clk_enable(fimc->clock[CLK_GATE]); fimc_hw_reset(fimc); - if (fimc->variant->out_buf_count > 4) - fimc_hw_set_dma_seq(fimc, 0xF); /* Resume the capture or mem-to-mem device */ if (fimc_capture_busy(fimc)) @@ -1749,8 +1747,6 @@ static int fimc_resume(struct device *dev) return 0; } fimc_hw_reset(fimc); - if (fimc->variant->out_buf_count > 4) - fimc_hw_set_dma_seq(fimc, 0xF); spin_unlock_irqrestore(&fimc->slock, flags); if (fimc_capture_busy(fimc)) diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 20e664e34163..44f5c2d1920b 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -35,6 +35,9 @@ void fimc_hw_reset(struct fimc_dev *dev) cfg = readl(dev->regs + S5P_CIGCTRL); cfg &= ~S5P_CIGCTRL_SWRST; writel(cfg, dev->regs + S5P_CIGCTRL); + + if (dev->variant->out_buf_count > 4) + fimc_hw_set_dma_seq(dev, 0xF); } static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx) @@ -251,7 +254,14 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx) struct fimc_scaler *sc = &ctx->scaler; struct fimc_frame *src_frame = &ctx->s_frame; struct fimc_frame *dst_frame = &ctx->d_frame; - u32 cfg = 0; + + u32 cfg = readl(dev->regs + S5P_CISCCTRL); + + cfg &= ~(S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE | + S5P_CISCCTRL_SCALEUP_H | S5P_CISCCTRL_SCALEUP_V | + S5P_CISCCTRL_SCALERBYPASS | S5P_CISCCTRL_ONE2ONE | + S5P_CISCCTRL_INRGB_FMT_MASK | S5P_CISCCTRL_OUTRGB_FMT_MASK | + S5P_CISCCTRL_INTERLACE | S5P_CISCCTRL_RGB_EXT); if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); @@ -308,9 +318,9 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) fimc_hw_set_scaler(ctx); cfg = readl(dev->regs + S5P_CISCCTRL); + cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK); if (variant->has_mainscaler_ext) { - cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK); cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio); cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio); writel(cfg, dev->regs + S5P_CISCCTRL); @@ -323,7 +333,6 @@ void fimc_hw_set_mainscaler(struct fimc_ctx *ctx) cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio); writel(cfg, dev->regs + S5P_CIEXTEN); } else { - cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK); cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio); cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio); writel(cfg, dev->regs + S5P_CISCCTRL); -- cgit From 5cbf6f16ecc07e9f73107c1adf95013bce9f2cf6 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 7 Oct 2011 07:40:00 -0300 Subject: [media] s5p-fimc: Allow probe() to succeed with null platform data The "s5p-fimc-md" platform device platform_data is used to pass attached camera sensor data. Not allowing device probe() to succeed when it's null prevents using FIMC as a mem-to-mem device only. Fix this by removing the platform_data check against null and registering sensors only if platform_data is specified. Also add logging of the information which /dev/video is assigned to which device during probe(). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 35 +++++++++++++++++------------ 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index d558ae79e320..fc81f6faa39a 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -385,20 +385,28 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) static int fimc_md_register_video_nodes(struct fimc_md *fmd) { + struct video_device *vdev; int i, ret = 0; for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) { if (!fmd->fimc[i]) continue; - if (fmd->fimc[i]->m2m.vfd) - ret = video_register_device(fmd->fimc[i]->m2m.vfd, - VFL_TYPE_GRABBER, -1); - if (ret) - break; - if (fmd->fimc[i]->vid_cap.vfd) - ret = video_register_device(fmd->fimc[i]->vid_cap.vfd, - VFL_TYPE_GRABBER, -1); + vdev = fmd->fimc[i]->m2m.vfd; + if (vdev) { + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (ret) + break; + v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", + vdev->name, video_device_node_name(vdev)); + } + + vdev = fmd->fimc[i]->vid_cap.vfd; + if (vdev == NULL) + continue; + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n", + vdev->name, video_device_node_name(vdev)); } return ret; @@ -746,9 +754,6 @@ static int __devinit fimc_md_probe(struct platform_device *pdev) struct fimc_md *fmd; int ret; - if (WARN(!pdev->dev.platform_data, "Platform data not specified!\n")) - return -EINVAL; - fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); if (!fmd) return -ENOMEM; @@ -786,9 +791,11 @@ static int __devinit fimc_md_probe(struct platform_device *pdev) if (ret) goto err3; - ret = fimc_md_register_sensor_entities(fmd); - if (ret) - goto err3; + if (pdev->dev.platform_data) { + ret = fimc_md_register_sensor_entities(fmd); + if (ret) + goto err3; + } ret = fimc_md_create_links(fmd); if (ret) goto err3; -- cgit From 9c63afcb02b4313838d83c3660e45544d9fc9976 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 27 May 2011 13:12:23 -0300 Subject: [media] s5p-fimc: Adjust pixel height alignments according to the IP revision Minimum vertical pixel size alignment for input and output DMA and the scaler depend on color format, rotation, the IP instance and revision. Make vertical pixel size of format and crop better fit for each SoC revision and the IP instance by adding min_vsize_align attribute to the FIMC variant data structure. It's now common for the DMA engines and the scaler. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 2 +- drivers/media/video/s5p-fimc/fimc-core.c | 16 +++++++++++----- drivers/media/video/s5p-fimc/fimc-core.h | 2 ++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 70f741f7659f..82d9ab6984eb 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -526,7 +526,7 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx, max_w = rotation ? pl->out_rot_en_w : pl->out_rot_dis_w; min_w = ctx->state & FIMC_DST_CROP ? dst->width : var->min_out_pixsize; min_h = ctx->state & FIMC_DST_CROP ? dst->height : var->min_out_pixsize; - if (fimc->id == 1 && var->pix_hoff) + if (var->min_vsize_align == 1 && !rotation) align_h = fimc_fmt_is_rgb(ffmt->color) ? 0 : 1; depth = fimc_get_format_depth(ffmt); diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 9c3a8c51da4f..7c22d78b0569 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -1038,12 +1038,11 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) mod_x = 6; /* 64 x 32 pixels tile */ mod_y = 5; } else { - if (fimc->id == 1 && variant->pix_hoff) + if (variant->min_vsize_align == 1) mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1; else - mod_y = mod_x; + mod_y = ffs(variant->min_vsize_align) - 1; } - dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_w); v4l_bound_align_image(&pix->width, 16, max_w, mod_x, &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); @@ -1226,10 +1225,10 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; /* Get pixel alignment constraints. */ - if (fimc->id == 1 && fimc->variant->pix_hoff) + if (fimc->variant->min_vsize_align == 1) halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1; else - halign = ffs(min_size) - 1; + halign = ffs(fimc->variant->min_vsize_align) - 1; for (i = 0; i < f->fmt->colplanes; i++) depth += f->fmt->depth[i]; @@ -1834,6 +1833,7 @@ static struct samsung_fimc_variant fimc0_variant_s5p = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 8, + .min_vsize_align = 16, .out_buf_count = 4, .pix_limit = &s5p_pix_limit[0], }; @@ -1843,6 +1843,7 @@ static struct samsung_fimc_variant fimc2_variant_s5p = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 8, + .min_vsize_align = 16, .out_buf_count = 4, .pix_limit = &s5p_pix_limit[1], }; @@ -1855,6 +1856,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv210 = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 8, + .min_vsize_align = 16, .out_buf_count = 4, .pix_limit = &s5p_pix_limit[1], }; @@ -1868,6 +1870,7 @@ static struct samsung_fimc_variant fimc1_variant_s5pv210 = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 1, + .min_vsize_align = 1, .out_buf_count = 4, .pix_limit = &s5p_pix_limit[2], }; @@ -1878,6 +1881,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv210 = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 8, + .min_vsize_align = 16, .out_buf_count = 4, .pix_limit = &s5p_pix_limit[2], }; @@ -1892,6 +1896,7 @@ static struct samsung_fimc_variant fimc0_variant_exynos4 = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 2, + .min_vsize_align = 1, .out_buf_count = 32, .pix_limit = &s5p_pix_limit[1], }; @@ -1904,6 +1909,7 @@ static struct samsung_fimc_variant fimc3_variant_exynos4 = { .min_inp_pixsize = 16, .min_out_pixsize = 16, .hor_offs_align = 2, + .min_vsize_align = 1, .out_buf_count = 32, .pix_limit = &s5p_pix_limit[3], }; diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index a6936dad5b10..c7f01c47b20f 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -377,6 +377,7 @@ struct fimc_pix_limit { * @min_inp_pixsize: minimum input pixel size * @min_out_pixsize: minimum output pixel size * @hor_offs_align: horizontal pixel offset aligment + * @min_vsize_align: minimum vertical pixel size alignment * @out_buf_count: the number of buffers in output DMA sequence */ struct samsung_fimc_variant { @@ -390,6 +391,7 @@ struct samsung_fimc_variant { u16 min_inp_pixsize; u16 min_out_pixsize; u16 hor_offs_align; + u16 min_vsize_align; u16 out_buf_count; }; -- cgit From d12392ec006d94e5cf6c98f7ed56ff0c881ec33f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 20 Oct 2011 05:15:59 -0300 Subject: [media] s5p-fimc: Fail driver probing when sensor configuration is wrong When a sensor with MIPI-CSI interface is attached through platform data definition and the MIPI-CSI receiver is not selected in kernel configuration s5p-fimc driver probe() will now succeed, issuing only a warning. It was done this way to allow the driver to work even if system configuration is not exactly right. Instead make the driver's probe() fail if a MIPI-CSI sensor was requested but s5p-csis module is not present. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index fc81f6faa39a..615c862f0360 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -514,7 +514,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) - continue; + return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, -- cgit From f83f71fda27650ae43558633be93652577dbc38c Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 4 Nov 2011 10:07:06 -0300 Subject: [media] s5p-fimc: Use correct fourcc for RGB565 colour format With 16-bit RGB565 colour format pixels are stored by the device in memory in the following order: | b3 | b2 | b1 | b0 | ~+-----+-----+-----+-----+ | R5 G6 B5 | R5 G6 B5 | This corresponds to V4L2_PIX_FMT_RGB565 fourcc, not V4L2_PIX_FMT_RGB565X. This change is required to avoid trouble when setting up video pipeline with the s5p-tv devices, so the colour formats at both devices can be properly matched. Cc: Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 7c22d78b0569..07c6254faee3 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -37,7 +37,7 @@ static char *fimc_clocks[MAX_FIMC_CLOCKS] = { static struct fimc_fmt fimc_formats[] = { { .name = "RGB565", - .fourcc = V4L2_PIX_FMT_RGB565X, + .fourcc = V4L2_PIX_FMT_RGB565, .depth = { 16 }, .color = S5P_FIMC_RGB565, .memplanes = 1, -- cgit From fbe78ddde1f217044ed854eff92e4d22112871cb Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 16 Nov 2011 08:19:58 -0300 Subject: [media] m5mols: Fix set_fmt to return proper pixel format code In case pixel format is modified in set_fmt by the driver, the changes are not propagated back to the caller. Fix this by adjusting passed data for TRY and ACTIVE format. Also remove redundant pixel format code information from struct m5mols_info, it's already available in 'ffmt' array. Remove pad number validation in set/get_fmt, this is already done in the core. Signed-off-by: Sylwester Nawrocki Acked-by: HeungJun Kim Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols.h | 2 -- drivers/media/video/m5mols/m5mols_core.c | 20 ++++++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 89d09a8914f8..82c8817bd32d 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h @@ -162,7 +162,6 @@ struct m5mols_version { * @pad: media pad * @ffmt: current fmt according to resolution type * @res_type: current resolution type - * @code: current code * @irq_waitq: waitqueue for the capture * @work_irq: workqueue for the IRQ * @flags: state variable for the interrupt handler @@ -192,7 +191,6 @@ struct m5mols_info { struct media_pad pad; struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; int res_type; - enum v4l2_mbus_pixelcode code; wait_queue_head_t irq_waitq; struct work_struct work_irq; unsigned long flags; diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 5d21d056d6a3..68497f8ddcd9 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -510,9 +510,6 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct m5mols_info *info = to_m5mols(sd); struct v4l2_mbus_framefmt *format; - if (fmt->pad != 0) - return -EINVAL; - format = __find_format(info, fh, fmt->which, info->res_type); if (!format) return -EINVAL; @@ -531,9 +528,6 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, u32 resolution = 0; int ret; - if (fmt->pad != 0) - return -EINVAL; - ret = __find_resolution(sd, format, &type, &resolution); if (ret < 0) return ret; @@ -542,13 +536,14 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, if (!sfmt) return 0; - *sfmt = m5mols_default_ffmt[type]; - sfmt->width = format->width; - sfmt->height = format->height; + + format->code = m5mols_default_ffmt[type].code; + format->colorspace = V4L2_COLORSPACE_JPEG; + format->field = V4L2_FIELD_NONE; if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + *sfmt = *format; info->resolution = resolution; - info->code = format->code; info->res_type = type; } @@ -625,13 +620,14 @@ static int m5mols_start_monitor(struct m5mols_info *info) static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); + u32 code = info->ffmt[info->res_type].code; if (enable) { int ret = -EINVAL; - if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) + if (is_code(code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); - if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) + if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); return ret; -- cgit From 13020be8be2d5843c3810169cdbcc51f07ff020f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 24 Nov 2011 09:40:07 +0000 Subject: powerpc: Fix compiliation with hugetlbfs enabled arch/powerpc/mm/hugetlbpage.c: In function 'reserve_hugetlb_gpages': arch/powerpc/mm/hugetlbpage.c:312:2: error: implicit declaration of function 'parse_args' Signed-off-by: Kumar Gala Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/mm/hugetlbpage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 5964371303ac..8558b572e55d 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include -- cgit From 49e44064d7e3f24f874a51dd513b83ef9994aa8a Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Tue, 22 Nov 2011 13:50:46 +0000 Subject: powerpc/44x: Add mtd ndfc to the ppx44x defconfig Signed-off-by: Tony Breeds Acked-by: Josh Boyer Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/configs/ppc44x_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index 6cdf1c0d2c8a..3b98d7354341 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig @@ -52,6 +52,8 @@ CONFIG_MTD_CFI=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_NDFC=m CONFIG_MTD_UBI=m CONFIG_MTD_UBI_GLUEBI=m CONFIG_PROC_DEVICETREE=y -- cgit From 025521f917b9a36d76fb701609b3578b1563818b Mon Sep 17 00:00:00 2001 From: Dmitry Artamonow Date: Sun, 20 Nov 2011 12:54:26 -0300 Subject: [media] omap3isp: fix compilation of ispvideo.c Fix following build error by explicitely including header file. CC drivers/media/video/omap3isp/ispvideo.o Signed-off-by: Dmitry Artamonow Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/ispvideo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c index d1000723c5ae..f2290578448c 100644 --- a/drivers/media/video/omap3isp/ispvideo.c +++ b/drivers/media/video/omap3isp/ispvideo.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include -- cgit From fc8ac777ae39409e81f7dd2d123d980c0dfb528e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Nov 2011 05:02:38 -0300 Subject: [media] media: video: s5p-tv: fix build break This patch fixes following build break: Signed-off-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-tv/mixer_video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index e16d3a4bc1dc..b47d0c06ecf5 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include -- cgit From 4c81f045c0bd2cbb78cc6446a4cd98038fe11a2e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 24 Nov 2011 19:22:24 -0500 Subject: ext4: fix racy use-after-free in ext4_end_io_dio() ext4_end_io_dio() queues io_end->work and then clears iocb->private; however, io_end->work calls aio_complete() which frees the iocb object. If that slab object gets reallocated, then ext4_end_io_dio() can end up clearing someone else's iocb->private, this use-after-free can cause a leak of a struct ext4_io_end_t structure. Detected and tested with slab poisoning. [ Note: Can also reproduce using 12 fio's against 12 file systems with the following configuration file: [global] direct=1 ioengine=libaio iodepth=1 bs=4k ba=4k size=128m [create] filename=${TESTDIR} rw=write -- tytso ] Google-Bug-Id: 5354697 Signed-off-by: Tejun Heo Signed-off-by: "Theodore Ts'o" Reported-by: Kent Overstreet Tested-by: Kent Overstreet Cc: stable@kernel.org --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fffec40d5996..848f436df29f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2807,8 +2807,8 @@ out: spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); /* queue the work to convert unwritten extents to written */ - queue_work(wq, &io_end->work); iocb->private = NULL; + queue_work(wq, &io_end->work); /* XXX: probably should move into the real I/O completion handler */ inode_dio_done(inode); -- cgit From 42ca0203fd59aa9be7b241be1fbc3bef1f903f9c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 23 Nov 2011 21:18:20 +0000 Subject: net/netlabel: copy and paste bug in netlbl_cfg_unlbl_map_add() This was copy and pasted from the IPv4 code. We're calling the ip4 version of that function and map4 is NULL. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/netlabel/netlabel_kapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 9c24de10a657..7b372a763c60 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -162,8 +162,8 @@ int netlbl_cfg_unlbl_map_add(const char *domain, map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3]; ipv6_addr_copy(&map6->list.mask, mask6); map6->list.valid = 1; - ret_val = netlbl_af4list_add(&map4->list, - &addrmap->list4); + ret_val = netlbl_af6list_add(&map6->list, + &addrmap->list6); if (ret_val != 0) goto cfg_unlbl_map_add_failure; break; -- cgit From ae95757a9065d89be7c1ca613b53163dd30858b7 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Fri, 25 Nov 2011 09:41:25 +0100 Subject: loop: fix loop block driver discard and encryption comment The loop driver does not support discard if encryption is enabled, fix the comment. Signed-off-by: Dave Young Signed-off-by: Jens Axboe --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 68b205a9338f..5579fda279b4 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -422,7 +422,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) /* * We use punch hole to reclaim the free space used by the - * image a.k.a. discard. However we do support discard if + * image a.k.a. discard. However we do not support discard if * encryption is enabled, because it may give an attacker * useful information. */ -- cgit From b52fabca369f433999837b73031bdd34feb6fca2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 24 Nov 2011 10:29:14 -0500 Subject: hwmon: Remove redundant spi driver bus initialization In ancient times it was necessary to manually initialize the bus field of an spi_driver to spi_bus_type. These days this is done in spi_register_driver(), so we can drop the manual assignment. The patch was generated using the following coccinelle semantic patch: // @@ identifier _driver; @@ struct spi_driver _driver = { .driver = { - .bus = &spi_bus_type, }, }; // Signed-off-by: Lars-Peter Clausen Cc: Jean Delvare Cc: Guenter Roeck Cc: lm-sensors@lm-sensors.org Signed-off-by: Guenter Roeck --- drivers/hwmon/ad7314.c | 1 - drivers/hwmon/ads7871.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index 318e38e85376..5d760f3d21c2 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -160,7 +160,6 @@ MODULE_DEVICE_TABLE(spi, ad7314_id); static struct spi_driver ad7314_driver = { .driver = { .name = "ad7314", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = ad7314_probe, diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index 52319340e182..04450f8bf5da 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -227,7 +227,6 @@ static int __devexit ads7871_remove(struct spi_device *spi) static struct spi_driver ads7871_driver = { .driver = { .name = DEVICE_NAME, - .bus = &spi_bus_type, .owner = THIS_MODULE, }, -- cgit From df07a94cf50eb73d09bf2350c3fe2598e4cbeee1 Mon Sep 17 00:00:00 2001 From: "Jorge Boncompte [DTI2]" Date: Fri, 25 Nov 2011 13:24:49 -0500 Subject: netns: fix proxy ARP entries listing on a netns Skip entries from foreign network namespaces. Signed-off-by: Jorge Boncompte [DTI2] Signed-off-by: David S. Miller --- net/core/neighbour.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 039d51e6c284..5ac07d31fbc9 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2397,7 +2397,10 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, struct net *net = seq_file_net(seq); struct neigh_table *tbl = state->tbl; - pn = pn->next; + do { + pn = pn->next; + } while (pn && !net_eq(pneigh_net(pn), net)); + while (!pn) { if (++state->bucket > PNEIGH_HASHMASK) break; -- cgit From 25a236a5dba47a16affb105525cfd75eaa03ceea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 25 Nov 2011 02:31:00 -0500 Subject: hwmon: convert drivers/hwmon/* to use module_platform_driver() This patch converts the drivers in drivers/hwmon/* to use the module_platform_driver() macro which makes the code smaller and a bit simpler. Cc: Donggeun Kim Cc: Simon Guinot Cc: Lars-Peter Clausen Cc: MyungJoo Ham Cc: Ben Dooks Cc: Hans de Goede Cc: J Keerthy Cc: David S. Miller Cc: Mark Brown Signed-off-by: Axel Lin Acked-by: Mark Brown Signed-off-by: Guenter Roeck --- drivers/hwmon/exynos4_tmu.c | 12 +----------- drivers/hwmon/gpio-fan.c | 13 +------------ drivers/hwmon/jz4740-hwmon.c | 12 +----------- drivers/hwmon/ntc_thermistor.c | 14 +------------- drivers/hwmon/s3c-hwmon.c | 13 +------------ drivers/hwmon/sch5627.c | 13 +------------ drivers/hwmon/sch5636.c | 13 +------------ drivers/hwmon/twl4030-madc-hwmon.c | 14 +------------- drivers/hwmon/ultra45_env.c | 13 +------------ drivers/hwmon/wm831x-hwmon.c | 12 +----------- drivers/hwmon/wm8350-hwmon.c | 12 +----------- 11 files changed, 11 insertions(+), 130 deletions(-) diff --git a/drivers/hwmon/exynos4_tmu.c b/drivers/hwmon/exynos4_tmu.c index faa0884f61f6..f2359a0093bd 100644 --- a/drivers/hwmon/exynos4_tmu.c +++ b/drivers/hwmon/exynos4_tmu.c @@ -506,17 +506,7 @@ static struct platform_driver exynos4_tmu_driver = { .resume = exynos4_tmu_resume, }; -static int __init exynos4_tmu_driver_init(void) -{ - return platform_driver_register(&exynos4_tmu_driver); -} -module_init(exynos4_tmu_driver_init); - -static void __exit exynos4_tmu_driver_exit(void) -{ - platform_driver_unregister(&exynos4_tmu_driver); -} -module_exit(exynos4_tmu_driver_exit); +module_platform_driver(exynos4_tmu_driver); MODULE_DESCRIPTION("EXYNOS4 TMU Driver"); MODULE_AUTHOR("Donggeun Kim "); diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 89aa9fb743af..9ba38f318ffb 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -539,18 +539,7 @@ static struct platform_driver gpio_fan_driver = { }, }; -static int __init gpio_fan_init(void) -{ - return platform_driver_register(&gpio_fan_driver); -} - -static void __exit gpio_fan_exit(void) -{ - platform_driver_unregister(&gpio_fan_driver); -} - -module_init(gpio_fan_init); -module_exit(gpio_fan_exit); +module_platform_driver(gpio_fan_driver); MODULE_AUTHOR("Simon Guinot "); MODULE_DESCRIPTION("GPIO FAN driver"); diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index fea292d43407..7a48b1eb4233 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c @@ -212,17 +212,7 @@ struct platform_driver jz4740_hwmon_driver = { }, }; -static int __init jz4740_hwmon_init(void) -{ - return platform_driver_register(&jz4740_hwmon_driver); -} -module_init(jz4740_hwmon_init); - -static void __exit jz4740_hwmon_exit(void) -{ - platform_driver_unregister(&jz4740_hwmon_driver); -} -module_exit(jz4740_hwmon_exit); +module_platform_driver(jz4740_hwmon_driver); MODULE_DESCRIPTION("JZ4740 SoC HWMON driver"); MODULE_AUTHOR("Lars-Peter Clausen "); diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index eab11615dced..9b382ec2c3bd 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -432,19 +432,7 @@ static struct platform_driver ntc_thermistor_driver = { .id_table = ntc_thermistor_id, }; -static int __init ntc_thermistor_init(void) -{ - return platform_driver_register(&ntc_thermistor_driver); -} - -module_init(ntc_thermistor_init); - -static void __exit ntc_thermistor_cleanup(void) -{ - platform_driver_unregister(&ntc_thermistor_driver); -} - -module_exit(ntc_thermistor_cleanup); +module_platform_driver(ntc_thermistor_driver); MODULE_DESCRIPTION("NTC Thermistor Driver"); MODULE_AUTHOR("MyungJoo Ham "); diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c index b39f52e2752a..f6c26d19f521 100644 --- a/drivers/hwmon/s3c-hwmon.c +++ b/drivers/hwmon/s3c-hwmon.c @@ -393,18 +393,7 @@ static struct platform_driver s3c_hwmon_driver = { .remove = __devexit_p(s3c_hwmon_remove), }; -static int __init s3c_hwmon_init(void) -{ - return platform_driver_register(&s3c_hwmon_driver); -} - -static void __exit s3c_hwmon_exit(void) -{ - platform_driver_unregister(&s3c_hwmon_driver); -} - -module_init(s3c_hwmon_init); -module_exit(s3c_hwmon_exit); +module_platform_driver(s3c_hwmon_driver); MODULE_AUTHOR("Ben Dooks "); MODULE_DESCRIPTION("S3C ADC HWMon driver"); diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index e3b5c6039c25..79b6dabe3161 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -590,19 +590,8 @@ static struct platform_driver sch5627_driver = { .remove = sch5627_remove, }; -static int __init sch5627_init(void) -{ - return platform_driver_register(&sch5627_driver); -} - -static void __exit sch5627_exit(void) -{ - platform_driver_unregister(&sch5627_driver); -} +module_platform_driver(sch5627_driver); MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver"); MODULE_AUTHOR("Hans de Goede "); MODULE_LICENSE("GPL"); - -module_init(sch5627_init); -module_exit(sch5627_exit); diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c index 244407aa79fc..9d5236fb09b4 100644 --- a/drivers/hwmon/sch5636.c +++ b/drivers/hwmon/sch5636.c @@ -521,19 +521,8 @@ static struct platform_driver sch5636_driver = { .remove = sch5636_remove, }; -static int __init sch5636_init(void) -{ - return platform_driver_register(&sch5636_driver); -} - -static void __exit sch5636_exit(void) -{ - platform_driver_unregister(&sch5636_driver); -} +module_platform_driver(sch5636_driver); MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver"); MODULE_AUTHOR("Hans de Goede "); MODULE_LICENSE("GPL"); - -module_init(sch5636_init); -module_exit(sch5636_exit); diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 57240740b161..0018c7dd0097 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -136,19 +136,7 @@ static struct platform_driver twl4030_madc_hwmon_driver = { }, }; -static int __init twl4030_madc_hwmon_init(void) -{ - return platform_driver_register(&twl4030_madc_hwmon_driver); -} - -module_init(twl4030_madc_hwmon_init); - -static void __exit twl4030_madc_hwmon_exit(void) -{ - platform_driver_unregister(&twl4030_madc_hwmon_driver); -} - -module_exit(twl4030_madc_hwmon_exit); +module_platform_driver(twl4030_madc_hwmon_driver); MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 3cd07bf42dca..b9a87e89bab4 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -309,15 +309,4 @@ static struct platform_driver env_driver = { .remove = __devexit_p(env_remove), }; -static int __init env_init(void) -{ - return platform_driver_register(&env_driver); -} - -static void __exit env_exit(void) -{ - platform_driver_unregister(&env_driver); -} - -module_init(env_init); -module_exit(env_exit); +module_platform_driver(env_driver); diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c index 97b1f834a471..9b598ed26020 100644 --- a/drivers/hwmon/wm831x-hwmon.c +++ b/drivers/hwmon/wm831x-hwmon.c @@ -209,17 +209,7 @@ static struct platform_driver wm831x_hwmon_driver = { }, }; -static int __init wm831x_hwmon_init(void) -{ - return platform_driver_register(&wm831x_hwmon_driver); -} -module_init(wm831x_hwmon_init); - -static void __exit wm831x_hwmon_exit(void) -{ - platform_driver_unregister(&wm831x_hwmon_driver); -} -module_exit(wm831x_hwmon_exit); +module_platform_driver(wm831x_hwmon_driver); MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("WM831x Hardware Monitoring"); diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c index 13290595ca86..3ff67edbdc44 100644 --- a/drivers/hwmon/wm8350-hwmon.c +++ b/drivers/hwmon/wm8350-hwmon.c @@ -133,17 +133,7 @@ static struct platform_driver wm8350_hwmon_driver = { }, }; -static int __init wm8350_hwmon_init(void) -{ - return platform_driver_register(&wm8350_hwmon_driver); -} -module_init(wm8350_hwmon_init); - -static void __exit wm8350_hwmon_exit(void) -{ - platform_driver_unregister(&wm8350_hwmon_driver); -} -module_exit(wm8350_hwmon_exit); +module_platform_driver(wm8350_hwmon_driver); MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("WM8350 Hardware Monitoring"); -- cgit From 6b600b26c0215bf9ed04062ecfacf0bc20e2588c Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 23 Nov 2011 02:12:13 +0000 Subject: route: Use the device mtu as the default for blackhole routes As it is, we return null as the default mtu of blackhole routes. This may lead to a propagation of a bogus pmtu if the default_mtu method of a blackhole route is invoked. So return dst->dev->mtu as the default mtu instead. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/route.c | 2 +- net/ipv6/route.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 0c74da8a0473..5b17bf124a33 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2757,7 +2757,7 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo static unsigned int ipv4_blackhole_default_mtu(const struct dst_entry *dst) { - return 0; + return dst->dev->mtu; } static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8473016bba4a..d8fbd18c9467 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -157,7 +157,7 @@ static struct dst_ops ip6_dst_ops_template = { static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) { - return 0; + return dst->dev->mtu; } static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) -- cgit From ebb762f27fed083cb993a0816393aba4615f6544 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 23 Nov 2011 02:12:51 +0000 Subject: net: Rename the dst_opt default_mtu method to mtu We plan to invoke the dst_opt->default_mtu() method unconditioally from dst_mtu(). So rename the method to dst_opt->mtu() to match the name with the new meaning. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- include/net/dst.h | 2 +- include/net/dst_ops.h | 2 +- net/decnet/dn_route.c | 6 +++--- net/ipv4/route.c | 10 +++++----- net/ipv6/route.c | 10 +++++----- net/xfrm/xfrm_policy.c | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 4fb6c4381791..666de31d8e7d 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -208,7 +208,7 @@ static inline u32 dst_mtu(const struct dst_entry *dst) u32 mtu = dst_metric_raw(dst, RTAX_MTU); if (!mtu) - mtu = dst->ops->default_mtu(dst); + mtu = dst->ops->mtu(dst); return mtu; } diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index 9adb99845a56..e1c2ee0eef47 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -17,7 +17,7 @@ struct dst_ops { int (*gc)(struct dst_ops *ops); struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); unsigned int (*default_advmss)(const struct dst_entry *); - unsigned int (*default_mtu)(const struct dst_entry *); + unsigned int (*mtu)(const struct dst_entry *); u32 * (*cow_metrics)(struct dst_entry *, unsigned long); void (*destroy)(struct dst_entry *); void (*ifdown)(struct dst_entry *, diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index a77d16158eb6..db4867963247 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -112,7 +112,7 @@ static unsigned long dn_rt_deadline; static int dn_dst_gc(struct dst_ops *ops); static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); -static unsigned int dn_dst_default_mtu(const struct dst_entry *dst); +static unsigned int dn_dst_mtu(const struct dst_entry *dst); static void dn_dst_destroy(struct dst_entry *); static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); static void dn_dst_link_failure(struct sk_buff *); @@ -135,7 +135,7 @@ static struct dst_ops dn_dst_ops = { .gc = dn_dst_gc, .check = dn_dst_check, .default_advmss = dn_dst_default_advmss, - .default_mtu = dn_dst_default_mtu, + .mtu = dn_dst_mtu, .cow_metrics = dst_cow_metrics_generic, .destroy = dn_dst_destroy, .negative_advice = dn_dst_negative_advice, @@ -825,7 +825,7 @@ static unsigned int dn_dst_default_advmss(const struct dst_entry *dst) return dn_mss_from_pmtu(dst->dev, dst_mtu(dst)); } -static unsigned int dn_dst_default_mtu(const struct dst_entry *dst) +static unsigned int dn_dst_mtu(const struct dst_entry *dst) { return dst->dev->mtu; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5b17bf124a33..f1ac3efc5524 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -138,7 +138,7 @@ static int rt_chain_length_max __read_mostly = 20; static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ipv4_default_advmss(const struct dst_entry *dst); -static unsigned int ipv4_default_mtu(const struct dst_entry *dst); +static unsigned int ipv4_mtu(const struct dst_entry *dst); static void ipv4_dst_destroy(struct dst_entry *dst); static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static void ipv4_link_failure(struct sk_buff *skb); @@ -193,7 +193,7 @@ static struct dst_ops ipv4_dst_ops = { .gc = rt_garbage_collect, .check = ipv4_dst_check, .default_advmss = ipv4_default_advmss, - .default_mtu = ipv4_default_mtu, + .mtu = ipv4_mtu, .cow_metrics = ipv4_cow_metrics, .destroy = ipv4_dst_destroy, .ifdown = ipv4_dst_ifdown, @@ -1814,7 +1814,7 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst) return advmss; } -static unsigned int ipv4_default_mtu(const struct dst_entry *dst) +static unsigned int ipv4_mtu(const struct dst_entry *dst) { unsigned int mtu = dst->dev->mtu; @@ -2755,7 +2755,7 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo return NULL; } -static unsigned int ipv4_blackhole_default_mtu(const struct dst_entry *dst) +static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst) { return dst->dev->mtu; } @@ -2775,7 +2775,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .protocol = cpu_to_be16(ETH_P_IP), .destroy = ipv4_dst_destroy, .check = ipv4_blackhole_dst_check, - .default_mtu = ipv4_blackhole_default_mtu, + .mtu = ipv4_blackhole_mtu, .default_advmss = ipv4_default_advmss, .update_pmtu = ipv4_rt_blackhole_update_pmtu, .cow_metrics = ipv4_rt_blackhole_cow_metrics, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d8fbd18c9467..76645d7077ff 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -77,7 +77,7 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, const struct in6_addr *dest); static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ip6_default_advmss(const struct dst_entry *dst); -static unsigned int ip6_default_mtu(const struct dst_entry *dst); +static unsigned int ip6_mtu(const struct dst_entry *dst); static struct dst_entry *ip6_negative_advice(struct dst_entry *); static void ip6_dst_destroy(struct dst_entry *); static void ip6_dst_ifdown(struct dst_entry *, @@ -144,7 +144,7 @@ static struct dst_ops ip6_dst_ops_template = { .gc_thresh = 1024, .check = ip6_dst_check, .default_advmss = ip6_default_advmss, - .default_mtu = ip6_default_mtu, + .mtu = ip6_mtu, .cow_metrics = ipv6_cow_metrics, .destroy = ip6_dst_destroy, .ifdown = ip6_dst_ifdown, @@ -155,7 +155,7 @@ static struct dst_ops ip6_dst_ops_template = { .neigh_lookup = ip6_neigh_lookup, }; -static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) +static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst) { return dst->dev->mtu; } @@ -175,7 +175,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { .protocol = cpu_to_be16(ETH_P_IPV6), .destroy = ip6_dst_destroy, .check = ip6_dst_check, - .default_mtu = ip6_blackhole_default_mtu, + .mtu = ip6_blackhole_mtu, .default_advmss = ip6_default_advmss, .update_pmtu = ip6_rt_blackhole_update_pmtu, .cow_metrics = ip6_rt_blackhole_cow_metrics, @@ -1041,7 +1041,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst) return mtu; } -static unsigned int ip6_default_mtu(const struct dst_entry *dst) +static unsigned int ip6_mtu(const struct dst_entry *dst) { unsigned int mtu = IPV6_MIN_MTU; struct inet6_dev *idev; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 552df27dcf53..b8be51eb7e29 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2382,7 +2382,7 @@ static unsigned int xfrm_default_advmss(const struct dst_entry *dst) return dst_metric_advmss(dst->path); } -static unsigned int xfrm_default_mtu(const struct dst_entry *dst) +static unsigned int xfrm_mtu(const struct dst_entry *dst) { return dst_mtu(dst->path); } @@ -2411,8 +2411,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) dst_ops->check = xfrm_dst_check; if (likely(dst_ops->default_advmss == NULL)) dst_ops->default_advmss = xfrm_default_advmss; - if (likely(dst_ops->default_mtu == NULL)) - dst_ops->default_mtu = xfrm_default_mtu; + if (likely(dst_ops->mtu == NULL)) + dst_ops->mtu = xfrm_mtu; if (likely(dst_ops->negative_advice == NULL)) dst_ops->negative_advice = xfrm_negative_advice; if (likely(dst_ops->link_failure == NULL)) -- cgit From 618f9bc74a039da76fa027ac2600c5b785b964c5 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 23 Nov 2011 02:13:31 +0000 Subject: net: Move mtu handling down to the protocol depended handlers We move all mtu handling from dst_mtu() down to the protocol layer. So each protocol can implement the mtu handling in a different manner. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- include/net/dst.h | 7 +------ net/decnet/dn_route.c | 4 +++- net/ipv4/route.c | 11 +++++++++-- net/ipv6/route.c | 11 +++++++++-- net/xfrm/xfrm_policy.c | 4 +++- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 666de31d8e7d..6faec1a60216 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -205,12 +205,7 @@ dst_feature(const struct dst_entry *dst, u32 feature) static inline u32 dst_mtu(const struct dst_entry *dst) { - u32 mtu = dst_metric_raw(dst, RTAX_MTU); - - if (!mtu) - mtu = dst->ops->mtu(dst); - - return mtu; + return dst->ops->mtu(dst); } /* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */ diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index db4867963247..94f4ec036669 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -827,7 +827,9 @@ static unsigned int dn_dst_default_advmss(const struct dst_entry *dst) static unsigned int dn_dst_mtu(const struct dst_entry *dst) { - return dst->dev->mtu; + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + return mtu ? : dst->dev->mtu; } static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f1ac3efc5524..11d1b2080a16 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1816,7 +1816,12 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst) static unsigned int ipv4_mtu(const struct dst_entry *dst) { - unsigned int mtu = dst->dev->mtu; + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + if (mtu) + return mtu; + + mtu = dst->dev->mtu; if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { const struct rtable *rt = (const struct rtable *) dst; @@ -2757,7 +2762,9 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst) { - return dst->dev->mtu; + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + return mtu ? : dst->dev->mtu; } static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 76645d7077ff..3399dd326287 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -157,7 +157,9 @@ static struct dst_ops ip6_dst_ops_template = { static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst) { - return dst->dev->mtu; + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + return mtu ? : dst->dev->mtu; } static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) @@ -1043,8 +1045,13 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst) static unsigned int ip6_mtu(const struct dst_entry *dst) { - unsigned int mtu = IPV6_MIN_MTU; struct inet6_dev *idev; + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + if (mtu) + return mtu; + + mtu = IPV6_MIN_MTU; rcu_read_lock(); idev = __in6_dev_get(dst->dev); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b8be51eb7e29..2118d6446630 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2384,7 +2384,9 @@ static unsigned int xfrm_default_advmss(const struct dst_entry *dst) static unsigned int xfrm_mtu(const struct dst_entry *dst) { - return dst_mtu(dst->path); + unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); + + return mtu ? : dst_mtu(dst->path); } static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr) -- cgit From b8400f3718a11c9b0ca400705cddf94f3132c1c3 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 23 Nov 2011 02:14:15 +0000 Subject: route: struct rtable can be const in rt_is_input_route and rt_is_output_route Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- include/net/route.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index db7b3432f07c..91855d185b53 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -71,12 +71,12 @@ struct rtable { struct fib_info *fi; /* for client ref to shared metrics */ }; -static inline bool rt_is_input_route(struct rtable *rt) +static inline bool rt_is_input_route(const struct rtable *rt) { return rt->rt_route_iif != 0; } -static inline bool rt_is_output_route(struct rtable *rt) +static inline bool rt_is_output_route(const struct rtable *rt) { return rt->rt_route_iif == 0; } -- cgit From 261663b0ee2ee8e3947f4c11c1a08be18cd2cea1 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 23 Nov 2011 02:14:50 +0000 Subject: ipv4: Don't use the cached pmtu informations for input routes The pmtu informations on the inetpeer are visible for output and input routes. On packet forwarding, we might propagate a learned pmtu to the sender. As we update the pmtu informations of the inetpeer on demand, the original sender of the forwarded packets might never notice when the pmtu to that inetpeer increases. So use the mtu of the outgoing device on packet forwarding instead of the pmtu to the final destination. Signed-off-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 11d1b2080a16..fb47c8f0cd86 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1816,15 +1816,15 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst) static unsigned int ipv4_mtu(const struct dst_entry *dst) { + const struct rtable *rt = (const struct rtable *) dst; unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); - if (mtu) + if (mtu && rt_is_output_route(rt)) return mtu; mtu = dst->dev->mtu; if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { - const struct rtable *rt = (const struct rtable *) dst; if (rt->rt_gateway != rt->rt_dst && mtu > 576) mtu = 576; -- cgit From fc0b927d9a5024e138c4318fe19a590f23e3eeec Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 25 Nov 2011 14:40:02 +0000 Subject: net: Revert ARCNET and PHYLIB to tristate options commit 88491d8103498a6166f70d5999902fec70924314 ("drivers/net: Kconfig & Makefile cleanup") changed the type of these options to bool, but they select code that could (and still can) be built as modules. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/arcnet/Kconfig | 2 +- drivers/net/phy/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index a73d9dc80ff6..84fb6349a59a 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -4,7 +4,7 @@ menuconfig ARCNET depends on NETDEVICES && (ISA || PCI || PCMCIA) - bool "ARCnet support" + tristate "ARCnet support" ---help--- If you have a network card of this type, say Y and check out the (arguably) beautiful poetry in diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index bb88e12101c7..a70244306c94 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -3,7 +3,7 @@ # menuconfig PHYLIB - bool "PHY Device support and infrastructure" + tristate "PHY Device support and infrastructure" depends on !S390 depends on NETDEVICES help -- cgit From 8a6e77d5209e459a9ec5c268c39800c06cd1dc86 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 21 Nov 2011 00:21:55 +0000 Subject: decnet: proper socket refcounting Better use sk_reset_timer() / sk_stop_timer() helpers to make sure we dont access already freed/reused memory later. Reported-by: Sasha Levin Signed-off-by: Eric Dumazet Tested-by: Sasha Levin Signed-off-by: David S. Miller --- net/decnet/dn_timer.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c index 67f691bd4acf..d9c150cc59a9 100644 --- a/net/decnet/dn_timer.c +++ b/net/decnet/dn_timer.c @@ -36,16 +36,13 @@ static void dn_slow_timer(unsigned long arg); void dn_start_slow_timer(struct sock *sk) { - sk->sk_timer.expires = jiffies + SLOW_INTERVAL; - sk->sk_timer.function = dn_slow_timer; - sk->sk_timer.data = (unsigned long)sk; - - add_timer(&sk->sk_timer); + setup_timer(&sk->sk_timer, dn_slow_timer, (unsigned long)sk); + sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL); } void dn_stop_slow_timer(struct sock *sk) { - del_timer(&sk->sk_timer); + sk_stop_timer(sk, &sk->sk_timer); } static void dn_slow_timer(unsigned long arg) @@ -53,12 +50,10 @@ static void dn_slow_timer(unsigned long arg) struct sock *sk = (struct sock *)arg; struct dn_scp *scp = DN_SK(sk); - sock_hold(sk); bh_lock_sock(sk); if (sock_owned_by_user(sk)) { - sk->sk_timer.expires = jiffies + HZ / 10; - add_timer(&sk->sk_timer); + sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 10); goto out; } @@ -100,9 +95,7 @@ static void dn_slow_timer(unsigned long arg) scp->keepalive_fxn(sk); } - sk->sk_timer.expires = jiffies + SLOW_INTERVAL; - - add_timer(&sk->sk_timer); + sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL); out: bh_unlock_sock(sk); sock_put(sk); -- cgit From 71b1391a41289735676be02e35239e5aa9fe6ba6 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 25 Nov 2011 06:47:16 +0000 Subject: l2tp: ensure sk->dst is still valid When using l2tp over ipsec, the tunnel will hang when rekeying occurs. Reason is that the transformer bundle attached to the dst entry is now in STATE_DEAD and thus xfrm_output_one() drops all packets (XfrmOutStateExpired increases). Fix this by calling __sk_dst_check (which drops the stale dst if xfrm dst->check callback finds that the bundle is no longer valid). Cc: James Chapman Signed-off-by: Florian Westphal Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index cf0f308abf5e..89ff8c67943e 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1072,7 +1072,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len /* Get routing info from the tunnel socket */ skb_dst_drop(skb); - skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); + skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0))); inet = inet_sk(sk); fl = &inet->cork.fl; -- cgit From 83b98fb46ff136945f9d06a9bf6e6aae2ffc37b3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 07:51:56 +0000 Subject: dm9000: Fix check for disabled wake on LAN We're trying to check if any options are defined which isn't wha the existing code does due to confusing & and &&. Signed-off-by: Mark Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/davicom/dm9000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 438f4580bf66..2a22f5256353 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -613,7 +613,7 @@ static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w) if (!dm->wake_state) irq_set_irq_wake(dm->irq_wake, 1); - else if (dm->wake_state & !opts) + else if (dm->wake_state && !opts) irq_set_irq_wake(dm->irq_wake, 0); } -- cgit From aaa0b4f00729d5530b7d983930e60255574b347b Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 25 Nov 2011 10:56:22 +0000 Subject: iio: iio_event_getfd -- fix ev_int build failure Fix build failure in staging iio driver: .../drivers/staging/iio/industrialio-core.c: In function 'iio_event_getfd': .../drivers/staging/iio/industrialio-core.c:262:32: error: 'ev_int' undeclared (first use in this function) Also convert the rest of the function to use the new variable. Signed-off-by: Andy Whitcroft Signed-off-by: Linus Torvalds --- drivers/staging/iio/industrialio-core.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 26564094e33b..aec9311b108c 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -242,25 +242,24 @@ static const struct file_operations iio_event_chrdev_fileops = { static int iio_event_getfd(struct iio_dev *indio_dev) { + struct iio_event_interface *ev_int = indio_dev->event_interface; int fd; - if (indio_dev->event_interface == NULL) + if (ev_int == NULL) return -ENODEV; - mutex_lock(&indio_dev->event_interface->event_list_lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, - &indio_dev->event_interface->flags)) { - mutex_unlock(&indio_dev->event_interface->event_list_lock); + mutex_lock(&ev_int->event_list_lock); + if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + mutex_unlock(&ev_int->event_list_lock); return -EBUSY; } - mutex_unlock(&indio_dev->event_interface->event_list_lock); + mutex_unlock(&ev_int->event_list_lock); fd = anon_inode_getfd("iio:event", - &iio_event_chrdev_fileops, - indio_dev->event_interface, O_RDONLY); + &iio_event_chrdev_fileops, ev_int, O_RDONLY); if (fd < 0) { - mutex_lock(&indio_dev->event_interface->event_list_lock); + mutex_lock(&ev_int->event_list_lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&indio_dev->event_interface->event_list_lock); + mutex_unlock(&ev_int->event_list_lock); } return fd; } -- cgit From 0884d7aa24e15e72b3c07f7da910a13bb7df3592 Mon Sep 17 00:00:00 2001 From: Alexey Moiseytsev Date: Mon, 21 Nov 2011 13:35:25 +0000 Subject: AF_UNIX: Fix poll blocking problem when reading from a stream socket poll() call may be blocked by concurrent reading from the same stream socket. Signed-off-by: Alexey Moiseytsev Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/unix/af_unix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 466fbcc5cf77..b595a3d8679f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if ((UNIXCB(skb).pid != siocb->scm->pid) || (UNIXCB(skb).cred != siocb->scm->cred)) { skb_queue_head(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk, skb->len); break; } } else { @@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, chunk = min_t(unsigned int, skb->len, size); if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { skb_queue_head(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk, skb->len); if (copied == 0) copied = -EFAULT; break; @@ -1991,6 +1993,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, /* put the skb back if we didn't use it up.. */ if (skb->len) { skb_queue_head(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk, skb->len); break; } @@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, /* put message back and return */ skb_queue_head(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk, skb->len); break; } } while (size); -- cgit From 41dfaa934c5d866d626de9bea785e6168524a47e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 22 Nov 2011 04:01:06 +0100 Subject: ARM: 7168/1: use cache type functions for arch_get_unmapped_area There are already cache type decoding functions, so use those instead of custom decode code which only works for ARMv6. Signed-off-by: Rob Herring Acked-by: Nicolas Pitre Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/mmap.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 74be05f3e03a..44b628e4d6ea 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -9,8 +9,7 @@ #include #include #include -#include -#include +#include #define COLOUR_ALIGN(addr,pgoff) \ ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ @@ -32,25 +31,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long start_addr; -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) - unsigned int cache_type; - int do_align = 0, aliasing = 0; + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); /* * We only need to do colour alignment if either the I or D - * caches alias. This is indicated by bits 9 and 21 of the - * cache type register. + * caches alias. */ - cache_type = read_cpuid_cachetype(); - if (cache_type != read_cpuid_id()) { - aliasing = (cache_type | cache_type >> 12) & (1 << 11); - if (aliasing) - do_align = filp || flags & MAP_SHARED; - } -#else -#define do_align 0 -#define aliasing 0 -#endif + if (aliasing) + do_align = filp || (flags & MAP_SHARED); /* * We enforce the MAP_FIXED case. -- cgit From c89cefed35c8c5f53f36757f8a6768e390394ee3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 22 Nov 2011 23:42:12 +0100 Subject: ARM: 7170/2: fix compilation breakage in entry-armv.S Fix compilation failure, when Thumb support is not enabled: arch/arm/kernel/entry-armv.S: Assembler messages: arch/arm/kernel/entry-armv.S:501: Error: backward ref to unknown label "2:" arch/arm/kernel/entry-armv.S:502: Error: backward ref to unknown label "3:" make[2]: *** [arch/arm/kernel/entry-armv.o] Error 1 Signed-off-by: Guennadi Liakhovetski Reviewed-by: Dave Martin Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 9ad50c4208ae..b145f16c91bc 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -497,7 +497,7 @@ ENDPROC(__und_usr) .popsection .pushsection __ex_table,"a" .long 1b, 4b -#if __LINUX_ARM_ARCH__ >= 7 +#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 .long 2b, 4b .long 3b, 4b #endif -- cgit From c36ef4b1762302a493c6cb754073bded084700e2 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 23 Nov 2011 11:28:25 +0100 Subject: ARM: 7171/1: unwind: add unwind directives to bitops assembly macros The bitops functions (e.g. _test_and_set_bit) on ARM do not have unwind annotations and therefore the kernel cannot backtrace out of them on a fatal error (for example, NULL pointer dereference). This patch annotates the bitops assembly macros with UNWIND annotations so that we can produce a meaningful backtrace on error. Callers of the macros are modified to pass their function name as a macro parameter, enforcing that the macros are used as standalone function implementations. Acked-by: Dave Martin Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/lib/bitops.h | 26 ++++++++++++++++++++++---- arch/arm/lib/changebit.S | 4 +--- arch/arm/lib/clearbit.S | 4 +--- arch/arm/lib/setbit.S | 4 +--- arch/arm/lib/testchangebit.S | 4 +--- arch/arm/lib/testclearbit.S | 4 +--- arch/arm/lib/testsetbit.S | 4 +--- 7 files changed, 28 insertions(+), 22 deletions(-) diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 10d868a5a481..d6408d1ee543 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -1,5 +1,9 @@ +#include + #if __LINUX_ARM_ARCH__ >= 6 - .macro bitop, instr + .macro bitop, name, instr +ENTRY( \name ) +UNWIND( .fnstart ) ands ip, r1, #3 strneb r1, [ip] @ assert word-aligned mov r2, #1 @@ -13,9 +17,13 @@ cmp r0, #0 bne 1b bx lr +UNWIND( .fnend ) +ENDPROC(\name ) .endm - .macro testop, instr, store + .macro testop, name, instr, store +ENTRY( \name ) +UNWIND( .fnstart ) ands ip, r1, #3 strneb r1, [ip] @ assert word-aligned mov r2, #1 @@ -34,9 +42,13 @@ cmp r0, #0 movne r0, #1 2: bx lr +UNWIND( .fnend ) +ENDPROC(\name ) .endm #else - .macro bitop, instr + .macro bitop, name, instr +ENTRY( \name ) +UNWIND( .fnstart ) ands ip, r1, #3 strneb r1, [ip] @ assert word-aligned and r2, r0, #31 @@ -49,6 +61,8 @@ str r2, [r1, r0, lsl #2] restore_irqs ip mov pc, lr +UNWIND( .fnend ) +ENDPROC(\name ) .endm /** @@ -59,7 +73,9 @@ * Note: we can trivially conditionalise the store instruction * to avoid dirtying the data cache. */ - .macro testop, instr, store + .macro testop, name, instr, store +ENTRY( \name ) +UNWIND( .fnstart ) ands ip, r1, #3 strneb r1, [ip] @ assert word-aligned and r3, r0, #31 @@ -73,5 +89,7 @@ moveq r0, #0 restore_irqs ip mov pc, lr +UNWIND( .fnend ) +ENDPROC(\name ) .endm #endif diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S index 68ed5b62e839..f4027862172f 100644 --- a/arch/arm/lib/changebit.S +++ b/arch/arm/lib/changebit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_change_bit) - bitop eor -ENDPROC(_change_bit) +bitop _change_bit, eor diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S index 4c04c3b51eeb..f6b75fb64d30 100644 --- a/arch/arm/lib/clearbit.S +++ b/arch/arm/lib/clearbit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_clear_bit) - bitop bic -ENDPROC(_clear_bit) +bitop _clear_bit, bic diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S index bbee5c66a23e..618fedae4b37 100644 --- a/arch/arm/lib/setbit.S +++ b/arch/arm/lib/setbit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_set_bit) - bitop orr -ENDPROC(_set_bit) +bitop _set_bit, orr diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S index 15a4d431f229..4becdc3a59cb 100644 --- a/arch/arm/lib/testchangebit.S +++ b/arch/arm/lib/testchangebit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_test_and_change_bit) - testop eor, str -ENDPROC(_test_and_change_bit) +testop _test_and_change_bit, eor, str diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S index 521b66b5b95d..918841dcce7a 100644 --- a/arch/arm/lib/testclearbit.S +++ b/arch/arm/lib/testclearbit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_test_and_clear_bit) - testop bicne, strne -ENDPROC(_test_and_clear_bit) +testop _test_and_clear_bit, bicne, strne diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S index 1c98cc2185bb..8d1b2fe9e487 100644 --- a/arch/arm/lib/testsetbit.S +++ b/arch/arm/lib/testsetbit.S @@ -12,6 +12,4 @@ #include "bitops.h" .text -ENTRY(_test_and_set_bit) - testop orreq, streq -ENDPROC(_test_and_set_bit) +testop _test_and_set_bit, orreq, streq -- cgit From ea2e7057c0234cfb8b09467d8f137760d371fc72 Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Thu, 24 Nov 2011 00:47:12 +0100 Subject: ARM: 7172/1: dma: Drop GFP_COMP for DMA memory allocations dma_alloc_coherent wants to split pages after allocation in order to reduce the memory footprint. This does not work well with GFP_COMP pages, so drop this flag before allocation. This patch is ported from arch/avr32 (commit 3611553ef985ef7c5863c8a94641738addd04cff). [swarren: s/HUGETLB_PAGE/HUGETLBFS/ in comment, minor comment cleanup] Signed-off-by: Sumit Bhattacharya Tested-by: Varun Colbert Signed-off-by: Stephen Warren Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ab584569930e..1aa664a1999f 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -332,6 +332,15 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct page *page; void *addr; + /* + * Following is a work-around (a.k.a. hack) to prevent pages + * with __GFP_COMP being passed to split_page() which cannot + * handle them. The real problem is that this flag probably + * should be 0 on ARM as it is not supported on this + * platform; see CONFIG_HUGETLBFS. + */ + gfp &= ~(__GFP_COMP); + *handle = ~0; size = PAGE_ALIGN(size); -- cgit From 46589e2922509f9134ce79fa75180886c9765c58 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 24 Nov 2011 13:01:08 +0100 Subject: ARM: 7174/1: Fix build error in kprobes test code on Thumb2 kernels When compiling kprobes-test-thumb.c an error like below may occur: /tmp/ccKcuJcG.s:19179: Error: offset out of range This is caused by the compiler underestimating the size of the inline assembler instructions containing ".space 0x1000" and failing to spill the literal pool in time to prevent the generation of PC relative load instruction with invalid offsets. The fix implemented by this patch is to replace a single large .space directive by a number of 4 byte .space's. This requires splitting the macros which generate test cases for branch instructions into two forms: one with, and one without support for inserting extra code between branch and target. Acked-by: Nicolas Pitre Signed-off-by: Jon Medhurst Signed-off-by: Russell King --- arch/arm/kernel/kprobes-test-thumb.c | 16 +++--- arch/arm/kernel/kprobes-test.h | 100 ++++++++++++++++++++++++----------- 2 files changed, 78 insertions(+), 38 deletions(-) diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c index 5e726c31c45a..5d8b85792222 100644 --- a/arch/arm/kernel/kprobes-test-thumb.c +++ b/arch/arm/kernel/kprobes-test-thumb.c @@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void) DONT_TEST_IN_ITBLOCK( TEST_BF_R( "cbnz r",0,0, ", 2f") TEST_BF_R( "cbz r",2,-1,", 2f") - TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20) - TEST_BF_RX( "cbz r",7,0, ", 2f",0x40) + TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20) + TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40) ) TEST_R("sxth r0, r",7, HH1,"") TEST_R("sxth r7, r",0, HH2,"") @@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK( TESTCASE_START(code) \ TEST_ARG_PTR(13, offset) \ TEST_ARG_END("") \ - TEST_BRANCH_F(code,0) \ + TEST_BRANCH_F(code) \ TESTCASE_END TEST("push {r0}") @@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8, TEST_BF( "b 2f") TEST_BB( "b 2b") - TEST_BF_X("b 2f", 0x400) - TEST_BB_X("b 2b", 0x400) + TEST_BF_X("b 2f", SPACE_0x400) + TEST_BB_X("b 2b", SPACE_0x400) TEST_GROUP("Testing instructions in IT blocks") @@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22, TEST_BB("bne.w 2b") TEST_BF("bgt.w 2f") TEST_BB("blt.w 2b") - TEST_BF_X("bpl.w 2f",0x1000) + TEST_BF_X("bpl.w 2f", SPACE_0x1000) ) TEST_UNSUPPORTED("msr cpsr, r0") @@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22, TEST_BF( "b.w 2f") TEST_BB( "b.w 2b") - TEST_BF_X("b.w 2f", 0x1000) + TEST_BF_X("b.w 2f", SPACE_0x1000) TEST_BF( "bl.w 2f") TEST_BB( "bl.w 2b") - TEST_BB_X("bl.w 2b", 0x1000) + TEST_BB_X("bl.w 2b", SPACE_0x1000) TEST_X( "blx __dummy_arm_subroutine", ".arm \n\t" diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h index 0dc5d77b9356..e28a869b1ae4 100644 --- a/arch/arm/kernel/kprobes-test.h +++ b/arch/arm/kernel/kprobes-test.h @@ -149,23 +149,31 @@ struct test_arg_end { "1: "instruction" \n\t" \ " nop \n\t" -#define TEST_BRANCH_F(instruction, xtra_dist) \ +#define TEST_BRANCH_F(instruction) \ TEST_INSTRUCTION(instruction) \ - ".if "#xtra_dist" \n\t" \ " b 99f \n\t" \ - ".space "#xtra_dist" \n\t" \ - ".endif \n\t" \ + "2: nop \n\t" + +#define TEST_BRANCH_B(instruction) \ + " b 50f \n\t" \ + " b 99f \n\t" \ + "2: nop \n\t" \ + " b 99f \n\t" \ + TEST_INSTRUCTION(instruction) + +#define TEST_BRANCH_FX(instruction, codex) \ + TEST_INSTRUCTION(instruction) \ + " b 99f \n\t" \ + codex" \n\t" \ " b 99f \n\t" \ "2: nop \n\t" -#define TEST_BRANCH_B(instruction, xtra_dist) \ +#define TEST_BRANCH_BX(instruction, codex) \ " b 50f \n\t" \ " b 99f \n\t" \ "2: nop \n\t" \ " b 99f \n\t" \ - ".if "#xtra_dist" \n\t" \ - ".space "#xtra_dist" \n\t" \ - ".endif \n\t" \ + codex" \n\t" \ TEST_INSTRUCTION(instruction) #define TESTCASE_END \ @@ -301,47 +309,60 @@ struct test_arg_end { TESTCASE_START(code1 #reg1 code2) \ TEST_ARG_PTR(reg1, val1) \ TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg1 code2, 0) \ + TEST_BRANCH_F(code1 #reg1 code2) \ TESTCASE_END -#define TEST_BF_X(code, xtra_dist) \ +#define TEST_BF(code) \ TESTCASE_START(code) \ TEST_ARG_END("") \ - TEST_BRANCH_F(code, xtra_dist) \ + TEST_BRANCH_F(code) \ TESTCASE_END -#define TEST_BB_X(code, xtra_dist) \ +#define TEST_BB(code) \ TESTCASE_START(code) \ TEST_ARG_END("") \ - TEST_BRANCH_B(code, xtra_dist) \ + TEST_BRANCH_B(code) \ TESTCASE_END -#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg code2, xtra_dist) \ +#define TEST_BF_R(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_BRANCH_F(code1 #reg code2) \ TESTCASE_END -#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_BRANCH_B(code1 #reg code2, xtra_dist) \ +#define TEST_BB_R(code1, reg, val, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_BRANCH_B(code1 #reg code2) \ TESTCASE_END -#define TEST_BF(code) TEST_BF_X(code, 0) -#define TEST_BB(code) TEST_BB_X(code, 0) - -#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0) -#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0) - #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ TEST_ARG_REG(reg1, val1) \ TEST_ARG_REG(reg2, val2) \ TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \ + TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \ + TESTCASE_END + +#define TEST_BF_X(code, codex) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_BRANCH_FX(code, codex) \ + TESTCASE_END + +#define TEST_BB_X(code, codex) \ + TESTCASE_START(code) \ + TEST_ARG_END("") \ + TEST_BRANCH_BX(code, codex) \ + TESTCASE_END + +#define TEST_BF_RX(code1, reg, val, code2, codex) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG(reg, val) \ + TEST_ARG_END("") \ + TEST_BRANCH_FX(code1 #reg code2, codex) \ TESTCASE_END #define TEST_X(code, codex) \ @@ -372,6 +393,25 @@ struct test_arg_end { TESTCASE_END +/* + * Macros for defining space directives spread over multiple lines. + * These are required so the compiler guesses better the length of inline asm + * code and will spill the literal pool early enough to avoid generating PC + * relative loads with out of range offsets. + */ +#define TWICE(x) x x +#define SPACE_0x8 TWICE(".space 4\n\t") +#define SPACE_0x10 TWICE(SPACE_0x8) +#define SPACE_0x20 TWICE(SPACE_0x10) +#define SPACE_0x40 TWICE(SPACE_0x20) +#define SPACE_0x80 TWICE(SPACE_0x40) +#define SPACE_0x100 TWICE(SPACE_0x80) +#define SPACE_0x200 TWICE(SPACE_0x100) +#define SPACE_0x400 TWICE(SPACE_0x200) +#define SPACE_0x800 TWICE(SPACE_0x400) +#define SPACE_0x1000 TWICE(SPACE_0x800) + + /* Various values used in test cases... */ #define N(val) (val ^ 0xffffffff) #define VAL1 0x12345678 -- cgit From 97371fa99c1900a84a5220639edd726b35d73931 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 25 Nov 2011 00:23:28 +0100 Subject: ARM: 7175/1: add subname parameter to mfp_set_groupg callers commit 798681bf "ARM: 7158/1: add new MFP implement for NUC900" adds subname parameter for mfp_set_groupg. Thus add subname parameter to the callers. Signed-off-by: Axel Lin Acked-by: Mark Brown Acked-by: Wan Zongshun Signed-off-by: Russell King --- drivers/i2c/busses/i2c-nuc900.c | 2 +- drivers/spi/spi-nuc900.c | 2 +- sound/soc/nuc900/nuc900-ac97.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index 835e47b39bc2..03b615778887 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -593,7 +593,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev) i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &pdev->dev; - mfp_set_groupg(&pdev->dev); + mfp_set_groupg(&pdev->dev, NULL); clk_get_rate(i2c->clk); diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index e763254741c2..21c70b2b8311 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -426,7 +426,7 @@ static int __devinit nuc900_spi_probe(struct platform_device *pdev) goto err_clk; } - mfp_set_groupg(&pdev->dev); + mfp_set_groupg(&pdev->dev, NULL); nuc900_init_spi(hw); err = spi_bitbang_start(&hw->bitbang); diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index 9c0edad90d8b..a4e3237956e2 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c @@ -365,7 +365,8 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) if (ret) goto out3; - mfp_set_groupg(nuc900_audio->dev); /* enbale ac97 multifunction pin*/ + /* enbale ac97 multifunction pin */ + mfp_set_groupg(nuc900_audio->dev, "nuc900-audio"); return 0; -- cgit From abdd7b91dab2f8b2e32e90e4b7e809ffb462a662 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 25 Nov 2011 17:58:19 +0100 Subject: ARM: 7176/1: cpu_pm: register GIC PM notifier only once When multiple GICs exist on a platform (RealView PB1176/11MP), we must make sure the PM notifier block is only registered once, otherwise we end up corrupting the PM notifier list. The fix is to only register the notifier when initializing the first GIC, as the power management functions seem to iterate over all the registered GICs. Tested on PB11MP and PB1176. Reported-by: Will Deacon Tested-by: Will Deacon Cc: Colin Cross Signed-off-by: Marc Zyngier Signed-off-by: Russell King --- arch/arm/common/gic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 0e6ae470c94f..43240f315dea 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -526,7 +526,8 @@ static void __init gic_pm_init(struct gic_chip_data *gic) sizeof(u32)); BUG_ON(!gic->saved_ppi_conf); - cpu_pm_register_notifier(&gic_notifier_block); + if (gic == &gic_data[0]) + cpu_pm_register_notifier(&gic_notifier_block); } #else static void __init gic_pm_init(struct gic_chip_data *gic) -- cgit From fe41db7b3aca512e19b8ef4fbd5ad55545005d25 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 25 Nov 2011 19:23:36 +0100 Subject: ARM: 7177/1: GIC: avoid skipping non-existent PPIs in irq_start calculation Commit 4294f8baa ("ARM: gic: add irq_domain support") defines irq_start as irq_start = (irq_start & ~31) + 16; On a platform with a GIC and a CPU without PPIs, this results in irq_start being off by 16. This patch fixes gic_init so that we only carve out a PPI space when PPIs exist for the GIC being initialised. Cc: Rob Herring Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/common/gic.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 43240f315dea..410a546060a2 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -582,13 +582,16 @@ void __init gic_init(unsigned int gic_nr, int irq_start, * For primary GICs, skip over SGIs. * For secondary GICs, skip over PPIs, too. */ + domain->hwirq_base = 32; if (gic_nr == 0) { gic_cpu_base_addr = cpu_base; - domain->hwirq_base = 16; - if (irq_start > 0) - irq_start = (irq_start & ~31) + 16; - } else - domain->hwirq_base = 32; + + if ((irq_start & 31) > 0) { + domain->hwirq_base = 16; + if (irq_start != -1) + irq_start = (irq_start & ~31) + 16; + } + } /* * Find out how many interrupts are supported. -- cgit From de68dca1816660b0d3ac89fa59ffb410007a143f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 26 Nov 2011 12:13:44 +0000 Subject: inet: add a redirect generation id in inetpeer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now inetpeer is the place where we cache redirect information for ipv4 destinations, we must be able to invalidate informations when a route is added/removed on host. As inetpeer is not yet namespace aware, this patch adds a shared redirect_genid, and a per inetpeer redirect_genid. This might be changed later if inetpeer becomes ns aware. Cache information for one inerpeer is valid as long as its redirect_genid has the same value than global redirect_genid. Reported-by: Arkadiusz Miśkiewicz Tested-by: Arkadiusz Miśkiewicz Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inetpeer.h | 1 + net/ipv4/route.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 78c83e62218f..e9ff3fc5e688 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -35,6 +35,7 @@ struct inet_peer { u32 metrics[RTAX_MAX]; u32 rate_tokens; /* rate limiting for ICMP */ + int redirect_genid; unsigned long rate_last; unsigned long pmtu_expires; u32 pmtu_orig; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fb47c8f0cd86..5c2847247f51 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -131,6 +131,7 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; static int ip_rt_min_advmss __read_mostly = 256; static int rt_chain_length_max __read_mostly = 20; +static int redirect_genid; /* * Interface to generic destination cache. @@ -837,6 +838,7 @@ static void rt_cache_invalidate(struct net *net) get_random_bytes(&shuffle, sizeof(shuffle)); atomic_add(shuffle + 1U, &net->ipv4.rt_genid); + redirect_genid++; } /* @@ -1391,8 +1393,10 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, peer = rt->peer; if (peer) { - if (peer->redirect_learned.a4 != new_gw) { + if (peer->redirect_learned.a4 != new_gw || + peer->redirect_genid != redirect_genid) { peer->redirect_learned.a4 = new_gw; + peer->redirect_genid = redirect_genid; atomic_inc(&__rt_peer_genid); } check_peer_redir(&rt->dst, peer); @@ -1701,6 +1705,8 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) if (peer) { check_peer_pmtu(dst, peer); + if (peer->redirect_genid != redirect_genid) + peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { if (check_peer_redir(dst, peer)) @@ -1857,6 +1863,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, dst_init_metrics(&rt->dst, peer->metrics, false); check_peer_pmtu(&rt->dst, peer); + if (peer->redirect_genid != redirect_genid) + peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { rt->rt_gateway = peer->redirect_learned.a4; -- cgit From 438957f8d4a84daa7fa5be6978ad5897a2e9e5e5 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Tue, 1 Nov 2011 15:01:28 -0400 Subject: staging: usbip: bugfix for deadlock Interrupts must be disabled prior to calling usb_hcd_unlink_urb_from_ep. If interrupts are not disabled, it can potentially lead to a deadlock. The deadlock is readily reproduceable on a slower (ARM based) device such as the TI Pandaboard. Signed-off-by: Bart Westgeest Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_rx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 09c44abb89e8..3872b8cccdcf 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); @@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); -- cgit From f7364ba04b0961f3a1f978bbe77102606801e35f Mon Sep 17 00:00:00 2001 From: wwang Date: Mon, 31 Oct 2011 15:02:53 +0800 Subject: staging:rts_pstor:Complete scanning_done variable Complete scanning_done variable if rtsx-scan thread created failed. Signed-off-by: wwang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/rtsx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index 480b0ed2e4de..115635f95024 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -1021,6 +1021,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { printk(KERN_ERR "Unable to start the device-scanning thread\n"); + complete(&dev->scanning_done); quiesce_and_remove_host(dev); err = PTR_ERR(th); goto errout; -- cgit From 8b78607fc4a26c2e26c4a614ff0bbd3380abc402 Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Tue, 8 Nov 2011 21:21:37 +0000 Subject: staging: comedi: usbduxsigma: Fixed wrong range for the analogue channel. It's actually +/-2.65V/2 and not +/-2.65V. Signed-off-by: Bernd Porr Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index a8fea9a91733..6144afb8cbaa 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.6" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com" /* @@ -25,7 +25,7 @@ Driver: usbduxsigma Description: University of Stirling USB DAQ & INCITE Technology Limited Devices: [ITL] USB-DUX (usbduxsigma.o) Author: Bernd Porr -Updated: 21 Jul 2011 +Updated: 8 Nov 2011 Status: testing */ /* @@ -44,6 +44,7 @@ Status: testing * 0.3: proper vendor ID and driver name * 0.4: fixed D/A voltage range * 0.5: various bug fixes, health check at startup + * 0.6: corrected wrong input range */ /* generates loads of debug info */ @@ -175,7 +176,7 @@ Status: testing /* comedi constants */ static const struct comedi_lrange range_usbdux_ai_range = { 1, { BIP_RANGE - (2.65) + (2.65/2.0) } }; -- cgit From 3ffab428f40849ed5f21bcfd7285bdef7902f9ca Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Tue, 8 Nov 2011 21:23:03 +0000 Subject: staging: comedi: fix oops for USB DAQ devices. This fixes kernel oops when an USB DAQ device is plugged out while it's communicating with the userspace software. Signed-off-by: Bernd Porr Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 71 +++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 21d8c1c16cd8..156622a6f162 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1452,9 +1452,6 @@ static struct vm_operations_struct comedi_vm_ops = { static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_async *async = NULL; unsigned long start = vma->vm_start; unsigned long size; @@ -1462,6 +1459,15 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) int i; int retval; struct comedi_subdevice *s; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + + dev_file_info = comedi_get_device_file_info(minor); + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1528,11 +1534,17 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *read_subdev; struct comedi_subdevice *write_subdev; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1578,9 +1590,15 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1683,9 +1701,15 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1885,11 +1909,17 @@ ok: static int comedi_close(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *s = NULL; int i; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); @@ -1923,10 +1953,15 @@ static int comedi_close(struct inode *inode, struct file *file) static int comedi_fasync(int fd, struct file *file, int on) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; return fasync_helper(fd, file, on, &dev->async_queue); } -- cgit From df30b21cb0eed5ba8a8e0cdfeebc66ba8cde821d Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:45:39 +0200 Subject: Staging: comedi: fix mmap_count In comedi_fops, mmap_count is decremented at comedi_vm_ops->close but it is not incremented at comedi_vm_ops->open. This may result in a negative counter. The patch introduces the open method to keep the counter consistent. The bug was triggerd by this sample code: mmap(0, ...., comedi_fd); fork(); exit(0); Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 156622a6f162..88caa7376999 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1432,7 +1432,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } -static void comedi_unmap(struct vm_area_struct *area) + +static void comedi_vm_open(struct vm_area_struct *area) +{ + struct comedi_async *async; + struct comedi_device *dev; + + async = area->vm_private_data; + dev = async->subdevice->device; + + mutex_lock(&dev->mutex); + async->mmap_count++; + mutex_unlock(&dev->mutex); +} + +static void comedi_vm_close(struct vm_area_struct *area) { struct comedi_async *async; struct comedi_device *dev; @@ -1446,7 +1460,8 @@ static void comedi_unmap(struct vm_area_struct *area) } static struct vm_operations_struct comedi_vm_ops = { - .close = comedi_unmap, + .open = comedi_vm_open, + .close = comedi_vm_close, }; static int comedi_mmap(struct file *file, struct vm_area_struct *vma) -- cgit From 6a9ce6b654e491981f6ef7e214cbd4f63e033848 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:47:39 +0200 Subject: Staging: comedi: fix signal handling in read and write After sleeping on a wait queue, signal_pending(current) should be checked (not before sleeping). Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 88caa7376999..ebdcecda3583 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1673,11 +1673,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) break; if (s->busy != file) { @@ -1780,11 +1780,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) { retval = 0; break; -- cgit From e384a41141949843899affcf51f4e6e646c1fe9f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:20:43 +0300 Subject: Staging: comedi: integer overflow in do_insnlist_ioctl() There is an integer overflow here that could cause memory corruption on 32 bit systems. insnlist.n_insns could be a very high value size calculation for kmalloc() could overflow resulting in a smaller "insns" than expected. In the for (i = 0; i < insnlist.n_insns; i++) {... loop we would read past the end of the buffer, possibly corrupting memory as well. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ebdcecda3583..ed4853f194c4 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -670,6 +670,11 @@ static int do_insnlist_ioctl(struct comedi_device *dev, goto error; } + if (sizeof(struct comedi_insn) * insnlist.n_insns < insnlist.n_insns) { + ret = -EINVAL; + goto error; + } + insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { -- cgit From 46b1848360c8e634e0b063932a1261062fa0f7d6 Mon Sep 17 00:00:00 2001 From: Dirk Nehring Date: Thu, 24 Nov 2011 19:22:23 +0100 Subject: usb: option: add Huawei E353 controlling interfaces This patch creates the missing controlling devices for the Huawei E353 HSPA+ stick. Signed-off-by: Dirk Nehring Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index d865878c9f97..6e09857c32eb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -661,6 +661,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -- cgit From ec0cd94d881ca89cc9fb61d00d0f4b2b52e605b3 Mon Sep 17 00:00:00 2001 From: Veli-Pekka Peltola Date: Thu, 24 Nov 2011 22:08:56 +0200 Subject: usb: option: add SIMCom SIM5218 Tested with SIM5218EVB-KIT evaluation kit. Signed-off-by: Veli-Pekka Peltola Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6e09857c32eb..e3426602dc82 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -750,6 +750,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, -- cgit From cec28a5428793b6bc64e56687fb239759d6da74e Mon Sep 17 00:00:00 2001 From: Qinglin Ye Date: Wed, 23 Nov 2011 23:39:32 +0800 Subject: USB: usb-storage: unusual_devs entry for Kingston DT 101 G2 Kingston DT 101 G2 replies a wrong tag while transporting, add an unusal_devs entry to ignore the tag validation. Signed-off-by: Qinglin Ye Cc: stable 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 3041a974faf3..24caba79d722 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1854,6 +1854,13 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Qinglin Ye */ +UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100, + "Kingston", + "DT 101 G2", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG ), + /* Reported by Francesco Foresti */ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, "Super Top", -- cgit From 8746c83d538cab273d335acb2be226d096f4a5af Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 22 Nov 2011 10:28:31 +0300 Subject: USB: whci-hcd: fix endian conversion in qset_clear() qset->qh.link is an __le64 field and we should be using cpu_to_le64() to fill it. Signed-off-by: Dan Carpenter Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/whci/qset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index d6e175428618..a403b53e86b9 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -124,7 +124,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) { qset->td_start = qset->td_end = qset->ntds = 0; - qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); + qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; qset->qh.err_count = 0; qset->qh.scratch[0] = 0; -- cgit From 5b895eec118ab5fec7b69102d73c1b04a86140b9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 27 Nov 2011 15:54:49 +0000 Subject: ASoC: Correct name of Speyside Main Speaker widget Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 85bf541a771d..4b8e35410eb1 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -191,7 +191,7 @@ static int speyside_late_probe(struct snd_soc_card *card) snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input"); -- cgit From 92bb43e6aae3dbdb199feba93da5f2d05d7716d0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 14:48:24 +0300 Subject: ALSA: hda - cut and paste typo in cs420x_models[] The CS420X_IMAC27 was copied from the line before but CS420X_APPLE was clearly intented. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 7bd2a52f2bac..70a7abda7e22 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1278,7 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = { [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", - [CS420X_IMAC27] = "apple", + [CS420X_APPLE] = "apple", [CS420X_AUTO] = "auto", }; -- cgit From 187d333edc0a8e1bb507900ce89853ffe3bd2c84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Nov 2011 16:33:09 +0100 Subject: ALSA: hda - Fix jack-detection control of VT1708 VT1708 has no support for unsolicited events per jack-plug, the driver implements the workq for polling the jack-detection. The mixer element "Jack Detect" was supposed to control this behavior on/off, but this doesn't work properly as is now. The workq is always started and the HP automute is always enabled. This patch fixes the jack-detect control behavior by triggering / stopping the work appropriately at the state change. Also the work checks the internal state to continue scheduling or not. Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 431c0d417eeb..b5137629f8e9 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -208,6 +208,7 @@ struct via_spec { /* work to check hp jack state */ struct hda_codec *codec; struct delayed_work vt1708_hp_work; + int hp_work_active; int vt1708_jack_detect; int vt1708_hp_present; @@ -305,27 +306,35 @@ enum { static void analog_low_current_mode(struct hda_codec *codec); static bool is_aa_path_mute(struct hda_codec *codec); -static void vt1708_start_hp_work(struct via_spec *spec) +#define hp_detect_with_aa(codec) \ + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \ + !is_aa_path_mute(codec)) + +static void vt1708_stop_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - if (!delayed_work_pending(&spec->vt1708_hp_work)) - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); + if (spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1); + cancel_delayed_work_sync(&spec->vt1708_hp_work); + spec->hp_work_active = 0; + } } -static void vt1708_stop_hp_work(struct via_spec *spec) +static void vt1708_update_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1 - && !is_aa_path_mute(spec->codec)) - return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - cancel_delayed_work_sync(&spec->vt1708_hp_work); + if (spec->vt1708_jack_detect && + (spec->active_streams || hp_detect_with_aa(spec->codec))) { + if (!spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0); + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); + spec->hp_work_active = 1; + } + } else if (!hp_detect_with_aa(spec->codec)) + vt1708_stop_hp_work(spec); } static void set_widgets_power_state(struct hda_codec *codec) @@ -343,12 +352,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol, set_widgets_power_state(codec); analog_low_current_mode(snd_kcontrol_chip(kcontrol)); - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { - if (is_aa_path_mute(codec)) - vt1708_start_hp_work(codec->spec); - else - vt1708_stop_hp_work(codec->spec); - } + vt1708_update_hp_work(codec->spec); return change; } @@ -1154,7 +1158,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_dac_stream_tag = stream_tag; spec->cur_dac_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1174,7 +1178,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_hp_stream_tag = stream_tag; spec->cur_hp_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1188,7 +1192,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); spec->active_streams &= ~STREAM_MULTI_OUT; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1203,7 +1207,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0); spec->active_streams &= ~STREAM_INDEP_HP; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1645,7 +1649,8 @@ static void via_hp_automute(struct hda_codec *codec) int nums; struct via_spec *spec = codec->spec; - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0]) + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && + (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); if (spec->smart51_enabled) @@ -2612,8 +2617,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol, if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1); ucontrol->value.integer.value[0] = spec->vt1708_jack_detect; return 0; } @@ -2623,18 +2626,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - int change; + int val; if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = ucontrol->value.integer.value[0]; - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8)) - == !spec->vt1708_jack_detect; - if (spec->vt1708_jack_detect) { + val = !!ucontrol->value.integer.value[0]; + if (spec->vt1708_jack_detect == val) + return 0; + spec->vt1708_jack_detect = val; + if (spec->vt1708_jack_detect && + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) { mute_aa_path(codec, 1); notify_aa_path_ctls(codec); } - return change; + via_hp_automute(codec); + vt1708_update_hp_work(spec); + return 1; } static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { @@ -2771,6 +2778,7 @@ static int via_init(struct hda_codec *codec) via_auto_init_unsol_event(codec); via_hp_automute(codec); + vt1708_update_hp_work(spec); return 0; } @@ -2787,7 +2795,9 @@ static void vt1708_update_hp_jack_state(struct work_struct *work) spec->vt1708_hp_present ^= 1; via_hp_automute(spec->codec); } - vt1708_start_hp_work(spec); + if (spec->vt1708_jack_detect) + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); } static int get_mux_nids(struct hda_codec *codec) -- cgit From 06b446c8af5db5a98b2eaa30b513c79089ed254b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 28 Nov 2011 04:34:34 +0900 Subject: Revert "Staging: comedi: integer overflow in do_insnlist_ioctl()" This reverts commit e384a41141949843899affcf51f4e6e646c1fe9f. It's not the correct way to solve this issue. Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ed4853f194c4..ebdcecda3583 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -670,11 +670,6 @@ static int do_insnlist_ioctl(struct comedi_device *dev, goto error; } - if (sizeof(struct comedi_insn) * insnlist.n_insns < insnlist.n_insns) { - ret = -EINVAL; - goto error; - } - insns = kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { -- cgit From dfd8ee92a9192d78aa38cf8699df3630a7c88c85 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Fri, 25 Nov 2011 16:46:51 -0500 Subject: Staging: comedi: fix integer overflow in do_insnlist_ioctl() There is a potential integer overflow in do_insnlist_ioctl() if userspace passes in a large insnlist.n_insns. The call to kmalloc() would allocate a small buffer, leading to a memory corruption. The bug was reported by Dan Carpenter and Haogang Chen . The patch was suggested by Ian Abbott and Lars-Peter Clausen . Reported-by: Dan Carpenter Reported-by: Haogang Chen . Cc: Ian Abbott Cc: Lars-Peter Clausen Signed-off-by: Xi Wang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ebdcecda3583..5e78c77d5a08 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -671,7 +671,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, } insns = - kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); + kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL); if (!insns) { DPRINTK("kmalloc failed\n"); ret = -ENOMEM; -- cgit From 06718f151144aa5eea97cdf2813fe7eb70e73d17 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 26 Nov 2011 23:37:43 +0100 Subject: ath9k: Revert change that broke AR928X on Acer Ferrari One Revert a hunk in drivers/net/wireless/ath/ath9k/hw.c introduced by commit 2577c6e8f232 ("ath9k_hw: Add support for AR946/8x chipsets") that caused a nasty regression to appear on my Acer Ferrari One (the box locks up entirely at random times after the wireless has been started without any way to get debug information out of it). Signed-off-by: Rafael J. Wysocki Acked-by: Felix Fietkau Signed-off-by: Linus Torvalds --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2f91acccb7db..8873c6e6fb96 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1827,7 +1827,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) } /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ - REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); + if (AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } /* -- cgit From c4860ba2e11261a541632ceee8267ca490d9eb98 Mon Sep 17 00:00:00 2001 From: Aries Lee Date: Mon, 21 Nov 2011 10:20:42 +0000 Subject: jme: PHY configuration for compatible issue To perform PHY calibration and set a different EA value by chip ID, Whenever the NIC chip power on, ie booting or resuming, we need to force HW to calibrate PHY parameter again, and also set a proper EA value which gather from experiment. Those procedures help to reduce compatible issues(NIC is unable to link up in some special case) in giga speed. Signed-off-by: AriesLee Signed-off-by: Guo-Fu Tseng Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 113 +++++++++++++++++++++++++++++++++++++++++++-- drivers/net/ethernet/jme.h | 19 ++++++++ 2 files changed, 129 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 7becff1f387d..76b84573566b 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1744,6 +1744,112 @@ jme_phy_off(struct jme_adapter *jme) jme_new_phy_off(jme); } +static int +jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg) +{ + u32 phy_addr; + + phy_addr = JM_PHY_SPEC_REG_READ | specreg; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, + phy_addr); + return jme_mdio_read(jme->dev, jme->mii_if.phy_id, + JM_PHY_SPEC_DATA_REG); +} + +static void +jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data) +{ + u32 phy_addr; + + phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, + phy_data); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, + phy_addr); +} + +static int +jme_phy_calibration(struct jme_adapter *jme) +{ + u32 ctrl1000, phy_data; + + jme_phy_off(jme); + jme_phy_on(jme); + /* Enabel PHY test mode 1 */ + ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; + ctrl1000 |= PHY_GAD_TEST_MODE_1; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); + + phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); + phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0; + phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH | + JM_PHY_EXT_COMM_2_CALI_ENABLE; + jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); + msleep(20); + phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); + phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE | + JM_PHY_EXT_COMM_2_CALI_MODE_0 | + JM_PHY_EXT_COMM_2_CALI_LATCH); + jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); + + /* Disable PHY test mode */ + ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); + return 0; +} + +static int +jme_phy_setEA(struct jme_adapter *jme) +{ + u32 phy_comm0 = 0, phy_comm1 = 0; + u8 nic_ctrl; + + pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl); + if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) + return 0; + + switch (jme->pdev->device) { + case PCI_DEVICE_ID_JMICRON_JMC250: + if (((jme->chip_main_rev == 5) && + ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) || + (jme->chip_sub_rev == 3))) || + (jme->chip_main_rev >= 6)) { + phy_comm0 = 0x008A; + phy_comm1 = 0x4109; + } + if ((jme->chip_main_rev == 3) && + ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2))) + phy_comm0 = 0xE088; + break; + case PCI_DEVICE_ID_JMICRON_JMC260: + if (((jme->chip_main_rev == 5) && + ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) || + (jme->chip_sub_rev == 3))) || + (jme->chip_main_rev >= 6)) { + phy_comm0 = 0x008A; + phy_comm1 = 0x4109; + } + if ((jme->chip_main_rev == 3) && + ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2))) + phy_comm0 = 0xE088; + if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0)) + phy_comm0 = 0x608A; + if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2)) + phy_comm0 = 0x408A; + break; + default: + return -ENODEV; + } + if (phy_comm0) + jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0); + if (phy_comm1) + jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1); + + return 0; +} + static int jme_open(struct net_device *netdev) { @@ -1769,7 +1875,8 @@ jme_open(struct net_device *netdev) jme_set_settings(netdev, &jme->old_ecmd); else jme_reset_phy_processor(jme); - + jme_phy_calibration(jme); + jme_phy_setEA(jme); jme_reset_link(jme); return 0; @@ -3184,7 +3291,8 @@ jme_resume(struct device *dev) jme_set_settings(netdev, &jme->old_ecmd); else jme_reset_phy_processor(jme); - + jme_phy_calibration(jme); + jme_phy_setEA(jme); jme_start_irq(jme); netif_device_attach(netdev); @@ -3239,4 +3347,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); MODULE_DEVICE_TABLE(pci, jme_pci_tbl); - diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h index 02ea27c1dcb5..4304072bd3c5 100644 --- a/drivers/net/ethernet/jme.h +++ b/drivers/net/ethernet/jme.h @@ -760,6 +760,25 @@ enum jme_rxmcs_bits { RXMCS_CHECKSUM, }; +/* Extern PHY common register 2 */ + +#define PHY_GAD_TEST_MODE_1 0x00002000 +#define PHY_GAD_TEST_MODE_MSK 0x0000E000 +#define JM_PHY_SPEC_REG_READ 0x00004000 +#define JM_PHY_SPEC_REG_WRITE 0x00008000 +#define PHY_CALIBRATION_DELAY 20 +#define JM_PHY_SPEC_ADDR_REG 0x1E +#define JM_PHY_SPEC_DATA_REG 0x1F + +#define JM_PHY_EXT_COMM_0_REG 0x30 +#define JM_PHY_EXT_COMM_1_REG 0x31 +#define JM_PHY_EXT_COMM_2_REG 0x32 +#define JM_PHY_EXT_COMM_2_CALI_ENABLE 0x01 +#define JM_PHY_EXT_COMM_2_CALI_MODE_0 0x02 +#define JM_PHY_EXT_COMM_2_CALI_LATCH 0x10 +#define PCI_PRIV_SHARE_NICCTRL 0xF5 +#define JME_FLAG_PHYEA_ENABLE 0x2 + /* * Wakeup Frame setup interface registers */ -- cgit From a5f70b6717a229ad10aa79382a29a8ee6f1976c3 Mon Sep 17 00:00:00 2001 From: Christian Hitz Date: Mon, 24 Oct 2011 08:57:32 +0200 Subject: ARM: at91: fix NAND bus width decoding from system_rev Make it is safe to assign the return value of this function to u8/u16 variables. Signed-off-by: Christian Hitz Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/include/mach/system_rev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/include/mach/system_rev.h b/arch/arm/mach-at91/include/mach/system_rev.h index 8f4866045b41..ec164a4124c9 100644 --- a/arch/arm/mach-at91/include/mach/system_rev.h +++ b/arch/arm/mach-at91/include/mach/system_rev.h @@ -19,7 +19,7 @@ #define BOARD_HAVE_NAND_16BIT (1 << 31) static inline int board_have_nand_16bit(void) { - return system_rev & BOARD_HAVE_NAND_16BIT; + return (system_rev & BOARD_HAVE_NAND_16BIT) ? 1 : 0; } #endif /* __ARCH_SYSTEM_REV_H__ */ -- cgit From d4d6373c1109b11c8118340be97ae31b8f94d66a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 28 Nov 2011 14:06:31 +0800 Subject: regulator: aat2870: Fix the logic of checking if no id is matched in aat2870_get_regulator In current implementation, the pointer ri is not NULL if no id is matched. Fix it by checking i == ARRAY_SIZE(aat2870_regulators) if no id is matched. Signed-off-by: Axel Lin Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/regulator/aat2870-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 5abeb3ac3e8d..298c6c6a2795 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -160,7 +160,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) break; } - if (!ri) + if (i == ARRAY_SIZE(aat2870_regulators)) return NULL; ri->enable_addr = AAT2870_LDO_EN; -- cgit From 58fb5cf5d1edb7e306574833ee55d732918c89e3 Mon Sep 17 00:00:00 2001 From: Lothar Waßmann Date: Mon, 28 Nov 2011 15:38:37 +0100 Subject: regulator: fix use after free bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is caused by dereferencing 'rdev' after device_unregister() in the regulator_unregister() function. 'rdev' is freed by device_unregister(), so it must not be dereferenced after this call. [Edited commit message for legibility -- broonie] Signed-off-by: Lothar Waßmann Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 669d02160221..938398f3e869 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2799,8 +2799,8 @@ void regulator_unregister(struct regulator_dev *rdev) list_del(&rdev->list); if (rdev->supply) regulator_put(rdev->supply); - device_unregister(&rdev->dev); kfree(rdev->constraints); + device_unregister(&rdev->dev); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_unregister); -- cgit From 52553ddffad76ccf192d4dd9ce88d5818f57f62a Mon Sep 17 00:00:00 2001 From: Edward Donovan Date: Sun, 27 Nov 2011 23:07:34 -0500 Subject: genirq: fix regression in irqfixup, irqpoll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit fa27271bc8d2("genirq: Fixup poll handling") introduced a regression that broke irqfixup/irqpoll for some hardware configurations. Amidst reorganizing 'try_one_irq', that patch removed a test that checked for 'action->handler' returning IRQ_HANDLED, before acting on the interrupt. Restoring this test back returns the functionality lost since 2.6.39. In the current set of tests, after 'action' is set, it must precede '!action->next' to take effect. With this and my previous patch to irq/spurious.c, c75d720fca8a, all IRQ regressions that I have encountered are fixed. Signed-off-by: Edward Donovan Reported-and-tested-by: Rogério Brito Cc: Thomas Gleixner Cc: stable@kernel.org (2.6.39+) Signed-off-by: Linus Torvalds --- kernel/irq/spurious.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index b5f4742693c0..dc813a948be2 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -84,7 +84,9 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) */ action = desc->action; if (!action || !(action->flags & IRQF_SHARED) || - (action->flags & __IRQF_TIMER) || !action->next) + (action->flags & __IRQF_TIMER) || + (action->handler(irq, action->dev_id) == IRQ_HANDLED) || + !action->next) goto out; /* Already running on another processor */ -- cgit From df711fc9962b9491af2b92bd0d21ecbfefe4e5fa Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 17 Nov 2011 13:07:44 +0800 Subject: xHCI: reset-on-resume quirk for NEC uPD720200 Julian Sikorski reports NEC uPD720200 does not work stable after suspend and resume. Re-initialize the host in xhci_resume(). This should be backported to stable kernels as old as 2.6.37. The kernel will need to include commit c877b3b2ad5cb9d4fe523c5496185cc328ff3ae9 "xhci: Add reset on resume quirk for asrock p67 host" for this patch to work. Signed-off-by: Andiry Xu Reported-by: Julian Sikorski Tested-by: Julian Sikorski Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-pci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ef98b38626fb..d2a7332daca4 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -33,6 +33,8 @@ #define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_DEVICE_ID_ASROCK_P67 0x7023 +#define PCI_DEVICE_ID_NEC_uPD720200 0x0194 + static const char hcd_name[] = "xhci_hcd"; /* called after powerup, by probe or system-pm "wakeup" */ @@ -74,8 +76,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->revision); } - if (pdev->vendor == PCI_VENDOR_ID_NEC) + if (pdev->vendor == PCI_VENDOR_ID_NEC) { xhci->quirks |= XHCI_NEC_HOST; + if (pdev->device == PCI_DEVICE_ID_NEC_uPD720200) + xhci->quirks |= XHCI_RESET_ON_RESUME; + } if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96) xhci->quirks |= XHCI_AMD_0x96_HOST; -- cgit From e007b857e88097c96c45620bf3b04a4e309053d1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 24 Nov 2011 18:13:56 +0200 Subject: nl80211: fix MAC address validation MAC addresses have a fixed length. The current policy allows passing < ETH_ALEN bytes, which might result in reading beyond the buffer. Cc: stable@vger.kernel.org Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b3a476fe8272..ffafda5022c2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -89,8 +89,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, - [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, - [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, + [NL80211_ATTR_MAC] = { .len = ETH_ALEN }, + [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN }, [NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, -- cgit From 24f50a9d165745fd0701c6e089d35f58a229ea69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Nov 2011 20:06:14 +0100 Subject: mac80211: don't stop a single aggregation session twice Nikolay noticed (by code review) that mac80211 can attempt to stop an aggregation session while it is already being stopped. So to fix it, check whether stop is already being done and bail out if so. Also move setting the STOPPING state into the lock so things are properly atomic. Cc: stable@vger.kernel.org Reported-by: Nikolay Martynov Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 2ac033989e01..674b345ade81 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -160,6 +160,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, return -ENOENT; } + /* if we're already stopping ignore any new requests to stop */ + if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { + spin_unlock_bh(&sta->lock); + return -EALREADY; + } + if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* not even started yet! */ ieee80211_assign_tid_tx(sta, tid, NULL); @@ -168,6 +174,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, return 0; } + set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); + spin_unlock_bh(&sta->lock); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -175,8 +183,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); - del_timer_sync(&tid_tx->addba_resp_timer); /* -- cgit From e55b32c110b025ce07b40227f620e99700bf8741 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 28 Nov 2011 10:33:40 +0100 Subject: rtlwifi: fix lps_lock deadlock rtl_lps_leave can be called from interrupt context, so we have to disable interrupts when taking lps_lock. Below is full lockdep info about deadlock: [ 93.815269] ================================= [ 93.815390] [ INFO: inconsistent lock state ] [ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 [ 93.815556] --------------------------------- [ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.815947] {SOFTIRQ-ON-W} state was registered at: [ 93.815947] [] __lock_acquire+0x369/0xd0c [ 93.815947] [] lock_acquire+0xf3/0x13e [ 93.815947] [] _raw_spin_lock+0x45/0x79 [ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] [ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] [ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] [ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] [ 93.815947] [] process_one_work+0x205/0x3e7 [ 93.815947] [] worker_thread+0xda/0x15d [ 93.815947] [] kthread+0xa8/0xb0 [ 93.815947] [] kernel_thread_helper+0x4/0x10 [ 93.815947] irq event stamp: 547822 [ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 [ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e [ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 [ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 [ 93.815947] [ 93.815947] other info that might help us debug this: [ 93.815947] Possible unsafe locking scenario: [ 93.815947] [ 93.815947] CPU0 [ 93.815947] ---- [ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); [ 93.815947] [ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); [ 93.815947] [ 93.815947] *** DEADLOCK *** [ 93.815947] [ 93.815947] no locks held by swapper/0. [ 93.815947] [ 93.815947] stack backtrace: [ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 [ 93.815947] Call Trace: [ 93.815947] [] print_usage_bug+0x1e7/0x1f8 [ 93.815947] [] ? save_stack_trace+0x2c/0x49 [ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 [ 93.815947] [] mark_lock+0x106/0x220 [ 93.815947] [] __lock_acquire+0x2f5/0xd0c [ 93.815947] [] ? native_sched_clock+0x34/0x36 [ 93.830125] [] ? sched_clock+0x9/0xd [ 93.830125] [] ? sched_clock_local+0x12/0x75 [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] lock_acquire+0xf3/0x13e [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] _raw_spin_lock+0x45/0x79 [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] ? skb_dequeue+0x62/0x6d [ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] [ 93.830125] [] tasklet_action+0x8d/0xee [ 93.830125] [] __do_softirq+0x112/0x25a [ 93.830125] [] call_softirq+0x1c/0x30 [ 93.830125] [] do_softirq+0x4b/0xa1 [ 93.830125] [] irq_exit+0x5d/0xcf [ 93.830125] [] do_IRQ+0x8e/0xa5 [ 93.830125] [] common_interrupt+0x73/0x73 [ 93.830125] [] ? trace_hardirqs_off+0xd/0xf [ 93.830125] [] ? intel_idle+0xe5/0x10c [ 93.830125] [] ? intel_idle+0xe1/0x10c [ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe [ 93.830125] [] cpu_idle+0xab/0x101 [ 93.830125] [] rest_init+0xd7/0xde [ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c [ 93.830125] [] start_kernel+0x3dd/0x3ea [ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 [ 93.830125] [] ? early_idt_handlers+0x140/0x140 [ 93.830125] [] x86_64_start_kernel+0x102/0x111 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=755154 Reported-by: vjain02@students.poly.edu Reported-and-tested-by: Oliver Paukstadt Cc: stable@vger.kernel.org Acked-by: Larry Finger Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index a693feffbe72..0b04b2e7b597 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -394,7 +394,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) if (mac->link_state != MAC80211_LINKED) return; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); /* Idle for a while if we connect to AP a while ago. */ if (mac->cnt_after_linked >= 2) { @@ -406,7 +406,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) } } - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); } /*Leave the leisure power save mode.*/ @@ -415,8 +415,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { @@ -437,7 +438,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) rtl_lps_set_psmode(hw, EACTIVE); } } - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); } /* For sw LPS*/ @@ -538,9 +539,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); } void rtl_swlps_rfon_wq_callback(void *data) @@ -573,9 +574,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) if (rtlpriv->link_info.busytraffic) return; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { -- cgit From a73228124bed4022d4d4c5663d9679ba2fb99c6c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 26 Nov 2011 23:37:43 +0100 Subject: ath9k: Revert change that broke AR928X on Acer Ferrari One Revert a hunk in drivers/net/wireless/ath/ath9k/hw.c introduced by commit 2577c6e8f2320f1d2f09be122efef5b9118efee4 (ath9k_hw: Add support for AR946/8x chipsets) that caused a nasty regression to appear on my Acer Ferrari One (the box locks up entirely at random times after the wireless has been started without any way to get debug information out of it). Signed-off-by: Rafael J. Wysocki Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b479160dc262..7a9c6f7cd7e1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1826,7 +1826,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) } /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ - REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); + if (AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } /* -- cgit From d305a6557b2c4dca0110f05ffe745b1ef94adb80 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Mon, 28 Nov 2011 09:18:00 +0100 Subject: mac80211: fix race condition caused by late addBA response If addBA responses comes in just after addba_resp_timer has expired mac80211 will still accept it and try to open the aggregation session. This causes drivers to be confused and in some cases even crash. This patch fixes the race condition and makes sure that if addba_resp_timer has expired addBA response is not longer accepted and we do not try to open half-closed session. Cc: stable@vger.kernel.org Signed-off-by: Nikolay Martynov [some adjustments] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 674b345ade81..eea6e5c8d168 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -762,11 +762,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, goto out; } - del_timer(&tid_tx->addba_resp_timer); + del_timer_sync(&tid_tx->addba_resp_timer); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); #endif + + /* + * addba_resp_timer may have fired before we got here, and + * caused WANT_STOP to be set. If the stop then was already + * processed further, STOPPING might be set. + */ + if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || + test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG + "got addBA resp for tid %d but we already gave up\n", + tid); +#endif + goto out; + } + /* * IEEE 802.11-2007 7.3.1.14: * In an ADDBA Response frame, when the Status Code field -- cgit From 2a1e0fd175dcfd72096ba9291d31e3b1b5342e60 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 27 Nov 2011 15:29:44 +0200 Subject: mac80211: fix race between the AGG SM and the Tx data path When a packet is supposed to sent be as an a-MPDU, mac80211 sets IEEE80211_TX_CTL_AMPDU to let the driver know. On the other hand, mac80211 configures the driver for aggregration with the ampdu_action callback. There is race between these two mechanisms since the following scenario can occur when the BA agreement is torn down: Tx softIRQ drv configuration ========== ================= check OPERATIONAL bit Set the TX_CTL_AMPDU bit in the packet clear OPERATIONAL bit stop Tx AGG Pass Tx packet to the driver. In that case the driver would get a packet with TX_CTL_AMPDU set although it has already been notified that the BA session has been torn down. To fix this, we need to synchronize all the Qdisc activity after we cleared the OPERATIONAL bit. After that step, all the following packets will be buffered until the driver reports it is ready to get new packets for this RA / TID. This buffering allows not to run into another race that would send packets with TX_CTL_AMPDU unset while the driver hasn't been requested to tear down the BA session yet. This race occurs in practice and iwlwifi complains with a WARN_ON when it happens. Cc: stable@kernel.org Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index eea6e5c8d168..331472ce038c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -192,6 +192,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, */ clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); + /* + * There might be a few packets being processed right now (on + * another CPU) that have already gotten past the aggregation + * check when it was still OPERATIONAL and consequently have + * IEEE80211_TX_CTL_AMPDU set. In that case, this code might + * call into the driver at the same time or even before the + * TX paths calls into it, which could confuse the driver. + * + * Wait for all currently running TX paths to finish before + * telling the driver. New packets will not go through since + * the aggregation session is no longer OPERATIONAL. + */ + synchronize_net(); + tid_tx->stop_initiator = initiator; tid_tx->tx_stop = tx; -- cgit From ba305e31e88ea5c2f598ff9fbc5424711a429e30 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 28 Nov 2011 16:53:19 +0200 Subject: regulator: twl: fix twl4030 support for smps regulators SMPS regulator voltage control differs from the one of the LDO ones. Current TWL code was using LDO regulator ops for controlling the SMPS regulators, which fails. This was fixed fixed by adding separate regulator type which uses correct logic and calculations for the voltage levels. Signed-off-by: Tero Kristo Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/regulator/twl-regulator.c | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index ee8747f4fa08..11cc308d66e9 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -71,6 +71,7 @@ struct twlreg_info { #define VREG_TYPE 1 #define VREG_REMAP 2 #define VREG_DEDICATED 3 /* LDO control */ +#define VREG_VOLTAGE_SMPS_4030 9 /* TWL6030 register offsets */ #define VREG_TRANS 1 #define VREG_STATE 2 @@ -514,6 +515,32 @@ static struct regulator_ops twl4030ldo_ops = { .get_status = twl4030reg_get_status, }; +static int +twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, + unsigned *selector) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); + + twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, + vsel); + return 0; +} + +static int twl4030smps_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE_SMPS_4030); + + return vsel * 12500 + 600000; +} + +static struct regulator_ops twl4030smps_ops = { + .set_voltage = twl4030smps_set_voltage, + .get_voltage = twl4030smps_get_voltage, +}; + static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -856,6 +883,21 @@ static struct regulator_ops twlsmps_ops = { }, \ } +#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ + { \ + .base = offset, \ + .id = num, \ + .delay = turnon_delay, \ + .remap = remap_conf, \ + .desc = { \ + .name = #label, \ + .id = TWL4030_REG_##label, \ + .ops = &twl4030smps_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + } + #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .min_mV = min_mVolts, \ @@ -947,8 +989,8 @@ static struct twlreg_info twl_regs[] = { TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08), TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08), - TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08), - TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08), + TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08), + TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08), TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08), TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08), TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08), -- cgit From 6225da481597ebff09454c785fe0afc7f5fdbb77 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 28 Nov 2011 20:12:05 +0100 Subject: cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler IRQF_SHARED is required for older controllers that don't support MSI(X) and which may end up sharing an interrupt. Also remove deprecated IRQF_DISABLED. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 8004ac30a7a8..6f22ed0dab65 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -4880,7 +4880,7 @@ static int cciss_request_irq(ctlr_info_t *h, { if (h->msix_vector || h->msi_vector) { if (!request_irq(h->intr[h->intr_mode], msixhandler, - IRQF_DISABLED, h->devname, h)) + 0, h->devname, h)) return 0; dev_err(&h->pdev->dev, "Unable to get msi irq %d" " for %s\n", h->intr[h->intr_mode], @@ -4889,7 +4889,7 @@ static int cciss_request_irq(ctlr_info_t *h, } if (!request_irq(h->intr[h->intr_mode], intxhandler, - IRQF_DISABLED, h->devname, h)) + IRQF_SHARED, h->devname, h)) return 0; dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", h->intr[h->intr_mode], h->devname); -- cgit From 59bd71a81b66990564eac69aedd28ad87a2c81f4 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 28 Nov 2011 20:12:05 +0100 Subject: cciss: fix flush cache transfer length We weren't filling in the transfer length of the flush cache command (it transfers 4 bytes of zeroes). Firmware didn't seem to be bothered by this, but it should be fixed. Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 6f22ed0dab65..587cce57adae 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2601,6 +2601,8 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, c->Request.Timeout = 0; c->Request.CDB[0] = BMIC_WRITE; c->Request.CDB[6] = BMIC_CACHE_FLUSH; + c->Request.CDB[7] = (size >> 8) & 0xFF; + c->Request.CDB[8] = size & 0xFF; break; case TEST_UNIT_READY: c->Request.CDBLen = 6; -- cgit From c34c97ad8c7c3cdacab2327235c2df4454ff1a06 Mon Sep 17 00:00:00 2001 From: Jonathan Lallinger Date: Thu, 20 Oct 2011 13:25:14 -0500 Subject: RDMA/cxgb4: Fix iw_cxgb4 count_rcqes() logic Fix another place in the code where logic dealing with the t4_cqe was using the wrong QID. This fixes the counting logic so that it tests against the SQ QID instead of the RQ QID when counting RCQES. Signed-off by: Jonathan Lallinger Signed-off by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index f35a935267e7..0f1607c8325a 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count) while (ptr != cq->sw_pidx) { cqe = &cq->sw_queue[ptr]; if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) && - (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq)) + (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq)) (*count)++; if (++ptr == cq->size) ptr = 0; -- cgit From 01b225e18fcb540c5d615ca79ef832473451f118 Mon Sep 17 00:00:00 2001 From: Kumar Sanghvi Date: Mon, 28 Nov 2011 22:09:15 +0530 Subject: RDMA/cxgb4: Fix retry with MPAv1 logic for MPAv2 Fix logic so that we don't retry with MPAv1 once we have done that already. Otherwise, we end up retrying with MPAv1 even when its not needed on getting peer aborts - and this could lead to kernel panic. Signed-off-by: Kumar Sanghvi Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index b36cdac9c558..760b2fe29365 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -542,8 +542,10 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0); mpa->private_data_size = htons(ep->plen); mpa->revision = mpa_rev_to_use; - if (mpa_rev_to_use == 1) + if (mpa_rev_to_use == 1) { ep->tried_with_mpa_v1 = 1; + ep->retry_with_mpa_v1 = 0; + } if (mpa_rev_to_use == 2) { mpa->private_data_size += -- cgit From 8ee887d74b3d741991edaa1836d22636c28926d9 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 9 Nov 2011 17:07:22 -0500 Subject: IB/qib: Fix over-scheduling of QSFP work Don't over-schedule QSFP work on driver initialization. It could end up being run simultaneously on two different CPUs resulting in bad EEPROM reads. In combination with setting the physical IB link state prior to the IBC being brought out of reset, this can cause the link state machine to start training early with wrong settings. Signed-off-by: Mitko Haralanov Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba7322.c | 16 ++++++++-------- drivers/infiniband/hw/qib/qib_qsfp.c | 12 ------------ 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 8b46b608c02f..1d5895941e19 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) SYM_LSB(IBCCtrlA_0, MaxPktLen); ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */ - /* initially come up waiting for TS1, without sending anything. */ - val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE << - QLOGIC_IB_IBCC_LINKINITCMD_SHIFT); - - ppd->cpspec->ibcctrl_a = val; /* * Reset the PCS interface to the serdes (and also ibc, which is still * in reset from above). Writes new value of ibcctrl_a as last step. */ qib_7322_mini_pcs_reset(ppd); - qib_write_kreg(dd, kr_scratch, 0ULL); - /* clear the linkinit cmds */ - ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd); if (!ppd->cpspec->ibcctrl_b) { unsigned lse = ppd->link_speed_enabled; @@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn); set_vls(ppd); + /* initially come up DISABLED, without sending anything. */ + val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE << + QLOGIC_IB_IBCC_LINKINITCMD_SHIFT); + qib_write_kreg_port(ppd, krp_ibcctrl_a, val); + qib_write_kreg(dd, kr_scratch, 0ULL); + /* clear the linkinit cmds */ + ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd); + /* be paranoid against later code motion, etc. */ spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags); ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable); diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c index e06c4ed383f1..fa71b1e666c5 100644 --- a/drivers/infiniband/hw/qib/qib_qsfp.c +++ b/drivers/infiniband/hw/qib/qib_qsfp.c @@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd, udelay(20); /* Generous RST dwell */ dd->f_gpio_mod(dd, mask, mask, mask); - /* Spec says module can take up to two seconds! */ - mask = QSFP_GPIO_MOD_PRS_N; - if (qd->ppd->hw_pidx) - mask <<= QSFP_GPIO_PORT2_SHIFT; - - /* Do not try to wait here. Better to let event handle it */ - if (!qib_qsfp_mod_present(qd->ppd)) - goto bail; - /* We see a module, but it may be unwise to look yet. Just schedule */ - qd->t_insert = get_jiffies_64(); - queue_work(ib_wq, &qd->work); -bail: return; } -- cgit From 5841eb6402707a387b216373e65c9c28e8136663 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 Nov 2011 21:18:39 +0100 Subject: PM / Domains: Document how PM domains are used by the PM core The current power management documentation in Documentation/power/ either doesn't cover PM domains at all, or gives inaccurate information about them, so update the relevant files in there to follow the code. Signed-off-by: Rafael J. Wysocki --- Documentation/power/devices.txt | 42 ++++++++++++++++++++++++-------------- Documentation/power/runtime_pm.txt | 29 ++++++++++++++++---------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 646a89e0c07d..4342acbeee10 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -123,9 +123,10 @@ please refer directly to the source code for more information about it. Subsystem-Level Methods ----------------------- The core methods to suspend and resume devices reside in struct dev_pm_ops -pointed to by the pm member of struct bus_type, struct device_type and -struct class. They are mostly of interest to the people writing infrastructure -for buses, like PCI or USB, or device type and device class drivers. +pointed to by the ops member of struct dev_pm_domain, or by the pm member of +struct bus_type, struct device_type and struct class. They are mostly of +interest to the people writing infrastructure for platforms and buses, like PCI +or USB, or device type and device class drivers. Bus drivers implement these methods as appropriate for the hardware and the drivers using it; PCI works differently from USB, and so on. Not many people @@ -251,18 +252,29 @@ various phases always run after tasks have been frozen and before they are unfrozen. Furthermore, the *_noirq phases run at a time when IRQ handlers have been disabled (except for those marked with the IRQ_WAKEUP flag). -All phases use bus, type, or class callbacks (that is, methods defined in -dev->bus->pm, dev->type->pm, or dev->class->pm). These callbacks are mutually -exclusive, so if the device type provides a struct dev_pm_ops object pointed to -by its pm field (i.e. both dev->type and dev->type->pm are defined), the -callbacks included in that object (i.e. dev->type->pm) will be used. Otherwise, -if the class provides a struct dev_pm_ops object pointed to by its pm field -(i.e. both dev->class and dev->class->pm are defined), the PM core will use the -callbacks from that object (i.e. dev->class->pm). Finally, if the pm fields of -both the device type and class objects are NULL (or those objects do not exist), -the callbacks provided by the bus (that is, the callbacks from dev->bus->pm) -will be used (this allows device types to override callbacks provided by bus -types or classes if necessary). +All phases use PM domain, bus, type, or class callbacks (that is, methods +defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm). +These callbacks are regarded by the PM core as mutually exclusive. Moreover, +PM domain callbacks always take precedence over bus, type and class callbacks, +while type callbacks take precedence over bus and class callbacks, and class +callbacks take precedence over bus callbacks. To be precise, the following +rules are used to determine which callback to execute in the given phase: + + 1. If dev->pm_domain is present, the PM core will attempt to execute the + callback included in dev->pm_domain->ops. If that callback is not + present, no action will be carried out for the given device. + + 2. Otherwise, if both dev->type and dev->type->pm are present, the callback + included in dev->type->pm will be executed. + + 3. Otherwise, if both dev->class and dev->class->pm are present, the + callback included in dev->class->pm will be executed. + + 4. Otherwise, if both dev->bus and dev->bus->pm are present, the callback + included in dev->bus->pm will be executed. + +This allows PM domains and device types to override callbacks provided by bus +types or device classes if necessary. These callbacks may in turn invoke device- or driver-specific methods stored in dev->driver->pm, but they don't have to. diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 5336149f831b..79b10a090c9f 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -44,17 +44,24 @@ struct dev_pm_ops { }; The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks -are executed by the PM core for either the power domain, or the device type -(if the device power domain's struct dev_pm_ops does not exist), or the class -(if the device power domain's and type's struct dev_pm_ops object does not -exist), or the bus type (if the device power domain's, type's and class' -struct dev_pm_ops objects do not exist) of the given device, so the priority -order of callbacks from high to low is that power domain callbacks, device -type callbacks, class callbacks and bus type callbacks, and the high priority -one will take precedence over low priority one. The bus type, device type and -class callbacks are referred to as subsystem-level callbacks in what follows, -and generally speaking, the power domain callbacks are used for representing -power domains within a SoC. +are executed by the PM core for the device's subsystem that may be either of +the following: + + 1. PM domain of the device, if the device's PM domain object, dev->pm_domain, + is present. + + 2. Device type of the device, if both dev->type and dev->type->pm are present. + + 3. Device class of the device, if both dev->class and dev->class->pm are + present. + + 4. Bus type of the device, if both dev->bus and dev->bus->pm are present. + +The PM core always checks which callback to use in the order given above, so the +priority order of callbacks from high to low is: PM domain, device type, class +and bus type. Moreover, the high-priority one will always take precedence over +a low-priority one. The PM domain, bus type, device type and class callbacks +are referred to as subsystem-level callbacks in what follows. By default, the callbacks are always invoked in process context with interrupts enabled. However, subsystems can use the pm_runtime_irq_safe() helper function -- cgit From fa8ce723936460fcf7e49f508fd5dbd5125e39c4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 Nov 2011 21:19:57 +0100 Subject: PM / Sleep: Correct inaccurate information in devices.txt The documentation file Documentation/power/devices.txt contains some information that isn't correct any more due to code modifications made after that file had been created (or updated last time). Fix this. Signed-off-by: Rafael J. Wysocki --- Documentation/power/devices.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 4342acbeee10..ed3228884133 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -250,7 +250,7 @@ for every device before the next phase begins. Not all busses or classes support all these callbacks and not all drivers use all the callbacks. The various phases always run after tasks have been frozen and before they are unfrozen. Furthermore, the *_noirq phases run at a time when IRQ handlers have -been disabled (except for those marked with the IRQ_WAKEUP flag). +been disabled (except for those marked with the IRQF_NO_SUSPEND flag). All phases use PM domain, bus, type, or class callbacks (that is, methods defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm). @@ -295,9 +295,8 @@ When the system goes into the standby or memory sleep state, the phases are: After the prepare callback method returns, no new children may be registered below the device. The method may also prepare the device or - driver in some way for the upcoming system power transition (for - example, by allocating additional memory required for this purpose), but - it should not put the device into a low-power state. + driver in some way for the upcoming system power transition, but it + should not put the device into a low-power state. 2. The suspend methods should quiesce the device to stop it from performing I/O. They also may save the device registers and put it into the -- cgit From 907565921966260921e4c4581ed8985ef4cf9a67 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 Nov 2011 21:20:07 +0100 Subject: PM / Runtime: Make documentation follow the new behavior of irq_safe The runtime PM core code behavior related to the power.irq_safe device flag has changed recently and the documentation should be modified to reflect it. Signed-off-by: Rafael J. Wysocki --- Documentation/power/runtime_pm.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 79b10a090c9f..c2ae8bf77d46 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -65,11 +65,12 @@ are referred to as subsystem-level callbacks in what follows. By default, the callbacks are always invoked in process context with interrupts enabled. However, subsystems can use the pm_runtime_irq_safe() helper function -to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume() -callbacks should be invoked in atomic context with interrupts disabled. -This implies that these callback routines must not block or sleep, but it also -means that the synchronous helper functions listed at the end of Section 4 can -be used within an interrupt handler or in an atomic context. +to tell the PM core that their ->runtime_suspend(), ->runtime_resume() and +->runtime_idle() callbacks may be invoked in atomic context with interrupts +disabled for a given device. This implies that the callback routines in +question must not block or sleep, but it also means that the synchronous helper +functions listed at the end of Section 4 may be used for that device within an +interrupt handler or generally in an atomic context. The subsystem-level suspend callback is _entirely_ _responsible_ for handling the suspend of the device as appropriate, which may, but need not include -- cgit From fafba48d4dd6fcbb1fd7ac4ab0ba22ef45b9796c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 Nov 2011 21:20:15 +0100 Subject: PM / Sleep: Update documentation related to system wakeup The system wakeup section of Documentation/power/devices.txt is outdated, so make it agree with the current code. Signed-off-by: Rafael J. Wysocki --- Documentation/power/devices.txt | 60 ++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index ed3228884133..3139fb505dce 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -140,41 +140,57 @@ sequencing in the driver model tree. /sys/devices/.../power/wakeup files ----------------------------------- -All devices in the driver model have two flags to control handling of wakeup -events (hardware signals that can force the device and/or system out of a low -power state). These flags are initialized by bus or device driver code using +All device objects in the driver model contain fields that control the handling +of system wakeup events (hardware signals that can force the system out of a +sleep state). These fields are initialized by bus or device driver code using device_set_wakeup_capable() and device_set_wakeup_enable(), defined in include/linux/pm_wakeup.h. -The "can_wakeup" flag just records whether the device (and its driver) can +The "power.can_wakeup" flag just records whether the device (and its driver) can physically support wakeup events. The device_set_wakeup_capable() routine -affects this flag. The "should_wakeup" flag controls whether the device should -try to use its wakeup mechanism. device_set_wakeup_enable() affects this flag; -for the most part drivers should not change its value. The initial value of -should_wakeup is supposed to be false for the majority of devices; the major -exceptions are power buttons, keyboards, and Ethernet adapters whose WoL -(wake-on-LAN) feature has been set up with ethtool. It should also default -to true for devices that don't generate wakeup requests on their own but merely -forward wakeup requests from one bus to another (like PCI bridges). +affects this flag. The "power.wakeup" field is a pointer to an object of type +struct wakeup_source used for controlling whether or not the device should use +its system wakeup mechanism and for notifying the PM core of system wakeup +events signaled by the device. This object is only present for wakeup-capable +devices (i.e. devices whose "can_wakeup" flags are set) and is created (or +removed) by device_set_wakeup_capable(). Whether or not a device is capable of issuing wakeup events is a hardware matter, and the kernel is responsible for keeping track of it. By contrast, whether or not a wakeup-capable device should issue wakeup events is a policy decision, and it is managed by user space through a sysfs attribute: the -power/wakeup file. User space can write the strings "enabled" or "disabled" to -set or clear the "should_wakeup" flag, respectively. This file is only present -for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set) -and is created (or removed) by device_set_wakeup_capable(). Reads from the -file will return the corresponding string. - -The device_may_wakeup() routine returns true only if both flags are set. +"power/wakeup" file. User space can write the strings "enabled" or "disabled" +to it to indicate whether or not, respectively, the device is supposed to signal +system wakeup. This file is only present if the "power.wakeup" object exists +for the given device and is created (or removed) along with that object, by +device_set_wakeup_capable(). Reads from the file will return the corresponding +string. + +The "power/wakeup" file is supposed to contain the "disabled" string initially +for the majority of devices; the major exceptions are power buttons, keyboards, +and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with +ethtool. It should also default to "enabled" for devices that don't generate +wakeup requests on their own but merely forward wakeup requests from one bus to +another (like PCI Express ports). + +The device_may_wakeup() routine returns true only if the "power.wakeup" object +exists and the corresponding "power/wakeup" file contains the string "enabled". This information is used by subsystems, like the PCI bus type code, to see whether or not to enable the devices' wakeup mechanisms. If device wakeup mechanisms are enabled or disabled directly by drivers, they also should use device_may_wakeup() to decide what to do during a system sleep transition. -However for runtime power management, wakeup events should be enabled whenever -the device and driver both support them, regardless of the should_wakeup flag. - +Device drivers, however, are not supposed to call device_set_wakeup_enable() +directly in any case. + +It ought to be noted that system wakeup is conceptually different from "remote +wakeup" used by runtime power management, although it may be supported by the +same physical mechanism. Remote wakeup is a feature allowing devices in +low-power states to trigger specific interrupts to signal conditions in which +they should be put into the full-power state. Those interrupts may or may not +be used to signal system wakeup events, depending on the hardware design. On +some systems it is impossible to trigger them from system sleep states. In any +case, remote wakeup should always be enabled for runtime power management for +all devices and drivers that support it. /sys/devices/.../power/control files ------------------------------------ -- cgit From f7bc83d87d242917ca0ee041ed509f57f361dd56 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 Nov 2011 21:20:32 +0100 Subject: PM: Update comments describing device power management callbacks The comments describing device power management callbacks in include/pm.h are outdated and somewhat confusing, so make them reflect the reality more accurately. Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 229 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 134 insertions(+), 95 deletions(-) diff --git a/include/linux/pm.h b/include/linux/pm.h index 5c4c8b18c8b7..3f3ed83a9aa5 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -54,118 +54,145 @@ typedef struct pm_message { /** * struct dev_pm_ops - device PM callbacks * - * Several driver power state transitions are externally visible, affecting + * Several device power state transitions are externally visible, affecting * the state of pending I/O queues and (for drivers that touch hardware) * interrupts, wakeups, DMA, and other hardware state. There may also be - * internal transitions to various low power modes, which are transparent + * internal transitions to various low-power modes which are transparent * to the rest of the driver stack (such as a driver that's ON gating off * clocks which are not in active use). * - * The externally visible transitions are handled with the help of the following - * callbacks included in this structure: - * - * @prepare: Prepare the device for the upcoming transition, but do NOT change - * its hardware state. Prevent new children of the device from being - * registered after @prepare() returns (the driver's subsystem and - * generally the rest of the kernel is supposed to prevent new calls to the - * probe method from being made too once @prepare() has succeeded). If - * @prepare() detects a situation it cannot handle (e.g. registration of a - * child already in progress), it may return -EAGAIN, so that the PM core - * can execute it once again (e.g. after the new child has been registered) - * to recover from the race condition. This method is executed for all - * kinds of suspend transitions and is followed by one of the suspend - * callbacks: @suspend(), @freeze(), or @poweroff(). - * The PM core executes @prepare() for all devices before starting to - * execute suspend callbacks for any of them, so drivers may assume all of - * the other devices to be present and functional while @prepare() is being - * executed. In particular, it is safe to make GFP_KERNEL memory - * allocations from within @prepare(). However, drivers may NOT assume - * anything about the availability of the user space at that time and it - * is not correct to request firmware from within @prepare() (it's too - * late to do that). [To work around this limitation, drivers may - * register suspend and hibernation notifiers that are executed before the - * freezing of tasks.] + * The externally visible transitions are handled with the help of callbacks + * included in this structure in such a way that two levels of callbacks are + * involved. First, the PM core executes callbacks provided by PM domains, + * device types, classes and bus types. They are the subsystem-level callbacks + * supposed to execute callbacks provided by device drivers, although they may + * choose not to do that. If the driver callbacks are executed, they have to + * collaborate with the subsystem-level callbacks to achieve the goals + * appropriate for the given system transition, given transition phase and the + * subsystem the device belongs to. + * + * @prepare: The principal role of this callback is to prevent new children of + * the device from being registered after it has returned (the driver's + * subsystem and generally the rest of the kernel is supposed to prevent + * new calls to the probe method from being made too once @prepare() has + * succeeded). If @prepare() detects a situation it cannot handle (e.g. + * registration of a child already in progress), it may return -EAGAIN, so + * that the PM core can execute it once again (e.g. after a new child has + * been registered) to recover from the race condition. + * This method is executed for all kinds of suspend transitions and is + * followed by one of the suspend callbacks: @suspend(), @freeze(), or + * @poweroff(). The PM core executes subsystem-level @prepare() for all + * devices before starting to invoke suspend callbacks for any of them, so + * generally devices may be assumed to be functional or to respond to + * runtime resume requests while @prepare() is being executed. However, + * device drivers may NOT assume anything about the availability of user + * space at that time and it is NOT valid to request firmware from within + * @prepare() (it's too late to do that). It also is NOT valid to allocate + * substantial amounts of memory from @prepare() in the GFP_KERNEL mode. + * [To work around these limitations, drivers may register suspend and + * hibernation notifiers to be executed before the freezing of tasks.] * * @complete: Undo the changes made by @prepare(). This method is executed for * all kinds of resume transitions, following one of the resume callbacks: * @resume(), @thaw(), @restore(). Also called if the state transition - * fails before the driver's suspend callback (@suspend(), @freeze(), - * @poweroff()) can be executed (e.g. if the suspend callback fails for one + * fails before the driver's suspend callback: @suspend(), @freeze() or + * @poweroff(), can be executed (e.g. if the suspend callback fails for one * of the other devices that the PM core has unsuccessfully attempted to * suspend earlier). - * The PM core executes @complete() after it has executed the appropriate - * resume callback for all devices. + * The PM core executes subsystem-level @complete() after it has executed + * the appropriate resume callbacks for all devices. * * @suspend: Executed before putting the system into a sleep state in which the - * contents of main memory are preserved. Quiesce the device, put it into - * a low power state appropriate for the upcoming system state (such as - * PCI_D3hot), and enable wakeup events as appropriate. + * contents of main memory are preserved. The exact action to perform + * depends on the device's subsystem (PM domain, device type, class or bus + * type), but generally the device must be quiescent after subsystem-level + * @suspend() has returned, so that it doesn't do any I/O or DMA. + * Subsystem-level @suspend() is executed for all devices after invoking + * subsystem-level @prepare() for all of them. * * @resume: Executed after waking the system up from a sleep state in which the - * contents of main memory were preserved. Put the device into the - * appropriate state, according to the information saved in memory by the - * preceding @suspend(). The driver starts working again, responding to - * hardware events and software requests. The hardware may have gone - * through a power-off reset, or it may have maintained state from the - * previous suspend() which the driver may rely on while resuming. On most - * platforms, there are no restrictions on availability of resources like - * clocks during @resume(). + * contents of main memory were preserved. The exact action to perform + * depends on the device's subsystem, but generally the driver is expected + * to start working again, responding to hardware events and software + * requests (the device itself may be left in a low-power state, waiting + * for a runtime resume to occur). The state of the device at the time its + * driver's @resume() callback is run depends on the platform and subsystem + * the device belongs to. On most platforms, there are no restrictions on + * availability of resources like clocks during @resume(). + * Subsystem-level @resume() is executed for all devices after invoking + * subsystem-level @resume_noirq() for all of them. * * @freeze: Hibernation-specific, executed before creating a hibernation image. - * Quiesce operations so that a consistent image can be created, but do NOT - * otherwise put the device into a low power device state and do NOT emit - * system wakeup events. Save in main memory the device settings to be - * used by @restore() during the subsequent resume from hibernation or by - * the subsequent @thaw(), if the creation of the image or the restoration - * of main memory contents from it fails. + * Analogous to @suspend(), but it should not enable the device to signal + * wakeup events or change its power state. The majority of subsystems + * (with the notable exception of the PCI bus type) expect the driver-level + * @freeze() to save the device settings in memory to be used by @restore() + * during the subsequent resume from hibernation. + * Subsystem-level @freeze() is executed for all devices after invoking + * subsystem-level @prepare() for all of them. * * @thaw: Hibernation-specific, executed after creating a hibernation image OR - * if the creation of the image fails. Also executed after a failing + * if the creation of an image has failed. Also executed after a failing * attempt to restore the contents of main memory from such an image. * Undo the changes made by the preceding @freeze(), so the device can be * operated in the same way as immediately before the call to @freeze(). + * Subsystem-level @thaw() is executed for all devices after invoking + * subsystem-level @thaw_noirq() for all of them. It also may be executed + * directly after @freeze() in case of a transition error. * * @poweroff: Hibernation-specific, executed after saving a hibernation image. - * Quiesce the device, put it into a low power state appropriate for the - * upcoming system state (such as PCI_D3hot), and enable wakeup events as - * appropriate. + * Analogous to @suspend(), but it need not save the device's settings in + * memory. + * Subsystem-level @poweroff() is executed for all devices after invoking + * subsystem-level @prepare() for all of them. * * @restore: Hibernation-specific, executed after restoring the contents of main - * memory from a hibernation image. Driver starts working again, - * responding to hardware events and software requests. Drivers may NOT - * make ANY assumptions about the hardware state right prior to @restore(). - * On most platforms, there are no restrictions on availability of - * resources like clocks during @restore(). - * - * @suspend_noirq: Complete the operations of ->suspend() by carrying out any - * actions required for suspending the device that need interrupts to be - * disabled - * - * @resume_noirq: Prepare for the execution of ->resume() by carrying out any - * actions required for resuming the device that need interrupts to be - * disabled - * - * @freeze_noirq: Complete the operations of ->freeze() by carrying out any - * actions required for freezing the device that need interrupts to be - * disabled - * - * @thaw_noirq: Prepare for the execution of ->thaw() by carrying out any - * actions required for thawing the device that need interrupts to be - * disabled - * - * @poweroff_noirq: Complete the operations of ->poweroff() by carrying out any - * actions required for handling the device that need interrupts to be - * disabled - * - * @restore_noirq: Prepare for the execution of ->restore() by carrying out any - * actions required for restoring the operations of the device that need - * interrupts to be disabled + * memory from a hibernation image, analogous to @resume(). + * + * @suspend_noirq: Complete the actions started by @suspend(). Carry out any + * additional operations required for suspending the device that might be + * racing with its driver's interrupt handler, which is guaranteed not to + * run while @suspend_noirq() is being executed. + * It generally is expected that the device will be in a low-power state + * (appropriate for the target system sleep state) after subsystem-level + * @suspend_noirq() has returned successfully. If the device can generate + * system wakeup signals and is enabled to wake up the system, it should be + * configured to do so at that time. However, depending on the platform + * and device's subsystem, @suspend() may be allowed to put the device into + * the low-power state and configure it to generate wakeup signals, in + * which case it generally is not necessary to define @suspend_noirq(). + * + * @resume_noirq: Prepare for the execution of @resume() by carrying out any + * operations required for resuming the device that might be racing with + * its driver's interrupt handler, which is guaranteed not to run while + * @resume_noirq() is being executed. + * + * @freeze_noirq: Complete the actions started by @freeze(). Carry out any + * additional operations required for freezing the device that might be + * racing with its driver's interrupt handler, which is guaranteed not to + * run while @freeze_noirq() is being executed. + * The power state of the device should not be changed by either @freeze() + * or @freeze_noirq() and it should not be configured to signal system + * wakeup by any of these callbacks. + * + * @thaw_noirq: Prepare for the execution of @thaw() by carrying out any + * operations required for thawing the device that might be racing with its + * driver's interrupt handler, which is guaranteed not to run while + * @thaw_noirq() is being executed. + * + * @poweroff_noirq: Complete the actions started by @poweroff(). Analogous to + * @suspend_noirq(), but it need not save the device's settings in memory. + * + * @restore_noirq: Prepare for the execution of @restore() by carrying out any + * operations required for thawing the device that might be racing with its + * driver's interrupt handler, which is guaranteed not to run while + * @restore_noirq() is being executed. Analogous to @resume_noirq(). * * All of the above callbacks, except for @complete(), return error codes. * However, the error codes returned by the resume operations, @resume(), - * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq() do + * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do * not cause the PM core to abort the resume transition during which they are - * returned. The error codes returned in that cases are only printed by the PM + * returned. The error codes returned in those cases are only printed by the PM * core to the system logs for debugging purposes. Still, it is recommended * that drivers only return error codes from their resume methods in case of an * unrecoverable failure (i.e. when the device being handled refuses to resume @@ -174,31 +201,43 @@ typedef struct pm_message { * their children. * * It is allowed to unregister devices while the above callbacks are being - * executed. However, it is not allowed to unregister a device from within any - * of its own callbacks. + * executed. However, a callback routine must NOT try to unregister the device + * it was called for, although it may unregister children of that device (for + * example, if it detects that a child was unplugged while the system was + * asleep). + * + * Refer to Documentation/power/devices.txt for more information about the role + * of the above callbacks in the system suspend process. * - * There also are the following callbacks related to run-time power management - * of devices: + * There also are callbacks related to runtime power management of devices. + * Again, these callbacks are executed by the PM core only for subsystems + * (PM domains, device types, classes and bus types) and the subsystem-level + * callbacks are supposed to invoke the driver callbacks. Moreover, the exact + * actions to be performed by a device driver's callbacks generally depend on + * the platform and subsystem the device belongs to. * * @runtime_suspend: Prepare the device for a condition in which it won't be * able to communicate with the CPU(s) and RAM due to power management. - * This need not mean that the device should be put into a low power state. + * This need not mean that the device should be put into a low-power state. * For example, if the device is behind a link which is about to be turned * off, the device may remain at full power. If the device does go to low - * power and is capable of generating run-time wake-up events, remote - * wake-up (i.e., a hardware mechanism allowing the device to request a - * change of its power state via a wake-up event, such as PCI PME) should - * be enabled for it. + * power and is capable of generating runtime wakeup events, remote wakeup + * (i.e., a hardware mechanism allowing the device to request a change of + * its power state via an interrupt) should be enabled for it. * * @runtime_resume: Put the device into the fully active state in response to a - * wake-up event generated by hardware or at the request of software. If - * necessary, put the device into the full power state and restore its + * wakeup event generated by hardware or at the request of software. If + * necessary, put the device into the full-power state and restore its * registers, so that it is fully operational. * - * @runtime_idle: Device appears to be inactive and it might be put into a low - * power state if all of the necessary conditions are satisfied. Check + * @runtime_idle: Device appears to be inactive and it might be put into a + * low-power state if all of the necessary conditions are satisfied. Check * these conditions and handle the device as appropriate, possibly queueing * a suspend request for it. The return value is ignored by the PM core. + * + * Refer to Documentation/power/runtime_pm.txt for more information about the + * role of the above callbacks in device runtime power management. + * */ struct dev_pm_ops { -- cgit From fc07ecd851bd082265b52838eff12f50b88f6114 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Nov 2011 21:16:56 +0000 Subject: ASoC: Error out if we can't generate a LRCLK at all for WM8994 Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9c982e47eb99..36ba1edfff80 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2357,6 +2357,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; lrclk = bclk_rate / params_rate(params); + if (!lrclk) { + dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n", + bclk_rate); + return -EINVAL; + } dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", lrclk, bclk_rate / lrclk); -- cgit From 5cac98dd06bc43a7baab3523184f70fd359e9f35 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 27 Nov 2011 21:14:46 +0000 Subject: net: Fix corruption in /proc/*/net/dev_mcast I just hit this during my testing. Isn't there another bug lurking? BUG kmalloc-8: Redzone overwritten INFO: 0xc0000000de9dec48-0xc0000000de9dec4b. First byte 0x0 instead of 0xcc INFO: Allocated in .__seq_open_private+0x30/0xa0 age=0 cpu=5 pid=3896 .__kmalloc+0x1e0/0x2d0 .__seq_open_private+0x30/0xa0 .seq_open_net+0x60/0xe0 .dev_mc_seq_open+0x4c/0x70 .proc_reg_open+0xd8/0x260 .__dentry_open.clone.11+0x2b8/0x400 .do_last+0xf4/0x950 .path_openat+0xf8/0x480 .do_filp_open+0x48/0xc0 .do_sys_open+0x140/0x250 syscall_exit+0x0/0x40 dev_mc_seq_ops uses dev_seq_start/next/stop but only allocates sizeof(struct seq_net_private) of private data, whereas it expects sizeof(struct dev_iter_state): struct dev_iter_state { struct seq_net_private p; unsigned int pos; /* bucket << BUCKET_SPACE + offset */ }; Create dev_seq_open_ops and use it so we don't have to expose struct dev_iter_state. [ Problem added by commit f04565ddf52e4 (dev: use name hash for dev_seq_ops) -Eric ] Signed-off-by: Anton Blanchard Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 6 ++++++ net/core/dev_addr_lists.c | 3 +-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cbeb5867cff7..a82ad4dd306a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2536,6 +2536,8 @@ extern void net_disable_timestamp(void); extern void *dev_seq_start(struct seq_file *seq, loff_t *pos); extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos); extern void dev_seq_stop(struct seq_file *seq, void *v); +extern int dev_seq_open_ops(struct inode *inode, struct file *file, + const struct seq_operations *ops); #endif extern int netdev_class_create_file(struct class_attribute *class_attr); diff --git a/net/core/dev.c b/net/core/dev.c index 6ba50a1e404c..1482eea0bbf0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4282,6 +4282,12 @@ static int dev_seq_open(struct inode *inode, struct file *file) sizeof(struct dev_iter_state)); } +int dev_seq_open_ops(struct inode *inode, struct file *file, + const struct seq_operations *ops) +{ + return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state)); +} + static const struct file_operations dev_seq_fops = { .owner = THIS_MODULE, .open = dev_seq_open, diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 277faef9148d..febba516db62 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -696,8 +696,7 @@ static const struct seq_operations dev_mc_seq_ops = { static int dev_mc_seq_open(struct inode *inode, struct file *file) { - return seq_open_net(inode, file, &dev_mc_seq_ops, - sizeof(struct seq_net_private)); + return dev_seq_open_ops(inode, file, &dev_mc_seq_ops); } static const struct file_operations dev_mc_seq_fops = { -- cgit From 2a38e6d5aed24bb7f0211e0819fac8c32c2b5791 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Sun, 27 Nov 2011 21:33:34 +0000 Subject: ipv6: Set mcast_hops to IPV6_DEFAULT_MCASTHOPS when -1 was given. We need to set np->mcast_hops to it's default value at this moment otherwise when we use it and found it's value is -1, the logic to get default hop limit doesn't take multicast into account and will return wrong hop limit(IPV6_DEFAULT_HOPLIMIT) which is for unicast. Signed-off-by: Li Wei Signed-off-by: David S. Miller --- net/ipv6/ipv6_sockglue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c99e3ee9781f..26cb08c84b74 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -503,7 +503,7 @@ done: goto e_inval; if (val > 255 || val < -1) goto e_inval; - np->mcast_hops = val; + np->mcast_hops = (val == -1 ? IPV6_DEFAULT_MCASTHOPS : val); retv = 0; break; -- cgit From fc8e6e8668e74fbf8e00d6e143d7f43b20f73f32 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 28 Nov 2011 18:48:46 +0000 Subject: ASoC: Supply dcs_codes for newer WM1811 revisions Based on initial data. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 36ba1edfff80..6c2988549003 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3183,6 +3183,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (wm8994->revision) { case 0: case 1: + case 2: + case 3: wm8994->hubs.dcs_codes_l = -9; wm8994->hubs.dcs_codes_r = -5; break; -- cgit From eee628da2ee3cbba6f14696278c92a464239eea6 Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Mon, 28 Nov 2011 23:49:33 +0100 Subject: efivars: add missing parameter to efi_pstore_read() In the case where CONFIG_PSTORE=n, the function efi_pstore_read() doesn't have the correct list of parameters. This patch provides a definition of efi_pstore_read() with 'char **buf' added to fix this warning: "drivers/firmware/efivars.c:609: warning: initialization from". problem introduced in commit f6f8285132907757ef84ef8dae0a1244b8cde6ac Signed-off-by: Christoph Fritz Signed-off-by: Tony Luck --- drivers/firmware/efivars.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index a54a6b972ced..b0a81173a268 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -581,7 +581,8 @@ static int efi_pstore_close(struct pstore_info *psi) } static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, - struct timespec *time, struct pstore_info *psi) + struct timespec *timespec, + char **buf, struct pstore_info *psi) { return -1; } -- cgit From e3420901eba65b1c46bed86d360e3a8685d20734 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Mon, 28 Nov 2011 11:30:22 +0100 Subject: EHCI : Fix a regression in the ISO scheduler Fix a regression that was introduced by commit 811c926c538f7e8d3c08b630dd5844efd7e000f6 (USB: EHCI: fix HUB TT scheduling issue with iso transfer). We detect an error if next == start, but this means uframe 0 can't be allocated anymore for iso transfer... Reported-by: Sander Eikelenboom Signed-off-by: Matthieu CASTET Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 56a32033adb3..a60679cbbf85 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1475,6 +1475,7 @@ iso_stream_schedule ( * jump until after the queue is primed. */ else { + int done = 0; start = SCHEDULE_SLOP + (now & ~0x07); /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ @@ -1492,18 +1493,18 @@ iso_stream_schedule ( if (stream->highspeed) { if (itd_slot_ok(ehci, mod, start, stream->usecs, period)) - break; + done = 1; } else { if ((start % 8) >= 6) continue; if (sitd_slot_ok(ehci, mod, stream, start, sched, period)) - break; + done = 1; } - } while (start > next); + } while (start > next && !done); /* no room in the schedule */ - if (start == next) { + if (!done) { ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", urb, now, now + mod); status = -ENOSPC; -- cgit From 118205d6b6752e22e19b771771174e6426582311 Mon Sep 17 00:00:00 2001 From: Klaus Schwarzkopf Date: Mon, 28 Nov 2011 13:03:25 +0100 Subject: USB: linux-cdc-acm.inf: add support for the acm_ms gadget Support for the acm_ms usb gadget on windows. Signed-off-by: Klaus Schwarzkopf Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/linux-cdc-acm.inf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf index 37a02ce54841..f0ffc27d4c0a 100644 --- a/Documentation/usb/linux-cdc-acm.inf +++ b/Documentation/usb/linux-cdc-acm.inf @@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys [SourceDisksFiles] [SourceDisksNames] [DeviceList] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00 [DeviceList.NTamd64] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00 ;------------------------------------------------------------------------------ -- cgit From fa8b18edd752a8b4e9d1ee2cd615b82c93cf8bba Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 20 Nov 2011 15:35:32 +0000 Subject: xfs: validate acl count This prevents in-memory corruption and possible panics if the on-disk ACL is badly corrupted. Signed-off-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_acl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index b6c4b3795c4a..76e4266d2e7e 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -42,6 +42,8 @@ xfs_acl_from_disk(struct xfs_acl *aclp) int count, i; count = be32_to_cpu(aclp->acl_cnt); + if (count > XFS_ACL_MAX_ENTRIES) + return ERR_PTR(-EFSCORRUPTED); acl = posix_acl_alloc(count, GFP_KERNEL); if (!acl) -- cgit -- cgit From ae7cc709f2ec11b49fc31b20cd8c943794ae9576 Mon Sep 17 00:00:00 2001 From: John F Leach Date: Mon, 28 Nov 2011 19:41:27 -0500 Subject: ALSA: usb-audio - Support for Roland GAIA SH-01 Synthesizer Added table quirks entry for Roland GAIA SH-01 Synthesizer based upon Roland SH-201 table entry as template. USB MIDI and audio was tested with Muse and Audacity. Signed-off-by: John F Leach Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index b61945f3af9e..32d2a21f2e3b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1632,6 +1632,37 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + /* Roland GAIA SH-01 */ + USB_DEVICE(0x0582, 0x0111), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Roland", + .product_name = "GAIA", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &(const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0003, + .in_cables = 0x0003 + } + }, + { + .ifnum = -1 + } + } + } +}, { USB_DEVICE(0x0582, 0x0113), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { -- cgit From 786228ab3095fe18dba3bc0d62055a123991d9d9 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 23 Nov 2011 20:56:45 +0800 Subject: writeback: Fix issue on make htmldocs Document the @reason parameter to make "make htmldocs" happy. Acked-by: Randy Dunlap Signed-off-by: Marcos Paulo de Souza Signed-off-by: Wu Fengguang --- fs/fs-writeback.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 73c3992b2bb4..ac86f8b3e3cb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -156,6 +156,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, * bdi_start_writeback - start writeback * @bdi: the backing device to write from * @nr_pages: the number of pages to write + * @reason: reason why some writeback work was initiated * * Description: * This does WB_SYNC_NONE opportunistic writeback. The IO is only @@ -1223,6 +1224,7 @@ static void wait_sb_inodes(struct super_block *sb) * writeback_inodes_sb_nr - writeback dirty inodes from given super_block * @sb: the superblock * @nr: the number of pages to write + * @reason: reason why some writeback work initiated * * Start writeback on some inodes on this super_block. No guarantees are made * on how many (if any) will be written, and this function does not wait @@ -1251,6 +1253,7 @@ EXPORT_SYMBOL(writeback_inodes_sb_nr); /** * writeback_inodes_sb - writeback dirty inodes from given super_block * @sb: the superblock + * @reason: reason why some writeback work was initiated * * Start writeback on some inodes on this super_block. No guarantees are made * on how many (if any) will be written, and this function does not wait @@ -1265,6 +1268,7 @@ EXPORT_SYMBOL(writeback_inodes_sb); /** * writeback_inodes_sb_if_idle - start writeback if none underway * @sb: the superblock + * @reason: reason why some writeback work was initiated * * Invoke writeback_inodes_sb if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. @@ -1285,6 +1289,7 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle); * writeback_inodes_sb_if_idle - start writeback if none underway * @sb: the superblock * @nr: the number of pages to write + * @reason: reason why some writeback work was initiated * * Invoke writeback_inodes_sb if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. -- cgit From 58aa4ebe9c718f77f2003a9f815e070bdb4bff5e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 20:44:13 +0100 Subject: ARM: u300: update defconfig This updates the U300 defconfig to support some new drivers like FSMC, sets it to use the MMC clock gating scheme, and removes some stale config options. Signed-off-by: Linus Walleij --- arch/arm/configs/u300_defconfig | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig index 4a5a12681be2..374000ec4e4e 100644 --- a/arch/arm/configs/u300_defconfig +++ b/arch/arm/configs/u300_defconfig @@ -14,8 +14,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_U300=y CONFIG_MACH_U300=y CONFIG_MACH_U300_BS335=y -CONFIG_MACH_U300_DUAL_RAM=y -CONFIG_U300_DEBUG=y CONFIG_MACH_U300_SPIDUMMY=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -26,19 +24,21 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072" CONFIG_CPU_IDLE=y CONFIG_FPE_NWFPE=y -CONFIG_PM=y # CONFIG_SUSPEND is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_FSMC=y # CONFIG_INPUT_MOUSEDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_KEYBOARD_ATKBD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_SERIO is not set +CONFIG_LEGACY_PTY_COUNT=16 CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_HWMON is not set @@ -51,6 +51,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y +CONFIG_MMC_CLKGATE=y CONFIG_MMC_ARMMMCI=y CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set @@ -65,10 +66,8 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set CONFIG_TIMER_STATS=y # CONFIG_DEBUG_PREEMPT is not set CONFIG_DEBUG_INFO=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_CRC32 is not set -- cgit From 6e2a587eb99267367409097b70cb2d61b09e5269 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Nov 2011 20:30:35 +0100 Subject: ARM: ux500: update defconfig This updates the Ux500 defconfig with the new drivers for HWSEM and AB5500 core that were merged in the 3.2 cycle. Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 97d31a4663da..2d7b6e7b7271 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -10,7 +10,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB5500=y CONFIG_UX500_SOC_DB8500=y -CONFIG_MACH_U8500=y +CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y CONFIG_MACH_U5500=y CONFIG_NO_HZ=y @@ -24,6 +24,7 @@ CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_VFP=y CONFIG_NEON=y +CONFIG_PM_RUNTIME=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -41,11 +42,8 @@ CONFIG_MISC_DEVICES=y CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_NETDEVICES=y -CONFIG_SMSC_PHY=y -CONFIG_NET_ETHERNET=y CONFIG_SMSC911X=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set +CONFIG_SMSC_PHY=y # CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y @@ -72,15 +70,12 @@ CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y -# CONFIG_HWMON is not set CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y +CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR_AB8500=y # CONFIG_HID_SUPPORT is not set -CONFIG_USB_MUSB_HDRC=y -CONFIG_USB_GADGET_MUSB_HDRC=y -CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_GADGET=y CONFIG_AB8500_USB=y CONFIG_MMC=y @@ -97,6 +92,7 @@ CONFIG_DMADEVICES=y CONFIG_STE_DMA40=y CONFIG_STAGING=y CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y +CONFIG_HSEM_U8500=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y -- cgit From 4f718a29fe4908c2cea782f751e9805319684e2b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:14 +0100 Subject: firmware: Sigma: Prevent out of bounds memory access The SigmaDSP firmware loader currently does not perform enough boundary size checks when processing the firmware. As a result it is possible that a malformed firmware can cause an out of bounds memory access. This patch adds checks which ensure that both the action header and the payload are completely inside the firmware data boundaries before processing them. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 76 +++++++++++++++++++++++++++++++++++------------- include/linux/sigma.h | 5 ---- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index f10fc521951b..c780baa59ed9 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -14,13 +14,34 @@ #include #include -/* Return: 0==OK, <0==error, =1 ==no more actions */ +static size_t sigma_action_size(struct sigma_action *sa) +{ + size_t payload = 0; + + switch (sa->instr) { + case SIGMA_ACTION_WRITEXBYTES: + case SIGMA_ACTION_WRITESINGLE: + case SIGMA_ACTION_WRITESAFELOAD: + payload = sigma_action_len(sa); + break; + default: + break; + } + + payload = ALIGN(payload, 2); + + return payload + sizeof(struct sigma_action); +} + +/* + * Returns a negative error value in case of an error, 0 if processing of + * the firmware should be stopped after this action, 1 otherwise. + */ static int -process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) +process_sigma_action(struct i2c_client *client, struct sigma_action *sa) { - struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); - int ret = 0; + int ret; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: - if (ssfw->fw->size < ssfw->pos + len) - return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; - case SIGMA_ACTION_DELAY: - ret = 0; udelay(len); len = 0; break; - case SIGMA_ACTION_END: - return 1; - + return 0; default: return -EINVAL; } - /* when arrive here ret=0 or sent data */ - ssfw->pos += sigma_action_size(sa, len); - return ssfw->pos == ssfw->fw->size; + return 1; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { - pr_debug("%s: processing %p\n", __func__, ssfw); + struct sigma_action *sa; + size_t size; + int ret; + + while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { + sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); + + size = sigma_action_size(sa); + ssfw->pos += size; + if (ssfw->pos > ssfw->fw->size || size == 0) + break; + + ret = process_sigma_action(client, sa); - while (1) { - int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); - if (ret == 1) - return 0; - else if (ret) + + if (ret <= 0) return ret; } + + if (ssfw->pos != ssfw->fw->size) + return -EINVAL; + + return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) @@ -89,7 +116,14 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; - if (fw->size < sizeof(*ssfw_head)) + + /* + * Reject too small or unreasonable large files. The upper limit has been + * chosen a bit arbitrarily, but it should be enough for all practical + * purposes and having the limit makes it easier to avoid integer + * overflows later in the loading process. + */ + if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) goto done; ssfw_head = (void *)fw->data; diff --git a/include/linux/sigma.h b/include/linux/sigma.h index e2accb3164d8..9a138c2946bb 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -50,11 +50,6 @@ static inline u32 sigma_action_len(struct sigma_action *sa) return (sa->len_hi << 16) | sa->len; } -static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) -{ - return sizeof(*sa) + payload_len + (payload_len % 2); -} - extern int process_sigma_firmware(struct i2c_client *client, const char *name); #endif -- cgit From c56935bdc0a8edf50237d3b0205133a5b0adc604 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:15 +0100 Subject: firmware: Sigma: Skip header during CRC generation The firmware header is not part of the CRC, so skip it. Otherwise the firmware will be rejected due to non-matching CRCs. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index c780baa59ed9..36265de0a9e8 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -130,7 +130,8 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; - crc = crc32(0, fw->data, fw->size); + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) goto done; -- cgit From bda63586bc5929e97288cdb371bb6456504867ed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:16 +0100 Subject: firmware: Sigma: Fix endianess issues Currently the SigmaDSP firmware loader only works correctly on little-endian systems. Fix this by using the proper endianess conversion functions. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Cc: stable@kernel.org --- drivers/firmware/sigma.c | 2 +- include/linux/sigma.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index 36265de0a9e8..1eedb6f7fdab 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -133,7 +133,7 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); - if (crc != ssfw_head->crc) + if (crc != le32_to_cpu(ssfw_head->crc)) goto done; ssfw.pos = sizeof(*ssfw_head); diff --git a/include/linux/sigma.h b/include/linux/sigma.h index 9a138c2946bb..d0de882c0d96 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; - u32 crc; + __le32 crc; }; enum { @@ -40,14 +40,14 @@ enum { struct sigma_action { u8 instr; u8 len_hi; - u16 len; - u16 addr; + __le16 len; + __be16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { - return (sa->len_hi << 16) | sa->len; + return (sa->len_hi << 16) | le16_to_cpu(sa->len); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); -- cgit From 542c9a0a2fa351149c4a3467589a54cafcf0a1dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 29 Nov 2011 13:01:30 +0100 Subject: ALSA: hda - Avoid touching mute-VREF pin for IDT codecs Some HP laptops use a pin VREF for controlling the mute LED, and such a pin shouldn't be powered off. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548e..f4f4ebeed9ea 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4441,7 +4441,9 @@ static int stac92xx_init(struct hda_codec *codec) int pinctl, def_conf; /* power on when no jack detection is available */ - if (!spec->hp_detect) { + /* or when the VREF is used for controlling LED */ + if (!spec->hp_detect || + (spec->gpio_led > 8 && spec->gpio_led == nid)) { stac_toggle_power_map(codec, nid, 1); continue; } -- cgit From 4f8b6c7dc80ac9619db033c7f6fc355eab9514f5 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 29 Nov 2011 12:21:17 +0100 Subject: ALSA: hda_intel - revert a quirk that affect VIA chipsets This quirk sould be reverted. It has the following probems: 1) The quirk was intended to "ASUS MV2-MX SE" motherboards only, but the ID used matches a much broader range, potentially all boards containing a VIA chipset model in the family of vendor VIA 0x1106 and audio device ID 0x3288, which encompasses VIA-VT82xx, VIA-VT1xx and VIA-VT20xx chipsets. 2) VIA chipsets rely on azx_via_get_position() to handle correctly dma transfers during capture. Using POS_FIX_LPIB instead of POS_FIX_VIACOMBO leads to partially corrupted input buffers during capture. The effects of this bug are not immediately visible, it took strong DSP expertise, some expensive signal generator and a spectrum analyzer to identify it and verify correct behaviour using original default. 3) It's almost certain that the quirk did not fix the real problem, if there was one. Refer to original submission: http://mailman.alsa-project.org/pipermail/alsa-devel/2010-February/025109.html Signed-of-by: Marc Vertes Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9a..7d98240def0b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2508,7 +2508,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), -- cgit From 5d193ce8f1fa7c67c7fd7be2c03ef31eed344a4f Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 22 Nov 2011 17:18:24 -0800 Subject: usb: musb: PM: fix context save/restore in suspend/resume path Currently the driver tries to save context in the suspend path, but will cause an abort if the device is already runtime suspended. This happens, for example, if MUSB loaded/compiled-in, in host mode, but no USB devices are attached. MUSB will be runtime suspended, but then attempting a system suspend will crash due to the context save being attempted while the device is disabled. On OMAP, as of v3.1, the driver's ->runtime_suspend() callback will be called late in the suspend path (by the PM domain layer) if the driver is not already runtime suspended, ensuring a full shutdown. Therefore, the context save is not needed in the ->suspend() method since it will be called in the ->runtime_suspend() method anyways (similarily for resume.) NOTE: this leaves the suspend/resume methods basically empty (with some FIXMEs and comments, but I'll leave it to the maintainers to decide whether to remove them. Cc: stable@vger.kernel.org Signed-off-by: Kevin Hilman Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c1fa12ec7a9a..b63ab1570103 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2301,18 +2301,12 @@ static int musb_suspend(struct device *dev) */ } - musb_save_context(musb); - spin_unlock_irqrestore(&musb->lock, flags); return 0; } static int musb_resume_noirq(struct device *dev) { - struct musb *musb = dev_to_musb(dev); - - musb_restore_context(musb); - /* for static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down or the USB * module got reset through the PSC (vs just being disabled). -- cgit From f8eff0a06116aee127152674e9ea9c51aecf6b69 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 17 Nov 2011 18:19:06 -0800 Subject: usb: renesas_usbhs: fixup device_register timing current renesas_usbhs is using new style udc_start/stop from af1d7056a5c1e5eaaf807ddd1423101db84668d0 (usb: gadget: renesas: convert to new style). But bind() function will fail if it was called before device_register() (or device_add()). This patch modifies this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 37 ++++++++++------------------------ 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index d9717e0bc1ff..ef82274ce70b 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -751,53 +751,31 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); - struct usbhs_priv *priv; - struct device *dev; - int ret; + struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); if (!driver || !driver->setup || driver->speed != USB_SPEED_HIGH) return -EINVAL; - dev = usbhsg_gpriv_to_dev(gpriv); - priv = usbhsg_gpriv_to_priv(gpriv); - /* first hook up the driver ... */ gpriv->driver = driver; gpriv->gadget.dev.driver = &driver->driver; - ret = device_add(&gpriv->gadget.dev); - if (ret) { - dev_err(dev, "device_add error %d\n", ret); - goto add_fail; - } - return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); - -add_fail: - gpriv->driver = NULL; - gpriv->gadget.dev.driver = NULL; - - return ret; } static int usbhsg_gadget_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); - struct usbhs_priv *priv; - struct device *dev; + struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); if (!driver || !driver->unbind) return -EINVAL; - dev = usbhsg_gpriv_to_dev(gpriv); - priv = usbhsg_gpriv_to_priv(gpriv); - usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); - device_del(&gpriv->gadget.dev); gpriv->driver = NULL; return 0; @@ -876,12 +854,14 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) /* * init gadget */ - device_initialize(&gpriv->gadget.dev); dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.is_dualspeed = 1; + ret = device_register(&gpriv->gadget.dev); + if (ret < 0) + goto err_add_udc; INIT_LIST_HEAD(&gpriv->gadget.ep_list); @@ -912,12 +892,15 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) ret = usb_add_gadget_udc(dev, &gpriv->gadget); if (ret) - goto err_add_udc; + goto err_register; dev_info(dev, "gadget probed\n"); return 0; + +err_register: + device_unregister(&gpriv->gadget.dev); err_add_udc: kfree(gpriv->uep); @@ -933,6 +916,8 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv) usb_del_gadget_udc(&gpriv->gadget); + device_unregister(&gpriv->gadget.dev); + usbhsg_controller_unregister(gpriv); kfree(gpriv->uep); -- cgit From 8885a897c26b2f63e1bbb6fa7bd9da3a73a09113 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 17 Nov 2011 18:19:38 -0800 Subject: usb: renesas_usbhs: fixup signal the driver that cable was disconnected current renesas_usbhs is using new style udc_start/stop from af1d7056a5c1e5eaaf807ddd1423101db84668d0 (usb: gadget: renesas: convert to new style). cable disconnected signal was needed. This patch fixup it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index ef82274ce70b..f4b032ed326a 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -805,6 +805,13 @@ static int usbhsg_start(struct usbhs_priv *priv) static int usbhsg_stop(struct usbhs_priv *priv) { + struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); + + /* cable disconnect */ + if (gpriv->driver && + gpriv->driver->disconnect) + gpriv->driver->disconnect(&gpriv->gadget); + return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); } -- cgit From 0cdd7d4b66aa740ce62aeeaf7fbd495130c2864f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 17 Nov 2011 18:19:56 -0800 Subject: usb: renesas_usbhs: fixup gadget.dev.driver when udc_stop. current renesas_usbhs is using new style udc_start/stop from af1d7056a5c1e5eaaf807ddd1423101db84668d0 (usb: gadget: renesas: convert to new style). But current renesas_usbhs driver didn't care about gadget.dev.driver when udc_stop. it cause rmmod oops. This patch care it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index f4b032ed326a..2be73817e47f 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -776,6 +776,7 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget, return -EINVAL; usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); + gpriv->gadget.dev.driver = NULL; gpriv->driver = NULL; return 0; -- cgit From 89f829a50f7d0d0f3a15c482a7a65dd0b133a5f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 17 Nov 2011 18:20:44 -0800 Subject: usb: renesas_usbhs: fixup driver speed This patch cares latest USB_SPEED_SUPER support. renesas_usbhs can not use super-speed, but can use full/high speed. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 2be73817e47f..7f4e80338570 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -755,7 +755,7 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, if (!driver || !driver->setup || - driver->speed != USB_SPEED_HIGH) + driver->speed < USB_SPEED_FULL) return -EINVAL; /* first hook up the driver ... */ -- cgit From fef6964452abae55c82e1615ac505b8377df00e9 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 18 Nov 2011 20:16:27 +0100 Subject: usb: gadget: fix g_serial regression Commit "usb: gadget: use config_ep_by_speed() instead of ep_choose()" broke g_serial in "non ACM nor OBEX" mode. Apply a trivial fix on usb endpoints discovery. Signed-off-by: Robert Jarzmik Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 91fdf790ed20..cf33a8d0fd5d 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -131,8 +131,8 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } if (!gser->port.in->desc || !gser->port.out->desc) { DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); - if (!config_ep_by_speed(cdev->gadget, f, gser->port.in) || - !config_ep_by_speed(cdev->gadget, f, gser->port.out)) { + if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || + config_ep_by_speed(cdev->gadget, f, gser->port.out)) { gser->port.in->desc = NULL; gser->port.out->desc = NULL; return -EINVAL; -- cgit From bfe0658b402dab3d6fbef4b7bd81a46d0e68eb86 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sat, 19 Nov 2011 18:26:25 +0100 Subject: usb: udc: Fix gadget driver's speed check in various UDC drivers Several UDC drivers had a gadget driver's speed sanity check of the form of: driver->speed != USB_SPEED_HIGH or: driver->speed != USB_SPEED_HIGH && driver->speed != USB_SPEED_FULL As more and more gadget drivers support USB SuperSpeed, driver->speed may be set to USB_SPEED_SUPER and UDC driver should handle such gadget correctly. The above checks however fail to recognise USB_SPEED_SUPER as a valid speed. This commit changes the two checks to: driver->speed < USB_SPEED_HIGH or: driver->speed < USB_SPEED_FULL respectively. Signed-off-by: Michal Nazarewicz Reported-by: Alan Stern Tested-by: Heiko Stuebner Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/fsl_qe_udc.c | 3 +-- drivers/usb/gadget/fsl_udc_core.c | 3 +-- drivers/usb/gadget/m66592-udc.c | 2 +- drivers/usb/gadget/net2280.c | 2 +- drivers/usb/gadget/r8a66597-udc.c | 2 +- drivers/usb/gadget/s3c-hsotg.c | 4 +--- drivers/usb/gadget/s3c-hsudc.c | 3 +-- drivers/usb/musb/musb_gadget.c | 2 +- 9 files changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 4730016d7cd4..45f422ac103f 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1959,7 +1959,7 @@ static int amd5536_start(struct usb_gadget_driver *driver, u32 tmp; if (!driver || !bind || !driver->setup - || driver->speed != USB_SPEED_HIGH) + || driver->speed < USB_SPEED_HIGH) return -EINVAL; if (!dev) return -ENODEV; diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 2a03e4de11c1..e00cf92409ce 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2336,8 +2336,7 @@ static int fsl_qe_start(struct usb_gadget_driver *driver, if (!udc_controller) return -ENODEV; - if (!driver || (driver->speed != USB_SPEED_FULL - && driver->speed != USB_SPEED_HIGH) + if (!driver || driver->speed < USB_SPEED_FULL || !bind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b3b3d83b7c33..1482b12db81d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1938,8 +1938,7 @@ static int fsl_start(struct usb_gadget_driver *driver, if (!udc_controller) return -ENODEV; - if (!driver || (driver->speed != USB_SPEED_FULL - && driver->speed != USB_SPEED_HIGH) + if (!driver || driver->speed < USB_SPEED_FULL || !bind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 91d0af2a24a8..9aa1cbbee45b 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1472,7 +1472,7 @@ static int m66592_start(struct usb_gadget_driver *driver, int retval; if (!driver - || driver->speed != USB_SPEED_HIGH + || driver->speed < USB_SPEED_HIGH || !bind || !driver->setup) return -EINVAL; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 7f1bc9a73cda..da2b9d0be3ca 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1881,7 +1881,7 @@ static int net2280_start(struct usb_gadget *_gadget, * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE) * "must not be used in normal operation" */ - if (!driver || driver->speed != USB_SPEED_HIGH + if (!driver || driver->speed < USB_SPEED_HIGH || !driver->setup) return -EINVAL; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 24f84b210ce1..fc719a3f8557 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1746,7 +1746,7 @@ static int r8a66597_start(struct usb_gadget *gadget, struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); if (!driver - || driver->speed != USB_SPEED_HIGH + || driver->speed < USB_SPEED_HIGH || !driver->setup) return -EINVAL; if (!r8a66597) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index a552453dc946..b31448229f0b 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2586,10 +2586,8 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, return -EINVAL; } - if (driver->speed != USB_SPEED_HIGH && - driver->speed != USB_SPEED_FULL) { + if (driver->speed < USB_SPEED_FULL) dev_err(hsotg->dev, "%s: bad speed\n", __func__); - } if (!bind || !driver->setup) { dev_err(hsotg->dev, "%s: missing entry points\n", __func__); diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 8d54f893cefe..20a553b46aed 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1142,8 +1142,7 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, int ret; if (!driver - || (driver->speed != USB_SPEED_FULL && - driver->speed != USB_SPEED_HIGH) + || driver->speed < USB_SPEED_FULL || !bind || !driver->unbind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d51043acfe1a..922148ff8d29 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1903,7 +1903,7 @@ static int musb_gadget_start(struct usb_gadget *g, unsigned long flags; int retval = -EINVAL; - if (driver->speed != USB_SPEED_HIGH) + if (driver->speed < USB_SPEED_HIGH) goto err0; pm_runtime_get_sync(musb->controller); -- cgit From 7c91d908f5af027ed14b3d103331f91f386c1043 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 22 Nov 2011 09:55:45 +0800 Subject: USB: fsl_udc_core: use usb_endpoint_xfer_isoc to judge ISO XFER Some ISO gadgets, like audio, has SYNC attribute as well as USB_ENDPOINT_XFER_ISOC for their bmAttributes at ISO endpoint descriptor. So, it needs to use usb_endpoint_xfer_isoc to judge ISO XFER. Signed-off-by: Peter Chen Acked-by: Michal Nazarewicz Acked-by: Li Yang Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 1482b12db81d..bf1cd6e55ed9 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -877,7 +877,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) VDBG("%s, bad ep", __func__); return -EINVAL; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (usb_endpoint_xfer_isoc(ep->desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -1032,7 +1032,7 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value) goto out; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (usb_endpoint_xfer_isoc(ep->desc)) { status = -EOPNOTSUPP; goto out; } -- cgit From 65cd5c4d03563f7118c2e83b7a50928e461cbc1e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 22 Nov 2011 13:48:28 -0200 Subject: usb: fsl_mxc_udc.c: Fix build issue by including missing header file Fix the following build error: CC [M] drivers/usb/gadget/fsl_mxc_udc.o drivers/usb/gadget/fsl_mxc_udc.c: In function 'fsl_udc_clk_finalize': drivers/usb/gadget/fsl_mxc_udc.c:98: error: implicit declaration of function 'readl' drivers/usb/gadget/fsl_mxc_udc.c:100: error: implicit declaration of function 'writel' This error is caused by the follwing commit: (16fcb63: arm/imx: remove mx31_setup_weimcs( ) from mx31.h) ,which removed '#include ' from mx31.h. fsl_mxc_udc.c includes , which in turns includes mx31.h, so that's the reason fsl_mxc_udc.c built fine previously. Instead of relying on the indirect inclusion of the linux/io.h header file, include it directly in fsl_mxc_udc.c. Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_mxc_udc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 43a49ecc1f36..23eaecfa3ed3 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include -- cgit From 5ce1d0eb1cd1071347618d0a95515f300239d201 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 22 Nov 2011 13:48:29 -0200 Subject: usb: fsl_mxc_udc.c: Remove compile-time dependency of MX35 SoC type In order to support multiple SoC kernel image, compile-time dependency on a specific SoC type should be avoided. fsl_udc_clk_finalize is already protected by cpu_is_mx35(), so remove the compile-time check for CONFIG_SOC_IMX35. Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_mxc_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 23eaecfa3ed3..dcbc0a2e48dd 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -89,7 +89,6 @@ eenahb: void fsl_udc_clk_finalize(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -#if defined(CONFIG_SOC_IMX35) if (cpu_is_mx35()) { unsigned int v; @@ -102,7 +101,6 @@ void fsl_udc_clk_finalize(struct platform_device *pdev) USBPHYCTRL_OTGBASE_OFFSET)); } } -#endif /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { -- cgit From 6414e94c203d92b163ca61b5f51a25b80a621dbe Mon Sep 17 00:00:00 2001 From: Li Yang Date: Wed, 23 Nov 2011 20:12:56 +0800 Subject: usb: gadget: fsl_udc: fix dequeuing a request in progress The original implementation of dequeuing a request in progress is not correct. Change to use a correct process and also clean up the related functions a little bit. Signed-off-by: Li Yang Acked-by: Peter Chen Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_udc_core.c | 68 ++++++++++++++++++--------------------- drivers/usb/gadget/fsl_usb2_udc.h | 10 ++++++ 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index bf1cd6e55ed9..dd28ef3def71 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -696,12 +696,31 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req) kfree(req); } -/*-------------------------------------------------------------------------*/ +/* Actually add a dTD chain to an empty dQH and let go */ +static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td) +{ + struct ep_queue_head *qh = get_qh_by_ep(ep); + + /* Write dQH next pointer and terminate bit to 0 */ + qh->next_dtd_ptr = cpu_to_hc32(td->td_dma + & EP_QUEUE_HEAD_NEXT_POINTER_MASK); + + /* Clear active and halt bit */ + qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE + | EP_QUEUE_HEAD_STATUS_HALT)); + + /* Ensure that updates to the QH will occur before priming. */ + wmb(); + + /* Prime endpoint by writing correct bit to ENDPTPRIME */ + fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16)) + : (1 << (ep_index(ep))), &dr_regs->endpointprime); +} + +/* Add dTD chain to the dQH of an EP */ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) { - int i = ep_index(ep) * 2 + ep_is_in(ep); u32 temp, bitmask, tmp_stat; - struct ep_queue_head *dQH = &ep->udc->ep_qh[i]; /* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr); VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */ @@ -719,7 +738,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) - goto out; + return; do { /* Set ATDTW bit in USBCMD */ @@ -736,28 +755,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd); if (tmp_stat) - goto out; + return; } - /* Write dQH next pointer and terminate bit to 0 */ - temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; - dQH->next_dtd_ptr = cpu_to_hc32(temp); - - /* Clear active and halt bit */ - temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE - | EP_QUEUE_HEAD_STATUS_HALT)); - dQH->size_ioc_int_sts &= temp; - - /* Ensure that updates to the QH will occur before priming. */ - wmb(); - - /* Prime endpoint by writing 1 to ENDPTPRIME */ - temp = ep_is_in(ep) - ? (1 << (ep_index(ep) + 16)) - : (1 << (ep_index(ep))); - fsl_writel(temp, &dr_regs->endpointprime); -out: - return; + fsl_prime_ep(ep, req->head); } /* Fill in the dTD structure @@ -973,25 +974,20 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) /* The request isn't the last request in this ep queue */ if (req->queue.next != &ep->queue) { - struct ep_queue_head *qh; struct fsl_req *next_req; - qh = ep->qh; next_req = list_entry(req->queue.next, struct fsl_req, queue); - /* Point the QH to the first TD of next request */ - fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr); + /* prime with dTD of next request */ + fsl_prime_ep(ep, next_req->head); } - - /* The request hasn't been processed, patch up the TD chain */ + /* The request hasn't been processed, patch up the TD chain */ } else { struct fsl_req *prev_req; prev_req = list_entry(req->queue.prev, struct fsl_req, queue); - fsl_writel(fsl_readl(&req->tail->next_td_ptr), - &prev_req->tail->next_td_ptr); - + prev_req->tail->next_td_ptr = req->tail->next_td_ptr; } done(ep, req, -ECONNRESET); @@ -1068,7 +1064,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) struct fsl_udc *udc; int size = 0; u32 bitmask; - struct ep_queue_head *d_qh; + struct ep_queue_head *qh; ep = container_of(_ep, struct fsl_ep, ep); if (!_ep || (!ep->desc && ep_index(ep) != 0)) @@ -1079,13 +1075,13 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; + qh = get_qh_by_ep(ep); bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) : (1 << (ep_index(ep))); if (fsl_readl(&dr_regs->endptstatus) & bitmask) - size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) + size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS; pr_debug("%s %u\n", __func__, size); diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 1d51be83fda8..f781f5dec417 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -569,6 +569,16 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) * 2 + ((windex & USB_DIR_IN) ? 1 : 0)) #define get_pipe_by_ep(EP) (ep_index(EP) * 2 + ep_is_in(EP)) +static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) +{ + /* we only have one ep0 structure but two queue heads */ + if (ep_index(ep) != 0) + return ep->qh; + else + return &ep->udc->ep_qh[(ep->udc->ep0_dir == + USB_DIR_IN) ? 1 : 0]; +} + struct platform_device; #ifdef CONFIG_ARCH_MXC int fsl_udc_clk_init(struct platform_device *pdev); -- cgit From d7fb6d0adb86ed1c5290e754092a5a1e3de76ee9 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sun, 27 Nov 2011 20:16:33 -0600 Subject: of/irq: of_irq_init: add check for parent equal to child node With the revert of "of/irq: of_irq_find_parent: check for parent equal to child" (dc9372808412edb), we need another way to handle parent node equal to the child node. This can simply be handled in of_irq_init by checking for this condition. Signed-off-by: Rob Herring Tested-by: Pawel Moll Tested-by: Stephen Warren --- drivers/of/irq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 791270b8bd1c..19c0115092dd 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -424,6 +424,8 @@ void __init of_irq_init(const struct of_device_id *matches) desc->dev = np; desc->interrupt_parent = of_irq_find_parent(np); + if (desc->interrupt_parent == np) + desc->interrupt_parent = NULL; list_add_tail(&desc->list, &intc_desc_list); } -- cgit From e43fce14088d9910b545c30c9a7127deb289d477 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 8 Nov 2011 11:35:20 +0000 Subject: of: Add Silicon Image vendor prefix "sil" is the most commonly used abbreviation for Silicon Image products. Signed-off-by: Pawel Moll --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index e8552782b440..874921e97802 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -33,6 +33,7 @@ qcom Qualcomm, Inc. ramtron Ramtron International samsung Samsung Semiconductor schindler Schindler +sil Silicon Image simtek sirf SiRF Technology, Inc. stericsson ST-Ericsson -- cgit From 4dd2cb4a28b7ab1f37163a4eba280926a13a8749 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Nov 2011 12:06:14 -0600 Subject: xfs: force buffer writeback before blocking on the ilock in inode reclaim If we are doing synchronous inode reclaim we block the VM from making progress in memory reclaim. So if we encouter a flush locked inode promote it in the delwri list and wake up xfsbufd to write it out now. Without this we can get hangs of up to 30 seconds during workloads hitting synchronous inode reclaim. The scheme is copied from what we do for dquot reclaims. Reported-by: Simon Kirby Signed-off-by: Christoph Hellwig Tested-by: Simon Kirby Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 21 +++++++++++++++++++++ fs/xfs/xfs_inode.h | 1 + fs/xfs/xfs_sync.c | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c0237c602f11..755ee8164880 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2835,6 +2835,27 @@ corrupt_out: return XFS_ERROR(EFSCORRUPTED); } +void +xfs_promote_inode( + struct xfs_inode *ip) +{ + struct xfs_buf *bp; + + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); + + bp = xfs_incore(ip->i_mount->m_ddev_targp, ip->i_imap.im_blkno, + ip->i_imap.im_len, XBF_TRYLOCK); + if (!bp) + return; + + if (XFS_BUF_ISDELAYWRITE(bp)) { + xfs_buf_delwri_promote(bp); + wake_up_process(ip->i_mount->m_ddev_targp->bt_task); + } + + xfs_buf_relse(bp); +} + /* * Return a pointer to the extent record at file index idx. */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 760140d1dd66..b4cd4739f98e 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -498,6 +498,7 @@ int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); void xfs_iext_realloc(xfs_inode_t *, int, int); void xfs_iunpin_wait(xfs_inode_t *); int xfs_iflush(xfs_inode_t *, uint); +void xfs_promote_inode(struct xfs_inode *); void xfs_lock_inodes(xfs_inode_t **, int, uint); void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index aa3dc1a4d53d..be5c51d8f757 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -770,6 +770,17 @@ restart: if (!xfs_iflock_nowait(ip)) { if (!(sync_mode & SYNC_WAIT)) goto out; + + /* + * If we only have a single dirty inode in a cluster there is + * a fair chance that the AIL push may have pushed it into + * the buffer, but xfsbufd won't touch it until 30 seconds + * from now, and thus we will lock up here. + * + * Promote the inode buffer to the front of the delwri list + * and wake up xfsbufd now. + */ + xfs_promote_inode(ip); xfs_iflock(ip); } -- cgit From 4c393a6059f8442a70512a48ce4639b882b6f6ad Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 19 Nov 2011 17:44:30 +0000 Subject: xfs: fix attr2 vs large data fork assert With Dmitry fsstress updates I've seen very reproducible crashes in xfs_attr_shortform_remove because xfs_attr_shortform_bytesfit claims that the attributes would not fit inline into the inode after removing an attribute. It turns out that we were operating on an inode with lots of delalloc extents, and thus an if_bytes values for the data fork that is larger than biggest possible on-disk storage for it which utterly confuses the code near the end of xfs_attr_shortform_bytesfit. Fix this by always allowing the current attribute fork, like we already do for the attr1 format, given that delalloc conversion will take care for moving either the data or attribute area out of line if it doesn't fit at that point - or making the point moot by merging extents at this point. Also document the function better, and clean up some loose bits. Reviewed-by: Dave Chinner Signed-off-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_attr_leaf.c | 64 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index d4906e7c9787..c1b55e596551 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -110,6 +110,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags) /* * Query whether the requested number of additional bytes of extended * attribute space will be able to fit inline. + * * Returns zero if not, else the di_forkoff fork offset to be used in the * literal area for attribute data once the new bytes have been added. * @@ -122,7 +123,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) int offset; int minforkoff; /* lower limit on valid forkoff locations */ int maxforkoff; /* upper limit on valid forkoff locations */ - int dsize; + int dsize; xfs_mount_t *mp = dp->i_mount; offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ @@ -136,47 +137,60 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) return (offset >= minforkoff) ? minforkoff : 0; } - if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { - if (bytes <= XFS_IFORK_ASIZE(dp)) - return dp->i_d.di_forkoff; + /* + * If the requested numbers of bytes is smaller or equal to the + * current attribute fork size we can always proceed. + * + * Note that if_bytes in the data fork might actually be larger than + * the current data fork size is due to delalloc extents. In that + * case either the extent count will go down when they are converted + * to real extents, or the delalloc conversion will take care of the + * literal area rebalancing. + */ + if (bytes <= XFS_IFORK_ASIZE(dp)) + return dp->i_d.di_forkoff; + + /* + * For attr2 we can try to move the forkoff if there is space in the + * literal area, but for the old format we are done if there is no + * space in the fixed attribute fork. + */ + if (!(mp->m_flags & XFS_MOUNT_ATTR2)) return 0; - } dsize = dp->i_df.if_bytes; - + switch (dp->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: - /* + /* * If there is no attr fork and the data fork is extents, - * determine if creating the default attr fork will result - * in the extents form migrating to btree. If so, the - * minimum offset only needs to be the space required for + * determine if creating the default attr fork will result + * in the extents form migrating to btree. If so, the + * minimum offset only needs to be the space required for * the btree root. - */ + */ if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > xfs_default_attroffset(dp)) dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); break; - case XFS_DINODE_FMT_BTREE: /* - * If have data btree then keep forkoff if we have one, - * otherwise we are adding a new attr, so then we set - * minforkoff to where the btree root can finish so we have + * If we have a data btree then keep forkoff if we have one, + * otherwise we are adding a new attr, so then we set + * minforkoff to where the btree root can finish so we have * plenty of room for attrs */ if (dp->i_d.di_forkoff) { - if (offset < dp->i_d.di_forkoff) + if (offset < dp->i_d.di_forkoff) return 0; - else - return dp->i_d.di_forkoff; - } else - dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); + return dp->i_d.di_forkoff; + } + dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); break; } - - /* - * A data fork btree root must have space for at least + + /* + * A data fork btree root must have space for at least * MINDBTPTRS key/ptr pairs if the data fork is small or empty. */ minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); @@ -186,10 +200,10 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); maxforkoff = maxforkoff >> 3; /* rounded down */ - if (offset >= minforkoff && offset < maxforkoff) - return offset; if (offset >= maxforkoff) return maxforkoff; + if (offset >= minforkoff) + return offset; return 0; } -- cgit From c89304b8ea34ab48ba6ae10e06a8b1b8c8212307 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Tue, 29 Nov 2011 09:26:30 +0000 Subject: sctp: better integer overflow check in sctp_auth_create_key() The check from commit 30c2235c is incomplete and cannot prevent cases like key_len = 0x80000000 (INT_MAX + 1). In that case, the left-hand side of the check (INT_MAX - key_len), which is unsigned, becomes 0xffffffff (UINT_MAX) and bypasses the check. However this shouldn't be a security issue. The function is called from the following two code paths: 1) setsockopt() 2) sctp_auth_asoc_set_secret() In case (1), sca_keylength is never going to exceed 65535 since it's bounded by a u16 from the user API. As such, the key length will never overflow. In case (2), sca_keylength is computed based on the user key (1 short) and 2 * key_vector (3 shorts) for a total of 7 * USHRT_MAX, which still will not overflow. In other words, this overflow check is not really necessary. Just make it more correct. Signed-off-by: Xi Wang Cc: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 865e68fef21c..bf812048cf6f 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -82,7 +82,7 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp) struct sctp_auth_bytes *key; /* Verify that we are not going to overflow INT_MAX */ - if ((INT_MAX - key_len) < sizeof(struct sctp_auth_bytes)) + if (key_len > (INT_MAX - sizeof(struct sctp_auth_bytes))) return NULL; /* Allocate the shared key */ -- cgit From 3874397c0bdec3c21ce071711cd105165179b8eb Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Mon, 21 Nov 2011 08:43:54 -0500 Subject: IB/ipoib: Prevent hung task or softlockup processing multicast response This following can occur with ipoib when processing a multicast reponse: BUG: soft lockup - CPU#0 stuck for 67s! [ib_mad1:982] Modules linked in: ... CPU 0: Modules linked in: ... Pid: 982, comm: ib_mad1 Not tainted 2.6.32-131.0.15.el6.x86_64 #1 ProLiant DL160 G5 RIP: 0010:[] [] _spin_unlock_irqrestore+0x17/0x20 RSP: 0018:ffff8802119ed860 EFLAGS: 00000246 0000000000000004 RBX: ffff8802119ed860 RCX: 000000000000a299 RDX: ffff88021086c700 RSI: 0000000000000246 RDI: 0000000000000246 RBP: ffffffff8100bc8e R08: ffff880210ac229c R09: 0000000000000000 R10: ffff88021278aab8 R11: 0000000000000000 R12: ffff8802119ed860 R13: ffffffff8100be6e R14: 0000000000000001 R15: 0000000000000003 FS: 0000000000000000(0000) GS:ffff880028200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 00000000006d4840 CR3: 0000000209aa5000 CR4: 00000000000406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Call Trace: [] ? ipoib_mcast_send+0x157/0x480 [ib_ipoib] [] ? apic_timer_interrupt+0xe/0x20 [] ? apic_timer_interrupt+0xe/0x20 [] ? ipoib_path_lookup+0x124/0x2d0 [ib_ipoib] [] ? ipoib_start_xmit+0x17c/0x430 [ib_ipoib] [] ? dev_hard_start_xmit+0x2c8/0x3f0 [] ? sch_direct_xmit+0x15a/0x1c0 [] ? dev_queue_xmit+0x388/0x4d0 [] ? ipoib_mcast_join_finish+0x2c7/0x510 [ib_ipoib] [] ? ipoib_mcast_sendonly_join_complete+0x1b8/0x1f0 [ib_ipoib] [] ? mcast_work_handler+0x1a6/0x710 [ib_sa] [] ? ib_send_mad+0xfe/0x3c0 [ib_mad] [] ? ib_get_cached_lmc+0xa3/0xb0 [ib_core] [] ? join_handler+0xeb/0x200 [ib_sa] [] ? ib_sa_mcmember_rec_callback+0x5c/0xa0 [ib_sa] [] ? recv_handler+0x3c/0x70 [ib_sa] [] ? ib_mad_completion_handler+0x844/0x9d0 [ib_mad] [] ? ib_mad_completion_handler+0x0/0x9d0 [ib_mad] [] ? worker_thread+0x170/0x2a0 [] ? autoremove_wake_function+0x0/0x40 [] ? worker_thread+0x0/0x2a0 [] ? kthread+0x96/0xa0 [] ? child_rip+0xa/0x20 Coinciding with stack trace is the following message: ib0: ib_address_create failed The code below in ipoib_mcast_join_finish() will note the above failure in the address handle but otherwise continue: ah = ipoib_create_ah(dev, priv->pd, &av); if (!ah) { ipoib_warn(priv, "ib_address_create failed\n"); } else { The while loop at the bottom of ipoib_mcast_join_finish() will attempt to send queued multicast packets in mcast->pkt_queue and eventually end up in ipoib_mcast_send(): if (!mcast->ah) { if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) skb_queue_tail(&mcast->pkt_queue, skb); else { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); } My read is that the code will requeue the packet and return to the ipoib_mcast_join_finish() while loop and the stage is set for the "hung" task diagnostic as the while loop never sees a non-NULL ah, and will do nothing to resolve. There are GFP_ATOMIC allocates in the provider routines, so this is possible and should be dealt with. The test that induced the failure is associated with a host SM on the same server during a shutdown. This patch causes ipoib_mcast_join_finish() to exit with an error which will flush the queued mcast packets. Nothing is done to unwind the QP attached state so that subsequent sends from above will retry the join. Reviewed-by: Ram Vepa Reviewed-by: Gary Leshner Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 13 ++++++++----- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 7 +++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 0ef9af94997d..4115be54ba3b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev, struct ib_pd *pd, struct ib_ah_attr *attr) { struct ipoib_ah *ah; + struct ib_ah *vah; ah = kmalloc(sizeof *ah, GFP_KERNEL); if (!ah) - return NULL; + return ERR_PTR(-ENOMEM); ah->dev = dev; ah->last_send = 0; kref_init(&ah->ref); - ah->ah = ib_create_ah(pd, attr); - if (IS_ERR(ah->ah)) { + vah = ib_create_ah(pd, attr); + if (IS_ERR(vah)) { kfree(ah); - ah = NULL; - } else + ah = (struct ipoib_ah *)vah; + } else { + ah->ah = vah; ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah); + } return ah; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7567b6000230..37c46c66b0f2 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -432,7 +432,7 @@ static void path_rec_completion(int status, spin_lock_irqsave(&priv->lock, flags); - if (ah) { + if (!IS_ERR_OR_NULL(ah)) { path->pathrec = *pathrec; old_ah = path->ah; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 1b7a97686356..30ca8f069a17 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, av.grh.dgid = mcast->mcmember.mgid; ah = ipoib_create_ah(dev, priv->pd, &av); - if (!ah) { - ipoib_warn(priv, "ib_address_create failed\n"); + if (IS_ERR(ah)) { + ipoib_warn(priv, "ib_address_create failed %ld\n", + -PTR_ERR(ah)); + /* use original error */ + return PTR_ERR(ah); } else { spin_lock_irq(&priv->lock); mcast->ah = ah; -- cgit From 580da35a31f91a594f3090b7a2c39b85cb051a12 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Nov 2011 22:31:23 +0100 Subject: IB: Fix RCU lockdep splats Commit f2c31e32b37 ("net: fix NULL dereferences in check_peer_redir()") forgot to take care of infiniband uses of dst neighbours. Many thanks to Marc Aurele who provided a nice bug report and feedback. Reported-by: Marc Aurele La France Signed-off-by: Eric Dumazet Cc: David Miller Cc: Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 9 ++++++--- drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++++ drivers/infiniband/hw/cxgb4/cm.c | 6 ++++++ drivers/infiniband/hw/nes/nes_cm.c | 6 ++++-- drivers/infiniband/ulp/ipoib/ipoib_main.c | 18 +++++++++++------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 ++++-- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 691276bafd78..e9cf51b1343b 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in, neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); if (!neigh || !(neigh->nud_state & NUD_VALID)) { + rcu_read_lock(); neigh_event_send(dst_get_neighbour(&rt->dst), NULL); + rcu_read_unlock(); ret = -ENODATA; if (neigh) goto release; @@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, goto put; } + rcu_read_lock(); neigh = dst_get_neighbour(dst); if (!neigh || !(neigh->nud_state & NUD_VALID)) { if (neigh) neigh_event_send(neigh, NULL); ret = -ENODATA; - goto put; + } else { + ret = rdma_copy_addr(addr, dst->dev, neigh->ha); } - - ret = rdma_copy_addr(addr, dst->dev, neigh->ha); + rcu_read_unlock(); put: dst_release(dst); return ret; diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index de6d0774e609..c88b12beef25 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) goto reject; } dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(dst); l2t = t3_l2t_get(tdev, neigh, neigh->dev); + rcu_read_unlock(); if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(ep->dst); /* get a l2t entry */ ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev); + rcu_read_unlock(); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index b36cdac9c558..75b57bee6622 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1594,6 +1594,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) goto reject; } dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(dst); if (neigh->dev->flags & IFF_LOOPBACK) { pdev = ip_dev_find(&init_net, peer_ip); @@ -1620,6 +1621,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) rss_qid = dev->rdev.lldi.rxq_ids[ cxgb4_port_idx(neigh->dev) * step]; } + rcu_read_unlock(); if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -1820,6 +1822,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) } ep->dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(ep->dst); /* get a l2t entry */ @@ -1856,6 +1859,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ cxgb4_port_idx(neigh->dev) * step]; } + rcu_read_unlock(); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; @@ -2301,6 +2305,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(ep->dst); /* get a l2t entry */ @@ -2339,6 +2344,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ep->retry_with_mpa_v1 = 0; ep->tried_with_mpa_v1 = 0; } + rcu_read_unlock(); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index dfce9ea98a39..0a52d72371ee 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi neigh_release(neigh); } - if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) + if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) { + rcu_read_lock(); neigh_event_send(dst_get_neighbour(&rt->dst), NULL); - + rcu_read_unlock(); + } ip_rt_put(rt); return rc; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7567b6000230..ef38848d1b0e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev, return 0; } +/* called with rcu_read_lock */ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); @@ -636,6 +637,7 @@ err_drop: spin_unlock_irqrestore(&priv->lock, flags); } +/* called with rcu_read_lock */ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(skb->dev); @@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) struct neighbour *n = NULL; unsigned long flags; + rcu_read_lock(); if (likely(skb_dst(skb))) n = dst_get_neighbour(skb_dst(skb)); if (likely(n)) { if (unlikely(!*to_ipoib_neigh(n))) { ipoib_path_lookup(skb, dev); - return NETDEV_TX_OK; + goto unlock; } neigh = *to_ipoib_neigh(n); @@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ipoib_neigh_free(dev, neigh); spin_unlock_irqrestore(&priv->lock, flags); ipoib_path_lookup(skb, dev); - return NETDEV_TX_OK; + goto unlock; } if (ipoib_cm_get(neigh)) { if (ipoib_cm_up(neigh)) { ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); - return NETDEV_TX_OK; + goto unlock; } } else if (neigh->ah) { ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); - return NETDEV_TX_OK; + goto unlock; } if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { @@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) phdr->hwaddr + 4); dev_kfree_skb_any(skb); ++dev->stats.tx_dropped; - return NETDEV_TX_OK; + goto unlock; } unicast_arp_send(skb, dev, phdr); } } - +unlock: + rcu_read_unlock(); return NETDEV_TX_OK; } @@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb, dst = skb_dst(skb); n = NULL; if (dst) - n = dst_get_neighbour(dst); + n = dst_get_neighbour_raw(dst); if ((!dst || !n) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 1b7a97686356..cad1894594a8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -266,7 +266,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, skb->dev = dev; if (dst) - n = dst_get_neighbour(dst); + n = dst_get_neighbour_raw(dst); if (!dst || !n) { /* put pseudoheader back on for next time */ skb_push(skb, sizeof (struct ipoib_pseudoheader)); @@ -722,6 +722,8 @@ out: if (mcast && mcast->ah) { struct dst_entry *dst = skb_dst(skb); struct neighbour *n = NULL; + + rcu_read_lock(); if (dst) n = dst_get_neighbour(dst); if (n && !*to_ipoib_neigh(n)) { @@ -734,7 +736,7 @@ out: list_add_tail(&neigh->list, &mcast->neigh_list); } } - + rcu_read_unlock(); spin_unlock_irqrestore(&priv->lock, flags); ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); return; -- cgit From 1281bc256543eb610b14fa95ce1967397931a120 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 29 Nov 2011 10:10:54 +0000 Subject: netlabel: Fix build problems when IPv6 is not enabled A recent fix to the the NetLabel code caused build problem with configurations that did not have IPv6 enabled; see below: netlabel_kapi.c: In function 'netlbl_cfg_unlbl_map_add': netlabel_kapi.c:165:4: error: implicit declaration of function 'netlbl_af6list_add' This patch fixes this problem by making the IPv6 specific code conditional on the IPv6 configuration flags as we done in the rest of NetLabel and the network stack as a whole. We have to move some variable declarations around as a result so things may not be quite as pretty, but at least it builds cleanly now. Some additional IPv6 conditionals were added to the NetLabel code as well for the sake of consistency. Reported-by: Randy Dunlap Signed-off-by: Paul Moore Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- net/netlabel/netlabel_kapi.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 7b372a763c60..824f184f7a9b 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -111,8 +111,6 @@ int netlbl_cfg_unlbl_map_add(const char *domain, struct netlbl_domaddr_map *addrmap = NULL; struct netlbl_domaddr4_map *map4 = NULL; struct netlbl_domaddr6_map *map6 = NULL; - const struct in_addr *addr4, *mask4; - const struct in6_addr *addr6, *mask6; entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) @@ -133,9 +131,9 @@ int netlbl_cfg_unlbl_map_add(const char *domain, INIT_LIST_HEAD(&addrmap->list6); switch (family) { - case AF_INET: - addr4 = addr; - mask4 = mask; + case AF_INET: { + const struct in_addr *addr4 = addr; + const struct in_addr *mask4 = mask; map4 = kzalloc(sizeof(*map4), GFP_ATOMIC); if (map4 == NULL) goto cfg_unlbl_map_add_failure; @@ -148,9 +146,11 @@ int netlbl_cfg_unlbl_map_add(const char *domain, if (ret_val != 0) goto cfg_unlbl_map_add_failure; break; - case AF_INET6: - addr6 = addr; - mask6 = mask; + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: { + const struct in6_addr *addr6 = addr; + const struct in6_addr *mask6 = mask; map6 = kzalloc(sizeof(*map6), GFP_ATOMIC); if (map6 == NULL) goto cfg_unlbl_map_add_failure; @@ -167,6 +167,8 @@ int netlbl_cfg_unlbl_map_add(const char *domain, if (ret_val != 0) goto cfg_unlbl_map_add_failure; break; + } +#endif /* IPv6 */ default: goto cfg_unlbl_map_add_failure; break; @@ -225,9 +227,11 @@ int netlbl_cfg_unlbl_static_add(struct net *net, case AF_INET: addr_len = sizeof(struct in_addr); break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: addr_len = sizeof(struct in6_addr); break; +#endif /* IPv6 */ default: return -EPFNOSUPPORT; } @@ -266,9 +270,11 @@ int netlbl_cfg_unlbl_static_del(struct net *net, case AF_INET: addr_len = sizeof(struct in_addr); break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: addr_len = sizeof(struct in6_addr); break; +#endif /* IPv6 */ default: return -EPFNOSUPPORT; } -- cgit From 746ae30f821a8533ffba7769e492f59a96fdbeec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 02:41:49 +0000 Subject: isdn: make sure strings are null terminated These strings come from the user. We strcpy() them inside cf_command() so we should check that they are NULL terminated and return an error if not. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/isdn/divert/divert_procfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 33ec9e467772..9021182c4b76 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -242,6 +242,12 @@ static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg) case IIOCDOCFINT: if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) return (-EINVAL); /* invalid driver */ + if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) == + sizeof(dioctl.cf_ctrl.msn)) + return -EINVAL; + if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) == + sizeof(dioctl.cf_ctrl.fwd_nr)) + return -EINVAL; if ((i = cf_command(dioctl.cf_ctrl.drvid, (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, dioctl.cf_ctrl.cfproc, -- cgit From 5dc5503f5a400be5a7dc611745a034f04b0679b8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 02:42:09 +0000 Subject: isdn: avoid copying too long drvid "cfg->drvid" comes from the user so there is a possibility they didn't NUL terminate it properly. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_net.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 1f73d7f7e024..2339d7396b9e 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2756,6 +2756,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) char *c, *e; + if (strnlen(cfg->drvid, sizeof(cfg->drvid)) == + sizeof(cfg->drvid)) + return -EINVAL; drvidx = -1; chidx = -1; strcpy(drvid, cfg->drvid); -- cgit From 33dbc27f1ab3a37d04a8d226327fb3d384870e43 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 30 Sep 2011 08:55:50 +1000 Subject: drm/nouveau: add dumb ioctl support Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 45 +++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.c | 4 +++ drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +++++ 3 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index ddbabefb4273..b12fd2c80812 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -369,3 +369,48 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, spin_unlock_irqrestore(&dev->event_lock, flags); return 0; } + +int +nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct nouveau_bo *bo; + int ret; + + args->pitch = roundup(args->width * (args->bpp / 8), 256); + args->size = args->pitch * args->height; + args->size = roundup(args->size, PAGE_SIZE); + + ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); + if (ret) + return ret; + + ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle); + drm_gem_object_unreference_unlocked(bo->gem); + return ret; +} + +int +nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} + +int +nouveau_display_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle, uint64_t *poffset) +{ + struct drm_gem_object *gem; + + gem = drm_gem_object_lookup(dev, file_priv, handle); + if (gem) { + struct nouveau_bo *bo = gem->driver_private; + *poffset = bo->bo.addr_space_offset; + drm_gem_object_unreference_unlocked(gem); + return 0; + } + + return -ENOENT; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 9f7bb1295262..9791d13c9e3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -433,6 +433,10 @@ static struct drm_driver driver = { .gem_open_object = nouveau_gem_object_open, .gem_close_object = nouveau_gem_object_close, + .dumb_create = nouveau_display_dumb_create, + .dumb_map_offset = nouveau_display_dumb_map_offset, + .dumb_destroy = nouveau_display_dumb_destroy, + .name = DRIVER_NAME, .desc = DRIVER_DESC, #ifdef GIT_REVISION diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 29837da1098b..4c0be3a4ed88 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1418,6 +1418,12 @@ int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event); int nouveau_finish_page_flip(struct nouveau_channel *, struct nouveau_page_flip_state *); +int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, + struct drm_mode_create_dumb *args); +int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, + uint32_t handle, uint64_t *offset); +int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, + uint32_t handle); /* nv10_gpio.c */ int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); -- cgit From ffe2dee49023c2a47ef7e177ceb22ec6bcaecc11 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Fri, 11 Nov 2011 20:47:58 +0100 Subject: drm/nvc0/gr: fix TP init for transform feedback offset queries Without this, they return bytes written since the last update of the offset, but we want the full offset. Trace shows setting this on GPC[0]/TP[0] is enough. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvc0_graph.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index a74e501afd25..ecfafd70cf0e 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -381,6 +381,8 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) u8 tpnr[GPC_MAX]; int i, gpc, tpc; + nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ + /* * TP ROP UNKVAL(magic_not_rop_nr) * 450: 4/0/0/0 2 3 -- cgit From 26cfa81357b67229f71d25b53cbfbdfb83a38bdf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 17 Nov 2011 09:10:02 +1000 Subject: drm/nvd0/disp: fix sor dpms typo, preventing dpms on in some situations Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 23d63b4b3d77..cb006a718e70 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -780,7 +780,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) continue; if (nv_partner != nv_encoder && - nv_partner->dcb->or == nv_encoder->or) { + nv_partner->dcb->or == nv_encoder->dcb->or) { if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) return; break; -- cgit From 1a97b4ace09d7d3fe213a73bc466ca33af98c91c Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Tue, 22 Nov 2011 14:58:31 -0500 Subject: drm/nouveau: Keep RAMIN heap within the channel. The entire RAMIN is allocated to be 'size', but the heap is specified as 'base' + 'size' inside RAMIN, so it will overflow past RAMIN by 'base' bytes on NV50+ and clobber other allocatons unless it's size is adjusted. Signed-off-by: Younes Manton Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 02222c540aee..960c0ae0c0c3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -680,7 +680,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) return ret; } - ret = drm_mm_init(&chan->ramin_heap, base, size); + ret = drm_mm_init(&chan->ramin_heap, base, size - base); if (ret) { NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); nouveau_gpuobj_ref(NULL, &chan->ramin); -- cgit From a10e9e1dbb39970f232b1e2b0e4f738e2d77079f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 25 Nov 2011 16:35:34 +1000 Subject: drm/nouveau: fix oopses caused by clear being called on unpopulated ttms Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b75258a9fe44..c8a463b76c89 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -67,7 +67,10 @@ nouveau_sgdma_clear(struct ttm_backend *be) pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); } + nvbe->unmap_pages = false; } + + nvbe->pages = NULL; } static void -- cgit From a55b68e06b593ef7311f4a1cf9d3ae349ef7e9ed Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 9 Nov 2011 15:30:08 +1000 Subject: drm/nv50/disp: silence compiler warning NFI why this only started appearing now. The use of the uninitialised var can't actually happen, so perhaps my compiler just got stupider. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index d23ca00e7d62..06de250fe617 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -616,7 +616,7 @@ nv50_display_unk10_handler(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *disp = nv50_display(dev); u32 unk30 = nv_rd32(dev, 0x610030), mc; - int i, crtc, or, type = OUTPUT_ANY; + int i, crtc, or = 0, type = OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); disp->irq.dcb = NULL; @@ -708,7 +708,7 @@ nv50_display_unk20_handler(struct drm_device *dev) struct nv50_display *disp = nv50_display(dev); u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; struct dcb_entry *dcb; - int i, crtc, or, type = OUTPUT_ANY; + int i, crtc, or = 0, type = OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); dcb = disp->irq.dcb; -- cgit From 2984ff38ccf6cbc02a7a996a36c7d6f69f3c6146 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Wed, 30 Nov 2011 15:47:48 +0100 Subject: cfq-iosched: free cic_index if blkio_alloc_blkg_stats fails If we fail allocating the blkpg stats, we free cfqd and cfgq. But we need to free the IDA cfqd->cic_index as well. Signed-off-by: majianpeng Cc: stable@kernel.org Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 16ace89613bc..3beed83437a3 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4036,6 +4036,11 @@ static void *cfq_init_queue(struct request_queue *q) if (blkio_alloc_blkg_stats(&cfqg->blkg)) { kfree(cfqg); + + spin_lock(&cic_index_lock); + ida_remove(&cic_index_ida, cfqd->cic_index); + spin_unlock(&cic_index_lock); + kfree(cfqd); return NULL; } -- cgit From 1808958d27b1250295f01dff4997d8a8814adaab Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 28 Nov 2011 12:53:08 +0100 Subject: ARM: at91: fix clock conid for atmel_tcb.1 on 9260/9g20 The conid is supposed to be t0/t1/t2_clk. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Nicolas Ferre Cc: stable --- arch/arm/mach-at91/at91sam9260.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index b84a9f642f59..0d20677fbef0 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -195,9 +195,9 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk), CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk), - CLKDEV_CON_DEV_ID("t3_clk", "atmel_tcb.1", &tc3_clk), - CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk), - CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk), + CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk), + CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk), + CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), /* more usart lookup table for DT entries */ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), -- cgit From 0e934e22f3fabb98c41737e2e30bd9db2668e935 Mon Sep 17 00:00:00 2001 From: Anders Darander Date: Wed, 30 Nov 2011 08:47:44 +0100 Subject: ARM: at91: Fix USB AT91 gadget registration Since 193ab2a6070039e7ee2b9b9bebea754a7c52fd1b, various AT91 boards don't register at91_udc anymore due to depending on a now non-existing symbol. Fix the symbol name. Signed-off-by: Anders Darander Signed-off-by: Nicolas Ferre Cc: stable --- arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 66591fa53e05..ad930688358c 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -83,7 +83,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} * USB Device (Gadget) * -------------------------------------------------------------------- */ -#ifdef CONFIG_USB_GADGET_AT91 +#ifdef CONFIG_USB_AT91 static struct at91_udc_data udc_data; static struct resource udc_resources[] = { diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 25e3464fb07f..629fa9774972 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -84,7 +84,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} * USB Device (Gadget) * -------------------------------------------------------------------- */ -#ifdef CONFIG_USB_GADGET_AT91 +#ifdef CONFIG_USB_AT91 static struct at91_udc_data udc_data; static struct resource udc_resources[] = { diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index ae78f4d03b73..a178b58b0b9c 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -87,7 +87,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} * USB Device (Gadget) * -------------------------------------------------------------------- */ -#ifdef CONFIG_USB_GADGET_AT91 +#ifdef CONFIG_USB_AT91 static struct at91_udc_data udc_data; static struct resource udc_resources[] = { diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index ad017eb1f8df..d5fbac9ff4fa 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -92,7 +92,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} * USB Device (Gadget) * -------------------------------------------------------------------- */ -#ifdef CONFIG_USB_GADGET_AT91 +#ifdef CONFIG_USB_AT91 static struct at91_udc_data udc_data; static struct resource udc_resources[] = { -- cgit From 26bdef541d26fd6a5ddffdf8949ace22f94f809f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Nov 2011 11:28:01 +0300 Subject: btrfs scrub: handle -ENOMEM from init_ipath() init_ipath() can return an ERR_PTR(-ENOMEM). Signed-off-by: Dan Carpenter --- fs/btrfs/scrub.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index fab420db5121..c27bcb67f330 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -256,6 +256,11 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx) btrfs_release_path(swarn->path); ipath = init_ipath(4096, local_root, swarn->path); + if (IS_ERR(ipath)) { + ret = PTR_ERR(ipath); + ipath = NULL; + goto err; + } ret = paths_from_inode(inum, ipath); if (ret < 0) -- cgit From b52f75a595e8a70ee453bd6fb8023ee294f7a729 Mon Sep 17 00:00:00 2001 From: Arnd Hannemann Date: Wed, 16 Nov 2011 17:35:37 +0100 Subject: Fix URL of btrfs-progs git repository in docs The location of the btrfs-progs repository has been changed. This patch updates the documentation accordingly. Signed-off-by: Arnd Hannemann --- Documentation/filesystems/btrfs.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/btrfs.txt b/Documentation/filesystems/btrfs.txt index 64087c34327f..7671352216f1 100644 --- a/Documentation/filesystems/btrfs.txt +++ b/Documentation/filesystems/btrfs.txt @@ -63,8 +63,8 @@ IRC network. Userspace tools for creating and manipulating Btrfs file systems are available from the git repository at the following location: - http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git - git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git + http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git + git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git These include the following tools: -- cgit From aa38a711a893accf5b5192f3d705a120deaa81e0 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Fri, 18 Nov 2011 17:43:00 +0800 Subject: Btrfs: fix deadlock on metadata reservation when evicting a inode When I ran the xfstests, I found the test tasks was blocked on meta-data reservation. By debugging, I found the reason of this bug: start transaction | v reserve meta-data space | v flush delay allocation -> iput inode -> evict inode ^ | | v wait for delay allocation flush <- reserve meta-data space And besides that, the flush on evicting inode will block the thread, which is reclaiming the memory, and make oom happen easily. Fix this bug by skipping the flush step when evicting inode. Signed-off-by: Miao Xie --- fs/btrfs/ctree.h | 3 +++ fs/btrfs/extent-tree.c | 22 ++++++++++++++++++---- fs/btrfs/inode.c | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 04a5dfcee5a1..50634abef9b4 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2369,6 +2369,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root, int btrfs_block_rsv_refill(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, u64 min_reserved); +int btrfs_block_rsv_refill_noflush(struct btrfs_root *root, + struct btrfs_block_rsv *block_rsv, + u64 min_reserved); int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, struct btrfs_block_rsv *dst_rsv, u64 num_bytes); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5d86877f10e1..b7e5f6898d07 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3887,9 +3887,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root, return ret; } -int btrfs_block_rsv_refill(struct btrfs_root *root, - struct btrfs_block_rsv *block_rsv, - u64 min_reserved) +static inline int __btrfs_block_rsv_refill(struct btrfs_root *root, + struct btrfs_block_rsv *block_rsv, + u64 min_reserved, int flush) { u64 num_bytes = 0; int ret = -ENOSPC; @@ -3908,7 +3908,7 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, if (!ret) return 0; - ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1); + ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush); if (!ret) { block_rsv_add_bytes(block_rsv, num_bytes, 0); return 0; @@ -3917,6 +3917,20 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, return ret; } +int btrfs_block_rsv_refill(struct btrfs_root *root, + struct btrfs_block_rsv *block_rsv, + u64 min_reserved) +{ + return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 1); +} + +int btrfs_block_rsv_refill_noflush(struct btrfs_root *root, + struct btrfs_block_rsv *block_rsv, + u64 min_reserved) +{ + return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 0); +} + int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, struct btrfs_block_rsv *dst_rsv, u64 num_bytes) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8ad26b135a1c..c5ccec23984c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3490,7 +3490,7 @@ void btrfs_evict_inode(struct inode *inode) * doing the truncate. */ while (1) { - ret = btrfs_block_rsv_refill(root, rsv, min_size); + ret = btrfs_block_rsv_refill_noflush(root, rsv, min_size); /* * Try and steal from the global reserve since we will -- cgit From ece7d20e8be6730fbb29f4550de6b19b1a3a9387 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Fri, 18 Nov 2011 18:55:01 +0000 Subject: Btrfs: Don't error on resizing FS to same size It seems overly harsh to fail a resize of a btrfs file system to the same size when a shrink or grow would succeed. User app GParted trips over this error. Allow it by bypassing the shrink or grow operation. Signed-off-by: Mike Fleetwood --- fs/btrfs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a90e749ed6d2..72d461656f60 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1278,7 +1278,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, } ret = btrfs_grow_device(trans, device, new_size); btrfs_commit_transaction(trans, root); - } else { + } else if (new_size < old_size) { ret = btrfs_shrink_device(device, new_size); } -- cgit From b772a86ea6d932ac29d5e50e67c977653c832f8a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 28 Nov 2011 16:43:00 +0800 Subject: Btrfs: fix oops when calling statfs on readonly device To reproduce this bug: # dd if=/dev/zero of=img bs=1M count=256 # mkfs.btrfs img # losetup -r /dev/loop1 img # mount /dev/loop1 /mnt OOPS!! It triggered BUG_ON(!nr_devices) in btrfs_calc_avail_data_space(). To fix this, instead of checking write-only devices, we check all open deivces: # df -h /dev/loop1 Filesystem Size Used Avail Use% Mounted on /dev/loop1 250M 28K 238M 1% /mnt Signed-off-by: Li Zefan --- fs/btrfs/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8bd9d6d0e07a..1a3ce9e0b495 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1083,7 +1083,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) int i = 0, nr_devices; int ret; - nr_devices = fs_info->fs_devices->rw_devices; + nr_devices = fs_info->fs_devices->open_devices; BUG_ON(!nr_devices); devices_info = kmalloc(sizeof(*devices_info) * nr_devices, @@ -1105,8 +1105,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) else min_stripe_size = BTRFS_STRIPE_LEN; - list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) { - if (!device->in_fs_metadata) + list_for_each_entry(device, &fs_devices->devices, dev_list) { + if (!device->in_fs_metadata || !device->bdev) continue; avail_space = device->total_bytes - device->bytes_used; -- cgit From f2d0f6765d6332f9be732965a0c6f3b8a55082b4 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 28 Nov 2011 12:04:43 -0200 Subject: Btrfs: initialize new bitmaps' list We're failing to create clusters with bitmaps because setup_cluster_no_bitmap checks that the list is empty before inserting the bitmap entry in the list for setup_cluster_bitmap, but the list field is only initialized when it is restored from the on-disk free space cache, or when it is written out to disk. Besides a potential race condition due to the multiple use of the list field, filesystem performance severely degrades over time: as we use up all non-bitmap free extents, the try-to-set-up-cluster dance is done at every metadata block allocation. For every block group, we fail to set up a cluster, and after failing on them all up to twice, we fall back to the much slower unclustered allocation. To make matters worse, before the unclustered allocation, we try to create new block groups until we reach the 1% threshold, which introduces additional bitmaps and thus block groups that we'll iterate over at each metadata block request. --- fs/btrfs/free-space-cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 6e5b7e463698..ff179b1e7423 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1470,6 +1470,7 @@ static void add_new_bitmap(struct btrfs_free_space_ctl *ctl, { info->offset = offset_to_bitmap(ctl, offset); info->bytes = 0; + INIT_LIST_HEAD(&info->list); link_free_space(ctl, info); ctl->total_bitmaps++; -- cgit From b78d09bceb524ee6481c21b77bda22d766b10e6a Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 30 Nov 2011 13:43:00 -0500 Subject: Btrfs: reset cluster's max_size when creating bitmap The field that indicates the size of the largest contiguous chunk of free space in the cluster is not initialized when setting up bitmaps, it's only increased when we find a larger contiguous chunk. We end up retaining a larger value than appropriate for highly-fragmented clusters, which may cause pointless searches for large contiguous groups, and even cause clusters that do not meet the density requirements to be set up. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index ff179b1e7423..ec23d43d0c35 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2320,6 +2320,7 @@ again: if (!found) { start = i; + cluster->max_size = 0; found = true; } -- cgit From 1b22bad779be7fe07242be04749ec969164528b8 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 30 Nov 2011 13:43:00 -0500 Subject: Btrfs: start search for new cluster at the beginning Instead of starting at zero (offset is always zero), request a cluster starting at search_start, that denotes the beginning of the current block group. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b7e5f6898d07..97c12067a4b0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5301,10 +5301,8 @@ alloc: spin_lock(&last_ptr->refill_lock); if (last_ptr->block_group && (last_ptr->block_group->ro || - !block_group_bits(last_ptr->block_group, data))) { - offset = 0; + !block_group_bits(last_ptr->block_group, data))) goto refill_cluster; - } offset = btrfs_alloc_from_cluster(block_group, last_ptr, num_bytes, search_start); @@ -5355,7 +5353,7 @@ refill_cluster: /* allocate a cluster in this block group */ ret = btrfs_find_space_cluster(trans, root, block_group, last_ptr, - offset, num_bytes, + search_start, num_bytes, empty_cluster + empty_size); if (ret == 0) { /* -- cgit From 425d83156ca27f74e2cc3f370138038c3c8947f8 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 30 Nov 2011 13:43:00 -0500 Subject: Btrfs: skip block groups without enough space for a cluster We test whether a block group has enough free space to hold the requested block, but when we're doing clustered allocation, we can save some cycles by testing whether it has enough room for the cluster upfront, otherwise we end up attempting to set up a cluster and failing. Only in the NO_EMPTY_SIZE loop do we attempt an unclustered allocation, and by then we'll have zeroed the cluster size, so this patch won't stop us from using the block group as a last resort. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 97c12067a4b0..71c8e7049d0c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5278,7 +5278,7 @@ alloc: spin_lock(&block_group->free_space_ctl->tree_lock); if (cached && block_group->free_space_ctl->free_space < - num_bytes + empty_size) { + num_bytes + empty_cluster + empty_size) { spin_unlock(&block_group->free_space_ctl->tree_lock); goto loop; } -- cgit From be064d113906f04ea13088a8260e1e68ae0a4050 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 30 Nov 2011 13:43:00 -0500 Subject: Btrfs: skip allocation attempt from empty cluster If we don't have a cluster, don't bother trying to allocate from it, jumping right away to the attempt to allocate a new cluster. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 71c8e7049d0c..813c6bb96c9a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5299,9 +5299,9 @@ alloc: * people trying to start a new cluster */ spin_lock(&last_ptr->refill_lock); - if (last_ptr->block_group && - (last_ptr->block_group->ro || - !block_group_bits(last_ptr->block_group, data))) + if (!last_ptr->block_group || + last_ptr->block_group->ro || + !block_group_bits(last_ptr->block_group, data)) goto refill_cluster; offset = btrfs_alloc_from_cluster(block_group, last_ptr, -- cgit From a042994dd377d86bff9446ee76151ceb6267c9ba Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:15 -0500 Subject: cfg80211: fix race on init and driver registration There is a theoretical race that if hit will trigger a crash. The race is between when we issue the first regulatory hint, regulatory_hint_core(), gets processed by the workqueue and between when the first device gets registered to the wireless core. This is not easy to reproduce but it was easy to do so through the regulatory simulator I have been working on. This is a port of the fix I implemented there [1]. [1] https://github.com/mcgrof/regsim/commit/a246ccf81f059cb662eee288aa13100f631e4cc8 Cc: stable@vger.kernel.org Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 186b7f2a27b6..0ec40715a67b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -55,8 +55,17 @@ #define REG_DBG_PRINT(args...) #endif +static struct regulatory_request core_request_world = { + .initiator = NL80211_REGDOM_SET_BY_CORE, + .alpha2[0] = '0', + .alpha2[1] = '0', + .intersect = false, + .processed = true, + .country_ie_env = ENVIRON_ANY, +}; + /* Receipt of information from last regulatory request */ -static struct regulatory_request *last_request; +static struct regulatory_request *last_request = &core_request_world; /* To trigger userspace events */ static struct platform_device *reg_pdev; @@ -148,7 +157,7 @@ static char user_alpha2[2]; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -static void reset_regdomains(void) +static void reset_regdomains(bool full_reset) { /* avoid freeing static information or freeing something twice */ if (cfg80211_regdomain == cfg80211_world_regdom) @@ -163,6 +172,13 @@ static void reset_regdomains(void) cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; + + if (!full_reset) + return; + + if (last_request != &core_request_world) + kfree(last_request); + last_request = &core_request_world; } /* @@ -173,7 +189,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) { BUG_ON(!last_request); - reset_regdomains(); + reset_regdomains(false); cfg80211_world_regdom = rd; cfg80211_regdomain = rd; @@ -1405,7 +1421,8 @@ static int __regulatory_hint(struct wiphy *wiphy, } new_request: - kfree(last_request); + if (last_request != &core_request_world) + kfree(last_request); last_request = pending_request; last_request->intersect = intersect; @@ -1575,9 +1592,6 @@ static int regulatory_hint_core(const char *alpha2) { struct regulatory_request *request; - kfree(last_request); - last_request = NULL; - request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); if (!request) @@ -1775,7 +1789,7 @@ static void restore_regulatory_settings(bool reset_user) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); + reset_regdomains(true); restore_alpha2(alpha2, reset_user); /* @@ -2044,7 +2058,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) int r; if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2065,7 +2079,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (r) return r; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2090,7 +2104,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2110,7 +2124,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) kfree(rd); rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2263,11 +2277,8 @@ void /* __init_or_exit */ regulatory_exit(void) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); - - kfree(last_request); + reset_regdomains(true); - last_request = NULL; dev_set_uevent_suppress(®_pdev->dev, true); platform_device_unregister(reg_pdev); -- cgit From 0bac71af6e66dc798bf07d0c0dd14ee5503362f9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:16 -0500 Subject: cfg80211: amend regulatory NULL dereference fix Johannes' patch for "cfg80211: fix regulatory NULL dereference" broke user regulaotry hints and it did not address the fact that last_request was left populated even if the previous regulatory hint was stale due to the wiphy disappearing. Fix user reguluatory hints by only bailing out if for those regulatory hints where a request_wiphy is expected. The stale last_request considerations are addressed through the previous fixes on last_request where we reset the last_request to a static world regdom request upon reset_regdomains(). In this case though we further enhance the effect by simply restoring reguluatory settings completely. Cc: stable@vger.kernel.org Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 0ec40715a67b..074c1122ce42 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2049,8 +2049,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - if (!request_wiphy) { - reg_set_request_processed(); + if (!request_wiphy && + (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || + last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { + schedule_delayed_work(®_timeout, 0); return -ENODEV; } -- cgit From c72e8d335e2c6a309b6281f2abcf491f37b8b92b Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 30 Nov 2011 16:56:30 +0100 Subject: mac80211: fill rate filter for internal scan requests The rates bitmap for internal scan requests shoud be filled, otherwise there will be probe requests with zero rates supported. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- net/mac80211/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d999bf3b84e1..cae443563ec9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -757,6 +757,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->int_scan_req) return -ENOMEM; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; + local->int_scan_req->rates[band] = (u32) -1; + } + /* if low-level driver supports AP, we also support VLAN */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); -- cgit From 15fc1f3617edea50fa58703d59f73e726377bc63 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 30 Nov 2011 17:07:21 -0500 Subject: net: fec: Select the FEC driver by default for i.MX SoCs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 230dec6 (net/fec: add imx6q enet support) the FEC driver is no longer built by default for i.MX SoCs. Let the FEC driver be built by default again. Signed-off-by: Fabio Estevam Suggested-by: Uwe Kleine-König Acked-by: Uwe Kleine-König Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index c520cfd3b298..5272f9d4dda9 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -24,6 +24,7 @@ config FEC bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \ ARCH_MXC || ARCH_MXS) + default ARCH_MXC || ARCH_MXS if ARM select PHYLIB ---help--- Say Y here if you want to use the built-in 10/100 Fast ethernet -- cgit From f7e57044eeb1841847c24aa06766c8290c202583 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 30 Nov 2011 04:08:58 +0000 Subject: sch_teql: fix lockdep splat We need rcu_read_lock() protection before using dst_get_neighbour(), and we must cache its value (pass it to __teql_resolve()) teql_master_xmit() is called under rcu_read_lock_bh() protection, its not enough. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_teql.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index a3b7120fcc74..4f4c52c0eeb3 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) static int -__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) +__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, + struct net_device *dev, struct netdev_queue *txq, + struct neighbour *mn) { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); - struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc); - struct neighbour *mn = dst_get_neighbour(skb_dst(skb)); + struct teql_sched_data *q = qdisc_priv(txq->qdisc); struct neighbour *n = q->ncache; if (mn->tbl == NULL) @@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * } static inline int teql_resolve(struct sk_buff *skb, - struct sk_buff *skb_res, struct net_device *dev) + struct sk_buff *skb_res, + struct net_device *dev, + struct netdev_queue *txq) { - struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *mn; + int res; + if (txq->qdisc == &noop_qdisc) return -ENODEV; - if (dev->header_ops == NULL || - skb_dst(skb) == NULL || - dst_get_neighbour(skb_dst(skb)) == NULL) + if (!dev->header_ops || !dst) return 0; - return __teql_resolve(skb, skb_res, dev); + + rcu_read_lock(); + mn = dst_get_neighbour(dst); + res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0; + rcu_read_unlock(); + + return res; } static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) @@ -307,7 +316,7 @@ restart: continue; } - switch (teql_resolve(skb, skb_res, slave)) { + switch (teql_resolve(skb, skb_res, slave, slave_txq)) { case 0: if (__netif_tx_trylock(slave_txq)) { unsigned int length = qdisc_pkt_len(skb); -- cgit From 218fa90f072e4aeff9003d57e390857f4f35513e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Nov 2011 20:05:55 +0000 Subject: ipv4: fix lockdep splat in rt_cache_seq_show After commit f2c31e32b378 (fix NULL dereferences in check_peer_redir()), dst_get_neighbour() should be guarded by rcu_read_lock() / rcu_read_unlock() section. Reported-by: Miles Lane Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5c2847247f51..57e01bc60947 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -417,9 +417,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) else { struct rtable *r = v; struct neighbour *n; - int len; + int len, HHUptod; + rcu_read_lock(); n = dst_get_neighbour(&r->dst); + HHUptod = (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0; + rcu_read_unlock(); + seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", r->dst.dev ? r->dst.dev->name : "*", @@ -433,7 +437,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) dst_metric(&r->dst, RTAX_RTTVAR)), r->rt_key_tos, -1, - (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0, + HHUptod, r->rt_spec_dst, &len); seq_printf(seq, "%*s\n", 127 - len, ""); -- cgit From 14383c295ab48178c449336f5d74e9e615e36723 Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Tue, 29 Nov 2011 08:14:35 +0100 Subject: ARM: 7180/1: Change kprobes testcase with unpredictable STRD instruction There is a kprobes testcase for the instruction "strd r2, [r3], r4". This has unpredictable behaviour as it uses r3 for register writeback addressing and also stores it to memory. On a cortex A9, this testcase would fail because the instruction writes the updated value of r3 to memory, whereas the kprobes emulation code writes the original value. Fix this by changing testcase to used r5 instead of r3. Reported-by: Leif Lindholm Tested-by: Leif Lindholm Acked-by: Nicolas Pitre Signed-off-by: Jon Medhurst Signed-off-by: Russell King --- arch/arm/kernel/kprobes-test-arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index fc82de8bdcce..edf9ad8d3c6b 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -550,7 +550,7 @@ void kprobe_arm_test_cases(void) TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") - TEST_RPR( "strd r",2, VAL1,", [r",3, 24,"], r",4,48,"") + TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"") TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!") -- cgit From b5bed7fe801d1460424b7aeb6b06464e23d2a1e6 Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Tue, 29 Nov 2011 08:16:02 +0100 Subject: ARM: 7181/1: Restrict kprobes probing SWP instructions to ARMv5 and below The SWP instruction is deprecated on ARMv6 and with ARMv7 it will be UNDEFINED when CONFIG_SWP_EMULATE is selected. In this case, probing a SWP instruction will cause an oops when the kprobes emulation code executes an undefined instruction. As the SWP instruction should be rare or non-existent in kernels for ARMv6 and later, we can simply avoid these problems by not allowing probing of these. Reported-by: Leif Lindholm Tested-by: Leif Lindholm Acked-by: Nicolas Pitre Signed-off-by: Jon Medhurst Signed-off-by: Russell King --- arch/arm/kernel/kprobes-arm.c | 4 +++- arch/arm/kernel/kprobes-test-arm.c | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 9fe8910308af..8a30c89da70e 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c @@ -519,10 +519,12 @@ static const union decode_item arm_cccc_0000_____1001_table[] = { static const union decode_item arm_cccc_0001_____1001_table[] = { /* Synchronization primitives */ +#if __LINUX_ARM_ARCH__ < 6 + /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, REGS(NOPC, NOPC, 0, 0, NOPC)), - +#endif /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ /* And unallocated instructions... */ DECODE_END diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index edf9ad8d3c6b..ba32b393b3f0 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -427,18 +427,25 @@ void kprobe_arm_test_cases(void) TEST_GROUP("Synchronization primitives") - /* - * Use hard coded constants for SWP instructions to avoid warnings - * about deprecated instructions. - */ - TEST_RP( ".word 0xe108e097 @ swp lr, r",7,VAL2,", [r",8,0,"]") - TEST_R( ".word 0x610d0091 @ swpvs r0, r",1,VAL1,", [sp]") - TEST_RP( ".word 0xe10cd09e @ swp sp, r",14,VAL2,", [r",12,13*4,"]") +#if __LINUX_ARM_ARCH__ < 6 + TEST_RP("swp lr, r",7,VAL2,", [r",8,0,"]") + TEST_R( "swpvs r0, r",1,VAL1,", [sp]") + TEST_RP("swp sp, r",14,VAL2,", [r",12,13*4,"]") +#else + TEST_UNSUPPORTED(".word 0xe108e097 @ swp lr, r7, [r8]") + TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs r0, r1, [sp]") + TEST_UNSUPPORTED(".word 0xe10cd09e @ swp sp, r14 [r12]") +#endif TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]") TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]") TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]") - TEST_RP( ".word 0xe148e097 @ swpb lr, r",7,VAL2,", [r",8,0,"]") - TEST_R( ".word 0x614d0091 @ swpvsb r0, r",1,VAL1,", [sp]") +#if __LINUX_ARM_ARCH__ < 6 + TEST_RP("swpb lr, r",7,VAL2,", [r",8,0,"]") + TEST_R( "swpvsb r0, r",1,VAL1,", [sp]") +#else + TEST_UNSUPPORTED(".word 0xe148e097 @ swpb lr, r7, [r8]") + TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb r0, r1, [sp]") +#endif TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]") TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */ -- cgit From 4cbd6b167f9ed756ced970e0a95538f60ae3b9ab Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Tue, 29 Nov 2011 15:50:20 +0100 Subject: ARM: 7182/1: ARM cpu topology: fix warning kernel/sched.c:7354:2: warning: initialization from incompatible pointer type Align cpu_coregroup_mask prototype interface with sched_domain_mask_f typedef use int cpu instead of unsigned int cpu Cc: Signed-off-by: Vincent Guittot Signed-off-by: Russell King --- arch/arm/include/asm/topology.h | 2 +- arch/arm/kernel/topology.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index a7e457ed27c3..58b8b84adcd2 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -25,7 +25,7 @@ extern struct cputopo_arm cpu_topology[NR_CPUS]; void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); -const struct cpumask *cpu_coregroup_mask(unsigned int cpu); +const struct cpumask *cpu_coregroup_mask(int cpu); #else diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 1040c00405d0..8200deaa14f6 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -43,7 +43,7 @@ struct cputopo_arm cpu_topology[NR_CPUS]; -const struct cpumask *cpu_coregroup_mask(unsigned int cpu) +const struct cpumask *cpu_coregroup_mask(int cpu) { return &cpu_topology[cpu].core_sibling; } -- cgit From 917fbdb32f37e9a93b00bb12ee83532982982df3 Mon Sep 17 00:00:00 2001 From: Henrik Saavedra Persson Date: Wed, 23 Nov 2011 23:37:15 +0000 Subject: bonding: only use primary address for ARP Only use the primary address of the bond device for master_ip. This will prevent changing the ARP source address in Active-Backup mode whenever a secondry address is added to the bond device. Signed-off-by: Henrik Saavedra Persson Signed-off-by: Andy Gospodarek Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b0c577256487..7f8756825b8a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2553,30 +2553,6 @@ re_arm: } } -static __be32 bond_glean_dev_ip(struct net_device *dev) -{ - struct in_device *idev; - struct in_ifaddr *ifa; - __be32 addr = 0; - - if (!dev) - return 0; - - rcu_read_lock(); - idev = __in_dev_get_rcu(dev); - if (!idev) - goto out; - - ifa = idev->ifa_list; - if (!ifa) - goto out; - - addr = ifa->ifa_local; -out: - rcu_read_unlock(); - return addr; -} - static int bond_has_this_ip(struct bonding *bond, __be32 ip) { struct vlan_entry *vlan; @@ -3322,6 +3298,10 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, struct bonding *bond; struct vlan_entry *vlan; + /* we only care about primary address */ + if(ifa->ifa_flags & IFA_F_SECONDARY) + return NOTIFY_DONE; + list_for_each_entry(bond, &bn->dev_list, bond_list) { if (bond->dev == event_dev) { switch (event) { @@ -3329,7 +3309,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, bond->master_ip = ifa->ifa_local; return NOTIFY_OK; case NETDEV_DOWN: - bond->master_ip = bond_glean_dev_ip(bond->dev); + bond->master_ip = 0; return NOTIFY_OK; default: return NOTIFY_DONE; @@ -3345,8 +3325,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, vlan->vlan_ip = ifa->ifa_local; return NOTIFY_OK; case NETDEV_DOWN: - vlan->vlan_ip = - bond_glean_dev_ip(vlan_dev); + vlan->vlan_ip = 0; return NOTIFY_OK; default: return NOTIFY_DONE; -- cgit From ea6a5d3b97b768561db6358f15e4c84ced0f4f7e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 30 Nov 2011 12:10:53 +0000 Subject: sch_red: fix red_calc_qavg_from_idle_time Since commit a4a710c4a7490587 (pkt_sched: Change PSCHED_SHIFT from 10 to 6) it seems RED/GRED are broken. red_calc_qavg_from_idle_time() computes a delay in us units, but this delay is now 16 times bigger than real delay, so the final qavg result smaller than expected. Use standard kernel time services since there is no need to obfuscate them. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/red.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/net/red.h b/include/net/red.h index 3319f16b3beb..b72a3b833936 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -116,7 +116,7 @@ struct red_parms { u32 qR; /* Cached random number */ unsigned long qavg; /* Average queue length: A scaled */ - psched_time_t qidlestart; /* Start of current idle period */ + ktime_t qidlestart; /* Start of current idle period */ }; static inline u32 red_rmask(u8 Plog) @@ -148,17 +148,17 @@ static inline void red_set_parms(struct red_parms *p, static inline int red_is_idling(struct red_parms *p) { - return p->qidlestart != PSCHED_PASTPERFECT; + return p->qidlestart.tv64 != 0; } static inline void red_start_of_idle_period(struct red_parms *p) { - p->qidlestart = psched_get_time(); + p->qidlestart = ktime_get(); } static inline void red_end_of_idle_period(struct red_parms *p) { - p->qidlestart = PSCHED_PASTPERFECT; + p->qidlestart.tv64 = 0; } static inline void red_restart(struct red_parms *p) @@ -170,13 +170,10 @@ static inline void red_restart(struct red_parms *p) static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) { - psched_time_t now; - long us_idle; + s64 delta = ktime_us_delta(ktime_get(), p->qidlestart); + long us_idle = min_t(s64, delta, p->Scell_max); int shift; - now = psched_get_time(); - us_idle = psched_tdiff_bounded(now, p->qidlestart, p->Scell_max); - /* * The problem: ideally, average length queue recalcultion should * be done over constant clock intervals. This is too expensive, so -- cgit From 8f891489866ec62a87494eff3ed17c88152c32d4 Mon Sep 17 00:00:00 2001 From: "RongQing.Li" Date: Wed, 30 Nov 2011 23:43:07 -0500 Subject: net/core: fix rollback handler in register_netdevice_notifier Within nested statements, the break statement terminates only the do, for, switch, or while statement that immediately encloses it, So replace the break with goto. Signed-off-by: RongQing.Li Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 1482eea0bbf0..5a13edfc9f73 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1396,7 +1396,7 @@ rollback: for_each_net(net) { for_each_netdev(net, dev) { if (dev == last) - break; + goto outroll; if (dev->flags & IFF_UP) { nb->notifier_call(nb, NETDEV_GOING_DOWN, dev); @@ -1407,6 +1407,7 @@ rollback: } } +outroll: raw_notifier_chain_unregister(&netdev_chain, nb); goto unlock; } -- cgit From 2a3267a489f1dc4284b64a4b88c62011946dc7ff Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 1 Dec 2011 14:35:29 +0800 Subject: arm/imx: fix return type of callback passed to of_irq_init() The of_irq_init() expects the callback passed by .data of of_device_id return 'int' instead of 'void'. This patch fixes it to have irq_init_cb() return the correct value, and in turn have the secondary interrupt controller (gpio in this case) initialized properly and also eliminate the error message 'of_irq_init: children remain, but no parents' which was overlooked before. Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-imx6q.c | 4 +++- arch/arm/mach-mx5/imx51-dt.c | 7 +++++-- arch/arm/mach-mx5/imx53-dt.c | 7 +++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 8bf5fa349484..eb7531bdfed7 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -36,7 +36,7 @@ static void __init imx6q_map_io(void) imx_scu_map_io(); } -static void __init imx6q_gpio_add_irq_domain(struct device_node *np, +static int __init imx6q_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - @@ -44,6 +44,8 @@ static void __init imx6q_gpio_add_irq_domain(struct device_node *np, irq_domain_add_simple(np, gpio_irq_base); gpio_irq_base += 32; + + return 0; } static const struct of_device_id imx6q_irq_match[] __initconst = { diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c index ccc61585659b..3451a463a79a 100644 --- a/arch/arm/mach-mx5/imx51-dt.c +++ b/arch/arm/mach-mx5/imx51-dt.c @@ -44,13 +44,14 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = { { /* sentinel */ } }; -static void __init imx51_tzic_add_irq_domain(struct device_node *np, +static int __init imx51_tzic_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { irq_domain_add_simple(np, 0); + return 0; } -static void __init imx51_gpio_add_irq_domain(struct device_node *np, +static int __init imx51_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - @@ -58,6 +59,8 @@ static void __init imx51_gpio_add_irq_domain(struct device_node *np, irq_domain_add_simple(np, gpio_irq_base); gpio_irq_base += 32; + + return 0; } static const struct of_device_id imx51_irq_match[] __initconst = { diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c index ccaa0b81b768..022bc0364b5f 100644 --- a/arch/arm/mach-mx5/imx53-dt.c +++ b/arch/arm/mach-mx5/imx53-dt.c @@ -48,13 +48,14 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = { { /* sentinel */ } }; -static void __init imx53_tzic_add_irq_domain(struct device_node *np, +static int __init imx53_tzic_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { irq_domain_add_simple(np, 0); + return 0; } -static void __init imx53_gpio_add_irq_domain(struct device_node *np, +static int __init imx53_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - @@ -62,6 +63,8 @@ static void __init imx53_gpio_add_irq_domain(struct device_node *np, irq_domain_add_simple(np, gpio_irq_base); gpio_irq_base += 32; + + return 0; } static const struct of_device_id imx53_irq_match[] __initconst = { -- cgit From 04aafd713bae8a75933c7821dc012b0ec9046bca Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 1 Dec 2011 14:49:29 +0800 Subject: arm/imx: fix irq_base for gpio When gpio core dynamically allocate gpio number for a port, it starts from the end of the total range, 0 ~ ARCH_NR_GPIOS. That said, the earlier a port gets probed, the bigger gpio number it gets assigned. To match this, the irq_base for gpio should be assigned from 'MXC_GPIO_IRQ_START + ARCH_NR_GPIOS' decreasingly. Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-imx6q.c | 5 ++--- arch/arm/mach-mx5/imx51-dt.c | 5 ++--- arch/arm/mach-mx5/imx53-dt.c | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index eb7531bdfed7..22aa54aa9b2a 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -39,11 +39,10 @@ static void __init imx6q_map_io(void) static int __init imx6q_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - - 32 * 7; /* imx6q gets 7 gpio ports */ + static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; + gpio_irq_base -= 32; irq_domain_add_simple(np, gpio_irq_base); - gpio_irq_base += 32; return 0; } diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c index 3451a463a79a..596edd967dbf 100644 --- a/arch/arm/mach-mx5/imx51-dt.c +++ b/arch/arm/mach-mx5/imx51-dt.c @@ -54,11 +54,10 @@ static int __init imx51_tzic_add_irq_domain(struct device_node *np, static int __init imx51_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - - 32 * 4; /* imx51 gets 4 gpio ports */ + static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; + gpio_irq_base -= 32; irq_domain_add_simple(np, gpio_irq_base); - gpio_irq_base += 32; return 0; } diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c index 022bc0364b5f..85bfd5ff21b0 100644 --- a/arch/arm/mach-mx5/imx53-dt.c +++ b/arch/arm/mach-mx5/imx53-dt.c @@ -58,11 +58,10 @@ static int __init imx53_tzic_add_irq_domain(struct device_node *np, static int __init imx53_gpio_add_irq_domain(struct device_node *np, struct device_node *interrupt_parent) { - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - - 32 * 7; /* imx53 gets 7 gpio ports */ + static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS; + gpio_irq_base -= 32; irq_domain_add_simple(np, gpio_irq_base); - gpio_irq_base += 32; return 0; } -- cgit From f64964796dedca340608fb1075ab6baad5625851 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Nov 2011 14:49:26 -0500 Subject: drm/radeon/kms: add some loop timeouts in pageflip code Avoid infinite loops waiting for surface updates if a GPU reset happens while waiting for a page flip. See: https://bugs.freedesktop.org/show_bug.cgi?id=43191 Signed-off-by: Alex Deucher Cc: stable@kernel.org Reviewed-by: Mario Kleiner Tested-by: Simon Farnsworth Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen.c | 7 ++++++- drivers/gpu/drm/radeon/r100.c | 7 ++++++- drivers/gpu/drm/radeon/rs600.c | 7 ++++++- drivers/gpu/drm/radeon/rv770.c | 7 ++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 1d603a3335db..5e00d1670aa9 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -82,6 +82,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= EVERGREEN_GRPH_UPDATE_LOCK; @@ -99,7 +100,11 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ad158ea49901..bfc08f6320f8 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -187,13 +187,18 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; + int i; /* Lock the graphics update lock */ /* update the scanout addresses */ WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); /* Wait for update_pending to go high. */ - while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 481b99e89f65..b1053d640423 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -62,6 +62,7 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index a983f410ab89..23ae1c60ab3d 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -47,6 +47,7 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ -- cgit From bc96f9424b0e95f2451398007be46824f93866d0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Nov 2011 17:26:36 +0100 Subject: drm/radeon/kms: Hide debugging message Use the proper macro to issue the debugging message in radeon_atif_call(). Otherwise we spam the log of many systems with a message which looks like an error message of unknown origin, and could thus confuse the user. Commit dc77de12dde95c8da39e4c417eb70c7d445cf84b was a first step in this direction, but was not sufficient IMHO. Signed-off-by: Jean Delvare Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_acpi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 3f6636bb2d7f..c039e5a6bf13 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -35,7 +35,8 @@ static int radeon_atif_call(acpi_handle handle) /* Fail only if calling the method fails and ATIF is supported */ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - printk(KERN_DEBUG "failed to evaluate ATIF got %s\n", acpi_format_exception(status)); + DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", + acpi_format_exception(status)); kfree(buffer.pointer); return 1; } -- cgit From 48cc9b2c7dae377e39836c0a88dd1c5ba5566d17 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Nov 2011 17:36:39 +0100 Subject: drm/radeon/kms: Skip ACPI call to ATIF when possible I am under the impression that it only makes sense to call the ATIF method if the graphics device has an ACPI handle attached. So we could skip the call altogether if there is no such handle. Signed-off-by: Jean Delvare Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_acpi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index c039e5a6bf13..3516a6081dcf 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -51,13 +51,13 @@ int radeon_acpi_init(struct radeon_device *rdev) acpi_handle handle; int ret; - /* No need to proceed if we're sure that ATIF is not supported */ - if (!ASIC_IS_AVIVO(rdev) || !rdev->bios) - return 0; - /* Get the device handle */ handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); + /* No need to proceed if we're sure that ATIF is not supported */ + if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) + return 0; + /* Call the ATIF method */ ret = radeon_atif_call(handle); if (ret) -- cgit From 88d686027bb43f585914c77dd363f6e817b42c2a Mon Sep 17 00:00:00 2001 From: Charles Chin Date: Thu, 1 Dec 2011 11:21:00 +0100 Subject: ALSA: hda - Fix S3/S4 problem on machines with VREF-pin mute-LED The verb command in stac92xx_post_suspend caused the audio to stop working after resuming from S3 mode on HP laptops with the VREF-pin mute-LED control. Removing relevant post_suspend registering. Although removing D3 on AFG is no optimal solution, the impact should be small in comparison with the broken S3/S4. Signed-off-by: Charles Chin Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f4f4ebeed9ea..d8d2f9dccd9b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5057,20 +5057,6 @@ static int stac92xx_pre_resume(struct hda_codec *codec) return 0; } -static int stac92xx_post_suspend(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - if (spec->gpio_led > 8) { - /* with vref-out pin used for mute led control - * codec AFG is prevented from D3 state, but on - * system suspend it can (and should) be used - */ - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - } - return 0; -} - static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { @@ -5670,8 +5656,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = @@ -5985,8 +5969,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = -- cgit From 5f894cbb6890d317699aa622b4dc9d73d009cd22 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 1 Dec 2011 13:32:14 +0100 Subject: [S390] kdump: Replace is_kdump_kernel() with OLDMEM_BASE check In order to have the same behavior for kdump based stand-alone dump as for the kexec method, the is_kdump_kernel() check (only true for the kexec method) has to be replaced by the OLDMEM_BASE check (true for both methods). Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index e58a462949b1..e54c4ff8abaa 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -579,7 +579,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size, *msg = "first memory chunk must be at least crashkernel size"; return 0; } - if (is_kdump_kernel() && (crash_size == OLDMEM_SIZE)) + if (OLDMEM_BASE && crash_size == OLDMEM_SIZE) return OLDMEM_BASE; for (i = MEMORY_CHUNKS - 1; i >= 0; i--) { -- cgit From d9ae6772d3a3d7325d535577d9fd09c0de8a9da3 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 1 Dec 2011 13:32:15 +0100 Subject: [S390] ptrace inferior call interactions with TIF_SYSCALL The TIF_SYSCALL bit needs to be cleared if the debugger changes the state of the ptraced process in regard to the presence of a system call. Otherwise the system call will be restarted although the debugger set up an inferior call. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/signal.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 05a85bc14c98..7f6f9f354545 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -460,9 +460,9 @@ void do_signal(struct pt_regs *regs) regs->svc_code >> 16); break; } - /* No longer in a system call */ - clear_thread_flag(TIF_SYSCALL); } + /* No longer in a system call */ + clear_thread_flag(TIF_SYSCALL); if ((is_compat_task() ? handle_signal32(signr, &ka, &info, oldset, regs) : @@ -486,6 +486,7 @@ void do_signal(struct pt_regs *regs) } /* No handlers present - check for system call restart */ + clear_thread_flag(TIF_SYSCALL); if (current_thread_info()->system_call) { regs->svc_code = current_thread_info()->system_call; switch (regs->gprs[2]) { @@ -500,9 +501,6 @@ void do_signal(struct pt_regs *regs) regs->gprs[2] = regs->orig_gpr2; set_thread_flag(TIF_SYSCALL); break; - default: - clear_thread_flag(TIF_SYSCALL); - break; } } -- cgit From 7c81878b34dd1b75dec5c8b68951d1439854d358 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Thu, 1 Dec 2011 13:32:16 +0100 Subject: [S390] fix page change underindication in pgste_update_all This patch makes sure we don't underindicate _PAGE_CHANGED in case we have a race between an operation that changes the page and this code path that hits us between page_get_storage_key and page_set_storage_key. Note that we still have a potential underindication on _PAGE_REFERENCED in the unlikely event that the page was changed but not referenced _and_ someone references the page in the race window. That's not considered to be a problem. Signed-off-by: Carsten Otte Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/pgtable.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 524d23b8610c..4f289ff0b7fe 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -599,10 +599,10 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) skey = page_get_storage_key(address); bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); /* Clear page changed & referenced bit in the storage key */ - if (bits) { - skey ^= bits; - page_set_storage_key(address, skey, 1); - } + if (bits & _PAGE_CHANGED) + page_set_storage_key(address, skey ^ bits, 1); + else if (bits) + page_reset_referenced(address); /* Transfer page changed & referenced bit to guest bits in pgste */ pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */ /* Get host changed & referenced bits from pgste */ -- cgit From b934069c991355d27a053a932591c77960f4e414 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 1 Dec 2011 13:32:17 +0100 Subject: [S390] add missing .set function for NT_S390_LAST_BREAK regset The last breaking event address is a read-only value, the regset misses the .set function. If a PTRACE_SETREGSET is done for NT_S390_LAST_BREAK we get an oops due to a branch to zero: Kernel BUG at 0000000000000002 verbose debug info unavailable illegal operation: 0001 #1 SMP ... Call Trace: (<0000000000158294> ptrace_regset+0x184/0x188) <00000000001595b6> ptrace_request+0x37a/0x4fc <0000000000109a78> arch_ptrace+0x108/0x1fc <00000000001590d6> SyS_ptrace+0xaa/0x12c <00000000005c7a42> sysc_noemu+0x16/0x1c <000003fffd5ec10c> 0x3fffd5ec10c Last Breaking-Event-Address: <0000000000158242> ptrace_regset+0x132/0x188 Add a nop .set function to prevent the branch to zero. Signed-off-by: Martin Schwidefsky Cc: stable@kernel.org --- arch/s390/kernel/ptrace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 450931a45b68..f05649fd0547 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -905,6 +905,14 @@ static int s390_last_break_get(struct task_struct *target, return 0; } +static int s390_last_break_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + return 0; +} + #endif static int s390_system_call_get(struct task_struct *target, @@ -951,6 +959,7 @@ static const struct user_regset s390_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_last_break_get, + .set = s390_last_break_set, }, #endif [REGSET_SYSTEM_CALL] = { @@ -1116,6 +1125,14 @@ static int s390_compat_last_break_get(struct task_struct *target, return 0; } +static int s390_compat_last_break_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + return 0; +} + static const struct user_regset s390_compat_regsets[] = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, @@ -1139,6 +1156,7 @@ static const struct user_regset s390_compat_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_compat_last_break_get, + .set = s390_compat_last_break_set, }, [REGSET_SYSTEM_CALL] = { .core_note_type = NT_S390_SYSTEM_CALL, -- cgit From cfc9066bcd3ab498268e1d075f1556bb5244c0aa Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 1 Dec 2011 13:32:18 +0100 Subject: [S390] remove reset of system call restart on psw changes git commit 20b40a794baf3b4b "signal race with restarting system calls" added code to the poke_user/poke_user_compat to reset the system call restart information in the thread-info if the PSW address is changed. The purpose of that change has been to workaround old gdbs that do not know about the REGSET_SYSTEM_CALL. It turned out that this is not a good idea, it makes the behaviour of the debuggee dependent on the order of specific ptrace call, e.g. the REGSET_SYSTEM_CALL register set needs to be written last. And the workaround does not really fix old gdbs, inferior calls on interrupted restarting system calls do not work either way. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ptrace.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f05649fd0547..573bc29551ef 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -296,13 +296,6 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)))) /* Invalid psw mask. */ return -EINVAL; - if (addr == (addr_t) &dummy->regs.psw.addr) - /* - * The debugger changed the instruction address, - * reset system call restart, see signal.c:do_signal - */ - task_thread_info(child)->system_call = 0; - *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { @@ -614,11 +607,6 @@ static int __poke_user_compat(struct task_struct *child, /* Transfer 31 bit amode bit to psw mask. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) | (__u64)(tmp & PSW32_ADDR_AMODE); - /* - * The debugger changed the instruction address, - * reset system call restart, see signal.c:do_signal - */ - task_thread_info(child)->system_call = 0; } else { /* gpr 0-15 */ *(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp; -- cgit From 817e5000ebc4d448ca514db49b55073a724f8552 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 1 Dec 2011 13:32:19 +0100 Subject: [S390] hibernate: directly trigger subchannel evaluation Using the generic css_schedule_eval to evaluate subchannels while resuming from hibernation is very slow when used with many devices. Provide a new evaluation trigger which exploits css_sched_sch_todo and use this in the resume callback for ccw devices. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/cio.h | 5 +++ drivers/s390/cio/css.c | 104 ++++++++++++++++++++++++++-------------------- drivers/s390/cio/device.c | 4 +- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 155a82bcb9e5..4a1ff5c2eb88 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -68,8 +68,13 @@ struct schib { __u8 mda[4]; /* model dependent area */ } __attribute__ ((packed,aligned(4))); +/* + * When rescheduled, todo's with higher values will overwrite those + * with lower values. + */ enum sch_todo { SCH_TODO_NOTHING, + SCH_TODO_EVAL, SCH_TODO_UNREG, }; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 92d7324acb1c..21908e67bf67 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -195,51 +195,6 @@ void css_sch_device_unregister(struct subchannel *sch) } EXPORT_SYMBOL_GPL(css_sch_device_unregister); -static void css_sch_todo(struct work_struct *work) -{ - struct subchannel *sch; - enum sch_todo todo; - - sch = container_of(work, struct subchannel, todo_work); - /* Find out todo. */ - spin_lock_irq(sch->lock); - todo = sch->todo; - CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, - sch->schid.sch_no, todo); - sch->todo = SCH_TODO_NOTHING; - spin_unlock_irq(sch->lock); - /* Perform todo. */ - if (todo == SCH_TODO_UNREG) - css_sch_device_unregister(sch); - /* Release workqueue ref. */ - put_device(&sch->dev); -} - -/** - * css_sched_sch_todo - schedule a subchannel operation - * @sch: subchannel - * @todo: todo - * - * Schedule the operation identified by @todo to be performed on the slow path - * workqueue. Do nothing if another operation with higher priority is already - * scheduled. Needs to be called with subchannel lock held. - */ -void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) -{ - CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", - sch->schid.ssid, sch->schid.sch_no, todo); - if (sch->todo >= todo) - return; - /* Get workqueue ref. */ - if (!get_device(&sch->dev)) - return; - sch->todo = todo; - if (!queue_work(cio_work_q, &sch->todo_work)) { - /* Already queued, release workqueue ref. */ - put_device(&sch->dev); - } -} - static void ssd_from_pmcw(struct chsc_ssd_info *ssd, struct pmcw *pmcw) { int i; @@ -466,6 +421,65 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) css_schedule_eval(schid); } +/** + * css_sched_sch_todo - schedule a subchannel operation + * @sch: subchannel + * @todo: todo + * + * Schedule the operation identified by @todo to be performed on the slow path + * workqueue. Do nothing if another operation with higher priority is already + * scheduled. Needs to be called with subchannel lock held. + */ +void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) +{ + CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", + sch->schid.ssid, sch->schid.sch_no, todo); + if (sch->todo >= todo) + return; + /* Get workqueue ref. */ + if (!get_device(&sch->dev)) + return; + sch->todo = todo; + if (!queue_work(cio_work_q, &sch->todo_work)) { + /* Already queued, release workqueue ref. */ + put_device(&sch->dev); + } +} + +static void css_sch_todo(struct work_struct *work) +{ + struct subchannel *sch; + enum sch_todo todo; + int ret; + + sch = container_of(work, struct subchannel, todo_work); + /* Find out todo. */ + spin_lock_irq(sch->lock); + todo = sch->todo; + CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, + sch->schid.sch_no, todo); + sch->todo = SCH_TODO_NOTHING; + spin_unlock_irq(sch->lock); + /* Perform todo. */ + switch (todo) { + case SCH_TODO_NOTHING: + break; + case SCH_TODO_EVAL: + ret = css_evaluate_known_subchannel(sch, 1); + if (ret == -EAGAIN) { + spin_lock_irq(sch->lock); + css_sched_sch_todo(sch, todo); + spin_unlock_irq(sch->lock); + } + break; + case SCH_TODO_UNREG: + css_sch_device_unregister(sch); + break; + } + /* Release workqueue ref. */ + put_device(&sch->dev); +} + static struct idset *slow_subchannel_set; static spinlock_t slow_subchannel_lock; static wait_queue_head_t css_eval_wq; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d734f4a0ecac..47269858ecb6 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1868,9 +1868,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev) */ cdev->private->flags.resuming = 1; cdev->private->path_new_mask = LPM_ANYPATH; - css_schedule_eval(sch->schid); + css_sched_sch_todo(sch, SCH_TODO_EVAL); spin_unlock_irq(sch->lock); - css_complete_work(); + css_wait_for_slow_path(); /* cdev may have been moved to a different subchannel. */ sch = to_subchannel(cdev->dev.parent); -- cgit From 659213b899f389d3a1e211796713ceaaa280fa44 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 1 Dec 2011 13:32:20 +0100 Subject: [S390] cio: disallow driver io for known to be broken paths When a driver requests to do IO, we will adjust the mask of paths to be used to exclude varied offline paths. Drivers trying to do IO solely on paths which are online but some way defective may lack the information to do proper error handling. There is no reason to allow the usage of known to be broken paths. Thus restrict the paths a ccw driver can use for IO to a subset of the paths cio found usable (this also excludes offline paths). Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_ops.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index f98698d5735e..41c21ad0d5f2 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -213,9 +213,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, ret = cio_set_options (sch, flags); if (ret) return ret; - /* Adjust requested path mask to excluded varied off paths. */ + /* Adjust requested path mask to exclude unusable paths. */ if (lpm) { - lpm &= sch->opm; + lpm &= sch->lpm; if (lpm == 0) return -EACCES; } @@ -607,9 +607,9 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw, return -EINVAL; if (cdev->private->state != DEV_STATE_ONLINE) return -EIO; - /* Adjust requested path mask to excluded varied off paths. */ + /* Adjust requested path mask to exclude unusable paths. */ if (lpm) { - lpm &= sch->opm; + lpm &= sch->lpm; if (lpm == 0) return -EACCES; } -- cgit From 50c8e31f38f380f04885c66bde0bc4c946e786ee Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 1 Dec 2011 13:32:21 +0100 Subject: [S390] cio: provide fake irb for transport mode IO If a driver wants to do command mode IO while CIO is doing online path verification we ignore this request and provide a fake irb when we are done and the driver can do IO again. For transport mode IO we have no such mechanism, giving the driver no other chance then to retry the action until we are done. This is not very reliable. Provide a fake irb for transport mode IO as well. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 30 ++++++++++++++++++++++-------- drivers/s390/cio/device_ops.c | 12 +++++++++++- drivers/s390/cio/io_sch.h | 5 ++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 52c233fa2b12..1b853513c891 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -496,8 +496,26 @@ static void ccw_device_reset_path_events(struct ccw_device *cdev) cdev->private->pgid_reset_mask = 0; } -void -ccw_device_verify_done(struct ccw_device *cdev, int err) +static void create_fake_irb(struct irb *irb, int type) +{ + memset(irb, 0, sizeof(*irb)); + if (type == FAKE_CMD_IRB) { + struct cmd_scsw *scsw = &irb->scsw.cmd; + scsw->cc = 1; + scsw->fctl = SCSW_FCTL_START_FUNC; + scsw->actl = SCSW_ACTL_START_PEND; + scsw->stctl = SCSW_STCTL_STATUS_PEND; + } else if (type == FAKE_TM_IRB) { + struct tm_scsw *scsw = &irb->scsw.tm; + scsw->x = 1; + scsw->cc = 1; + scsw->fctl = SCSW_FCTL_START_FUNC; + scsw->actl = SCSW_ACTL_START_PEND; + scsw->stctl = SCSW_STCTL_STATUS_PEND; + } +} + +void ccw_device_verify_done(struct ccw_device *cdev, int err) { struct subchannel *sch; @@ -520,12 +538,8 @@ callback: ccw_device_done(cdev, DEV_STATE_ONLINE); /* Deliver fake irb to device driver, if needed. */ if (cdev->private->flags.fake_irb) { - memset(&cdev->private->irb, 0, sizeof(struct irb)); - cdev->private->irb.scsw.cmd.cc = 1; - cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC; - cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND; - cdev->private->irb.scsw.cmd.stctl = - SCSW_STCTL_STATUS_PEND; + create_fake_irb(&cdev->private->irb, + cdev->private->flags.fake_irb); cdev->private->flags.fake_irb = 0; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 41c21ad0d5f2..ec7fb6d3b479 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, if (cdev->private->state == DEV_STATE_VERIFY) { /* Remember to fake irb when finished. */ if (!cdev->private->flags.fake_irb) { - cdev->private->flags.fake_irb = 1; + cdev->private->flags.fake_irb = FAKE_CMD_IRB; cdev->private->intparm = intparm; return 0; } else @@ -605,6 +605,16 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw, sch = to_subchannel(cdev->dev.parent); if (!sch->schib.pmcw.ena) return -EINVAL; + if (cdev->private->state == DEV_STATE_VERIFY) { + /* Remember to fake irb when finished. */ + if (!cdev->private->flags.fake_irb) { + cdev->private->flags.fake_irb = FAKE_TM_IRB; + cdev->private->intparm = intparm; + return 0; + } else + /* There's already a fake I/O around. */ + return -EBUSY; + } if (cdev->private->state != DEV_STATE_ONLINE) return -EIO; /* Adjust requested path mask to exclude unusable paths. */ diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index 2ebb492a5c17..76253dfcc1be 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -111,6 +111,9 @@ enum cdev_todo { CDEV_TODO_UNREG_EVAL, }; +#define FAKE_CMD_IRB 1 +#define FAKE_TM_IRB 2 + struct ccw_device_private { struct ccw_device *cdev; struct subchannel *sch; @@ -138,7 +141,7 @@ struct ccw_device_private { unsigned int doverify:1; /* delayed path verification */ unsigned int donotify:1; /* call notify function */ unsigned int recog_done:1; /* dev. recog. complete */ - unsigned int fake_irb:1; /* deliver faked irb */ + unsigned int fake_irb:2; /* deliver faked irb */ unsigned int resuming:1; /* recognition while resume */ unsigned int pgroup:1; /* pathgroup is set up */ unsigned int mpath:1; /* multipathing is set up */ -- cgit From 3b484ec648490518dd16ed7d8f02206a39539a59 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 1 Dec 2011 13:32:22 +0100 Subject: [S390] cio: fix chsc_chp_vary The functions called by chsc_chp_vary operate on pointers to channel path ids not channel path links. (This worked by chance since the id is the first member of the link structure) Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 75c3f1f8fd43..a84631a7391d 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -529,10 +529,7 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data) int chsc_chp_vary(struct chp_id chpid, int on) { struct channel_path *chp = chpid_to_chp(chpid); - struct chp_link link; - memset(&link, 0, sizeof(struct chp_link)); - link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); /* @@ -542,10 +539,10 @@ int chsc_chp_vary(struct chp_id chpid, int on) /* Try to update the channel path descritor. */ chsc_determine_base_channel_path_desc(chpid, &chp->desc); for_each_subchannel_staged(s390_subchannel_vary_chpid_on, - __s390_vary_chpid_on, &link); + __s390_vary_chpid_on, &chpid); } else for_each_subchannel_staged(s390_subchannel_vary_chpid_off, - NULL, &link); + NULL, &chpid); return 0; } -- cgit From 75464960fc0ccc505527edc1459c8ad191fbc0cc Mon Sep 17 00:00:00 2001 From: Holger Dengler Date: Thu, 1 Dec 2011 13:32:23 +0100 Subject: [S390] ap: Setup timer for sending messages after reset. Setup timer for processing messages in request queue after a successful AP bus device reset. Signed-off-by: Holger Dengler Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index ec94f049e995..96bbe9d12a79 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1552,6 +1552,8 @@ static void ap_reset(struct ap_device *ap_dev) rc = ap_init_queue(ap_dev->qid); if (rc == -ENODEV) ap_dev->unregistered = 1; + else + __ap_schedule_poll_timer(); } static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) -- cgit From f4a8e6563ea5366f563cb741a27fe90c5fa7f0fc Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 1 Dec 2011 09:30:36 -0500 Subject: Btrfs: fix meta data raid-repair merge problem Commit 4a54c8c16 introduced raid-repair, killing the individual readpage_io_failed_hook entries from inode.c and disk-io.c. Commit 4bb31e92 introduced new readahead code, adding a readpage_io_failed_hook to disk-io.c. The raid-repair commit had logic to disable raid-repair, if readpage_io_failed_hook is set. Thus, the readahead commit effectively disabled raid-repair for meta data. This commit changes the logic to always attempt raid-repair when needed and call the readpage_io_failed_hook in case raid-repair fails. This is much more straight forward and should have been like that from the beginning. Signed-off-by: Jan Schmidt Reported-by: Stefan Behrens Signed-off-by: Chris Mason --- fs/btrfs/extent_io.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 9472d3de5e52..be1bf627a14b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2287,14 +2287,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err) if (!uptodate) { int failed_mirror; failed_mirror = (int)(unsigned long)bio->bi_bdev; - if (tree->ops && tree->ops->readpage_io_failed_hook) - ret = tree->ops->readpage_io_failed_hook( - bio, page, start, end, - failed_mirror, state); - else - ret = bio_readpage_error(bio, page, start, end, - failed_mirror, NULL); + /* + * The generic bio_readpage_error handles errors the + * following way: If possible, new read requests are + * created and submitted and will end up in + * end_bio_extent_readpage as well (if we're lucky, not + * in the !uptodate case). In that case it returns 0 and + * we just go on with the next page in our bio. If it + * can't handle the error it will return -EIO and we + * remain responsible for that page. + */ + ret = bio_readpage_error(bio, page, start, end, + failed_mirror, NULL); if (ret == 0) { +error_handled: uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); if (err) @@ -2302,6 +2308,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err) uncache_state(&cached); continue; } + if (tree->ops && tree->ops->readpage_io_failed_hook) { + ret = tree->ops->readpage_io_failed_hook( + bio, page, start, end, + failed_mirror, state); + if (ret == 0) + goto error_handled; + } } if (uptodate) { -- cgit From 03360c5a405999d605ffc7373a7b90f3388db92e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 1 Dec 2011 10:44:17 -0500 Subject: Revert "mac80211: clear sta.drv_priv on reconfiguration" This reverts commit f785d83a19bca326f79d127a413e35769afc0105. This was provoking WARNINGs from the iwlegacy drivers. Signed-off-by: John W. Linville --- net/mac80211/util.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0c9490722aa5..6719bce4a081 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1038,7 +1038,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_sub_if_data, u.ap); - memset(&sta->sta.drv_priv, 0, hw->sta_data_size); WARN_ON(drv_sta_add(local, sdata, &sta->sta)); } } -- cgit From 2ed4d9d648cbd4fb1c232a646dbdbdfdd373ca94 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 1 Dec 2011 11:02:11 -0500 Subject: drm/radeon/kms: add some new pci ids Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- include/drm/drm_pciids.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index f81676f1b310..4e4fbb820e20 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -197,6 +197,14 @@ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6843, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6849, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ -- cgit From 158886cd2cf4599e04f9b7e10cb767f5f39b14f1 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Wed, 30 Nov 2011 16:37:41 +0800 Subject: xHCI: fix bug in xhci_clear_command_ring() When system enters suspend, xHCI driver clears command ring by writing zero to all the TRBs. However, this also writes zero to the Link TRB, and the ring is mangled. This may cause driver accesses wrong memory address and the result is unpredicted. When clear the command ring, keep the last Link TRB intact, only clear its cycle bit. This should fix the "command ring full" issue reported by Oliver Neukum. This should be backported to stable kernels as old as 2.6.37, since the commit 89821320 "xhci: Fix command ring replay after resume" is merged. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Reported-by: Oliver Neukum --- drivers/usb/host/xhci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index aa94c0195791..a1afb7c39f7e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -711,7 +711,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) ring = xhci->cmd_ring; seg = ring->deq_seg; do { - memset(seg->trbs, 0, SEGMENT_SIZE); + memset(seg->trbs, 0, + sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1)); + seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= + cpu_to_le32(~TRB_CYCLE); seg = seg->next; } while (seg != ring->deq_seg); -- cgit From efbc368dcc6426d5430b9b8eeda944cf2cb74b8c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Dec 2011 13:38:59 -0500 Subject: ipv4: Perform peer validation on cached route lookup. Otherwise we won't notice the peer GENID change. Reported-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv4/route.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 57e01bc60947..ca5e237df029 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1693,12 +1693,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } -static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) +static struct rtable *ipv4_validate_peer(struct rtable *rt) { - struct rtable *rt = (struct rtable *) dst; - - if (rt_is_expired(rt)) - return NULL; if (rt->rt_peer_genid != rt_peer_genid()) { struct inet_peer *peer; @@ -1707,19 +1703,29 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) peer = rt->peer; if (peer) { - check_peer_pmtu(dst, peer); + check_peer_pmtu(&rt->dst, peer); if (peer->redirect_genid != redirect_genid) peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { - if (check_peer_redir(dst, peer)) + if (check_peer_redir(&rt->dst, peer)) return NULL; } } rt->rt_peer_genid = rt_peer_genid(); } + return rt; +} + +static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) +{ + struct rtable *rt = (struct rtable *) dst; + + if (rt_is_expired(rt)) + return NULL; + dst = (struct dst_entry *) ipv4_validate_peer(rt); return dst; } @@ -2374,6 +2380,9 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + rth = ipv4_validate_peer(rth); + if (!rth) + continue; if (noref) { dst_use_noref(&rth->dst, jiffies); skb_dst_set_noref(skb, &rth->dst); @@ -2749,6 +2758,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + rth = ipv4_validate_peer(rth); + if (!rth) + continue; dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); -- cgit From 0de13500ad1d8a66b7dc1e7fa517ea15a2625c9e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 1 Dec 2011 10:30:16 -0800 Subject: Revert "xHCI: reset-on-resume quirk for NEC uPD720200" This reverts commit df711fc9962b9491af2b92bd0d21ecbfefe4e5fa. The commit added a reset-on-resume quirk because the NEC chipset stopped responding to commands about 30 minutes after a system resume from suspend. We thought it was a chipset issue, but it turns out that the xHCI driver was zeroing out the link TRB after a successful context restore during resume. The host controller would fall off the command ring sometime later, causing it to not respond to new commands. The link TRB issue has been fixed with commit 158886cd2cf4599e04f9b7e10cb767f5f39b14f1 "xHCI: fix bug in xhci_clear_command_ring()", so revert the reset-on-resume quirk, as it's not necessary. Commit df711fc9962b9491af2b92bd0d21ecbfefe4e5fa was marked for stable trees back to 2.6.37, but according to my mail, it has not made it into Linus' tree or the stable trees yet. Signed-off-by: Sarah Sharp Tested-by: Julian Sikorski Cc: Andiry Xu --- drivers/usb/host/xhci-pci.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index d2a7332daca4..ef98b38626fb 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -33,8 +33,6 @@ #define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_DEVICE_ID_ASROCK_P67 0x7023 -#define PCI_DEVICE_ID_NEC_uPD720200 0x0194 - static const char hcd_name[] = "xhci_hcd"; /* called after powerup, by probe or system-pm "wakeup" */ @@ -76,11 +74,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->revision); } - if (pdev->vendor == PCI_VENDOR_ID_NEC) { + if (pdev->vendor == PCI_VENDOR_ID_NEC) xhci->quirks |= XHCI_NEC_HOST; - if (pdev->device == PCI_DEVICE_ID_NEC_uPD720200) - xhci->quirks |= XHCI_RESET_ON_RESUME; - } if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96) xhci->quirks |= XHCI_AMD_0x96_HOST; -- cgit From 307369b0ca06b27b511b61714e335ddfccf19c4f Mon Sep 17 00:00:00 2001 From: Marcin Kościelnicki Date: Wed, 30 Nov 2011 17:01:04 +0100 Subject: usb: ftdi_sio: add PID for Propox ISPcable III MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Kościelnicki Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bd4298bb6750..ff3db5d056a5 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -736,6 +736,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 571fa96b49c7..055b64ef0bba 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -112,6 +112,7 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739 /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 -- cgit From 7fdcf13b292e8b2e38e42de24be2503e37b2cf97 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 1 Dec 2011 14:00:15 -0500 Subject: SUNRPC: Fix the execution time statistics in the face of RPC restarts If the rpc_task gets restarted, then we want to ensure that we don't double-count the execution time statistics, timeout data, etc. Signed-off-by: Trond Myklebust --- net/sunrpc/sched.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index d12ffa545811..00a1a2acd587 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -590,6 +590,27 @@ void rpc_prepare_task(struct rpc_task *task) task->tk_ops->rpc_call_prepare(task, task->tk_calldata); } +static void +rpc_init_task_statistics(struct rpc_task *task) +{ + /* Initialize retry counters */ + task->tk_garb_retry = 2; + task->tk_cred_retry = 2; + task->tk_rebind_retry = 2; + + /* starting timestamp */ + task->tk_start = ktime_get(); +} + +static void +rpc_reset_task_statistics(struct rpc_task *task) +{ + task->tk_timeouts = 0; + task->tk_flags &= ~(RPC_CALL_MAJORSEEN|RPC_TASK_KILLED|RPC_TASK_SENT); + + rpc_init_task_statistics(task); +} + /* * Helper that calls task->tk_ops->rpc_call_done if it exists */ @@ -602,6 +623,7 @@ void rpc_exit_task(struct rpc_task *task) WARN_ON(RPC_ASSASSINATED(task)); /* Always release the RPC slot and buffer memory */ xprt_release(task); + rpc_reset_task_statistics(task); } } } @@ -804,11 +826,6 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta task->tk_calldata = task_setup_data->callback_data; INIT_LIST_HEAD(&task->tk_task); - /* Initialize retry counters */ - task->tk_garb_retry = 2; - task->tk_cred_retry = 2; - task->tk_rebind_retry = 2; - task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; task->tk_owner = current->tgid; @@ -818,8 +835,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta if (task->tk_ops->rpc_call_prepare != NULL) task->tk_action = rpc_prepare_task; - /* starting timestamp */ - task->tk_start = ktime_get(); + rpc_init_task_statistics(task); dprintk("RPC: new task initialized, procpid %u\n", task_pid_nr(current)); -- cgit From b03b6dd58cef7d15b7c46a6729b83dd535ef08ab Mon Sep 17 00:00:00 2001 From: Vitalii Demianets Date: Fri, 25 Nov 2011 00:16:37 +0000 Subject: bridge: master device stuck in no-carrier state forever when in user-stp mode When in user-stp mode, bridge master do not follow state of its slaves, so after the following sequence of events it can stuck forever in no-carrier state: 1) turn stp off 2) put all slaves down - master device will follow their state and also go in no-carrier state 3) turn stp on with bridge-stp script returning 0 (go to the user-stp mode) Now bridge master won't follow slaves' state and will never reach running state. This patch solves the problem by making user-stp and kernel-stp behavior similar regarding master following slaves' states. Signed-off-by: Vitalii Demianets Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_netlink.c | 6 ++++++ net/bridge/br_stp.c | 29 ++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index e5f9ece3c9a0..a1daf8227ed1 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -18,6 +18,7 @@ #include #include "br_private.h" +#include "br_private_stp.h" static inline size_t br_nlmsg_size(void) { @@ -188,6 +189,11 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) p->state = new_state; br_log_state(p); + + spin_lock_bh(&p->br->lock); + br_port_state_selection(p->br); + spin_unlock_bh(&p->br->lock); + br_ifinfo_notify(RTM_NEWLINK, p); return 0; diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index ad0a3f7cf6cc..dd147d78a588 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -399,25 +399,24 @@ void br_port_state_selection(struct net_bridge *br) struct net_bridge_port *p; unsigned int liveports = 0; - /* Don't change port states if userspace is handling STP */ - if (br->stp_enabled == BR_USER_STP) - return; - list_for_each_entry(p, &br->port_list, list) { if (p->state == BR_STATE_DISABLED) continue; - if (p->port_no == br->root_port) { - p->config_pending = 0; - p->topology_change_ack = 0; - br_make_forwarding(p); - } else if (br_is_designated_port(p)) { - del_timer(&p->message_age_timer); - br_make_forwarding(p); - } else { - p->config_pending = 0; - p->topology_change_ack = 0; - br_make_blocking(p); + /* Don't change port states if userspace is handling STP */ + if (br->stp_enabled != BR_USER_STP) { + if (p->port_no == br->root_port) { + p->config_pending = 0; + p->topology_change_ack = 0; + br_make_forwarding(p); + } else if (br_is_designated_port(p)) { + del_timer(&p->message_age_timer); + br_make_forwarding(p); + } else { + p->config_pending = 0; + p->topology_change_ack = 0; + br_make_blocking(p); + } } if (p->state == BR_STATE_FORWARDING) -- cgit From 59c2cdae2791c0b2ee13d148edc6b771e7e7953f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Dec 2011 14:12:55 -0500 Subject: Revert "udp: remove redundant variable" This reverts commit 81d54ec8479a2c695760da81f05b5a9fb2dbe40a. If we take the "try_again" goto, due to a checksum error, the 'len' has already been truncated. So we won't compute the same values as the original code did. Reported-by: paul bilke Signed-off-by: David S. Miller --- net/ipv4/udp.c | 15 ++++++++------- net/ipv6/udp.c | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ab0966df1e2a..5a65eeac1d29 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1164,7 +1164,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; struct sk_buff *skb; - unsigned int ulen; + unsigned int ulen, copied; int peeked; int err; int is_udplite = IS_UDPLITE(sk); @@ -1186,9 +1186,10 @@ try_again: goto out; ulen = skb->len - sizeof(struct udphdr); - if (len > ulen) - len = ulen; - else if (len < ulen) + copied = len; + if (copied > ulen) + copied = ulen; + else if (copied < ulen) msg->msg_flags |= MSG_TRUNC; /* @@ -1197,14 +1198,14 @@ try_again: * coverage checksum (UDP-Lite), do it before the copy. */ - if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { if (udp_lib_checksum_complete(skb)) goto csum_copy_err; } if (skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), - msg->msg_iov, len); + msg->msg_iov, copied); else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), @@ -1233,7 +1234,7 @@ try_again: if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); - err = len; + err = copied; if (flags & MSG_TRUNC) err = ulen; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 846f4757eb8d..8c2541915183 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -340,7 +340,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, struct ipv6_pinfo *np = inet6_sk(sk); struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; - unsigned int ulen; + unsigned int ulen, copied; int peeked; int err; int is_udplite = IS_UDPLITE(sk); @@ -363,9 +363,10 @@ try_again: goto out; ulen = skb->len - sizeof(struct udphdr); - if (len > ulen) - len = ulen; - else if (len < ulen) + copied = len; + if (copied > ulen) + copied = ulen; + else if (copied < ulen) msg->msg_flags |= MSG_TRUNC; is_udp4 = (skb->protocol == htons(ETH_P_IP)); @@ -376,14 +377,14 @@ try_again: * coverage checksum (UDP-Lite), do it before the copy. */ - if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { if (udp_lib_checksum_complete(skb)) goto csum_copy_err; } if (skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), - msg->msg_iov,len); + msg->msg_iov, copied ); else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); if (err == -EINVAL) @@ -432,7 +433,7 @@ try_again: datagram_recv_ctl(sk, msg, skb); } - err = len; + err = copied; if (flags & MSG_TRUNC) err = ulen; -- cgit From c25573b5134294c0be82bfaecc6d08136835b271 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 1 Dec 2011 14:16:17 -0500 Subject: SUNRPC: Ensure we always bump the backlog queue in xprt_free_slot Whenever we free a slot, we know that the resulting xprt->num_reqs will be less than xprt->max_reqs, so we know that we can release at least one backlogged rpc_task. Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>=3.1] --- net/sunrpc/xprt.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index f4385e45a5fc..c64c0ef519b5 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -995,13 +995,11 @@ out_init_req: static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) { - if (xprt_dynamic_free_slot(xprt, req)) - return; - - memset(req, 0, sizeof(*req)); /* mark unused */ - spin_lock(&xprt->reserve_lock); - list_add(&req->rq_list, &xprt->free); + if (!xprt_dynamic_free_slot(xprt, req)) { + memset(req, 0, sizeof(*req)); /* mark unused */ + list_add(&req->rq_list, &xprt->free); + } rpc_wake_up_next(&xprt->backlog); spin_unlock(&xprt->reserve_lock); } -- cgit From 4f38e4aadcca319650c0de31edf7193d7c384de2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 1 Dec 2011 16:31:34 -0500 Subject: NFSv4: Don't error if we handled it in nfs4_recovery_handle_error If we handled an error condition, then nfs4_recovery_handle_error should return '0' so that the state recovery thread can continue. Also ensure that nfs4_check_lease() continues to abort if we haven't got any credentials by having it return ENOKEY (which is not handled). Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 39914be40b03..1da95e3947bb 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1350,12 +1350,14 @@ static void nfs4_warn_keyexpired(const char *s) static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) { switch (error) { + case 0: + break; case -NFS4ERR_CB_PATH_DOWN: nfs_handle_cb_pathdown(clp); - return 0; + break; case -NFS4ERR_NO_GRACE: nfs4_state_end_reclaim_reboot(clp); - return 0; + break; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); @@ -1375,13 +1377,15 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) case -NFS4ERR_SEQ_MISORDERED: set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* Zero session reset errors */ - return 0; + break; case -EKEYEXPIRED: /* Nothing we can do */ nfs4_warn_keyexpired(clp->cl_hostname); - return 0; + break; + default: + return error; } - return error; + return 0; } static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) @@ -1428,7 +1432,7 @@ static int nfs4_check_lease(struct nfs_client *clp) struct rpc_cred *cred; const struct nfs4_state_maintenance_ops *ops = clp->cl_mvops->state_renewal_ops; - int status = -NFS4ERR_EXPIRED; + int status; /* Is the client already known to have an expired lease? */ if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) @@ -1438,6 +1442,7 @@ static int nfs4_check_lease(struct nfs_client *clp) spin_unlock(&clp->cl_lock); if (cred == NULL) { cred = nfs4_get_setclientid_cred(clp); + status = -ENOKEY; if (cred == NULL) goto out; } @@ -1662,10 +1667,10 @@ static void nfs4_state_manager(struct nfs_client *clp) if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { status = nfs4_check_lease(clp); + if (status < 0) + goto out_error; if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue; - if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN) - goto out_error; } /* Initialize or reset the session */ -- cgit From 111d489f0fb431f4ae85d96851fbf8d3248c09d8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 1 Dec 2011 16:37:42 -0500 Subject: NFSv4.1: Ensure that we handle _all_ SEQUENCE status bits. Currently, the code assumes that the SEQUENCE status bits are mutually exclusive. They are not... Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>= 2.6.34] --- fs/nfs/nfs4state.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 1da95e3947bb..da8d73ed9e0f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1530,16 +1530,16 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) { if (!flags) return; - else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) + if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) nfs41_handle_server_reboot(clp); - else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | + if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | SEQ4_STATUS_ADMIN_STATE_REVOKED | SEQ4_STATUS_LEASE_MOVED)) nfs41_handle_state_revoked(clp); - else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) + if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) nfs41_handle_recallable_state_revoked(clp); - else if (flags & (SEQ4_STATUS_CB_PATH_DOWN | + if (flags & (SEQ4_STATUS_CB_PATH_DOWN | SEQ4_STATUS_BACKCHANNEL_FAULT | SEQ4_STATUS_CB_PATH_DOWN_SESSION)) nfs41_handle_cb_path_down(clp); -- cgit From 939255798a468e1a92f03546de6e87be7b491e57 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 15 Nov 2011 14:56:34 -0800 Subject: ocfs2: avoid unaligned access to dqc_bitmap The dqc_bitmap field of struct ocfs2_local_disk_chunk is 32-bit aligned, but not 64-bit aligned. The dqc_bitmap is accessed by ocfs2_set_bit(), ocfs2_clear_bit(), ocfs2_test_bit(), or ocfs2_find_next_zero_bit(). These are wrapper macros for ext2_*_bit() which need to take an unsigned long aligned address (though some architectures are able to handle unaligned address correctly) So some 64bit architectures may not be able to access the dqc_bitmap correctly. This avoids such unaligned access by using another wrapper functions for ext2_*_bit(). The code is taken from fs/ext4/mballoc.c which also need to handle unaligned bitmap access. Signed-off-by: Akinobu Mita Acked-by: Joel Becker Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Joel Becker --- fs/ocfs2/ocfs2.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/quota_local.c | 10 +++++----- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index bcde467acca3..d355e6e36b36 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -849,5 +849,52 @@ static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap) #define ocfs2_test_bit test_bit_le #define ocfs2_find_next_zero_bit find_next_zero_bit_le #define ocfs2_find_next_bit find_next_bit_le + +static inline void *correct_addr_and_bit_unaligned(int *bit, void *addr) +{ +#if BITS_PER_LONG == 64 + *bit += ((unsigned long) addr & 7UL) << 3; + addr = (void *) ((unsigned long) addr & ~7UL); +#elif BITS_PER_LONG == 32 + *bit += ((unsigned long) addr & 3UL) << 3; + addr = (void *) ((unsigned long) addr & ~3UL); +#else +#error "how many bits you are?!" +#endif + return addr; +} + +static inline void ocfs2_set_bit_unaligned(int bit, void *bitmap) +{ + bitmap = correct_addr_and_bit_unaligned(&bit, bitmap); + ocfs2_set_bit(bit, bitmap); +} + +static inline void ocfs2_clear_bit_unaligned(int bit, void *bitmap) +{ + bitmap = correct_addr_and_bit_unaligned(&bit, bitmap); + ocfs2_clear_bit(bit, bitmap); +} + +static inline int ocfs2_test_bit_unaligned(int bit, void *bitmap) +{ + bitmap = correct_addr_and_bit_unaligned(&bit, bitmap); + return ocfs2_test_bit(bit, bitmap); +} + +static inline int ocfs2_find_next_zero_bit_unaligned(void *bitmap, int max, + int start) +{ + int fix = 0, ret, tmpmax; + bitmap = correct_addr_and_bit_unaligned(&fix, bitmap); + tmpmax = max + fix; + start += fix; + + ret = ocfs2_find_next_zero_bit(bitmap, tmpmax, start) - fix; + if (ret > max) + return max; + return ret; +} + #endif /* OCFS2_H */ diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 942fd65bdad3..f100bf70a906 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -551,8 +551,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, goto out_commit; } lock_buffer(qbh); - WARN_ON(!ocfs2_test_bit(bit, dchunk->dqc_bitmap)); - ocfs2_clear_bit(bit, dchunk->dqc_bitmap); + WARN_ON(!ocfs2_test_bit_unaligned(bit, dchunk->dqc_bitmap)); + ocfs2_clear_bit_unaligned(bit, dchunk->dqc_bitmap); le32_add_cpu(&dchunk->dqc_free, 1); unlock_buffer(qbh); ocfs2_journal_dirty(handle, qbh); @@ -949,7 +949,7 @@ static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb, * ol_quota_entries_per_block(sb); } - found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0); + found = ocfs2_find_next_zero_bit_unaligned(dchunk->dqc_bitmap, len, 0); /* We failed? */ if (found == len) { mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u" @@ -1213,7 +1213,7 @@ static void olq_alloc_dquot(struct buffer_head *bh, void *private) struct ocfs2_local_disk_chunk *dchunk; dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; - ocfs2_set_bit(*offset, dchunk->dqc_bitmap); + ocfs2_set_bit_unaligned(*offset, dchunk->dqc_bitmap); le32_add_cpu(&dchunk->dqc_free, -1); } @@ -1294,7 +1294,7 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot) (od->dq_chunk->qc_headerbh->b_data); /* Mark structure as freed */ lock_buffer(od->dq_chunk->qc_headerbh); - ocfs2_clear_bit(offset, dchunk->dqc_bitmap); + ocfs2_clear_bit_unaligned(offset, dchunk->dqc_bitmap); le32_add_cpu(&dchunk->dqc_free, 1); unlock_buffer(od->dq_chunk->qc_headerbh); ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh); -- cgit From 5611cc4572e889b62a7b4c72a413536bf6a9c416 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 1 Dec 2011 14:56:01 -0800 Subject: Linux 3.2-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3a8f0640cda0..12aafc20efbd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit From b1f919664d04a8d0ba29cb76673c7ca3325a2006 Mon Sep 17 00:00:00 2001 From: "Yang Honggang (Joseph)" Date: Thu, 1 Dec 2011 22:22:41 -0500 Subject: clocksource: Fix bug with max_deferment margin calculation In order to leave a margin of 12.5% we should >> 3 not >> 5. CC: stable@kernel.org Signed-off-by: Yang Honggang (Joseph) [jstultz: Modified commit subject] Signed-off-by: John Stultz --- kernel/time/clocksource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index cfc65e1eb9fb..da2f760e780c 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -548,7 +548,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs) * note a margin of 12.5% is used because this can be computed with * a shift, versus say 10% which would require division. */ - return max_nsecs - (max_nsecs >> 5); + return max_nsecs - (max_nsecs >> 3); } #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET @@ -669,7 +669,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) * ~ 0.06ppm granularity for NTP. We apply the same 12.5% * margin as we do in clocksource_max_deferment() */ - sec = (cs->mask - (cs->mask >> 5)); + sec = (cs->mask - (cs->mask >> 3)); do_div(sec, freq); do_div(sec, scale); if (!sec) -- cgit From 1ee5fa1e9970a16036e37c7b9d5ce81c778252fc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 1 Dec 2011 11:06:34 +0000 Subject: sch_red: fix red_change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le mercredi 30 novembre 2011 à 14:36 -0800, Stephen Hemminger a écrit : > (Almost) nobody uses RED because they can't figure it out. > According to Wikipedia, VJ says that: > "there are not one, but two bugs in classic RED." RED is useful for high throughput routers, I doubt many linux machines act as such devices. I was considering adding Adaptative RED (Sally Floyd, Ramakrishna Gummadi, Scott Shender), August 2001 In this version, maxp is dynamic (from 1% to 50%), and user only have to setup min_th (target average queue size) (max_th and wq (burst in linux RED) are automatically setup) By the way it seems we have a small bug in red_change() if (skb_queue_empty(&sch->q)) red_end_of_idle_period(&q->parms); First, if queue is empty, we should call red_start_of_idle_period(&q->parms); Second, since we dont use anymore sch->q, but q->qdisc, the test is meaningless. Oh well... [PATCH] sch_red: fix red_change() Now RED is classful, we must check q->qdisc->q.qlen, and if queue is empty, we start an idle period, not end it. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_red.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 6649463da1b6..d617161f8dd3 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -209,8 +209,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) ctl->Plog, ctl->Scell_log, nla_data(tb[TCA_RED_STAB])); - if (skb_queue_empty(&sch->q)) - red_end_of_idle_period(&q->parms); + if (!q->qdisc->q.qlen) + red_start_of_idle_period(&q->parms); sch_tree_unlock(sch); return 0; -- cgit From a50527b19c62c808a7fca022816fff88a50b948d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 2 Dec 2011 09:17:02 +0800 Subject: fs: Make write(2) interruptible by a fatal signal Currently write(2) to a file is not interruptible by any signal. Sometimes this is desirable, e.g. when you want to quickly kill a process hogging your disk. Also, with commit 499d05ecf990 ("mm: Make task in balance_dirty_pages() killable"), it's necessary to abort the current write accordingly to avoid it quickly dirtying lots more pages at unthrottled rate. This patch makes write interruptible by SIGKILL. We do not allow write to be interruptible by any other signal because that has larger potential of screwing some badly written applications. Reported-by: Kazuya Mio Tested-by: Kazuya Mio Acked-by: Matthew Wilcox Signed-off-by: Jan Kara Signed-off-by: Wu Fengguang --- mm/filemap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index c0018f2d50e0..c106d3b3cc64 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2407,7 +2407,6 @@ static ssize_t generic_perform_write(struct file *file, iov_iter_count(i)); again: - /* * Bring in the user page that we will copy from _first_. * Otherwise there's a nasty deadlock on copying from the @@ -2463,7 +2462,10 @@ again: written += copied; balance_dirty_pages_ratelimited(mapping); - + if (fatal_signal_pending(current)) { + status = -EINTR; + break; + } } while (iov_iter_count(i)); return written ? written : status; -- cgit From 650f7a72b8cc235ffe4a0e3eff37954349026721 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 1 Dec 2011 17:47:06 -0800 Subject: ARM: OMAP1: Fix reprogramming of DPLL1 for systems that boot at rates below 60MHz Commit e9b7086b80c4d9e354f4edc9e280ae85a60df408 (ARM: OMAP: Fix reprogramming of dpll1 rate) fixed a regression for systems that did not rely on bootloader set rates. However, it also introduced a new problem where the rates selected in .config would not take affect as omap1_select_table_rate currently refuses to reprogram DPLL1 if it's already initialized. This was not a problem earlier, as the reprogramming was done earlier with ck_dpll1_p->rate uninitialized. Fix this by forcing the reprogramming on systems booting at rates below 60MHz. Note that the long term fix is to make the rates SoC specific later on. Thanks for Janusz Krzysztofik for figuring this one out. Reported-by: Janusz Krzysztofik Acked-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/clock_data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index 1297bb58869c..3f305610efa0 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c @@ -930,6 +930,9 @@ void __init omap1_clk_late_init(void) if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE) return; + /* System booting at unusable rate, force reprogramming of DPLL1 */ + ck_dpll1_p->rate = 0; + /* Find the highest supported frequency and enable it */ if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { pr_err("System frequencies not set, using default. Check your config.\n"); -- cgit From b29e23547ecb2a609777288cd81fc83b01f9f43f Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 1 Dec 2011 21:30:39 +0100 Subject: ARM: OMAP1: Remove unsafe clock values from omap1_defconfig DPLL1 reprogramming to a different rate is actually blocked inside omap1_select_table_rate(), resulting in the defalut rate of 60 MHz always used instead of the one selected in .config. OTOH, in omap1_defconfig we currently rely on Kconfig options for the supported MHz rates in case of boards which boot with dpll1 not set correctly by their boot loaders. This means that before we allow for reprogramming of dpll1 rate, we should remove all unsafe clock selections from omap1_defconfig, otherwise it will stop booting on boards with imperfect boot loaders, as it would always try to change to 216MHz. Keep only one safe clock rate per each supported xtal frequency, i.e. 60MHZ dpll1 for 12MHz xtal and 182MHz dpll1 for 13MHz xtal. BTW, this change goes into the direction of removing all OMAP1 clock rate options, planned for next merge window. Signed-off-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/configs/omap1_defconfig | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig index a7e777581378..945a34f2a34d 100644 --- a/arch/arm/configs/omap1_defconfig +++ b/arch/arm/configs/omap1_defconfig @@ -48,12 +48,7 @@ CONFIG_MACH_SX1=y CONFIG_MACH_NOKIA770=y CONFIG_MACH_AMS_DELTA=y CONFIG_MACH_OMAP_GENERIC=y -CONFIG_OMAP_ARM_216MHZ=y -CONFIG_OMAP_ARM_195MHZ=y -CONFIG_OMAP_ARM_192MHZ=y CONFIG_OMAP_ARM_182MHZ=y -CONFIG_OMAP_ARM_168MHZ=y -# CONFIG_OMAP_ARM_60MHZ is not set # CONFIG_ARM_THUMB is not set CONFIG_PCCARD=y CONFIG_OMAP_CF=y -- cgit From c2cb211116192690605eaa70d39deb04241003e2 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 1 Dec 2011 21:13:01 +0100 Subject: ARM: OMAP1: Fix ckctl value used for dpll1 defualt rate Use the exact value found in omap1_rate_table, otherwise I have been experiencing issues with correct timekeeping on my Amstrad Delta. Signed-off-by: Janusz Krzysztofik [tony@atomide.com: removed comment referencing a development branch] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/clock_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index 3f305610efa0..86b2dec11788 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c @@ -937,7 +937,7 @@ void __init omap1_clk_late_init(void) if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { pr_err("System frequencies not set, using default. Check your config.\n"); omap_writew(0x2290, DPLL_CTL); - omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); + omap_writew(cpu_is_omap7xx() ? 0x2005 : 0x0005, ARM_CKCTL); ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE; } propagate_rate(&ck_dpll1); -- cgit From d01ff0a049f749e0bf10a35bb23edd012718c8c2 Mon Sep 17 00:00:00 2001 From: "Peter Pan(潘卫平)" Date: Thu, 1 Dec 2011 15:47:06 +0000 Subject: ipv4: flush route cache after change accept_local After reset ipv4_devconf->data[IPV4_DEVCONF_ACCEPT_LOCAL] to 0, we should flush route cache, or it will continue receive packets with local source address, which should be dropped. Signed-off-by: Weiping Pan Signed-off-by: David S. Miller --- net/ipv4/devinet.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index c6b5092f29a1..65f01dc47565 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1490,7 +1490,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { + int old_value = *(int *)ctl->data; int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + int new_value = *(int *)ctl->data; if (write) { struct ipv4_devconf *cnf = ctl->extra1; @@ -1501,6 +1503,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write, if (cnf == net->ipv4.devconf_dflt) devinet_copy_dflt_conf(net, i); + if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1) + if ((new_value == 0) && (old_value != 0)) + rt_cache_flush(net, 0); } return ret; -- cgit From 1bdfd27a0bd65ccdd7294c1080bdb59f6a5a6e72 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 17 Nov 2011 22:18:14 +0800 Subject: ARM: CSR: fix build error due to new mdesc->dma_zone_size commit 98b0124f0e2b88 "ARM: mach-prima2: move ARM_DMA_ZONE_SIZE to mdesc->dma_zone_size" causes building error: arch/arm/mach-prima2/prima2.c:39:19: error: 'SZ_256M' undeclared here (not in a function) Signed-off-by: Barry Song --- arch/arm/mach-prima2/prima2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c index ef555c041962..a12b689a8702 100644 --- a/arch/arm/mach-prima2/prima2.c +++ b/arch/arm/mach-prima2/prima2.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include -- cgit From b2dcb8723eb61d00c40d526702d08f6d805f5f01 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 17 Nov 2011 22:27:22 +0800 Subject: ARM: CSR: PM: fix build error due to undeclared 'THIS_MODULE' In the new kernel, we will get the following compile error: arch/arm/mach-prima2/pm.c:141: error: 'THIS_MODULE' undeclared here (not in a function) so include module.h head file explicitly Signed-off-by: Barry Song --- arch/arm/mach-prima2/pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c index cb53160f6c5d..26ebb57719df 100644 --- a/arch/arm/mach-prima2/pm.c +++ b/arch/arm/mach-prima2/pm.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include -- cgit From d3d9acf646679c1981032b0985b386d12fccc60c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 23 Nov 2011 08:49:49 -0800 Subject: trace_events_filter: Use rcu_assign_pointer() when setting ftrace_event_call->filter ftrace_event_call->filter is sched RCU protected but didn't use rcu_assign_pointer(). Use it. TODO: Add proper __rcu annotation to call->filter and all its users. -v2: Use RCU_INIT_POINTER() for %NULL clearing as suggested by Eric. Link: http://lkml.kernel.org/r/20111123164949.GA29639@google.com Cc: Eric Dumazet Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: stable@kernel.org # (2.6.39+) Signed-off-by: Tejun Heo Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 816d3d074979..d6e7926dcd26 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1686,7 +1686,7 @@ static int replace_system_preds(struct event_subsystem *system, * replace the filter for the call. */ filter = call->filter; - call->filter = filter_item->filter; + rcu_assign_pointer(call->filter, filter_item->filter); filter_item->filter = filter; fail = false; @@ -1741,7 +1741,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) filter = call->filter; if (!filter) goto out_unlock; - call->filter = NULL; + RCU_INIT_POINTER(call->filter, NULL); /* Make sure the filter is not being used */ synchronize_sched(); __free_filter(filter); @@ -1782,7 +1782,7 @@ out: * string */ tmp = call->filter; - call->filter = filter; + rcu_assign_pointer(call->filter, filter); if (tmp) { /* Make sure the call is done with the filter */ synchronize_sched(); -- cgit From 3ced1be5490f5c415d51a1e5918beeb9239d546b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Dec 2011 22:19:01 -0500 Subject: netfilter: Remove ADVANCED dependency from NF_CONNTRACK_NETBIOS_NS firewalld in Fedora 16 needs this. Signed-off-by: David S. Miller --- net/netfilter/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index e8f379692294..d5597b759ba3 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -201,7 +201,6 @@ config NF_CONNTRACK_BROADCAST config NF_CONNTRACK_NETBIOS_NS tristate "NetBIOS name service protocol support" - depends on NETFILTER_ADVANCED select NF_CONNTRACK_BROADCAST help NetBIOS name service requests are sent as broadcast messages from an -- cgit From 769bbb634f30c1b76277623676011a77f31bcc20 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 2 Dec 2011 13:51:56 +0900 Subject: MAINTAINERS: Consolidate Samsung MAINTAINERS These days most Samsung stuff gets in the kernel through Kukjin Kim. This patch changes MAINTAINERS to reflect this. By adding Kukjin Kim to the maintainers for S3C2410, S3C244x and S3C64xx alongside Ben Dooks the extra entries become identical to the base ARM/SAMSUNG entry and can move into it. Also the S3C2416 gets a maintainer through the s3c24* wildcard - as it did not have one until now. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- MAINTAINERS | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 447560284996..1445a830b4f8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1059,31 +1059,11 @@ S: Maintained F: arch/arm/plat-samsung/ F: arch/arm/plat-s3c24xx/ F: arch/arm/plat-s5p/ +F: arch/arm/mach-s3c24*/ +F: arch/arm/mach-s3c64xx/ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* -ARM/S3C2410 ARM ARCHITECTURE -M: Ben Dooks -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.fluff.org/ben/linux/ -S: Maintained -F: arch/arm/mach-s3c2410/ - -ARM/S3C244x ARM ARCHITECTURE -M: Ben Dooks -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.fluff.org/ben/linux/ -S: Maintained -F: arch/arm/mach-s3c2440/ -F: arch/arm/mach-s3c2443/ - -ARM/S3C64xx ARM ARCHITECTURE -M: Ben Dooks -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.fluff.org/ben/linux/ -S: Maintained -F: arch/arm/mach-s3c64xx/ - ARM/S5P EXYNOS ARM ARCHITECTURES M: Kukjin Kim L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- cgit From 7a549d78e7d897651a4bc36ade7563c34cab9f8b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Dec 2011 13:52:12 +0900 Subject: MAINTAINERS: Add linux-samsung-soc mailing list for Samsung There's a Samsung-specific mailing list but it's not advertised in MAINTAINERS - add it to the overall architecture to make it more discoverable. Signed-off-by: Mark Brown [kgene.kim@samsung.com: added notice of 'moderated'] Signed-off-by: Kukjin Kim --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1445a830b4f8..523039045b36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1054,6 +1054,7 @@ ARM/SAMSUNG ARM ARCHITECTURES M: Ben Dooks M: Kukjin Kim L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/plat-samsung/ -- cgit From 40c76662a1ae7f88afa22ae3b1265497e4271f72 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Dec 2011 13:54:25 +0900 Subject: MAINTAINERS: Extend Samsung patterns to cover SPI and ASoC drivers Help people find the overall architecture. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 523039045b36..b4f18024f4e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1064,6 +1064,8 @@ F: arch/arm/mach-s3c24*/ F: arch/arm/mach-s3c64xx/ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* +F: drivers/spi/spi-s3c* +F: sound/soc/samsung/* ARM/S5P EXYNOS ARM ARCHITECTURES M: Kukjin Kim -- cgit From ade145cc4885fbdf47b3abd9cd6baf23b8367fef Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Dec 2011 14:17:36 +0900 Subject: ARM: S3C64XX: Remove extern from definition of framebuffer setup call The extern is only useful on prototypes. Signed-off-by: Mark Brown Cc: stable@kernel.org Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/setup-fb-24bpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c index 83d2afb79e9f..2cf80026c58d 100644 --- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c +++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c @@ -20,7 +20,7 @@ #include #include -extern void s3c64xx_fb_gpio_setup_24bpp(void) +void s3c64xx_fb_gpio_setup_24bpp(void) { s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2)); s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2)); -- cgit From f4a65ad6eb9b56180724de52ddd6dd6712121be1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Dec 2011 14:17:54 +0900 Subject: ARM: S3C64XX: Add linux/export.h to dev-spi.c This is required for the EXPORT_SYMBOL()s the code uses, previously the header was being included implicitly by another header. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/dev-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c index 5e6b42089eb4..3341fd118723 100644 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ b/arch/arm/mach-s3c64xx/dev-spi.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include -- cgit From 71b33a4f7c864bf5fc893b5ca144770ad05f1d4a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Dec 2011 14:18:02 +0900 Subject: ARM: S3C64XX: Staticise s3c6400_sysclass The symbol is not exported and doesn't need to be. Signed-off-by: Mark Brown Cc: stable@kernel.org Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/s3c6400.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c index 7a3bc32df425..51c00f2453c6 100644 --- a/arch/arm/mach-s3c64xx/s3c6400.c +++ b/arch/arm/mach-s3c64xx/s3c6400.c @@ -70,7 +70,7 @@ void __init s3c6400_init_irq(void) s3c64xx_init_irq(~0 & ~(0xf << 5), ~0); } -struct sysdev_class s3c6400_sysclass = { +static struct sysdev_class s3c6400_sysclass = { .name = "s3c6400-core", }; -- cgit From 5d348401ed03450395ce674594c1c08c7d85bd8d Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sat, 12 Nov 2011 00:09:05 +0800 Subject: ARM: mxs/tx28: add __initconst for fec pdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dong Aisheng Acked-by: Lothar Waßmann Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/module-tx28.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mxs/module-tx28.c b/arch/arm/mach-mxs/module-tx28.c index 0fcff47009cf..9a7b08b2a925 100644 --- a/arch/arm/mach-mxs/module-tx28.c +++ b/arch/arm/mach-mxs/module-tx28.c @@ -66,11 +66,11 @@ static const iomux_cfg_t tx28_fec1_pads[] __initconst = { MX28_PAD_ENET0_CRS__ENET1_RX_EN, }; -static struct fec_platform_data tx28_fec0_data = { +static const struct fec_platform_data tx28_fec0_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; -static struct fec_platform_data tx28_fec1_data = { +static const struct fec_platform_data tx28_fec1_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; -- cgit From 8d2d2d1d7e96f12d9fe140169fb39ef9fd27b7c1 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Mon, 21 Nov 2011 10:55:55 +0200 Subject: ARM: mxs: fix machines' initializers order Initializers of m28evk and stmp378x_devb fixed to be in order they are called. reference: http://article.gmane.org/gmane.linux.ports.arm.omap/50721 Cc: Shawn Guo Signed-off-by: Lauri Hintsala Acked-by: Russell King Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/mach-m28evk.c | 2 +- arch/arm/mach-mxs/mach-stmp378x_devb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c index 3b1681e4f49a..6b00577b7025 100644 --- a/arch/arm/mach-mxs/mach-m28evk.c +++ b/arch/arm/mach-mxs/mach-m28evk.c @@ -361,6 +361,6 @@ static struct sys_timer m28evk_timer = { MACHINE_START(M28EVK, "DENX M28 EVK") .map_io = mx28_map_io, .init_irq = mx28_init_irq, - .init_machine = m28evk_init, .timer = &m28evk_timer, + .init_machine = m28evk_init, MACHINE_END diff --git a/arch/arm/mach-mxs/mach-stmp378x_devb.c b/arch/arm/mach-mxs/mach-stmp378x_devb.c index 177e53123a02..6834dea38c04 100644 --- a/arch/arm/mach-mxs/mach-stmp378x_devb.c +++ b/arch/arm/mach-mxs/mach-stmp378x_devb.c @@ -115,6 +115,6 @@ static struct sys_timer stmp378x_dvb_timer = { MACHINE_START(STMP378X, "STMP378X") .map_io = mx23_map_io, .init_irq = mx23_init_irq, - .init_machine = stmp378x_dvb_init, .timer = &stmp378x_dvb_timer, + .init_machine = stmp378x_dvb_init, MACHINE_END -- cgit From 11357be9246c7d1acf9b37ad54a18b29bbb734be Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 26 Nov 2011 11:39:14 +0100 Subject: arm: mx23: recognise stmp378x as mx23 Adding the machine_is_* line was forgotten when converting mach-stmp378x to mach-mxs. Signed-off-by: Wolfram Sang Signed-off-by: Shawn Guo Cc: stable@kernel.org --- arch/arm/mach-mxs/include/mach/mxs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h index 0d2d2b470998..bde5f6634747 100644 --- a/arch/arm/mach-mxs/include/mach/mxs.h +++ b/arch/arm/mach-mxs/include/mach/mxs.h @@ -30,6 +30,7 @@ */ #define cpu_is_mx23() ( \ machine_is_mx23evk() || \ + machine_is_stmp378x() || \ 0) #define cpu_is_mx28() ( \ machine_is_mx28evk() || \ -- cgit From 7d8b894ca135a896f32934f7d096714d5bc687e6 Mon Sep 17 00:00:00 2001 From: Peter Rusko Date: Wed, 30 Nov 2011 16:43:27 +0100 Subject: ARM: mx28: LRADC macro rename It's a correction of two macro names, renaming them from IRADC to LRADC. Signed-off-by: Peter Rusko Acked-by: Wolfram Sang Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/include/mach/mx28.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mxs/include/mach/mx28.h b/arch/arm/mach-mxs/include/mach/mx28.h index 75d86118b76a..30c7990f3c01 100644 --- a/arch/arm/mach-mxs/include/mach/mx28.h +++ b/arch/arm/mach-mxs/include/mach/mx28.h @@ -104,8 +104,8 @@ #define MX28_INT_CAN1 9 #define MX28_INT_LRADC_TOUCH 10 #define MX28_INT_HSADC 13 -#define MX28_INT_IRADC_THRESH0 14 -#define MX28_INT_IRADC_THRESH1 15 +#define MX28_INT_LRADC_THRESH0 14 +#define MX28_INT_LRADC_THRESH1 15 #define MX28_INT_LRADC_CH0 16 #define MX28_INT_LRADC_CH1 17 #define MX28_INT_LRADC_CH2 18 -- cgit From 5eb46851de3904cd1be9192fdacb8d34deadc1fc Mon Sep 17 00:00:00 2001 From: Yasuaki Ishimatsu Date: Fri, 2 Dec 2011 10:07:07 +0100 Subject: cfq-iosched: fix cfq_cic_link() race confition cfq_cic_link() has race condition. When some processes which shared ioc issue I/O to same block device simultaneously, cfq_cic_link() returns -EEXIST sometimes. The race condition might stop I/O by following steps: step 1: Process A: Issue an I/O to /dev/sda step 2: Process A: Get an ioc (iocA here) in get_io_context() which does not linked with a cic for the device step 3: Process A: Get a new cic for the device (cicA here) in cfq_alloc_io_context() step 4: Process B: Issue an I/O to /dev/sda step 5: Process B: Get iocA in get_io_context() since process A and B share the same ioc step 6: Process B: Get a new cic for the device (cicB here) in cfq_alloc_io_context() since iocA has not been linked with a cic for the device yet step 7: Process A: Link cicA to iocA in cfq_cic_link() step 8: Process A: Dispatch I/O to driver and finish it step 9: Process B: Try to link cicB to iocA in cfq_cic_link() But it fails with showing "cfq: cic link failed!" kernel message, since iocA has already linked with cicA at step 7. step 10: Process B: Wait for finishig I/O in get_request_wait() The function does not wake up, when there is no I/O to the device. When cfq_cic_link() returns -EEXIST, it means ioc has already linked with cic. So when cfq_cic_link() return -EEXIST, retry cfq_cic_lookup(). Signed-off-by: Yasuaki Ishimatsu Cc: stable@kernel.org Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3beed83437a3..4c12869fcf77 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3184,7 +3184,7 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, } } - if (ret) + if (ret && ret != -EEXIST) printk(KERN_ERR "cfq: cic link failed!\n"); return ret; @@ -3200,6 +3200,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) { struct io_context *ioc = NULL; struct cfq_io_context *cic; + int ret; might_sleep_if(gfp_mask & __GFP_WAIT); @@ -3207,6 +3208,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (!ioc) return NULL; +retry: cic = cfq_cic_lookup(cfqd, ioc); if (cic) goto out; @@ -3215,7 +3217,12 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (cic == NULL) goto err; - if (cfq_cic_link(cfqd, ioc, cic, gfp_mask)) + ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask); + if (ret == -EEXIST) { + /* someone has linked cic to ioc already */ + cfq_cic_free(cic); + goto retry; + } else if (ret) goto err_free; out: -- cgit From fc084e0b930d546872ab23667052499f7daf0fed Mon Sep 17 00:00:00 2001 From: David Dillow Date: Thu, 1 Dec 2011 23:26:53 -0500 Subject: ALSA: sis7019 - give slow codecs more time to reset There are some AC97 codec and board combinations that have been observed to take a very long time to respond after the cold reset has completed. In one case, more than 350 ms was required. To allow users to have sound on those platforms, we'll wait up to 500ms for the codec to become ready. As a board may have multiple codecs, with some faster than others to reset, we add a module parameter to inform the driver which codecs should be present. Reported-by: KotCzarny Signed-off-by: David Dillow Cc: Signed-off-by: Takashi Iwai --- sound/pci/sis7019.c | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index a391e622a192..28dfafb56dd1 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int enable = 1; +static int codecs = 1; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); @@ -48,6 +49,8 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); module_param(enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); +module_param(codecs, int, 0444); +MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, @@ -140,6 +143,9 @@ struct sis7019 { dma_addr_t silence_dma_addr; }; +/* These values are also used by the module param 'codecs' to indicate + * which codecs should be present. + */ #define SIS_PRIMARY_CODEC_PRESENT 0x0001 #define SIS_SECONDARY_CODEC_PRESENT 0x0002 #define SIS_TERTIARY_CODEC_PRESENT 0x0004 @@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis) { unsigned long io = sis->ioport; void __iomem *ioaddr = sis->ioaddr; + unsigned long timeout; u16 status; int count; int i; @@ -1104,21 +1111,45 @@ static int sis_chip_init(struct sis7019 *sis) while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) udelay(1); + /* Command complete, we can let go of the semaphore now. + */ + outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); + if (!count) + return -EIO; + /* Now that we've finished the reset, find out what's attached. + * There are some codec/board combinations that take an extremely + * long time to come up. 350+ ms has been observed in the field, + * so we'll give them up to 500ms. */ - status = inl(io + SIS_AC97_STATUS); - if (status & SIS_AC97_STATUS_CODEC_READY) - sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC2_READY) - sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC3_READY) - sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; - - /* All done, let go of the semaphore, and check for errors + sis->codecs_present = 0; + timeout = msecs_to_jiffies(500) + jiffies; + while (time_before_eq(jiffies, timeout)) { + status = inl(io + SIS_AC97_STATUS); + if (status & SIS_AC97_STATUS_CODEC_READY) + sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC2_READY) + sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC3_READY) + sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; + + if (sis->codecs_present == codecs) + break; + + msleep(1); + } + + /* All done, check for errors. */ - outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); - if (!sis->codecs_present || !count) + if (!sis->codecs_present) { + printk(KERN_ERR "sis7019: could not find any codecs\n"); return -EIO; + } + + if (sis->codecs_present != codecs) { + printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", + sis->codecs_present, codecs); + } /* Let the hardware know that the audio driver is alive, * and enable PCM slots on the AC-link for L/R playback (3 & 4) and @@ -1390,6 +1421,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, if (!enable) goto error_out; + /* The user can specify which codecs should be present so that we + * can wait for them to show up if they are slow to recover from + * the AC97 cold reset. We default to a single codec, the primary. + * + * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. + */ + codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | + SIS_TERTIARY_CODEC_PRESENT; + if (!codecs) + codecs = SIS_PRIMARY_CODEC_PRESENT; + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); if (rc < 0) goto error_out; -- cgit From 6eebd6bb5f1ea04f04019e5c39f87a0f17ffb472 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 28 Nov 2011 21:10:05 +0000 Subject: drm: Fix lack of CRTC disable for drm_crtc_helper_set_config(.fb=NULL) Disabling the CRTC by setting its framebuffer to NULL, as used by drm_framebuffer_cleanup(), was failing to pass the current framebuffer to the crtc_func->disable callback. This is because of the dance within drm_crtc_helper_set_config to pass the new_fb (NULL in this case) to the drm_crtc_helper_set_mode with the currently attached fb as a parameter. drm_crtc_helper_set_mode treats this as a no-op and the encoder is still enabled. And so the current fb is forgotten before the call to drm_helper_disable_unused_functions. This patch treats disabling the CRTC as a simple special case rather than adding further complexity into the configuration logic. This fixes a pin-leak of the fb bo on Xserver close. Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3969f7553fe7..d2619d72cece 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -456,6 +456,30 @@ done: EXPORT_SYMBOL(drm_crtc_helper_set_mode); +static int +drm_crtc_helper_disable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + struct drm_encoder *encoder; + + /* Decouple all encoders and their attached connectors from this crtc */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc != crtc) + continue; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder != encoder) + continue; + + connector->encoder = NULL; + } + } + + drm_helper_disable_unused_functions(dev); + return 0; +} + /** * drm_crtc_helper_set_config - set a new config from userspace * @crtc: CRTC to setup @@ -510,8 +534,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) (int)set->num_connectors, set->x, set->y); } else { DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); - set->mode = NULL; - set->num_connectors = 0; + return drm_crtc_helper_disable(set->crtc); } dev = set->crtc->dev; -- cgit From 392e37229f0d6358dcc7b43641df776e9f62a6e6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Nov 2011 14:49:27 -0500 Subject: drm/radeon/kms: fix scanout of 2D tiled buffers on EG/CM Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=43191 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 35 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreen_reg.h | 29 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 87631fede1f8..2b97262e3ab1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1107,9 +1107,40 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, return -EINVAL; } - if (tiling_flags & RADEON_TILING_MACRO) + if (tiling_flags & RADEON_TILING_MACRO) { + if (rdev->family >= CHIP_CAYMAN) + tmp = rdev->config.cayman.tile_config; + else + tmp = rdev->config.evergreen.tile_config; + + switch ((tmp & 0xf0) >> 4) { + case 0: /* 4 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); + break; + case 1: /* 8 banks */ + default: + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); + break; + case 2: /* 16 banks */ + fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); + break; + } + + switch ((tmp & 0xf000) >> 12) { + case 0: /* 1KB rows */ + default: + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB); + break; + case 1: /* 2KB rows */ + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB); + break; + case 2: /* 4KB rows */ + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB); + break; + } + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); - else if (tiling_flags & RADEON_TILING_MICRO) + } else if (tiling_flags & RADEON_TILING_MICRO) fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); switch (radeon_crtc->crtc_id) { diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index c781c92c3451..7d7f2155e34c 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -42,6 +42,17 @@ # define EVERGREEN_GRPH_DEPTH_8BPP 0 # define EVERGREEN_GRPH_DEPTH_16BPP 1 # define EVERGREEN_GRPH_DEPTH_32BPP 2 +# define EVERGREEN_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) +# define EVERGREEN_ADDR_SURF_2_BANK 0 +# define EVERGREEN_ADDR_SURF_4_BANK 1 +# define EVERGREEN_ADDR_SURF_8_BANK 2 +# define EVERGREEN_ADDR_SURF_16_BANK 3 +# define EVERGREEN_GRPH_Z(x) (((x) & 0x3) << 4) +# define EVERGREEN_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_1 0 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_2 1 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_4 2 +# define EVERGREEN_ADDR_SURF_BANK_WIDTH_8 3 # define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8) /* 8 BPP */ # define EVERGREEN_GRPH_FORMAT_INDEXED 0 @@ -61,6 +72,24 @@ # define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5 # define EVERGREEN_GRPH_FORMAT_RGB111110 6 # define EVERGREEN_GRPH_FORMAT_BGR101111 7 +# define EVERGREEN_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1 0 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2 1 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4 2 +# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8 3 +# define EVERGREEN_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B 0 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B 1 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B 2 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B 3 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB 4 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB 5 +# define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB 6 +# define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8 3 # define EVERGREEN_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) # define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL 0 # define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED 1 -- cgit From f3a71df05082c84d1408129084736c5f742a6165 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Nov 2011 14:49:28 -0500 Subject: drm/radeon/kms: fix 2D tiling CS support on EG/CM Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=43191 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen_cs.c | 149 ++++++++++++++++++++++++++++------ drivers/gpu/drm/radeon/evergreend.h | 31 +++++++ 2 files changed, 154 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 38e1bda73d33..cd4590aae154 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -38,6 +38,7 @@ struct evergreen_cs_track { u32 group_size; u32 nbanks; u32 npipes; + u32 row_size; /* value we track */ u32 nsamples; u32 cb_color_base_last[12]; @@ -77,6 +78,44 @@ struct evergreen_cs_track { struct radeon_bo *db_s_write_bo; }; +static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) +{ + if (tiling_flags & RADEON_TILING_MACRO) + return ARRAY_2D_TILED_THIN1; + else if (tiling_flags & RADEON_TILING_MICRO) + return ARRAY_1D_TILED_THIN1; + else + return ARRAY_LINEAR_GENERAL; +} + +static u32 evergreen_cs_get_num_banks(u32 nbanks) +{ + switch (nbanks) { + case 2: + return ADDR_SURF_2_BANK; + case 4: + return ADDR_SURF_4_BANK; + case 8: + default: + return ADDR_SURF_8_BANK; + case 16: + return ADDR_SURF_16_BANK; + } +} + +static u32 evergreen_cs_get_tile_split(u32 row_size) +{ + switch (row_size) { + case 1: + default: + return ADDR_SURF_TILE_SPLIT_1KB; + case 2: + return ADDR_SURF_TILE_SPLIT_2KB; + case 4: + return ADDR_SURF_TILE_SPLIT_4KB; + } +} + static void evergreen_cs_track_init(struct evergreen_cs_track *track) { int i; @@ -490,12 +529,11 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) } ib[idx] &= ~Z_ARRAY_MODE(0xf); track->db_z_info &= ~Z_ARRAY_MODE(0xf); + ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else { - ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); } } break; @@ -618,13 +656,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) "0x%04X\n", reg); return -EINVAL; } - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - } + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); } break; case CB_COLOR8_INFO: @@ -640,13 +673,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) "0x%04X\n", reg); return -EINVAL; } - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { - ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); - } + ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); } break; case CB_COLOR0_PITCH: @@ -701,6 +729,16 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR9_ATTRIB: case CB_COLOR10_ATTRIB: case CB_COLOR11_ATTRIB: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); + } break; case CB_COLOR0_DIM: case CB_COLOR1_DIM: @@ -1318,10 +1356,14 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, } ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); if (!p->keep_tiling_flags) { - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); - else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) - ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + ib[idx+1+(i*8)+1] |= + TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx+1+(i*8)+6] |= + TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); + ib[idx+1+(i*8)+7] |= + TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); + } } texture = reloc->robj; /* tex mip base */ @@ -1422,6 +1464,7 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) { struct radeon_cs_packet pkt; struct evergreen_cs_track *track; + u32 tmp; int r; if (p->track == NULL) { @@ -1430,9 +1473,63 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) if (track == NULL) return -ENOMEM; evergreen_cs_track_init(track); - track->npipes = p->rdev->config.evergreen.tiling_npipes; - track->nbanks = p->rdev->config.evergreen.tiling_nbanks; - track->group_size = p->rdev->config.evergreen.tiling_group_size; + if (p->rdev->family >= CHIP_CAYMAN) + tmp = p->rdev->config.cayman.tile_config; + else + tmp = p->rdev->config.evergreen.tile_config; + + switch (tmp & 0xf) { + case 0: + track->npipes = 1; + break; + case 1: + default: + track->npipes = 2; + break; + case 2: + track->npipes = 4; + break; + case 3: + track->npipes = 8; + break; + } + + switch ((tmp & 0xf0) >> 4) { + case 0: + track->nbanks = 4; + break; + case 1: + default: + track->nbanks = 8; + break; + case 2: + track->nbanks = 16; + break; + } + + switch ((tmp & 0xf00) >> 8) { + case 0: + track->group_size = 256; + break; + case 1: + default: + track->group_size = 512; + break; + } + + switch ((tmp & 0xf000) >> 12) { + case 0: + track->row_size = 1; + break; + case 1: + default: + track->row_size = 2; + break; + case 2: + track->row_size = 4; + break; + } + p->track = track; } do { diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b937c49054d9..e00039e59a75 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -899,6 +899,10 @@ #define DB_HTILE_DATA_BASE 0x28014 #define DB_Z_INFO 0x28040 # define Z_ARRAY_MODE(x) ((x) << 4) +# define DB_TILE_SPLIT(x) (((x) & 0x7) << 8) +# define DB_NUM_BANKS(x) (((x) & 0x3) << 12) +# define DB_BANK_WIDTH(x) (((x) & 0x3) << 16) +# define DB_BANK_HEIGHT(x) (((x) & 0x3) << 20) #define DB_STENCIL_INFO 0x28044 #define DB_Z_READ_BASE 0x28048 #define DB_STENCIL_READ_BASE 0x2804c @@ -951,6 +955,29 @@ # define CB_SF_EXPORT_FULL 0 # define CB_SF_EXPORT_NORM 1 #define CB_COLOR0_ATTRIB 0x28c74 +# define CB_TILE_SPLIT(x) (((x) & 0x7) << 5) +# define ADDR_SURF_TILE_SPLIT_64B 0 +# define ADDR_SURF_TILE_SPLIT_128B 1 +# define ADDR_SURF_TILE_SPLIT_256B 2 +# define ADDR_SURF_TILE_SPLIT_512B 3 +# define ADDR_SURF_TILE_SPLIT_1KB 4 +# define ADDR_SURF_TILE_SPLIT_2KB 5 +# define ADDR_SURF_TILE_SPLIT_4KB 6 +# define CB_NUM_BANKS(x) (((x) & 0x3) << 10) +# define ADDR_SURF_2_BANK 0 +# define ADDR_SURF_4_BANK 1 +# define ADDR_SURF_8_BANK 2 +# define ADDR_SURF_16_BANK 3 +# define CB_BANK_WIDTH(x) (((x) & 0x3) << 13) +# define ADDR_SURF_BANK_WIDTH_1 0 +# define ADDR_SURF_BANK_WIDTH_2 1 +# define ADDR_SURF_BANK_WIDTH_4 2 +# define ADDR_SURF_BANK_WIDTH_8 3 +# define CB_BANK_HEIGHT(x) (((x) & 0x3) << 16) +# define ADDR_SURF_BANK_HEIGHT_1 0 +# define ADDR_SURF_BANK_HEIGHT_2 1 +# define ADDR_SURF_BANK_HEIGHT_4 2 +# define ADDR_SURF_BANK_HEIGHT_8 3 #define CB_COLOR0_DIM 0x28c78 /* only CB0-7 blocks have these regs */ #define CB_COLOR0_CMASK 0x28c7c @@ -1137,7 +1164,11 @@ # define SQ_SEL_1 5 #define SQ_TEX_RESOURCE_WORD5_0 0x30014 #define SQ_TEX_RESOURCE_WORD6_0 0x30018 +# define TEX_TILE_SPLIT(x) (((x) & 0x7) << 29) #define SQ_TEX_RESOURCE_WORD7_0 0x3001c +# define TEX_BANK_WIDTH(x) (((x) & 0x3) << 8) +# define TEX_BANK_HEIGHT(x) (((x) & 0x3) << 10) +# define TEX_NUM_BANKS(x) (((x) & 0x3) << 16) #define SQ_VTX_CONSTANT_WORD0_0 0x30000 #define SQ_VTX_CONSTANT_WORD1_0 0x30004 -- cgit From bab9efc206ba89766c53a9042eb771e87e68c42b Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Mon, 28 Nov 2011 12:25:43 +0100 Subject: vmwgfx: integer overflow in vmw_kms_update_layout_ioctl() There are two issues in vmw_kms_update_layout_ioctl(). First, the for loop forgets to index rects and only checks the first element. Second, there is a potential integer overflow if userspace passes in a large arg->num_outputs. The call to kzalloc() would allocate a small buffer, leading to out-of-bounds read. Reported-by: Haogang Chen Signed-off-by: Xi Wang Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 880e285d7578..37d40545ed77 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1809,7 +1809,8 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, } rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect); - rects = kzalloc(rects_size, GFP_KERNEL); + rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect), + GFP_KERNEL); if (unlikely(!rects)) { ret = -ENOMEM; goto out_unlock; @@ -1824,10 +1825,10 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, } for (i = 0; i < arg->num_outputs; ++i) { - if (rects->x < 0 || - rects->y < 0 || - rects->x + rects->w > mode_config->max_width || - rects->y + rects->h > mode_config->max_height) { + if (rects[i].x < 0 || + rects[i].y < 0 || + rects[i].x + rects[i].w > mode_config->max_width || + rects[i].y + rects[i].h > mode_config->max_height) { DRM_ERROR("Invalid GUI layout.\n"); ret = -EINVAL; goto out_free; -- cgit From 550acb19269d65f32e9ac4ddb26c2b2070e37f1c Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 1 Dec 2011 13:55:08 +0200 Subject: genirq: Fix race condition when stopping the irq thread In irq_wait_for_interrupt(), the should_stop member is verified before setting the task's state to TASK_INTERRUPTIBLE and calling schedule(). In case kthread_stop sets should_stop and wakes up the process after should_stop is checked by the irq thread but before the task's state is changed, the irq thread might never exit: kthread_stop irq_wait_for_interrupt ------------ ---------------------- ... ... while (!kthread_should_stop()) { kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); ... set_current_state(TASK_INTERRUPTIBLE); ... schedule(); } Fix this by checking if the thread should stop after modifying the task's state. [ tglx: Simplified it a bit ] Signed-off-by: Ido Yariv Link: http://lkml.kernel.org/r/1322740508-22640-1-git-send-email-ido@wizery.com Signed-off-by: Thomas Gleixner Cc: stable@kernel.org --- kernel/irq/manage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0e2b179bc7b3..1da999f5e746 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -623,8 +623,9 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id) static int irq_wait_for_interrupt(struct irqaction *action) { + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)) { @@ -632,7 +633,9 @@ static int irq_wait_for_interrupt(struct irqaction *action) return 0; } schedule(); + set_current_state(TASK_INTERRUPTIBLE); } + __set_current_state(TASK_RUNNING); return -1; } -- cgit From dfaf3c036cd46a73f4ef3e4b75c1f647e503d4e1 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Fri, 2 Dec 2011 14:47:03 +0100 Subject: loop: Fix discard_alignment default setting discard_alignment is not relevant to the loop driver since it is supposed to be set as a workaround for the old sector 63 alignments. So set it to zero rather than block size. Signed-off-by: Lukas Czerner Reported-by: Milan Broz Signed-off-by: Jens Axboe --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 5579fda279b4..1e888c9e85b3 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -797,7 +797,7 @@ static void loop_config_discard(struct loop_device *lo) } q->limits.discard_granularity = inode->i_sb->s_blocksize; - q->limits.discard_alignment = inode->i_sb->s_blocksize; + q->limits.discard_alignment = 0; q->limits.max_discard_sectors = UINT_MAX >> 9; q->limits.discard_zeroes_data = 1; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); -- cgit From cce4aa378a049f4275416ee6302dd24f37b289df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 Dec 2011 15:29:12 +0100 Subject: ALSA: hda/realtek - Fix Oops in alc_mux_select() When no imux is available (e.g. a single capture source), alc_auto_init_input_src() may trigger an Oops due to the access to -1. Add a proper zero-check to avoid it. Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbde019d3d52..a7d1bc4e0d09 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -297,6 +297,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) imux = &spec->input_mux[0]; + if (!imux->num_items) + return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; -- cgit From c1be84309c58b1e7c6d626e28fba41a22b364c3d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Dec 2011 12:34:16 +0100 Subject: tick-broadcast: Stop active broadcast device when replacing it When a better rated broadcast device is installed, then the current active device is not disabled, which results in two running broadcast devices. Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org --- kernel/time/tick-broadcast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f954282d9a82..fd4a7b1625a2 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -71,7 +71,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev) (dev->features & CLOCK_EVT_FEAT_C3STOP)) return 0; - clockevents_exchange_device(NULL, dev); + clockevents_exchange_device(tick_broadcast_device.evtdev, dev); tick_broadcast_device.evtdev = dev; if (!cpumask_empty(tick_get_broadcast_mask())) tick_broadcast_start_periodic(dev); -- cgit From de28f25e8244c7353abed8de0c7792f5f883588c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Dec 2011 16:02:45 +0100 Subject: clockevents: Set noop handler in clockevents_exchange_device() If a device is shutdown, then there might be a pending interrupt, which will be processed after we reenable interrupts, which causes the original handler to be run. If the old handler is the (broadcast) periodic handler the shutdown state might hang the kernel completely. Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org --- kernel/time/clockevents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 1ecd6ba36d6c..c4eb71c8b2ea 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -387,6 +387,7 @@ void clockevents_exchange_device(struct clock_event_device *old, * released list and do a notify add later. */ if (old) { + old->event_handler = clockevents_handle_noop; clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); list_del(&old->list); list_add(&old->list, &clockevents_released); -- cgit From 629be5f275ddf0791614f8cbdafc11bde4247850 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Tue, 22 Nov 2011 15:39:11 +1100 Subject: mtd: ndfc: fix typo in structure dereference In commit 9d7948c50055e74b693ce9e99a709b2e5bbc1942 (mtd: ndfc: use ofpart through generic parsing) we dereference a non pointer type causing the following compiler error: drivers/mtd/nand/ndfc.c: In function 'ndfc_chip_init': drivers/mtd/nand/ndfc.c:191: error: invalid type argument of '->' (have 'struct mtd_part_parser_data') Fix that. Signed-off-by: Tony Breeds Acked-by: Dmitry Eremin-Solenikov Signed-off-by: David Woodhouse --- drivers/mtd/nand/ndfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index ee1713907b92..f8aacf48ecdd 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -188,7 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, if (!flash_np) return -ENODEV; - ppdata->of_node = flash_np; + ppdata.of_node = flash_np; ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev), flash_np->name); if (!ndfc->mtd.name) { -- cgit From 2151937d7ce491bfbe269a1ae742c6686904474c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 1 Dec 2011 08:06:52 -0800 Subject: ceph: fix rasize reporting by ceph_show_options Fix typo. Reported-by: mowang da Signed-off-by: Sage Weil --- fs/ceph/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 8dc73a594a90..b48f15f101a0 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -383,7 +383,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt) if (fsopt->rsize != CEPH_RSIZE_DEFAULT) seq_printf(m, ",rsize=%d", fsopt->rsize); if (fsopt->rasize != CEPH_RASIZE_DEFAULT) - seq_printf(m, ",rasize=%d", fsopt->rsize); + seq_printf(m, ",rasize=%d", fsopt->rasize); if (fsopt->congestion_kb != default_congestion_kb()) seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb); if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT) -- cgit From 87b86ade8bb07473596e2551de7bb64c1f44bbe4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 14 Aug 2011 13:39:20 +0900 Subject: ASoC: Mark WM8994 ADC muxes as virtual Since they don't actually have power bits but do have events associated with them it's important that we bootstrap their state properly which making them virtual does. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6c2988549003..d0c545b73d78 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1325,15 +1325,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), }; static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { -SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, + adc_mux_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, + adc_mux_ev, SND_SOC_DAPM_PRE_PMU), }; static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { -SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), -SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), +SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), +SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), }; static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { -- cgit From 274b89ca3b006926cb9b45d78ab5906f4c0fc0aa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:19:17 -0800 Subject: iwlagn: fix HW crypto for TX-only keys Group keys in IBSS or AP mode are not programmed into the device since we give the key to it with every TX packet. However, we do need mac80211 to create the MMIC & PN in all cases. Move the code around to set the key flags all the time. We set them even when the key is removed again but that is obviously harmless. Cc: stable@vger.kernel.org Reported-by: Reinette Chatre Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index ed6283623932..4b2aa1da0953 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1268,9 +1268,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_TKIP: - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (sta) addr = sta->addr; else /* station mode case only */ @@ -1283,8 +1280,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, seq.tkip.iv32, p1k, CMD_SYNC); break; case WLAN_CIPHER_SUITE_CCMP: - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - /* fall through */ case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: ret = iwlagn_send_sta_key(priv, keyconf, sta_id, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ccba69b7f8a7..6094deab5106 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2316,6 +2316,17 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + /* fall through */ + case WLAN_CIPHER_SUITE_CCMP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + break; + default: + break; + } + /* * We could program these keys into the hardware as well, but we * don't expect much multicast traffic in IBSS and having keys -- cgit From 34a5b4b6af104cf18eb50748509528b9bdbc4036 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Dec 2011 08:19:18 -0800 Subject: iwlwifi: do not re-configure HT40 after associated The ht40 setting should not change after association unless channel switch This fix a problem we are seeing which cause uCode assert because driver sending invalid information and make uCode confuse Here is the firmware assert message: kernel: iwlagn 0000:03:00.0: Microcode SW error detected. Restarting 0x82000000. kernel: iwlagn 0000:03:00.0: Loaded firmware version: 17.168.5.3 build 42301 kernel: iwlagn 0000:03:00.0: Start IWL Error Log Dump: kernel: iwlagn 0000:03:00.0: Status: 0x000512E4, count: 6 kernel: iwlagn 0000:03:00.0: 0x00002078 | ADVANCED_SYSASSERT kernel: iwlagn 0000:03:00.0: 0x00009514 | uPc kernel: iwlagn 0000:03:00.0: 0x00009496 | branchlink1 kernel: iwlagn 0000:03:00.0: 0x00009496 | branchlink2 kernel: iwlagn 0000:03:00.0: 0x0000D1F2 | interruptlink1 kernel: iwlagn 0000:03:00.0: 0x00000000 | interruptlink2 kernel: iwlagn 0000:03:00.0: 0x01008035 | data1 kernel: iwlagn 0000:03:00.0: 0x0000C90F | data2 kernel: iwlagn 0000:03:00.0: 0x000005A7 | line kernel: iwlagn 0000:03:00.0: 0x5080B520 | beacon time kernel: iwlagn 0000:03:00.0: 0xCC515AE0 | tsf low kernel: iwlagn 0000:03:00.0: 0x00000003 | tsf hi kernel: iwlagn 0000:03:00.0: 0x00000000 | time gp1 kernel: iwlagn 0000:03:00.0: 0x29703BF0 | time gp2 kernel: iwlagn 0000:03:00.0: 0x00000000 | time gp3 kernel: iwlagn 0000:03:00.0: 0x000111A8 | uCode version kernel: iwlagn 0000:03:00.0: 0x000000B0 | hw version kernel: iwlagn 0000:03:00.0: 0x00480303 | board version kernel: iwlagn 0000:03:00.0: 0x09E8004E | hcmd kernel: iwlagn 0000:03:00.0: CSR values: kernel: iwlagn 0000:03:00.0: (2nd byte of CSR_INT_COALESCING is CSR_INT_PERIODIC_REG) kernel: iwlagn 0000:03:00.0: CSR_HW_IF_CONFIG_REG: 0X00480303 kernel: iwlagn 0000:03:00.0: CSR_INT_COALESCING: 0X0000ff40 kernel: iwlagn 0000:03:00.0: CSR_INT: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_INT_MASK: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_FH_INT_STATUS: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_GPIO_IN: 0X00000030 kernel: iwlagn 0000:03:00.0: CSR_RESET: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_GP_CNTRL: 0X080403c5 kernel: iwlagn 0000:03:00.0: CSR_HW_REV: 0X000000b0 kernel: iwlagn 0000:03:00.0: CSR_EEPROM_REG: 0X07d60ffd kernel: iwlagn 0000:03:00.0: CSR_EEPROM_GP: 0X90000001 kernel: iwlagn 0000:03:00.0: CSR_OTP_GP_REG: 0X00030001 kernel: iwlagn 0000:03:00.0: CSR_GIO_REG: 0X00080044 kernel: iwlagn 0000:03:00.0: CSR_GP_UCODE_REG: 0X000093bb kernel: iwlagn 0000:03:00.0: CSR_GP_DRIVER_REG: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_UCODE_DRV_GP1: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_UCODE_DRV_GP2: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_LED_REG: 0X00000078 kernel: iwlagn 0000:03:00.0: CSR_DRAM_INT_TBL_REG: 0X88214dd2 kernel: iwlagn 0000:03:00.0: CSR_GIO_CHICKEN_BITS: 0X27800200 kernel: iwlagn 0000:03:00.0: CSR_ANA_PLL_CFG: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_HW_REV_WA_REG: 0X0001001a kernel: iwlagn 0000:03:00.0: CSR_DBG_HPET_MEM_REG: 0Xffff0010 kernel: iwlagn 0000:03:00.0: FH register values: kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_STTS_WPTR_REG: 0X21316d00 kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_RBDCB_BASE_REG: 0X021479c0 kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_WPTR: 0X00000060 kernel: iwlagn 0000:03:00.0: FH_MEM_RCSR_CHNL0_CONFIG_REG: 0X80819104 kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_SHARED_CTRL_REG: 0X000000fc kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_RX_STATUS_REG: 0X07030000 kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV: 0X00000000 kernel: iwlagn 0000:03:00.0: FH_TSSR_TX_STATUS_REG: 0X07ff0001 kernel: iwlagn 0000:03:00.0: FH_TSSR_TX_ERROR_REG: 0X00000000 kernel: iwlagn 0000:03:00.0: Start IWL Event Log Dump: display last 20 entries kernel: ------------[ cut here ]------------ WARNING: at net/mac80211/util.c:1208 ieee80211_reconfig+0x1f1/0x407() kernel: Hardware name: 4290W4H kernel: Pid: 1896, comm: kworker/0:0 Not tainted 3.1.0 #2 kernel: Call Trace: kernel: [] ? warn_slowpath_common+0x73/0x87 kernel: [] ? ieee80211_reconfig+0x1f1/0x407 kernel: [] ? ieee80211_recalc_smps_work+0x32/0x32 kernel: [] ? ieee80211_restart_work+0x7e/0x87 kernel: [] ? process_one_work+0x1c8/0x2e3 kernel: [] ? worker_thread+0x17a/0x23a kernel: [] ? manage_workers.clone.18+0x15b/0x15b kernel: [] ? manage_workers.clone.18+0x15b/0x15b kernel: [] ? kthread+0x7a/0x82 kernel: [] ? kernel_thread_helper+0x4/0x10 kernel: [] ? kthread_flush_work_fn+0x11/0x11 kernel: [] ? gs_change+0xb/0xb Cc: 3.1+ Reported-by: Udo Steinberg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 36 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 +++------------ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 58a381c01c89..a7a6def40d05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -528,6 +528,24 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return 0; } +void iwlagn_config_ht40(struct ieee80211_conf *conf, + struct iwl_rxon_context *ctx) +{ + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } +} + int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) { struct iwl_priv *priv = hw->priv; @@ -586,19 +604,11 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->ht.enabled = conf_is_ht(conf); if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } + /* if HT40 is used, it should not change + * after associated except channel switch */ + if (iwl_is_associated_ctx(ctx) && + !ctx->ht.is_40mhz) + iwlagn_config_ht40(conf, ctx); } else ctx->ht.is_40mhz = false; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6094deab5106..f5564514868e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2610,21 +2610,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, /* Configure HT40 channels */ ctx->ht.enabled = conf_is_ht(conf); - if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } - } else + if (ctx->ht.enabled) + iwlagn_config_ht40(conf, ctx); + else ctx->ht.is_40mhz = false; if ((le16_to_cpu(ctx->staging.channel) != ch)) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5b936ec1a541..3856abaea507 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -86,6 +86,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); +void iwlagn_config_ht40(struct ieee80211_conf *conf, + struct iwl_rxon_context *ctx); /* uCode */ int iwlagn_rx_calib_result(struct iwl_priv *priv, -- cgit From 9995ffe5f5fdddcc73e4465cc3f8b38714df8108 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Dec 2011 08:19:19 -0800 Subject: iwlwifi: change the default behavior of watchdog timer The current default watchdog timer is enabled, but we are seeing issues on legacy devices. So change the default setting of watchdog timer to per device based. But user still can use the "wd_disable" module parameter to overwrite the system setting Cc: stable@vger.kernel.org #3.0+ Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-core.c | 22 +++++++++++++++++----- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-shared.h | 4 ++-- 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index e12b48c2cff6..dd008b0e6417 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -191,6 +191,7 @@ static struct iwl_base_params iwl1000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, + .wd_disable = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c511c98a89a8..f55fb2d1af52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -364,6 +364,7 @@ static struct iwl_base_params iwl5000_base_params = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .no_idle_support = true, + .wd_disable = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f5564514868e..bacc06c95e7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3498,9 +3498,10 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); -module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO); +module_param_named(wd_disable, iwlagn_mod_params.wd_disable, int, S_IRUGO); MODULE_PARM_DESC(wd_disable, - "Disable stuck queue watchdog timer (default: 0 [enabled])"); + "Disable stuck queue watchdog timer 0=system default, " + "1=disable, 2=enable (default: 0)"); /* * set bt_coex_active to true, uCode will do kill/defer diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 001fdf140abb..fcf54160e4ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1810,11 +1810,23 @@ void iwl_setup_watchdog(struct iwl_priv *priv) { unsigned int timeout = priv->cfg->base_params->wd_timeout; - if (timeout && !iwlagn_mod_params.wd_disable) - mod_timer(&priv->watchdog, - jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); - else - del_timer(&priv->watchdog); + if (!iwlagn_mod_params.wd_disable) { + /* use system default */ + if (timeout && !priv->cfg->base_params->wd_disable) + mod_timer(&priv->watchdog, + jiffies + + msecs_to_jiffies(IWL_WD_TICK(timeout))); + else + del_timer(&priv->watchdog); + } else { + /* module parameter overwrite default configuration */ + if (timeout && iwlagn_mod_params.wd_disable == 2) + mod_timer(&priv->watchdog, + jiffies + + msecs_to_jiffies(IWL_WD_TICK(timeout))); + else + del_timer(&priv->watchdog); + } } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 137da3380704..f2fc288f3dd3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -113,6 +113,7 @@ struct iwl_lib_ops { * @shadow_reg_enable: HW shadhow register bit * @no_idle_support: do not support idle mode * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up + * wd_disable: disable watchdog timer */ struct iwl_base_params { int eeprom_size; @@ -134,6 +135,7 @@ struct iwl_base_params { const bool shadow_reg_enable; const bool no_idle_support; const bool hd_v2; + const bool wd_disable; }; /* * @advanced_bt_coexist: support advanced bt coexist diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 1f7a93c67c45..14eaf37ce3b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -120,7 +120,7 @@ extern struct iwl_mod_params iwlagn_mod_params; * @restart_fw: restart firmware, default = 1 * @plcp_check: enable plcp health check, default = true * @ack_check: disable ack health check, default = false - * @wd_disable: enable stuck queue check, default = false + * @wd_disable: enable stuck queue check, default = 0 * @bt_coex_active: enable bt coex, default = true * @led_mode: system default, default = 0 * @no_sleep_autoadjust: disable autoadjust, default = true @@ -141,7 +141,7 @@ struct iwl_mod_params { int restart_fw; bool plcp_check; bool ack_check; - bool wd_disable; + int wd_disable; bool bt_coex_active; int led_mode; bool no_sleep_autoadjust; -- cgit From a99ebf43f49f4499ab0e2a8a9132ad6ed6ba2409 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 1 Dec 2011 11:24:20 +0000 Subject: xfs: fix allocation length overflow in xfs_bmapi_write() When testing the new xfstests --large-fs option that does very large file preallocations, this assert was tripped deep in xfs_alloc_vextent(): XFS: Assertion failed: args->minlen <= args->maxlen, file: fs/xfs/xfs_alloc.c, line: 2239 The allocation was trying to allocate a zero length extent because the lower 32 bits of the allocation length was zero. The remaining length of the allocation to be done was an exact multiple of 2^32 - the first case I saw was at 496TB remaining to be allocated. This turns out to be an overflow when converting the allocation length (a 64 bit quantity) into the extent length to allocate (a 32 bit quantity), and it requires the length to be allocated an exact multiple of 2^32 blocks to trip the assert. Fix it by limiting the extent lenth to allocate to MAXEXTLEN. Signed-off-by: Dave Chinner Signed-off-by: Ben Myers Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_bmap.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c68baeb0974a..d0ab78837057 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2383,6 +2383,8 @@ xfs_bmap_btalloc( int tryagain; int error; + ASSERT(ap->length); + mp = ap->ip->i_mount; align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; if (unlikely(align)) { @@ -4629,6 +4631,8 @@ xfs_bmapi_allocate( int error; int rt; + ASSERT(bma->length > 0); + rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip); /* @@ -4849,6 +4853,7 @@ xfs_bmapi_write( ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); ASSERT(!(flags & XFS_BMAPI_IGSTATE)); ASSERT(tp != NULL); + ASSERT(len > 0); whichfork = (flags & XFS_BMAPI_ATTRFORK) ? XFS_ATTR_FORK : XFS_DATA_FORK; @@ -4918,9 +4923,22 @@ xfs_bmapi_write( bma.eof = eof; bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; - bma.length = len; bma.offset = bno; + /* + * There's a 32/64 bit type mismatch between the + * allocation length request (which can be 64 bits in + * length) and the bma length request, which is + * xfs_extlen_t and therefore 32 bits. Hence we have to + * check for 32-bit overflows and handle them here. + */ + if (len > (xfs_filblks_t)MAXEXTLEN) + bma.length = MAXEXTLEN; + else + bma.length = len; + + ASSERT(len > 0); + ASSERT(bma.length > 0); error = xfs_bmapi_allocate(&bma, flags); if (error) goto error0; -- cgit From 54a8a79c55ce283c94ce4c67a98d28c21830405a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 22 Nov 2011 09:32:57 +0800 Subject: btusb: fix a memory leak in btusb_send_frame() This patch fixes the following memory leak reported by kmemleak: unreferenced object 0xffff880060a53840 (size 192): comm "softirq", pid 0, jiffies 4320571771 (age 1406.569s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] create_object+0x187/0x28b [] kmemleak_alloc+0x73/0x98 [] __kmalloc+0xfc/0x123 [] usb_alloc_urb+0x1e/0x48 [] btusb_send_frame+0x86/0x385 [btusb] [] hci_send_frame+0xa0/0xa5 [bluetooth] [] hci_cmd_task+0xa0/0xfb [bluetooth] [] tasklet_action+0x8f/0xef [] __do_softirq+0xf4/0x1db [] run_ksoftirqd+0x84/0x129 [] kthread+0xa0/0xa8 [] kernel_thread_helper+0x4/0x10 [] 0xffffffffffffffff The problem is that when inc_tx() returns non-zero, we forgot to call usb_free_urb(). Cc: Marcel Holtmann Cc: "Gustavo F. Padovan" Signed-off-by: WANG Cong Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index fe4ebc375b3d..eabc437ce500 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -777,9 +777,8 @@ skip_waking: usb_mark_last_busy(data->udev); } - usb_free_urb(urb); - done: + usb_free_urb(urb); return err; } -- cgit From 33cb722c22f28964a501a56cc76397834c221c7a Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 23 Nov 2011 11:23:34 +0200 Subject: Bluetooth: Correct version check in hci_setup Check for hci_ver instead of lmp_ver Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d7d96b6b1f0d..643a41b76e2e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -545,7 +545,7 @@ static void hci_setup(struct hci_dev *hdev) { hci_setup_event_mask(hdev); - if (hdev->lmp_ver > 1) + if (hdev->hci_ver > 1) hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); if (hdev->features[6] & LMP_SIMPLE_PAIR) { -- cgit From f61759e6b831a55b89e584b198c3da325e2bc379 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Fri, 2 Dec 2011 11:39:42 +0000 Subject: ipv4: make sure RTO_ONLINK is saved in routing cache __mkroute_output fails to work with the original tos and uses value with stripped RTO_ONLINK bit. Make sure we put the original TOS bits into rt_key_tos because it used to match cached route. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller --- net/ipv4/route.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ca5e237df029..588d971a3ba1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -112,7 +112,7 @@ #include #define RT_FL_TOS(oldflp4) \ - ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) + ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) #define IP_MAX_MTU 0xFFF0 @@ -2441,11 +2441,11 @@ EXPORT_SYMBOL(ip_route_input_common); static struct rtable *__mkroute_output(const struct fib_result *res, const struct flowi4 *fl4, __be32 orig_daddr, __be32 orig_saddr, - int orig_oif, struct net_device *dev_out, + int orig_oif, __u8 orig_rtos, + struct net_device *dev_out, unsigned int flags) { struct fib_info *fi = res->fi; - u32 tos = RT_FL_TOS(fl4); struct in_device *in_dev; u16 type = res->type; struct rtable *rth; @@ -2496,7 +2496,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_flags = flags; rth->rt_type = type; - rth->rt_key_tos = tos; + rth->rt_key_tos = orig_rtos; rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; @@ -2546,7 +2546,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) { struct net_device *dev_out = NULL; - u32 tos = RT_FL_TOS(fl4); + __u8 tos = RT_FL_TOS(fl4); unsigned int flags = 0; struct fib_result res; struct rtable *rth; @@ -2722,7 +2722,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) make_route: rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, - dev_out, flags); + tos, dev_out, flags); if (!IS_ERR(rth)) { unsigned int hash; -- cgit From 36d54dc0c893b143748bcf13a1e3b7a00696115d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 3 Dec 2011 18:38:25 +0800 Subject: ASoC: kirkwood: Make SND_KIRKWOOD_SOC_OPENRD and SND_KIRKWOOD_SOC_T5325 depend on I2C SND_KIRKWOOD_SOC_T5325 selects SND_SOC_ALC5623, but SND_SOC_ALC5623 needs CONFIG_I2C. So we need to make SND_KIRKWOOD_SOC_T5325 depend on I2C, otherwise I got below build error if CONFIG_I2C is not selected. CC sound/soc/codecs/alc5623.o sound/soc/codecs/alc5623.c: In function 'alc5623_i2c_probe': sound/soc/codecs/alc5623.c:1002: error: implicit declaration of function 'i2c_smbus_read_word_data' sound/soc/codecs/alc5623.c:1009: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/alc5623.c: In function 'alc5623_modinit': sound/soc/codecs/alc5623.c:1096: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/alc5623.c: In function 'alc5623_modexit': sound/soc/codecs/alc5623.c:1108: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/alc5623.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Also fix the same issue for SND_KIRKWOOD_SOC_OPENRD. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/kirkwood/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 8f49e165f4d1..c62d715235e2 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -12,6 +12,7 @@ config SND_KIRKWOOD_SOC_I2S config SND_KIRKWOOD_SOC_OPENRD tristate "SoC Audio support for Kirkwood Openrd Client" depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE) + depends on I2C select SND_KIRKWOOD_SOC_I2S select SND_SOC_CS42L51 help @@ -20,7 +21,7 @@ config SND_KIRKWOOD_SOC_OPENRD config SND_KIRKWOOD_SOC_T5325 tristate "SoC Audio support for HP t5325" - depends on SND_KIRKWOOD_SOC && MACH_T5325 + depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C select SND_KIRKWOOD_SOC_I2S select SND_SOC_ALC5623 help -- cgit From e5fd47bfab2df0c2184cc0bf4245d8e1bb7724fb Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 21 Nov 2011 18:02:02 -0500 Subject: xen/pm_idle: Make pm_idle be default_idle under Xen. The idea behind commit d91ee5863b71 ("cpuidle: replace xen access to x86 pm_idle and default_idle") was to have one call - disable_cpuidle() which would make pm_idle not be molested by other code. It disallows cpuidle_idle_call to be set to pm_idle (which is excellent). But in the select_idle_routine() and idle_setup(), the pm_idle can still be set to either: amd_e400_idle, mwait_idle or default_idle. This depends on some CPU flags (MWAIT) and in AMD case on the type of CPU. In case of mwait_idle we can hit some instances where the hypervisor (Amazon EC2 specifically) sets the MWAIT and we get: Brought up 2 CPUs invalid opcode: 0000 [#1] SMP Pid: 0, comm: swapper Not tainted 3.1.0-0.rc6.git0.3.fc16.x86_64 #1 RIP: e030:[] [] mwait_idle+0x6f/0xb4 ... Call Trace: [] cpu_idle+0xae/0xe8 [] cpu_bringup_and_idle+0xe/0x10 RIP [] mwait_idle+0x6f/0xb4 RSP In the case of amd_e400_idle we don't get so spectacular crashes, but we do end up making an MSR which is trapped in the hypervisor, and then follow it up with a yield hypercall. Meaning we end up going to hypervisor twice instead of just once. The previous behavior before v3.0 was that pm_idle was set to default_idle regardless of select_idle_routine/idle_setup. We want to do that, but only for one specific case: Xen. This patch does that. Fixes RH BZ #739499 and Ubuntu #881076 Reported-by: Stefan Bader Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Linus Torvalds --- arch/x86/include/asm/system.h | 1 + arch/x86/kernel/process.c | 8 ++++++++ arch/x86/xen/setup.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index c2ff2a1d845e..2d2f01ce6dcb 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -401,6 +401,7 @@ extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); +bool set_pm_idle_to_default(void); void stop_this_cpu(void *dummy); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index b9b3b1a51643..ee5d4fbd53b4 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -403,6 +403,14 @@ void default_idle(void) EXPORT_SYMBOL(default_idle); #endif +bool set_pm_idle_to_default(void) +{ + bool ret = !!pm_idle; + + pm_idle = default_idle; + + return ret; +} void stop_this_cpu(void *dummy) { local_irq_disable(); diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 38d0af4fefec..1093f80c162d 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -410,6 +410,6 @@ void __init xen_arch_setup(void) #endif disable_cpuidle(); boot_option_idle_override = IDLE_HALT; - + WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); } -- cgit From 3989efb77046ad334518b6cddcf817184affe7c9 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 1 Dec 2011 11:37:20 -0500 Subject: arch/tile: add a few #includes and an EXPORT to catch up with kernel changes. The empty_zero_page[] export is required for ZERO_PAGE() module references. The #includes are due to changes in implicit inclusion, and should of course have been in the sources from the beginning. Signed-off-by: Chris Metcalf --- arch/tile/kernel/pci-dma.c | 1 + arch/tile/kernel/pci.c | 1 + arch/tile/kernel/sysfs.c | 1 + arch/tile/lib/exports.c | 3 +++ 4 files changed, 6 insertions(+) diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c index 658f2ce426a4..b3ed19f8779c 100644 --- a/arch/tile/kernel/pci-dma.c +++ b/arch/tile/kernel/pci-dma.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 2a8014cb1ff5..9d610d3fb11e 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c index b671a86f4515..602908268093 100644 --- a/arch/tile/kernel/sysfs.c +++ b/arch/tile/kernel/sysfs.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* Return a string queried from the hypervisor, truncated to page size. */ diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c index a87d2a859ba9..2a81d32de0da 100644 --- a/arch/tile/lib/exports.c +++ b/arch/tile/lib/exports.c @@ -39,6 +39,9 @@ EXPORT_SYMBOL(finv_user_asm); EXPORT_SYMBOL(current_text_addr); EXPORT_SYMBOL(dump_stack); +/* arch/tile/kernel/head.S */ +EXPORT_SYMBOL(empty_zero_page); + /* arch/tile/lib/, various memcpy files */ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__copy_to_user_inatomic); -- cgit From c2851a9b1caa420c2cdbd517617166990e3723c0 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 1 Dec 2011 12:51:05 -0500 Subject: arch/tile: fix double-free bug in homecache_free_pages() When freeing the page with this API, the page was "put" twice. This was only discovered bringing up an MPT fusion controller, which actually used the API; it hadn't been invoked previously, so the bug had gone unnoticed. Signed-off-by: Chris Metcalf --- arch/tile/mm/homecache.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c index cbe6f4f9eca3..1cc6ae477c98 100644 --- a/arch/tile/mm/homecache.c +++ b/arch/tile/mm/homecache.c @@ -449,9 +449,12 @@ void homecache_free_pages(unsigned long addr, unsigned int order) VM_BUG_ON(!virt_addr_valid((void *)addr)); page = virt_to_page((void *)addr); if (put_page_testzero(page)) { - int pages = (1 << order); homecache_change_page_home(page, order, initial_page_home()); - while (pages--) - __free_page(page++); + if (order == 0) { + free_hot_cold_page(page, 0); + } else { + init_page_count(page); + __free_pages(page, order); + } } } -- cgit From a67ba43d30bf8c1cfdc2615439455302d2408453 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 1 Dec 2011 12:54:31 -0500 Subject: asm-generic/unistd.h: support new process_vm_{readv,write} syscalls Also prototype the "compat" functions so they can be referenced from C code. Signed-off-by: Chris Metcalf Acked-by: Arnd Bergmann --- include/asm-generic/unistd.h | 8 +++++++- include/linux/compat.h | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index f4c38d8c6674..2292d1af9d70 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -685,9 +685,15 @@ __SYSCALL(__NR_syncfs, sys_syncfs) __SYSCALL(__NR_setns, sys_setns) #define __NR_sendmmsg 269 __SC_COMP(__NR_sendmmsg, sys_sendmmsg, compat_sys_sendmmsg) +#define __NR_process_vm_readv 270 +__SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \ + compat_sys_process_vm_readv) +#define __NR_process_vm_writev 271 +__SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ + compat_sys_process_vm_writev) #undef __NR_syscalls -#define __NR_syscalls 270 +#define __NR_syscalls 272 /* * All syscalls below here should go away really, diff --git a/include/linux/compat.h b/include/linux/compat.h index 154bf5683015..66ed067fb729 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -552,5 +552,14 @@ extern ssize_t compat_rw_copy_check_uvector(int type, extern void __user *compat_alloc_user_space(unsigned long len); +asmlinkage ssize_t compat_sys_process_vm_readv(compat_pid_t pid, + const struct compat_iovec __user *lvec, + unsigned long liovcnt, const struct compat_iovec __user *rvec, + unsigned long riovcnt, unsigned long flags); +asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid, + const struct compat_iovec __user *lvec, + unsigned long liovcnt, const struct compat_iovec __user *rvec, + unsigned long riovcnt, unsigned long flags); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ -- cgit From 781a5e92bc3b666bc5752e3ce7e977978c2f64e9 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 1 Dec 2011 12:56:03 -0500 Subject: drivers/net/ethernet/tile: use skb_frag_page() API This replaces raw access to the "page" field of the skb_frag_t. Signed-off-by: Chris Metcalf Acked-by: David S. Miller --- drivers/net/ethernet/tile/tilepro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 10826d8a2a2d..1c0f9facb9b1 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -1697,7 +1697,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags, for (i = 0; i < sh->nr_frags; i++) { skb_frag_t *f = &sh->frags[i]; - unsigned long pfn = page_to_pfn(f->page); + unsigned long pfn = page_to_pfn(skb_frag_page(f)); /* FIXME: Compute "hash_for_home" properly. */ /* ISSUE: The hypervisor checks CHIP_HAS_REV1_DMA_PACKETS(). */ @@ -1706,7 +1706,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags, /* FIXME: Hmmm. */ if (!hash_default) { void *va = pfn_to_kaddr(pfn) + f->page_offset; - BUG_ON(PageHighMem(f->page)); + BUG_ON(PageHighMem(skb_frag_page(f))); finv_buffer_remote(va, f->size, 0); } -- cgit From 0c90547b4a3fcee184db4d54ffc1a4fb17fd54d6 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Thu, 1 Dec 2011 12:58:19 -0500 Subject: arch/tile: use new generic {enable,disable}_percpu_irq() routines We provided very similar routines internally, but now we can hook into the generic framework by supplying our routines as function pointers in the irq_chip structure instead. Signed-off-by: Chris Metcalf --- arch/tile/include/asm/irq.h | 10 ---------- arch/tile/kernel/irq.c | 16 ++++++++-------- drivers/net/ethernet/tile/tilepro.c | 4 ++-- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/arch/tile/include/asm/irq.h b/arch/tile/include/asm/irq.h index 94e9a511de84..f80f8ceabc67 100644 --- a/arch/tile/include/asm/irq.h +++ b/arch/tile/include/asm/irq.h @@ -74,16 +74,6 @@ enum { */ void tile_irq_activate(unsigned int irq, int tile_irq_type); -/* - * For onboard, non-PCI (e.g. TILE_IRQ_PERCPU) devices, drivers know - * how to use enable/disable_percpu_irq() to manage interrupts on each - * core. We can't use the generic enable/disable_irq() because they - * use a single reference count per irq, rather than per cpu per irq. - */ -void enable_percpu_irq(unsigned int irq); -void disable_percpu_irq(unsigned int irq); - - void setup_irq_regs(void); #endif /* _ASM_TILE_IRQ_H */ diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index aa0134db2dd6..02e628065012 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c @@ -152,14 +152,13 @@ void tile_dev_intr(struct pt_regs *regs, int intnum) * Remove an irq from the disabled mask. If we're in an interrupt * context, defer enabling the HW interrupt until we leave. */ -void enable_percpu_irq(unsigned int irq) +static void tile_irq_chip_enable(struct irq_data *d) { - get_cpu_var(irq_disable_mask) &= ~(1UL << irq); + get_cpu_var(irq_disable_mask) &= ~(1UL << d->irq); if (__get_cpu_var(irq_depth) == 0) - unmask_irqs(1UL << irq); + unmask_irqs(1UL << d->irq); put_cpu_var(irq_disable_mask); } -EXPORT_SYMBOL(enable_percpu_irq); /* * Add an irq to the disabled mask. We disable the HW interrupt @@ -167,13 +166,12 @@ EXPORT_SYMBOL(enable_percpu_irq); * in an interrupt context, the return path is careful to avoid * unmasking a newly disabled interrupt. */ -void disable_percpu_irq(unsigned int irq) +static void tile_irq_chip_disable(struct irq_data *d) { - get_cpu_var(irq_disable_mask) |= (1UL << irq); - mask_irqs(1UL << irq); + get_cpu_var(irq_disable_mask) |= (1UL << d->irq); + mask_irqs(1UL << d->irq); put_cpu_var(irq_disable_mask); } -EXPORT_SYMBOL(disable_percpu_irq); /* Mask an interrupt. */ static void tile_irq_chip_mask(struct irq_data *d) @@ -209,6 +207,8 @@ static void tile_irq_chip_eoi(struct irq_data *d) static struct irq_chip tile_irq_chip = { .name = "tile_irq_chip", + .irq_enable = tile_irq_chip_enable, + .irq_disable = tile_irq_chip_disable, .irq_ack = tile_irq_chip_ack, .irq_eoi = tile_irq_chip_eoi, .irq_mask = tile_irq_chip_mask, diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 1c0f9facb9b1..1187a1169eb2 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -926,7 +926,7 @@ static int tile_net_poll(struct napi_struct *napi, int budget) goto done; /* Re-enable the ingress interrupt. */ - enable_percpu_irq(priv->intr_id); + enable_percpu_irq(priv->intr_id, 0); /* HACK: Avoid the "rotting packet" problem (see above). */ if (qup->__packet_receive_read != @@ -1296,7 +1296,7 @@ static void tile_net_open_enable(void *dev_ptr) info->napi_enabled = true; /* Enable the ingress interrupt. */ - enable_percpu_irq(priv->intr_id); + enable_percpu_irq(priv->intr_id, 0); } -- cgit From f0a4cf31017ac8179a2fe295c1bd8e821d7674f4 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 12:43:40 +0000 Subject: sparc: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: David S. Miller --- arch/sparc/kernel/ds.c | 6 ++---- arch/sparc/kernel/prom_common.c | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 7429b47c3aca..381edcd5bc29 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -1181,13 +1181,11 @@ static int __devinit ds_probe(struct vio_dev *vdev, dp->rcv_buf_len = 4096; - dp->ds_states = kzalloc(sizeof(ds_states_template), - GFP_KERNEL); + dp->ds_states = kmemdup(ds_states_template, + sizeof(ds_states_template), GFP_KERNEL); if (!dp->ds_states) goto out_free_rcv_buf; - memcpy(dp->ds_states, ds_states_template, - sizeof(ds_states_template)); dp->num_ds_states = ARRAY_SIZE(ds_states_template); for (i = 0; i < dp->num_ds_states; i++) diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 46614807a57f..741df916c124 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -58,12 +58,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *new_val; int err; - new_val = kmalloc(len, GFP_KERNEL); + new_val = kmemdup(val, len, GFP_KERNEL); if (!new_val) return -ENOMEM; - memcpy(new_val, val, len); - err = -ENODEV; mutex_lock(&of_set_property_mutex); -- cgit From e410471029ba99e85af5e2a1e7e747c7b4de2bc3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 Nov 2011 21:42:20 +0000 Subject: bbc_i2c: Remove unneeded err variable Signed-off-by: Axel Lin Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_i2c.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 5f94d22c491e..a0d1399577cc 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -233,13 +233,9 @@ int bbc_i2c_write_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_writeb(client, *buf, off); - - if (err < 0) { - ret = err; + ret = bbc_i2c_writeb(client, *buf, off); + if (ret < 0) break; - } - len--; buf++; off++; @@ -253,11 +249,9 @@ int bbc_i2c_read_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_readb(client, buf, off); - if (err < 0) { - ret = err; + ret = bbc_i2c_readb(client, buf, off); + if (ret < 0) break; - } len--; buf++; off++; -- cgit From dbf2b92d54e73e4a2524b90d29bd498ecc4aa593 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 19:04:25 +0000 Subject: sbus: convert drivers/sbus/char/* to use module_platform_driver() This patch converts the drivers in drivers/sbus/char/* to use the module_platform_driver() macro which makes the code smaller and a bit simpler. Signed-off-by: Axel Lin Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_i2c.c | 13 +------------ drivers/sbus/char/display7seg.c | 13 +------------ drivers/sbus/char/envctrl.c | 12 +----------- drivers/sbus/char/flash.c | 12 +----------- drivers/sbus/char/uctrl.c | 12 +----------- 5 files changed, 5 insertions(+), 57 deletions(-) diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index a0d1399577cc..542668292900 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -416,17 +416,6 @@ static struct platform_driver bbc_i2c_driver = { .remove = __devexit_p(bbc_i2c_remove), }; -static int __init bbc_i2c_init(void) -{ - return platform_driver_register(&bbc_i2c_driver); -} - -static void __exit bbc_i2c_exit(void) -{ - platform_driver_unregister(&bbc_i2c_driver); -} - -module_init(bbc_i2c_init); -module_exit(bbc_i2c_exit); +module_platform_driver(bbc_i2c_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 965a1fccd66a..4b9939726c34 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -275,15 +275,4 @@ static struct platform_driver d7s_driver = { .remove = __devexit_p(d7s_remove), }; -static int __init d7s_init(void) -{ - return platform_driver_register(&d7s_driver); -} - -static void __exit d7s_exit(void) -{ - platform_driver_unregister(&d7s_driver); -} - -module_init(d7s_init); -module_exit(d7s_exit); +module_platform_driver(d7s_driver); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index be7b4e56154f..339fd6f65eda 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1138,16 +1138,6 @@ static struct platform_driver envctrl_driver = { .remove = __devexit_p(envctrl_remove), }; -static int __init envctrl_init(void) -{ - return platform_driver_register(&envctrl_driver); -} - -static void __exit envctrl_exit(void) -{ - platform_driver_unregister(&envctrl_driver); -} +module_platform_driver(envctrl_driver); -module_init(envctrl_init); -module_exit(envctrl_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 73dd4e7afaaa..826157f38694 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -216,16 +216,6 @@ static struct platform_driver flash_driver = { .remove = __devexit_p(flash_remove), }; -static int __init flash_init(void) -{ - return platform_driver_register(&flash_driver); -} - -static void __exit flash_cleanup(void) -{ - platform_driver_unregister(&flash_driver); -} +module_platform_driver(flash_driver); -module_init(flash_init); -module_exit(flash_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index ebce9639a26a..0b31658ccde5 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -435,16 +435,6 @@ static struct platform_driver uctrl_driver = { }; -static int __init uctrl_init(void) -{ - return platform_driver_register(&uctrl_driver); -} - -static void __exit uctrl_exit(void) -{ - platform_driver_unregister(&uctrl_driver); -} +module_platform_driver(uctrl_driver); -module_init(uctrl_init); -module_exit(uctrl_exit); MODULE_LICENSE("GPL"); -- cgit From 8e8da023f5af71662867729db5547dc54786093c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Dec 2011 11:57:09 -0800 Subject: x86: Fix boot failures on older AMD CPU's People with old AMD chips are getting hung boots, because commit bcb80e53877c ("x86, microcode, AMD: Add microcode revision to /proc/cpuinfo") moved the microcode detection too early into "early_init_amd()". At that point we are *so* early in the booth that the exception tables haven't even been set up yet, so the whole rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); doesn't actually work: if the rdmsr does a GP fault (due to non-existant MSR register on older CPU's), we can't fix it up yet, and the boot fails. Fix it by simply moving the code to a slightly later point in the boot (init_amd() instead of early_init_amd()), since the kernel itself doesn't even really care about the microcode patchlevel at this point (or really ever: it's made available to user space in /proc/cpuinfo, and updated if you do a microcode load). Reported-tested-and-bisected-by: Larry Finger Tested-by: Bob Tracy Acked-by: Borislav Petkov Cc: Ingo Molnar Cc: Srivatsa S. Bhat Signed-off-by: Linus Torvalds --- arch/x86/kernel/cpu/amd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c7e46cb35327..0bab2b18bb20 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -442,8 +442,6 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) { - u32 dummy; - early_init_amd_mc(c); /* @@ -473,12 +471,12 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_EXTD_APICID); } #endif - - rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); } static void __cpuinit init_amd(struct cpuinfo_x86 *c) { + u32 dummy; + #ifdef CONFIG_SMP unsigned long long value; @@ -657,6 +655,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask); } } + + rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); } #ifdef CONFIG_X86_32 -- cgit From ef1497707c69f3805bbca97c5d10c2913b6d2fa1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 19:35:20 +0800 Subject: ASoC: uda1380: Return proper error in uda1380_modinit failure path Return proper error for uda1380_modinit if i2c_add_driver() fails. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index c5ca8cfea60f..0441893e270e 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -863,13 +863,13 @@ static struct i2c_driver uda1380_i2c_driver = { static int __init uda1380_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&uda1380_i2c_driver); if (ret != 0) pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); #endif - return 0; + return ret; } module_init(uda1380_modinit); -- cgit From b971c370a4d265848d9df0793b2f7fcc5b16b378 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 16:30:18 +0800 Subject: ASoC: Fix dependency for SND_SOC_RAUMFELD and SND_PXA2XX_SOC_HX4700 SND_SOC_RAUMFELD selects SND_SOC_CS4270 which needs CONFIG_I2C, and also selects SND_SOC_AK4104 which needs SPI_MASTER. Thus make SND_SOC_RAUMFELD depend on I2C && SPI_MASTER. Add depend on SPI_MASTER to fix below build error if CONFIG_SPI_MASTER is not selected. LD .tmp_vmlinux1 sound/built-in.o: In function `ak4104_spi_write': last.c:(.text+0x290cc): undefined reference to `spi_sync' sound/built-in.o: In function `ak4104_probe': last.c:(.text+0x292a0): undefined reference to `spi_write_then_read' sound/built-in.o: In function `ak4104_spi_probe': last.c:(.text+0x29398): undefined reference to `spi_setup' sound/built-in.o: In function `ak4104_init': last.c:(.init.text+0x4ec): undefined reference to `spi_register_driver' make: *** [.tmp_vmlinux1] Error 1 Add depend on I2C to fix below build error if CONFIG_I2C is not selected: CC sound/soc/codecs/cs4270.o sound/soc/codecs/cs4270.c: In function 'cs4270_i2c_probe': sound/soc/codecs/cs4270.c:657: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/cs4270.c: In function 'cs4270_init': sound/soc/codecs/cs4270.c:730: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/cs4270.c: In function 'cs4270_exit': sound/soc/codecs/cs4270.c:736: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/cs4270.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 SND_PXA2XX_SOC_HX4700 selects SND_SOC_AK4641 which needs CONFIG_I2C. Thus make SND_PXA2XX_SOC_HX4700 depend on I2C. Add depend on I2C to fix below build error if CONFIG_I2C is not selected: CC sound/soc/codecs/ak4641.o sound/soc/codecs/ak4641.c: In function 'ak4641_modinit': sound/soc/codecs/ak4641.c:646: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/ak4641.c: In function 'ak4641_exit': sound/soc/codecs/ak4641.c:656: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/ak4641.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index ffd2242e305f..a0f7d3cfa470 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -151,6 +151,7 @@ config SND_SOC_ZYLONITE config SND_SOC_RAUMFELD tristate "SoC Audio support Raumfeld audio adapter" depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR) + depends on I2C && SPI_MASTER select SND_PXA_SOC_SSP select SND_SOC_CS4270 select SND_SOC_AK4104 @@ -159,7 +160,7 @@ config SND_SOC_RAUMFELD config SND_PXA2XX_SOC_HX4700 tristate "SoC Audio support for HP iPAQ hx4700" - depends on SND_PXA2XX_SOC && MACH_H4700 + depends on SND_PXA2XX_SOC && MACH_H4700 && I2C select SND_PXA2XX_SOC_I2S select SND_SOC_AK4641 help -- cgit From 570a2429e964f8d63338b3450ba801a263b29b3a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 16:11:16 +0800 Subject: ASoC: Make SND_SOC_MX27VIS_AIC32X4 depend on I2C SND_SOC_MX27VIS_AIC32X4 selects SND_SOC_TLV320AIC32X4, but SND_SOC_TLV320AIC32X4 needs CONFIG_I2C. So we need to make SND_SOC_MX27VIS_AIC32X4 depend on I2C. otherwise I got below build error if CONFIG_I2C is not selected. CC sound/soc/codecs/tlv320aic32x4.o sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_read': sound/soc/codecs/tlv320aic32x4.c:323: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_probe': sound/soc/codecs/tlv320aic32x4.c:641: error: 'i2c_master_send' undeclared (first use in this function) sound/soc/codecs/tlv320aic32x4.c:641: error: (Each undeclared identifier is reported only once sound/soc/codecs/tlv320aic32x4.c:641: error: for each function it appears in.) sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_modinit': sound/soc/codecs/tlv320aic32x4.c:763: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_exit': sound/soc/codecs/tlv320aic32x4.c:774: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/tlv320aic32x4.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index b133bfcc5848..738391757f2c 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -28,7 +28,7 @@ config SND_MXC_SOC_WM1133_EV1 config SND_SOC_MX27VIS_AIC32X4 tristate "SoC audio support for Visstrim M10 boards" - depends on MACH_IMX27_VISSTRIM_M10 + depends on MACH_IMX27_VISSTRIM_M10 && I2C select SND_SOC_TLV320AIC32X4 select SND_MXC_SOC_MX2 help -- cgit From 6a600a8b8749566a7d81ad75dcb8bf5342b5a39a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 15 Nov 2011 10:51:15 +0100 Subject: perf, x86: Disable PEBS on SandyBridge chips Cc: Stephane Eranian Cc: stable@kernel.org Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 2be5ebe99872..8d601b18bf9f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1545,6 +1545,13 @@ static void intel_clovertown_quirks(void) x86_pmu.pebs_constraints = NULL; } +static void intel_sandybridge_quirks(void) +{ + printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); + x86_pmu.pebs = 0; + x86_pmu.pebs_constraints = NULL; +} + __init int intel_pmu_init(void) { union cpuid10_edx edx; @@ -1694,6 +1701,7 @@ __init int intel_pmu_init(void) break; case 42: /* SandyBridge */ + x86_pmu.quirks = intel_sandybridge_quirks; case 45: /* SandyBridge, "Romely-EP" */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); -- cgit From 16e5294e5f8303756a179cf218e37dfb9ed34417 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 8 Nov 2011 19:20:44 +0100 Subject: perf, x86: Force IBS LVT offset assignment for family 10h On AMD family 10h we see firmware bug messages like the following: [Firmware Bug]: cpu 6, try to use APIC500 (LVT offset 0) for vector 0x10400, but the register is already in use for vector 0xf9 on another cpu [Firmware Bug]: cpu 6, IBS interrupt offset 0 not available (MSRC001103A=0x0000000000000100) [Firmware Bug]: using offset 1 for IBS interrupts [Firmware Bug]: workaround enabled for IBS LVT offset perf: AMD IBS detected (0x00000007) We always see this, since the offsets are not assigned by the BIOS for this family. Force LVT offset assignment in this case. If the OS assignment fails, fallback to BIOS settings and try to setup this. The fallback to BIOS settings weakens the family check since force_ibs_eilvt_setup() may fail e.g. in case of virtual machines. But setup may still succeed if BIOS offsets are correct. Other families don't have a workaround implemented that assigns LVT offsets. It's ok, to drop calling force_ibs_eilvt_setup() for that families. With the patch the [Firmware Bug] messages vanish. We see now: IBS: LVT offset 1 assigned perf: AMD IBS detected (0x00000007) Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111109162225.GO12451@erda.amd.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index ab6343d21825..3b8a2d30d14e 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -199,8 +199,7 @@ static int force_ibs_eilvt_setup(void) goto out; } - pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); - pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); + pr_info("IBS: LVT offset %d assigned\n", offset); return 0; out: @@ -265,19 +264,23 @@ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *h static __init int amd_ibs_init(void) { u32 caps; - int ret; + int ret = -EINVAL; caps = __get_ibs_caps(); if (!caps) return -ENODEV; /* ibs not supported by the cpu */ - if (!ibs_eilvt_valid()) { - ret = force_ibs_eilvt_setup(); - if (ret) { - pr_err("Failed to setup IBS, %d\n", ret); - return ret; - } - } + /* + * Force LVT offset assignment for family 10h: The offsets are + * not assigned by the BIOS for this family, so the OS is + * responsible for doing it. If the OS assignment fails, fall + * back to BIOS settings and try to setup this. + */ + if (boot_cpu_data.x86 == 0x10) + force_ibs_eilvt_setup(); + + if (!ibs_eilvt_valid()) + goto out; get_online_cpus(); ibs_caps = caps; @@ -287,7 +290,11 @@ static __init int amd_ibs_init(void) smp_call_function(setup_APIC_ibs, NULL, 1); put_online_cpus(); - return perf_event_ibs_init(); + ret = perf_event_ibs_init(); +out: + if (ret) + pr_err("Failed to setup IBS, %d\n", ret); + return ret; } /* Since we need the pci subsystem to init ibs we can't do this earlier: */ -- cgit From 10c6db110d0eb4466b59812c49088ab56218fc2e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 26 Nov 2011 02:47:31 +0100 Subject: perf: Fix loss of notification with multi-event When you do: $ perf record -e cycles,cycles,cycles noploop 10 You expect about 10,000 samples for each event, i.e., 10s at 1000samples/sec. However, this is not what's happening. You get much fewer samples, maybe 3700 samples/event: $ perf report -D | tail -15 Aggregated stats: TOTAL events: 10998 MMAP events: 66 COMM events: 2 SAMPLE events: 10930 cycles stats: TOTAL events: 3644 SAMPLE events: 3644 cycles stats: TOTAL events: 3642 SAMPLE events: 3642 cycles stats: TOTAL events: 3644 SAMPLE events: 3644 On a Intel Nehalem or even AMD64, there are 4 counters capable of measuring cycles, so there is plenty of space to measure those events without multiplexing (even with the NMI watchdog active). And even with multiplexing, we'd expect roughly the same number of samples per event. The root of the problem was that when the event that caused the buffer to become full was not the first event passed on the cmdline, the user notification would get lost. The notification was sent to the file descriptor of the overflowed event but the perf tool was not polling on it. The perf tool aggregates all samples into a single buffer, i.e., the buffer of the first event. Consequently, it assumes notifications for any event will come via that descriptor. The seemingly straight forward solution of moving the waitq into the ringbuffer object doesn't work because of life-time issues. One could perf_event_set_output() on a fd that you're also blocking on and cause the old rb object to be freed while its waitq would still be referenced by the blocked thread -> FAIL. Therefore link all events to the ringbuffer and broadcast the wakeup from the ringbuffer object to all possible events that could be waited upon. This is rather ugly, and we're open to better solutions but it works for now. Reported-by: Stephane Eranian Finished-by: Stephane Eranian Reviewed-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111126014731.GA7030@quad Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 1 + kernel/events/core.c | 86 +++++++++++++++++++++++++++++++++++++++++++-- kernel/events/internal.h | 3 ++ kernel/events/ring_buffer.c | 3 ++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 1e9ebe5e0091..b1f89122bf6a 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -822,6 +822,7 @@ struct perf_event { int mmap_locked; struct user_struct *mmap_user; struct ring_buffer *rb; + struct list_head rb_entry; /* poll related */ wait_queue_head_t waitq; diff --git a/kernel/events/core.c b/kernel/events/core.c index b0c1186fd97b..600c1629b64d 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -185,6 +185,9 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, static void update_context_time(struct perf_event_context *ctx); static u64 perf_event_time(struct perf_event *event); +static void ring_buffer_attach(struct perf_event *event, + struct ring_buffer *rb); + void __weak perf_event_print_debug(void) { } extern __weak const char *perf_pmu_name(void) @@ -3191,12 +3194,33 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) struct ring_buffer *rb; unsigned int events = POLL_HUP; + /* + * Race between perf_event_set_output() and perf_poll(): perf_poll() + * grabs the rb reference but perf_event_set_output() overrides it. + * Here is the timeline for two threads T1, T2: + * t0: T1, rb = rcu_dereference(event->rb) + * t1: T2, old_rb = event->rb + * t2: T2, event->rb = new rb + * t3: T2, ring_buffer_detach(old_rb) + * t4: T1, ring_buffer_attach(rb1) + * t5: T1, poll_wait(event->waitq) + * + * To avoid this problem, we grab mmap_mutex in perf_poll() + * thereby ensuring that the assignment of the new ring buffer + * and the detachment of the old buffer appear atomic to perf_poll() + */ + mutex_lock(&event->mmap_mutex); + rcu_read_lock(); rb = rcu_dereference(event->rb); - if (rb) + if (rb) { + ring_buffer_attach(event, rb); events = atomic_xchg(&rb->poll, 0); + } rcu_read_unlock(); + mutex_unlock(&event->mmap_mutex); + poll_wait(file, &event->waitq, wait); return events; @@ -3497,6 +3521,49 @@ unlock: return ret; } +static void ring_buffer_attach(struct perf_event *event, + struct ring_buffer *rb) +{ + unsigned long flags; + + if (!list_empty(&event->rb_entry)) + return; + + spin_lock_irqsave(&rb->event_lock, flags); + if (!list_empty(&event->rb_entry)) + goto unlock; + + list_add(&event->rb_entry, &rb->event_list); +unlock: + spin_unlock_irqrestore(&rb->event_lock, flags); +} + +static void ring_buffer_detach(struct perf_event *event, + struct ring_buffer *rb) +{ + unsigned long flags; + + if (list_empty(&event->rb_entry)) + return; + + spin_lock_irqsave(&rb->event_lock, flags); + list_del_init(&event->rb_entry); + wake_up_all(&event->waitq); + spin_unlock_irqrestore(&rb->event_lock, flags); +} + +static void ring_buffer_wakeup(struct perf_event *event) +{ + struct ring_buffer *rb; + + rcu_read_lock(); + rb = rcu_dereference(event->rb); + list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { + wake_up_all(&event->waitq); + } + rcu_read_unlock(); +} + static void rb_free_rcu(struct rcu_head *rcu_head) { struct ring_buffer *rb; @@ -3522,9 +3589,19 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event) static void ring_buffer_put(struct ring_buffer *rb) { + struct perf_event *event, *n; + unsigned long flags; + if (!atomic_dec_and_test(&rb->refcount)) return; + spin_lock_irqsave(&rb->event_lock, flags); + list_for_each_entry_safe(event, n, &rb->event_list, rb_entry) { + list_del_init(&event->rb_entry); + wake_up_all(&event->waitq); + } + spin_unlock_irqrestore(&rb->event_lock, flags); + call_rcu(&rb->rcu_head, rb_free_rcu); } @@ -3547,6 +3624,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm); vma->vm_mm->pinned_vm -= event->mmap_locked; rcu_assign_pointer(event->rb, NULL); + ring_buffer_detach(event, rb); mutex_unlock(&event->mmap_mutex); ring_buffer_put(rb); @@ -3701,7 +3779,7 @@ static const struct file_operations perf_fops = { void perf_event_wakeup(struct perf_event *event) { - wake_up_all(&event->waitq); + ring_buffer_wakeup(event); if (event->pending_kill) { kill_fasync(&event->fasync, SIGIO, event->pending_kill); @@ -5823,6 +5901,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, INIT_LIST_HEAD(&event->group_entry); INIT_LIST_HEAD(&event->event_entry); INIT_LIST_HEAD(&event->sibling_list); + INIT_LIST_HEAD(&event->rb_entry); + init_waitqueue_head(&event->waitq); init_irq_work(&event->pending, perf_pending_event); @@ -6029,6 +6109,8 @@ set: old_rb = event->rb; rcu_assign_pointer(event->rb, rb); + if (old_rb) + ring_buffer_detach(event, old_rb); ret = 0; unlock: mutex_unlock(&event->mmap_mutex); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 09097dd8116c..64568a699375 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -22,6 +22,9 @@ struct ring_buffer { local_t lost; /* nr records lost */ long watermark; /* wakeup watermark */ + /* poll crap */ + spinlock_t event_lock; + struct list_head event_list; struct perf_event_mmap_page *user_page; void *data_pages[0]; diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index a2a29205cc0f..7f3011c6b57f 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -209,6 +209,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) rb->writable = 1; atomic_set(&rb->refcount, 1); + + INIT_LIST_HEAD(&rb->event_list); + spin_lock_init(&rb->event_lock); } #ifndef CONFIG_PERF_USE_VMALLOC -- cgit From 52cef189165d74a5d6030184a8e05595194c69ca Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 28 Nov 2011 21:12:40 +0100 Subject: slab, lockdep: Fix silly bug Commit 30765b92 ("slab, lockdep: Annotate the locks before using them") moves the init_lock_keys() call from after g_cpucache_up = FULL, to before it. And overlooks the fact that init_node_lock_keys() tests for it and ignores everything !FULL. Introduce a LATE stage and change the lockdep test to be Cc: Pekka Enberg Cc: stable@kernel.org Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- mm/slab.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/slab.c b/mm/slab.c index 708efe886154..83311c9aaf9d 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -595,6 +595,7 @@ static enum { PARTIAL_AC, PARTIAL_L3, EARLY, + LATE, FULL } g_cpucache_up; @@ -671,7 +672,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up != FULL) + if (g_cpucache_up < LATE) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -1666,6 +1667,8 @@ void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; + g_cpucache_up = LATE; + /* Annotate slab for lockdep -- annotate the malloc caches */ init_lock_keys(); -- cgit From 69682b625a043b567873e6cda397969b502f0054 Mon Sep 17 00:00:00 2001 From: Mitsuo Hayasaka Date: Tue, 29 Nov 2011 15:08:21 +0900 Subject: x86: Add user_mode_vm check in stack_overflow_check The kernel stack overflow is checked in stack_overflow_check(), which may wrongly detect the overflow if the stack pointer in user space points to the kernel stack intentionally or accidentally. So, the actual overflow is never detected after this misdetection because WARN_ONCE() is used on the detection of it. This patch adds user-mode-vm checking before it to avoid this problem and bails out early if the user stack is used. Signed-off-by: Mitsuo Hayasaka Cc: yrl.pp-manager.tt@hitachi.com Cc: Randy Dunlap Link: http://lkml.kernel.org/r/20111129060821.11076.55315.stgit@ltc219.sdl.hitachi.co.jp Signed-off-by: Ingo Molnar Cc: "H. Peter Anvin" --- arch/x86/kernel/irq_64.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index acf8fbf8fbda..69bca468c47a 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -38,6 +38,9 @@ static inline void stack_overflow_check(struct pt_regs *regs) #ifdef CONFIG_DEBUG_STACKOVERFLOW u64 curbase = (u64)task_stack_page(current); + if (user_mode_vm(regs)) + return; + WARN_ONCE(regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE && regs->sp < curbase + sizeof(struct thread_info) + -- cgit From b495e039b4ce2ce4a96b3006004faf082f4d50e2 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Tue, 29 Nov 2011 15:00:58 -0600 Subject: x86, UV: Fix UV2 hub part number There was a mixup when the SGI UV2 hub chip was sent to be fabricated, and it ended up with the wrong part number in the HRP_NODE_ID mmr. Future versions of the chip will (may) have the correct part number. Change the UV infrastructure to recognize both part numbers as valid IDs of a UV2 hub chip. Signed-off-by: Jack Steiner Link: http://lkml.kernel.org/r/20111129210058.GA20452@sgi.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/uv/uv_mmrs.h | 1 + arch/x86/kernel/apic/x2apic_uv_x.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index 10474fb1185d..cf1d73643f60 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h @@ -57,6 +57,7 @@ #define UV1_HUB_PART_NUMBER 0x88a5 #define UV2_HUB_PART_NUMBER 0x8eb8 +#define UV2_HUB_PART_NUMBER_X 0x1111 /* Compat: if this #define is present, UV headers support UV2 */ #define UV2_HUB_IS_SUPPORTED 1 diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 62ae3001ae02..9d59bbacd4e3 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -93,6 +93,8 @@ static int __init early_get_pnodeid(void) if (node_id.s.part_number == UV2_HUB_PART_NUMBER) uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; + if (node_id.s.part_number == UV2_HUB_PART_NUMBER_X) + uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; uv_hub_info->hub_revision = uv_min_hub_revision_id; pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1); -- cgit From 8f9a0981aca6bd454ef2a4bdac510af0f6e55bd4 Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Tue, 15 Nov 2011 01:42:06 +0530 Subject: ARM: davinci: psc: fix incorrect mask There are 5 LSB bits defined in PDSTAT and the code currently uses a mask of 1 bit to check the status. Use a proper mask per the hardware specification. While at it, use a #define for the mask to improve readability. Reviewed-by: Sergei Shtylyov Signed-off-by: Murali Karicheri Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/include/mach/psc.h | 1 + arch/arm/mach-davinci/psc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index fa59c097223d..8bf279a88b4b 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -244,6 +244,7 @@ #define PSC_STATE_ENABLE 3 #define MDSTAT_STATE_MASK 0x3f +#define PDSTAT_STATE_MASK 0x1f #define MDCTL_FORCE BIT(31) #ifndef __ASSEMBLER__ diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 1fb6bdff38c1..a0e17707c981 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -80,7 +80,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, __raw_writel(mdctl, psc_base + MDCTL + 4 * id); pdstat = __raw_readl(psc_base + PDSTAT); - if ((pdstat & 0x00000001) == 0) { + if ((pdstat & PDSTAT_STATE_MASK) == 0) { pdctl1 = __raw_readl(psc_base + PDCTL1); pdctl1 |= 0x1; __raw_writel(pdctl1, psc_base + PDCTL1); -- cgit From 78b838252fa986f66c7ec8047726ea500a08d98f Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Tue, 15 Nov 2011 01:42:07 +0530 Subject: ARM: davinci: psc: fix incorrect offsets Seperate PDSTAT and PDCTL registers are defined for domain 0 and domain 1 where as the code always reads the domain 0 PDSTAT register and domain 1 PDCTL register. Fix this issue. While at it, introduce usage of macros for register masks to improve readability. Reviewed-by: Sergei Shtylyov Signed-off-by: Murali Karicheri Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/include/mach/psc.h | 4 +++- arch/arm/mach-davinci/psc.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 8bf279a88b4b..8bc3fc256171 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -233,7 +233,7 @@ #define PTCMD 0x120 #define PTSTAT 0x128 #define PDSTAT 0x200 -#define PDCTL1 0x304 +#define PDCTL 0x300 #define MDSTAT 0x800 #define MDCTL 0xA00 @@ -246,6 +246,8 @@ #define MDSTAT_STATE_MASK 0x3f #define PDSTAT_STATE_MASK 0x1f #define MDCTL_FORCE BIT(31) +#define PDCTL_NEXT BIT(1) +#define PDCTL_EPCGOOD BIT(8) #ifndef __ASSEMBLER__ diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index a0e17707c981..d7e210f4b55c 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -52,7 +52,7 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) void davinci_psc_config(unsigned int domain, unsigned int ctlr, unsigned int id, bool enable, u32 flags) { - u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl; + u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl; void __iomem *psc_base; struct davinci_soc_info *soc_info = &davinci_soc_info; u32 next_state = PSC_STATE_ENABLE; @@ -79,11 +79,11 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, mdctl |= MDCTL_FORCE; __raw_writel(mdctl, psc_base + MDCTL + 4 * id); - pdstat = __raw_readl(psc_base + PDSTAT); + pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain); if ((pdstat & PDSTAT_STATE_MASK) == 0) { - pdctl1 = __raw_readl(psc_base + PDCTL1); - pdctl1 |= 0x1; - __raw_writel(pdctl1, psc_base + PDCTL1); + pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); + pdctl |= PDCTL_NEXT; + __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); ptcmd = 1 << domain; __raw_writel(ptcmd, psc_base + PTCMD); @@ -92,9 +92,9 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, epcpr = __raw_readl(psc_base + EPCPR); } while ((((epcpr >> domain) & 1) == 0)); - pdctl1 = __raw_readl(psc_base + PDCTL1); - pdctl1 |= 0x100; - __raw_writel(pdctl1, psc_base + PDCTL1); + pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); + pdctl |= PDCTL_EPCGOOD; + __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); } else { ptcmd = 1 << domain; __raw_writel(ptcmd, psc_base + PTCMD); -- cgit From 9ab409e402cbfde11e2516be43921954db480f4d Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 15 Nov 2011 01:42:08 +0530 Subject: ARM: davinci: dm646x does not have a DSP domain Fix the incorrect classification of DSP clock into a seperate DSP domain on DM646x. Per the reference guide (http://www.ti.com/lit/ug/spruep9e/spruep9e.pdf) there is only one "AlwaysON" power domain on DM6467. Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/dm646x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 0b68ed534f8e..af27c130595f 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -161,7 +161,6 @@ static struct clk dsp_clk = { .name = "dsp", .parent = &pll1_sysclk1, .lpsc = DM646X_LPSC_C64X_CPU, - .flags = PSC_DSP, .usecount = 1, /* REVISIT how to disable? */ }; -- cgit From 83713fc9373be2e943f82e9d36213708c6b0050e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 14 Nov 2011 19:20:49 +0100 Subject: ARM: davinci: dm646x evm: wrong register used in setup_vpif_input_channel_mode The function setup_vpif_input_channel_mode() used the VSCLKDIS register instead of VIDCLKCTL. This meant that when in HD mode videoport channel 0 used a different clock from channel 1. Clearly a copy-and-paste error. Signed-off-by: Hans Verkuil Acked-by: Manjunath Hadli Signed-off-by: Sekhar Nori Cc: stable@kernel.org --- arch/arm/mach-davinci/board-dm646x-evm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index e574d7f837a8..635bf7740157 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -564,7 +564,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) int val; u32 value; - if (!vpif_vsclkdis_reg || !cpld_client) + if (!vpif_vidclkctl_reg || !cpld_client) return -ENXIO; val = i2c_smbus_read_byte(cpld_client); @@ -572,7 +572,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) return val; spin_lock_irqsave(&vpif_reg_lock, flags); - value = __raw_readl(vpif_vsclkdis_reg); + value = __raw_readl(vpif_vidclkctl_reg); if (mux_mode) { val &= VPIF_INPUT_TWO_CHANNEL; value |= VIDCH1CLK; @@ -580,7 +580,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) val |= VPIF_INPUT_ONE_CHANNEL; value &= ~VIDCH1CLK; } - __raw_writel(value, vpif_vsclkdis_reg); + __raw_writel(value, vpif_vidclkctl_reg); spin_unlock_irqrestore(&vpif_reg_lock, flags); err = i2c_smbus_write_byte(cpld_client, val); -- cgit From f1b21c525693b0159aed83b5871f2d0f077f208e Mon Sep 17 00:00:00 2001 From: "Manjunathappa, Prakash" Date: Thu, 10 Nov 2011 11:43:21 +0530 Subject: ARM: davinci: da850 evm: change audio edma event queue to EVENTQ_0 On OMAP-L138 platform, EDMA event queue 0 should be used for audio transfers so that they are not starved by video data moving on event queue 1. Commit 48519f0ae03bc7e86b3dc93e56f1334d53803770 (ASoC: davinci: let platform data define edma queue numbers) had a side-effect of changing this behavior by making the driver actually honor the platform data passed. Fix this now by passing event queue 0 as the queue to be used for audio transfers. Signed-off-by: Manjunathappa, Prakash Signed-off-by: Sekhar Nori Cc: # v2.6.36.x and above --- arch/arm/mach-davinci/board-da850-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 1d7d24995226..6659a90dbcad 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -753,7 +753,7 @@ static struct snd_platform_data da850_evm_snd_data = { .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction), .tdm_slots = 2, .serial_dir = da850_iis_serializer_direction, - .asp_chan_q = EVENTQ_1, + .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_2, .txnumevt = 1, .rxnumevt = 1, -- cgit From 45fc4cce939adc883fba5e02f1f3e0e9ff020c30 Mon Sep 17 00:00:00 2001 From: "Shankarmurthy,Akshay" Date: Wed, 9 Nov 2011 17:55:20 +0530 Subject: ARM: davinci: dm365 evm: align nand partition table to u-boot Current partition information maintained in kernel does not match with u-boot, this leads to corruption of u-boot env when we update uImage from kernel. Patch fixes it to match with u-boot partition information. Signed-off-by: Shankarmurthy,Akshay Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/board-dm365-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 1918ae711428..46e1f4173b97 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -107,7 +107,7 @@ static struct mtd_partition davinci_nand_partitions[] = { /* UBL (a few copies) plus U-Boot */ .name = "bootloader", .offset = 0, - .size = 28 * NAND_BLOCK_SIZE, + .size = 30 * NAND_BLOCK_SIZE, .mask_flags = MTD_WRITEABLE, /* force read-only */ }, { /* U-Boot environment */ -- cgit From 6be30bb7d7504ec687a65c9bbdae8d1d2f8eaa19 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 16 Nov 2011 00:19:51 +0100 Subject: x86/reboot: Blacklist Dell OptiPlex 990 known to require PCI reboot Dell OptiPlex 990 is known to require PCI reboot, so add it to the reboot blacklist in pci_reboot_dmi_table[]. Signed-off-by: Rafael J. Wysocki Link: http://lkml.kernel.org/r/201111160019.51303.rjw@sisk.pl Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e334be1182b9..4463d2fee4e3 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -443,6 +443,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), }, }, + { /* Handle problems with rebooting on the OptiPlex 990. */ + .callback = set_pci_reboot, + .ident = "Dell OptiPlex 990", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), + }, + }, { } }; -- cgit From df16c86a56595d1c28e58532ec25dd612c39c6c7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 23 Nov 2011 15:57:06 +0100 Subject: mtd: gpmi: add missing include 'module.h' Fixes: drivers/mtd/nand/gpmi-nand/gpmi-nand.c: In function 'gpmi_nfc_init': drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1475:16: error: 'THIS_MODULE' undeclared (first use in this function) drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1475:16: note: each undeclared identifier is reported only once for each function it appears in drivers/mtd/nand/gpmi-nand/gpmi-nand.c: At top level: drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1617:15: error: expected declaration specifiers or '...' before string constant drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1617:1: warning: data definition has no type or storage class drivers/mtd/nand/gpmi-nand/gpmi-nand.c:1617:1: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' and some more... Signed-off-by: Wolfram Sang Acked-by: Huang Shijie Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 071b63420f0e..493ec2fcf97f 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -21,9 +21,9 @@ #include #include #include +#include #include #include - #include "gpmi-nand.h" /* add our owner bbt descriptor */ -- cgit From 48bc5562103412590e4487b666b49e7b6c84ba44 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Wed, 16 Nov 2011 16:07:22 +0000 Subject: x86,mrst: Power control commands update On the Intel MID devices SCU commands are issued to manage power off and the like. We need to issue different ones for non-Lincroft based devices. Signed-off-by: Alek Du Signed-off-by: Jacob Pan Signed-off-by: Alan Cox Signed-off-by: Ingo Molnar --- arch/x86/include/asm/intel_scu_ipc.h | 14 +++++++++----- arch/x86/platform/mrst/mrst.c | 25 ++++++++++++++----------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h index 4420993acc47..925b605eb5c6 100644 --- a/arch/x86/include/asm/intel_scu_ipc.h +++ b/arch/x86/include/asm/intel_scu_ipc.h @@ -3,11 +3,15 @@ #include -#define IPCMSG_VRTC 0xFA /* Set vRTC device */ - -/* Command id associated with message IPCMSG_VRTC */ -#define IPC_CMD_VRTC_SETTIME 1 /* Set time */ -#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ +#define IPCMSG_WARM_RESET 0xF0 +#define IPCMSG_COLD_RESET 0xF1 +#define IPCMSG_SOFT_RESET 0xF2 +#define IPCMSG_COLD_BOOT 0xF3 + +#define IPCMSG_VRTC 0xFA /* Set vRTC device */ + /* Command id associated with message IPCMSG_VRTC */ + #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ + #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ /* Read single register */ int intel_scu_ipc_ioread8(u16 addr, u8 *data); diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index b1489a06a49d..fedc3d7ffa77 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -76,6 +76,20 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; EXPORT_SYMBOL_GPL(sfi_mrtc_array); int sfi_mrtc_num; +static void mrst_power_off(void) +{ + if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) + intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1); +} + +static void mrst_reboot(void) +{ + if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) + intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); + else + intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); +} + /* parse all the mtimer info to a static mtimer array */ static int __init sfi_parse_mtmr(struct sfi_table_header *table) { @@ -265,17 +279,6 @@ static int mrst_i8042_detect(void) return 0; } -/* Reboot and power off are handled by the SCU on a MID device */ -static void mrst_power_off(void) -{ - intel_scu_ipc_simple_command(0xf1, 1); -} - -static void mrst_reboot(void) -{ - intel_scu_ipc_simple_command(0xf1, 0); -} - /* * Moorestown does not have external NMI source nor port 0x61 to report * NMI status. The possible NMI sources are from pmu as a result of NMI -- cgit From 28744b3e9c85ea281d6371d4914c2498bceec10c Mon Sep 17 00:00:00 2001 From: Jekyll Lai Date: Wed, 16 Nov 2011 18:01:20 +0000 Subject: mrst: Added some platform data for the SFI translations Add SFI glue for the following devices: tca6416: a gpio expander compatible with max7315 mpu3050: gyro sensor Both of these actual drivers are already upstream Signed-off-by: Jekyll Lai Signed-off-by: Alan Cox Signed-off-by: Ingo Molnar --- arch/x86/platform/mrst/mrst.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index fedc3d7ffa77..940a0807a5ca 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -487,6 +487,46 @@ static void __init *max7315_platform_data(void *info) return max7315; } +static void *tca6416_platform_data(void *info) +{ + static struct pca953x_platform_data tca6416; + struct i2c_board_info *i2c_info = info; + int gpio_base, intr; + char base_pin_name[SFI_NAME_LEN + 1]; + char intr_pin_name[SFI_NAME_LEN + 1]; + + strcpy(i2c_info->type, "tca6416"); + strcpy(base_pin_name, "tca6416_base"); + strcpy(intr_pin_name, "tca6416_int"); + + gpio_base = get_gpio_by_name(base_pin_name); + intr = get_gpio_by_name(intr_pin_name); + + if (gpio_base == -1) + return NULL; + tca6416.gpio_base = gpio_base; + if (intr != -1) { + i2c_info->irq = intr + MRST_IRQ_OFFSET; + tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET; + } else { + i2c_info->irq = -1; + tca6416.irq_base = -1; + } + return &tca6416; +} + +static void *mpu3050_platform_data(void *info) +{ + struct i2c_board_info *i2c_info = info; + int intr = get_gpio_by_name("mpu3050_int"); + + if (intr == -1) + return NULL; + + i2c_info->irq = intr + MRST_IRQ_OFFSET; + return NULL; +} + static void __init *emc1403_platform_data(void *info) { static short intr2nd_pdata; @@ -652,9 +692,11 @@ static const struct devs_id __initconst device_ids[] = { {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, + {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data}, {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, + {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data}, /* MSIC subdevices */ {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data}, -- cgit From efa221268566c2caa0e2a540068a2e8250fbb819 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 16 Nov 2011 18:32:34 +0000 Subject: x86, mrst: Change the pmic_gpio device type to IPC In latest firmware's SFI tables, pmic_gpio has been set to IPC type of device, so we need handle it too. Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Ingo Molnar --- arch/x86/platform/mrst/mrst.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 940a0807a5ca..ad4ec1cb097e 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -689,6 +689,7 @@ static void *msic_ocd_platform_data(void *info) static const struct devs_id __initconst device_ids[] = { {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data}, {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, + {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data}, {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, -- cgit From 9e6866686bdf2dcf3aeb0838076237ede532dcc8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 25 Sep 2011 15:29:00 -0600 Subject: x86/mpparse: Account for bus types other than ISA and PCI In commit f8924e770e04 ("x86: unify mp_bus_info"), the 32-bit and 64-bit versions of MP_bus_info were rearranged to match each other better. Unfortunately it introduced a regression: prior to that change we used to always set the mp_bus_not_pci bit, then clear it if we found a PCI bus. After it, we set mp_bus_not_pci for ISA buses, clear it for PCI buses, and leave it alone otherwise. In the cases of ISA and PCI, there's not much difference. But ISA is not the only non-PCI bus, so it's better to always set mp_bus_not_pci and clear it only for PCI. Without this change, Dan's Dell PowerEdge 4200 panics on boot with a log indicating interrupt routing trouble unless the "noapic" option is supplied. With this change, the machine boots reliably without "noapic". Fixes http://bugs.debian.org/586494 Reported-bisected-and-tested-by: Dan McGrath Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org # 2.6.26+ Cc: Dan McGrath Cc: Alexey Starikovskiy [jrnieder@gmail.com: clarified commit message] Signed-off-by: Jonathan Nieder Link: http://lkml.kernel.org/r/20111122215000.GA9151@elie.hsd1.il.comcast.net Signed-off-by: Ingo Molnar --- arch/x86/kernel/mpparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 9103b89c145a..0741b062a304 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mpc_bus *m) } #endif + set_bit(m->busid, mp_bus_not_pci); if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) { - set_bit(m->busid, mp_bus_not_pci); #if defined(CONFIG_EISA) || defined(CONFIG_MCA) mp_bus_id_to_type[m->busid] = MP_BUS_ISA; #endif -- cgit From 644ddf588f5dba34df483a6ea8abe639cc102289 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 18 Oct 2011 13:24:10 -0400 Subject: Add TAINT_FIRMWARE_WORKAROUND on MTRR fixup TAINT_FIRMWARE_WORKAROUND should be set when an MTRR fixup is done. Signed-off-by: Prarit Bhargava Acked-by: David Rientjes Link: http://lkml.kernel.org/r/1318958650-12447-1-git-send-email-prarit@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index a71efcdbb092..e1fe7f42e0fb 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -547,6 +547,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, if (tmp != mask_lo) { printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); + add_taint(TAINT_FIRMWARE_WORKAROUND); mask_lo = tmp; } } -- cgit From bd399063976c6c7a09beb4730ed1d93cadbcc739 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Mon, 7 Nov 2011 18:05:32 +0530 Subject: x86, microcode: Fix the failure path of microcode update driver init code The microcode update driver's initialization code does not handle failures correctly. This patch fixes this issue. Signed-off-by: Jan Beulich Signed-off-by: Srivatsa S. Bhat Link: http://lkml.kernel.org/r/20111107123530.12164.31227.stgit@srivatsabhat.in.ibm.com Link: http://lkml.kernel.org/r/4ED8E2270200007800065120@nat28.tlf.novell.com Signed-off-by: Borislav Petkov --- arch/x86/kernel/microcode_core.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index f2d2a664e797..9d46f5e43b51 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -256,7 +256,7 @@ static int __init microcode_dev_init(void) return 0; } -static void microcode_dev_exit(void) +static void __exit microcode_dev_exit(void) { misc_deregister(µcode_dev); } @@ -519,10 +519,8 @@ static int __init microcode_init(void) microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0); - if (IS_ERR(microcode_pdev)) { - microcode_dev_exit(); + if (IS_ERR(microcode_pdev)) return PTR_ERR(microcode_pdev); - } get_online_cpus(); mutex_lock(µcode_mutex); @@ -532,14 +530,12 @@ static int __init microcode_init(void) mutex_unlock(µcode_mutex); put_online_cpus(); - if (error) { - platform_device_unregister(microcode_pdev); - return error; - } + if (error) + goto out_pdev; error = microcode_dev_init(); if (error) - return error; + goto out_sysdev_driver; register_syscore_ops(&mc_syscore_ops); register_hotcpu_notifier(&mc_cpu_notifier); @@ -548,6 +544,20 @@ static int __init microcode_init(void) " , Peter Oruba\n"); return 0; + +out_sysdev_driver: + get_online_cpus(); + mutex_lock(µcode_mutex); + + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + + mutex_unlock(µcode_mutex); + put_online_cpus(); + +out_pdev: + platform_device_unregister(microcode_pdev); + return error; + } module_init(microcode_init); -- cgit From ce37defc0f6673f5ca2c92ed5cfcaf290ae7dd16 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 5 Dec 2011 14:28:37 +0100 Subject: x86: Document rdmsr_safe restrictions Recently, I got bitten by using rdmsr_safe too early in the boot process. Document its shortcomings for future reference. Link: http://lkml.kernel.org/r/4ED5B70F.606@lwfinger.net Signed-off-by: Borislav Petkov --- arch/x86/include/asm/msr.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 084ef95274cd..95203d40ffdd 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -169,7 +169,14 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high) return native_write_msr_safe(msr, low, high); } -/* rdmsr with exception handling */ +/* + * rdmsr with exception handling. + * + * Please note that the exception handling works only after we've + * switched to the "smart" #GP handler in trap_init() which knows about + * exception tables - using this macro earlier than that causes machine + * hangs on boxes which do not implement the @msr in the first argument. + */ #define rdmsr_safe(msr, p1, p2) \ ({ \ int __err; \ -- cgit From 8dbf4a30033ff61091015f0076e872b5c8f717cc Mon Sep 17 00:00:00 2001 From: Ajaykumar Hotchandani Date: Fri, 11 Nov 2011 18:31:57 +0530 Subject: x86/mtrr: Resolve inconsistency with Intel processor manual Following is from Notes of section 11.5.3 of Intel processor manual available at: http://www.intel.com/Assets/PDF/manual/325384.pdf For the Pentium 4 and Intel Xeon processors, after the sequence of steps given above has been executed, the cache lines containing the code between the end of the WBINVD instruction and before the MTRRS have actually been disabled may be retained in the cache hierarchy. Here, to remove code from the cache completely, a second WBINVD instruction must be executed after the MTRRs have been disabled. This patch provides resolution for that. Ideally, I will like to make changes only for Pentium 4 and Xeon processors. But, I am not finding easier way to do it. And, extra wbinvd() instruction does not hurt much for other processors. Signed-off-by: Ajaykumar Hotchandani Cc: Linus Torvalds Cc: Arjan van de Ven Cc: Lucas De Marchi Link: http://lkml.kernel.org/r/4EBD1CC5.3030008@oracle.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mtrr/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index e1fe7f42e0fb..97b26356e9ee 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -694,6 +694,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) /* Disable MTRRs, and set the default type to uncached */ mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi); + wbinvd(); } static void post_set(void) __releases(set_atomicity_lock) -- cgit From 1ef03890969932e9359b9a4c658f7f87771910ac Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Mon, 5 Dec 2011 16:53:53 +0300 Subject: x86: Fix "Acer Aspire 1" reboot hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like on some Acer Aspire 1s with older bioses, reboot via bios fails. It works on my machine, (with BIOS version 0.3310) but not on some others (BIOS version 0.3309). There's a log of problems at: https://bbs.archlinux.org/viewtopic.php?id=124136 This patch adds a different callback to the reboot quirk table, to allow rebooting via keybaord controller. Reported-by: Uroš Vampl Tested-by: Vasily Khoruzhick Signed-off-by: Peter Chubb Cc: Don Zickus Cc: Peter Zijlstra Cc: stable@kernel.org Link: http://lkml.kernel.org/r/1323093233-9481-1-git-send-email-anarsoul@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 4463d2fee4e3..37a458b521a6 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -124,7 +124,7 @@ __setup("reboot=", reboot_setup); */ /* - * Some machines require the "reboot=b" commandline option, + * Some machines require the "reboot=b" or "reboot=k" commandline options, * this quirk makes that automatic. */ static int __init set_bios_reboot(const struct dmi_system_id *d) @@ -136,6 +136,15 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) return 0; } +static int __init set_kbd_reboot(const struct dmi_system_id *d) +{ + if (reboot_type != BOOT_KBD) { + reboot_type = BOOT_KBD; + printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident); + } + return 0; +} + static struct dmi_system_id __initdata reboot_dmi_table[] = { { /* Handle problems with rebooting on Dell E520's */ .callback = set_bios_reboot, @@ -295,7 +304,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { }, }, { /* Handle reboot issue on Acer Aspire one */ - .callback = set_bios_reboot, + .callback = set_kbd_reboot, .ident = "Acer Aspire One A110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -- cgit From 2cd1c8d4dc7ecca9e9431e2dabe41ae9c7d89e51 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 15 Nov 2011 14:49:09 -0800 Subject: x86/paravirt: PTE updates in k(un)map_atomic need to be synchronous, regardless of lazy_mmu mode Fix an outstanding issue that has been reported since 2.6.37. Under a heavy loaded machine processing "fork()" calls could crash with: BUG: unable to handle kernel paging request at f573fc8c IP: [] swap_count_continued+0x104/0x180 *pdpt = 000000002a3b9027 *pde = 0000000001bed067 *pte = 0000000000000000 Oops: 0000 [#1] SMP Modules linked in: Pid: 1638, comm: apache2 Not tainted 3.0.4-linode37 #1 EIP: 0061:[] EFLAGS: 00210246 CPU: 3 EIP is at swap_count_continued+0x104/0x180 .. snip.. Call Trace: [] ? __swap_duplicate+0xc2/0x160 [] ? pte_mfn_to_pfn+0x87/0xe0 [] ? swap_duplicate+0x14/0x40 [] ? copy_pte_range+0x45b/0x500 [] ? copy_page_range+0x195/0x200 [] ? dup_mmap+0x1c6/0x2c0 [] ? dup_mm+0xa8/0x130 [] ? copy_process+0x98a/0xb30 [] ? do_fork+0x4f/0x280 [] ? getnstimeofday+0x43/0x100 [] ? sys_clone+0x30/0x40 [] ? ptregs_clone+0x15/0x48 [] ? syscall_call+0x7/0xb The problem is that in copy_page_range() we turn lazy mode on, and then in swap_entry_free() we call swap_count_continued() which ends up in: map = kmap_atomic(page, KM_USER0) + offset; and then later we touch *map. Since we are running in batched mode (lazy) we don't actually set up the PTE mappings and the kmap_atomic is not done synchronously and ends up trying to dereference a page that has not been set. Looking at kmap_atomic_prot_pfn(), it uses 'arch_flush_lazy_mmu_mode' and doing the same in kmap_atomic_prot() and __kunmap_atomic() makes the problem go away. Interestingly, commit b8bcfe997e4615 ("x86/paravirt: remove lazy mode in interrupts") removed part of this to fix an interrupt issue - but it went to far and did not consider this scenario. Signed-off-by: Konrad Rzeszutek Wilk Cc: Peter Zijlstra Cc: Jeremy Fitzhardinge Cc: Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/mm/highmem_32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index b49962662101..f4f29b19fac5 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -45,6 +45,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot) vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); BUG_ON(!pte_none(*(kmap_pte-idx))); set_pte(kmap_pte-idx, mk_pte(page, prot)); + arch_flush_lazy_mmu_mode(); return (void *)vaddr; } @@ -88,6 +89,7 @@ void __kunmap_atomic(void *kvaddr) */ kpte_clear_flush(kmap_pte-idx, vaddr); kmap_atomic_idx_pop(); + arch_flush_lazy_mmu_mode(); } #ifdef CONFIG_DEBUG_HIGHMEM else { -- cgit From a7a280493fb63f8e9fbfc8feec5810bf50e1e54f Mon Sep 17 00:00:00 2001 From: Major Lee Date: Tue, 15 Nov 2011 15:31:23 -0800 Subject: x86/mrst: Battery fixes When DCDC input line over current detecting, PMIC will change charging current automatically. Logging event is enough. Signed-off-by: Major Lee Signed-off-by: Alan Cox Cc: Mathias Nyman Cc: Feng Tang Cc: "H. Peter Anvin" [fix build] Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- drivers/power/intel_mid_battery.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index cffcb7c00b00..01fa671ec97f 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -61,7 +61,8 @@ MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages."); #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) -#define PMIC_BATT_CHR_EXCPT_MASK 0xC6 +#define PMIC_BATT_CHR_EXCPT_MASK 0x86 + #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF @@ -304,11 +305,6 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); batt_exception = 1; - } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { - pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; - pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); - batt_exception = 1; } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; @@ -316,6 +312,10 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) batt_exception = 1; } else { pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; + if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { + /* PMIC will change charging current automatically */ + pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); + } } } -- cgit From 35d476996288af6a4aaa8b172bcd31decd233de7 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 15 Nov 2011 14:46:52 -0800 Subject: x86/rtc, mrst: Don't register a platform RTC device for for Intel MID platforms Intel MID x86 platforms have a memory mapped virtual RTC instead. No MID platform have the default ports (and accessing them may do weird stuff). Signed-off-by: Mathias Nyman Signed-off-by: Alan Cox Cc: feng.tang@intel.com Cc: Feng Tang Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mrst.h | 9 +++++++++ arch/x86/kernel/rtc.c | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index e6283129c821..93f79094c224 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h @@ -31,11 +31,20 @@ enum mrst_cpu_type { }; extern enum mrst_cpu_type __mrst_cpu_chip; + +#ifdef CONFIG_X86_INTEL_MID + static inline enum mrst_cpu_type mrst_identify_cpu(void) { return __mrst_cpu_chip; } +#else /* !CONFIG_X86_INTEL_MID */ + +#define mrst_identify_cpu() (0) + +#endif /* !CONFIG_X86_INTEL_MID */ + enum mrst_timer_options { MRST_TIMER_DEFAULT, MRST_TIMER_APBT_ONLY, diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 348ce016a835..af6db6ec5b2a 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_X86_32 /* @@ -242,6 +243,10 @@ static __init int add_rtc_cmos(void) if (of_have_populated_dt()) return 0; + /* Intel MID platforms don't have ioport rtc */ + if (mrst_identify_cpu()) + return -ENODEV; + platform_device_register(&rtc_device); dev_info(&rtc_device.dev, "registered platform RTC device (no PNP device found)\n"); -- cgit From 38f6ae1e1b0d5e8b0a95f88c1eee2c5e8b001631 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 2 Dec 2011 09:38:33 +1100 Subject: perf stat: Failure with "Operation not supported" perf stat is failing on PowerPC: Error: open_counter returned with 95 (Operation not supported). /bin/dmesg may provide additional information. Fatal: Not all events could be opened. commit 370faf1dd046 (perf stat: Fail softly on unsupported events) added a check for failure returning ENOENT, but the POWER backend returns EOPNOTSUPP. It looks like alpha, blackfin and mips do the same. With the patch applied, things work as expected: Performance counter stats for '/bin/true': 0.362176 task-clock # 0.623 CPUs utilized 0 context-switches # 0.000 M/sec 0 CPU-migrations # 0.000 M/sec 28 page-faults # 0.077 M/sec 1,677,020 cycles # 4.630 GHz stalled-cycles-frontend stalled-cycles-backend 431,220 instructions # 0.26 insns per cycle 101,889 branches # 281.325 M/sec 4,145 branch-misses # 4.07% of all branches 0.000581361 seconds time elapsed Cc: # 3.0+ Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20111202093833.5fef7226@kryten Signed-off-by: Anton Blanchard Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7d98676808d8..955930e0a5c3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -463,7 +463,8 @@ static int run_perf_stat(int argc __used, const char **argv) list_for_each_entry(counter, &evsel_list->entries, node) { if (create_perf_stat_counter(counter, first) < 0) { - if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) { + if (errno == EINVAL || errno == ENOSYS || + errno == ENOENT || errno == EOPNOTSUPP) { if (verbose) ui__warning("%s event is not supported by the kernel.\n", event_name(counter)); -- cgit From 8360ee2f74bda2b794bdf4e23ab19d8b4e93807f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Nov 2011 12:10:19 +0100 Subject: x86, AMD: Correct align_va_addr documentation Commit dfb09f9b7ab0 ("x86, amd: Avoid cache aliasing penalties on AMD family 15h") introduced a kernel command line parameter called 'align_va_addr' which still refers to arguments used in an earlier version of the patch and which got changed without updating the documentation. Correct that omission. Signed-off-by: Borislav Petkov Cc: Frank Arnold Link: http://lkml.kernel.org/r/1321873819-29541-1-git-send-email-bp@amd64.org Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a0c5c5f4fce6..5e22c3f1f8bd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -315,8 +315,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. CPU-intensive style benchmark, and it can vary highly in a microbenchmark depending on workload and compiler. - 1: only for 32-bit processes - 2: only for 64-bit processes + 32: only for 32-bit processes + 64: only for 64-bit processes on: enable for both 32- and 64-bit processes off: disable for both 32- and 64-bit processes -- cgit From f62ef5f3e9cff065aa845e2b7f487e1810b8e57e Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 2 Dec 2011 08:21:43 +0100 Subject: x86, amd: Fix up numa_node information for AMD CPU family 15h model 0-0fh northbridge functions I've received complaints that the numa_node attribute for family 15h model 00-0fh (e.g. Interlagos) northbridge functions shows -1 instead of the proper node ID. Correct this with attached quirks (similar to quirks for other AMD CPU families used in multi-socket systems). Signed-off-by: Andreas Herrmann Cc: Frank Arnold Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20111202072143.GA31916@alberich.amd.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/quirks.c | 13 +++++++++++++ include/linux/pci_ids.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index b78643d0f9a5..03920a15a632 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -553,4 +553,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC, quirk_amd_nb_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK, quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0, + quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1, + quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2, + quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3, + quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4, + quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5, + quirk_amd_nb_node); + #endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 172ba70306d1..2aaee0ca9da8 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -517,8 +517,12 @@ #define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 +#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 +#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 +#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 #define PCI_DEVICE_ID_AMD_15H_NB_F3 0x1603 #define PCI_DEVICE_ID_AMD_15H_NB_F4 0x1604 +#define PCI_DEVICE_ID_AMD_15H_NB_F5 0x1605 #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 -- cgit From c8f369ab6003a2df3cdae30f9aba641a4a606034 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 26 Oct 2011 18:45:39 +0300 Subject: intel-iommu: Fix section mismatch in dmar_parse_rmrr_atsr_dev() dmar_parse_rmrr_atsr_dev() calls rmrr_parse_dev() and atsr_parse_dev() which are both marked as __init. Section mismatch in reference from the function dmar_parse_rmrr_atsr_dev() to the function .init.text:dmar_parse_dev_scope() The function dmar_parse_rmrr_atsr_dev() references the function __init dmar_parse_dev_scope(). Section mismatch in reference from the function dmar_parse_rmrr_atsr_dev() to the function .init.text:dmar_parse_dev_scope() The function dmar_parse_rmrr_atsr_dev() references the function __init dmar_parse_dev_scope(). Signed-off-by: Sergey Senozhatsky Cc: David Woodhouse Cc: iommu@lists.linux-foundation.org Cc: Joerg Roedel Cc: Ohad Ben-Cohen Link: http://lkml.kernel.org/r/20111026154539.GA10103@swordfish Signed-off-by: Ingo Molnar --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c0c7820d4c46..a004c3945c67 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3524,7 +3524,7 @@ found: return 0; } -int dmar_parse_rmrr_atsr_dev(void) +int __init dmar_parse_rmrr_atsr_dev(void) { struct dmar_rmrr_unit *rmrr, *rmrr_n; struct dmar_atsr_unit *atsr, *atsr_n; -- cgit From 61ed26e388ac67da262bb1a95d0474e4cabd4b0d Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 26 Oct 2011 19:15:07 +0300 Subject: intr_remapping: Fix section mismatch in ir_dev_scope_init() Fix: Section mismatch in reference from the function ir_dev_scope_init() to the function .init.text:dmar_dev_scope_init() The function ir_dev_scope_init() references the function __init dmar_dev_scope_init(). Signed-off-by: Sergey Senozhatsky Cc: Suresh Siddha Cc: Youquan Song Cc: Ohad Ben-Cohen Link: http://lkml.kernel.org/r/20111026161507.GB10103@swordfish Signed-off-by: Ingo Molnar --- drivers/iommu/intr_remapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index 07c9f189f314..6777ca049471 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c @@ -773,7 +773,7 @@ int __init parse_ioapics_under_ir(void) return ir_supported; } -int ir_dev_scope_init(void) +int __init ir_dev_scope_init(void) { if (!intr_remapping_enabled) return 0; -- cgit From 6560ee07dc946e94f7cc2cd8e3b5a5f5ee7340c1 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 1 Dec 2011 21:13:02 +0100 Subject: ARM: OMAP1: recalculate loops per jiffy after dpll1 reprogram Otherwise timing is inaccurate, resulting in devices which depend on it, like omap-keypad, broken. Tested on Amstrad Delta. Signed-off-by: Janusz Krzysztofik [tony@atomide.com: removed comment referencing a development branch] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/clock_data.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index 86b2dec11788..9ff90a744a21 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include /* for machine_is_* */ @@ -927,7 +929,9 @@ int __init omap1_clk_init(void) void __init omap1_clk_late_init(void) { - if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE) + unsigned long rate = ck_dpll1.rate; + + if (rate >= OMAP1_DPLL1_SANE_VALUE) return; /* System booting at unusable rate, force reprogramming of DPLL1 */ @@ -942,4 +946,5 @@ void __init omap1_clk_late_init(void) } propagate_rate(&ck_dpll1); omap1_show_rates(); + loops_per_jiffy = cpufreq_scale(loops_per_jiffy, rate, ck_dpll1.rate); } -- cgit From 11948b9335865dc0ba3a5ca2c9c255291a8d50fb Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 16 Nov 2011 17:37:45 -0600 Subject: toshiba_acpi: Fix machines that don't support HCI_SYSTEM_EVENT The Satellite C670-10V generates notifications for hotkeys but does not support HCI_SYSTEM_EVENT. As a result when a hotkey is pressed it gets stuck in an infinite loop in toshiba_acpi_notify. To fix this, detect whether or not HCI_SYSTEM_EVENT is supported up-front and don't try to read system events if it isn't supported. In addition, limit the number of retries when reading HCI_SYSTEM_EVENT fails so that this loop cannot run unbounded. Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/toshiba_acpi.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 13ef8c37471d..dcdc1f4a4624 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -121,6 +121,7 @@ struct toshiba_acpi_dev { int illumination_supported:1; int video_supported:1; int fan_supported:1; + int system_event_supported:1; struct mutex mutex; }; @@ -724,7 +725,7 @@ static int keys_proc_show(struct seq_file *m, void *v) u32 hci_result; u32 value; - if (!dev->key_event_valid) { + if (!dev->key_event_valid && dev->system_event_supported) { hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); if (hci_result == HCI_SUCCESS) { dev->key_event_valid = 1; @@ -964,6 +965,8 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) /* enable event fifo */ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); + if (hci_result == HCI_SUCCESS) + dev->system_event_supported = 1; props.type = BACKLIGHT_PLATFORM; props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; @@ -1032,12 +1035,15 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); u32 hci_result, value; + int retries = 3; - if (event != 0x80) + if (!dev->system_event_supported || event != 0x80) return; + do { hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); - if (hci_result == HCI_SUCCESS) { + switch (hci_result) { + case HCI_SUCCESS: if (value == 0x100) continue; /* act on key press; ignore key release */ @@ -1049,14 +1055,19 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) pr_info("Unknown key %x\n", value); } - } else if (hci_result == HCI_NOT_SUPPORTED) { + break; + case HCI_NOT_SUPPORTED: /* This is a workaround for an unresolved issue on * some machines where system events sporadically * become disabled. */ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); pr_notice("Re-enabled hotkeys\n"); + /* fall through */ + default: + retries--; + break; } - } while (hci_result != HCI_EMPTY); + } while (retries && hci_result != HCI_EMPTY); } -- cgit From de398fb8b92eba3447298053a483727bdd5fe37e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 5 Dec 2011 13:21:42 -0500 Subject: ipv4: Fix peer validation on cached lookup. If ipv4_valdiate_peer() fails during a cached entry lookup, we'll NULL derer since the loop iterator assumes rth is not NULL. Letting this be handled as a failure is just bogus, so just make it not fail. If we have trouble getting a non-NULL neighbour for the redirected gateway, just restore the original gateway and continue. The very next use of this cached route will try again. Reported-by: Dan Carpenter Signed-off-by: David S. Miller --- net/ipv4/route.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 588d971a3ba1..46af62363b8c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1310,7 +1310,7 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } -static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) { struct rtable *rt = (struct rtable *) dst; __be32 orig_gw = rt->rt_gateway; @@ -1321,21 +1321,19 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) rt->rt_gateway = peer->redirect_learned.a4; n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); - if (IS_ERR(n)) - return PTR_ERR(n); + if (IS_ERR(n)) { + rt->rt_gateway = orig_gw; + return; + } old_n = xchg(&rt->dst._neighbour, n); if (old_n) neigh_release(old_n); - if (!n || !(n->nud_state & NUD_VALID)) { - if (n) - neigh_event_send(n, NULL); - rt->rt_gateway = orig_gw; - return -EAGAIN; + if (!(n->nud_state & NUD_VALID)) { + neigh_event_send(n, NULL); } else { rt->rt_flags |= RTCF_REDIRECTED; call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); } - return 0; } /* called in rcu_read_lock() section */ @@ -1693,7 +1691,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } -static struct rtable *ipv4_validate_peer(struct rtable *rt) +static void ipv4_validate_peer(struct rtable *rt) { if (rt->rt_peer_genid != rt_peer_genid()) { struct inet_peer *peer; @@ -1708,15 +1706,12 @@ static struct rtable *ipv4_validate_peer(struct rtable *rt) if (peer->redirect_genid != redirect_genid) peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && - peer->redirect_learned.a4 != rt->rt_gateway) { - if (check_peer_redir(&rt->dst, peer)) - return NULL; - } + peer->redirect_learned.a4 != rt->rt_gateway) + check_peer_redir(&rt->dst, peer); } rt->rt_peer_genid = rt_peer_genid(); } - return rt; } static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) @@ -1725,7 +1720,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) if (rt_is_expired(rt)) return NULL; - dst = (struct dst_entry *) ipv4_validate_peer(rt); + ipv4_validate_peer(rt); return dst; } @@ -2380,9 +2375,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { - rth = ipv4_validate_peer(rth); - if (!rth) - continue; + ipv4_validate_peer(rth); if (noref) { dst_use_noref(&rth->dst, jiffies); skb_dst_set_noref(skb, &rth->dst); @@ -2758,9 +2751,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { - rth = ipv4_validate_peer(rth); - if (!rth) - continue; + ipv4_validate_peer(rth); dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); -- cgit From cb59974742aea24adf6637eb0c4b8e7b48bca6fb Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 31 Oct 2011 11:07:42 +0200 Subject: tracing: fix event_subsystem ref counting Fix a bug introduced by e9dbfae5, which prevents event_subsystem from ever being released. Ref_count was added to keep track of subsystem users, not for counting events. Subsystem is created with ref_count = 1, so there is no need to increment it for every event, we have nr_events for that. Fix this by touching ref_count only when we actually have a new user - subsystem_open(). Cc: stable@vger.kernel.org Signed-off-by: Ilya Dryomov Link: http://lkml.kernel.org/r/1320052062-7846-1-git-send-email-idryomov@gmail.com Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 581876f9f387..c212a7f934ec 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1078,7 +1078,6 @@ event_subsystem_dir(const char *name, struct dentry *d_events) /* First see if we did not already create this dir */ list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { - __get_system(system); system->nr_events++; return system->entry; } -- cgit From 27b14b56af081ec7edeefb3a38b2c9577cc5ef48 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 1 Nov 2011 09:09:35 +0800 Subject: tracing: Restore system filter behavior Though not all events have field 'prev_pid', it was allowed to do this: # echo 'prev_pid == 100' > events/sched/filter but commit 75b8e98263fdb0bfbdeba60d4db463259f1fe8a2 (tracing/filter: Swap entire filter of events) broke it without any reason. Link: http://lkml.kernel.org/r/4EAF46CF.8040408@cn.fujitsu.com Signed-off-by: Li Zefan Signed-off-by: Steven Rostedt --- include/linux/ftrace_event.h | 2 ++ kernel/trace/trace_events_filter.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 96efa6794ea5..c3da42dd22ba 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -172,6 +172,7 @@ enum { TRACE_EVENT_FL_FILTERED_BIT, TRACE_EVENT_FL_RECORDED_CMD_BIT, TRACE_EVENT_FL_CAP_ANY_BIT, + TRACE_EVENT_FL_NO_SET_FILTER_BIT, }; enum { @@ -179,6 +180,7 @@ enum { TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT), TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT), + TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT), }; struct ftrace_event_call { diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index d6e7926dcd26..95dc31efd6dd 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1649,7 +1649,9 @@ static int replace_system_preds(struct event_subsystem *system, */ err = replace_preds(call, NULL, ps, filter_string, true); if (err) - goto fail; + call->flags |= TRACE_EVENT_FL_NO_SET_FILTER; + else + call->flags &= ~TRACE_EVENT_FL_NO_SET_FILTER; } list_for_each_entry(call, &ftrace_events, list) { @@ -1658,6 +1660,9 @@ static int replace_system_preds(struct event_subsystem *system, if (strcmp(call->class->system, system->name) != 0) continue; + if (call->flags & TRACE_EVENT_FL_NO_SET_FILTER) + continue; + filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL); if (!filter_item) goto fail_mem; -- cgit From c7c6ec8becaf742b223c7b491f4893014be23a07 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 4 Nov 2011 10:45:23 -0400 Subject: ftrace: Remove force undef config value left for testing A forced undef of a config value was used for testing and was accidently left in during the final commit. This causes x86 to run slower than needed while running function tracing as well as causes the function graph selftest to fail when DYNMAIC_FTRACE is not set. This is because the code in MCOUNT expects the ftrace code to be processed with the config value set that happened to be forced not set. The forced config option was left in by: commit 6331c28c962561aee59e5a493b7556a4bb585957 ftrace: Fix dynamic selftest failure on some archs Link: http://lkml.kernel.org/r/20111102150255.GA6973@debian Cc: stable@vger.kernel.org Reported-by: Rabin Vincent Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 900b409543db..1276b3ca1598 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -152,7 +152,6 @@ void clear_ftrace_function(void) ftrace_pid_function = ftrace_stub; } -#undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST /* * For those archs that do not test ftrace_trace_stop in their -- cgit From bbbf7af4bf8fc69bc751818cf30521080fa47dcb Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 18 Oct 2011 19:55:51 +0200 Subject: jump_label: jump_label_inc may return before the code is patched If cpu A calls jump_label_inc() just after atomic_add_return() is called by cpu B, atomic_inc_not_zero() will return value greater then zero and jump_label_inc() will return to a caller before jump_label_update() finishes its job on cpu B. Link: http://lkml.kernel.org/r/20111018175551.GH17571@redhat.com Cc: stable@vger.kernel.org Cc: Peter Zijlstra Acked-by: Jason Baron Signed-off-by: Gleb Natapov Signed-off-by: Steven Rostedt --- kernel/jump_label.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index bbdfe2a462a0..66ff7109f697 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -66,8 +66,9 @@ void jump_label_inc(struct jump_label_key *key) return; jump_label_lock(); - if (atomic_add_return(1, &key->enabled) == 1) + if (atomic_read(&key->enabled) == 0) jump_label_update(key, JUMP_LABEL_ENABLE); + atomic_inc(&key->enabled); jump_label_unlock(); } -- cgit From d06c27b22aa66e48e32f03f9387328a9af9b0625 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 4 Nov 2011 16:32:25 -0400 Subject: perf: Fix parsing of __print_flags() in TP_printk() A update is made to the sched:sched_switch event that adds some logic to the first parameter of the __print_flags() that shows the state of tasks. This change cause perf to fail parsing the flags. A simple fix is needed to have the parser be able to process ops within the argument. Cc: stable@vger.kernel.org Reported-by: Andrew Vagin Signed-off-by: Steven Rostedt --- tools/perf/util/trace-event-parse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0a7ed5b5e281..6c164dc9ee95 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1537,6 +1537,8 @@ process_flags(struct event *event, struct print_arg *arg, char **tok) field = malloc_or_die(sizeof(*field)); type = process_arg(event, field, &token); + while (type == EVENT_OP) + type = process_op(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; -- cgit From ddf6e0e50723b62ac76ed18eb53e9417c6eefba7 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 4 Nov 2011 20:32:39 -0400 Subject: ftrace: Fix hash record accounting bug If the set_ftrace_filter is cleared by writing just whitespace to it, then the filter hash refcounts will be decremented but not updated. This causes two bugs: 1) No functions will be enabled for tracing when they all should be 2) If the users clears the set_ftrace_filter twice, it will crash ftrace: ------------[ cut here ]------------ WARNING: at /home/rostedt/work/git/linux-trace.git/kernel/trace/ftrace.c:1384 __ftrace_hash_rec_update.part.27+0x157/0x1a7() Modules linked in: Pid: 2330, comm: bash Not tainted 3.1.0-test+ #32 Call Trace: [] warn_slowpath_common+0x83/0x9b [] warn_slowpath_null+0x1a/0x1c [] __ftrace_hash_rec_update.part.27+0x157/0x1a7 [] ? ftrace_regex_release+0xa7/0x10f [] ? kfree+0xe5/0x115 [] ftrace_hash_move+0x2e/0x151 [] ftrace_regex_release+0xba/0x10f [] fput+0xfd/0x1c2 [] filp_close+0x6d/0x78 [] sys_dup3+0x197/0x1c1 [] sys_dup2+0x4f/0x54 [] system_call_fastpath+0x16/0x1b ---[ end trace 77a3a7ee73794a02 ]--- Link: http://lkml.kernel.org/r/20111101141420.GA4918@debian Reported-by: Rabin Vincent Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1276b3ca1598..b1e8943fed1d 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1211,7 +1211,9 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable, if (!src->count) { free_ftrace_hash_rcu(*dst); rcu_assign_pointer(*dst, EMPTY_HASH); - return 0; + /* still need to update the function records */ + ret = 0; + goto out; } /* -- cgit From bbef98ab0f019f1b0c25c1acdf1683c68933d41b Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Sun, 6 Nov 2011 10:33:10 +0800 Subject: PCI: defer enablement of SRIOV BARS All the PCI BARs of a device are enabled when the device is enabled using pci_enable_device(). This unnecessarily enables SRIOV BARs of the device. On some platforms, which do not support SRIOV as yet, the pci_enable_device() fails to enable the device if its SRIOV BARs are not allocated resources correctly. The following patch fixes the above problem. The SRIOV BARs are now enabled when IOV capability of the device is enabled in sriov_enable(). NOTE: Note, there is subtle change in the pci_enable_device() API. Any driver that depends on SRIOV BARS to be enabled in pci_enable_device() can fail. The patch has been touch tested on power and x86 platform. Tested-by: Michael Wang Signed-off-by: Ram Pai Signed-off-by: Jesse Barnes --- drivers/pci/iov.c | 7 +++++++ drivers/pci/pci.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index b82c155d7b37..1969a3ee3058 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -283,6 +283,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) struct resource *res; struct pci_dev *pdev; struct pci_sriov *iov = dev->sriov; + int bars = 0; if (!nr_virtfn) return 0; @@ -307,6 +308,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) nres = 0; for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + bars |= (1 << (i + PCI_IOV_RESOURCES)); res = dev->resource + PCI_IOV_RESOURCES + i; if (res->parent) nres++; @@ -324,6 +326,11 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) return -ENOMEM; } + if (pci_enable_resources(dev, bars)) { + dev_err(&dev->dev, "SR-IOV: IOV BARS not allocated\n"); + return -ENOMEM; + } + if (iov->link != dev->devfn) { pdev = pci_get_slot(dev->bus, iov->link); if (!pdev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6f45a73c6e9f..4788413f43d7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1126,7 +1126,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev, if (atomic_add_return(1, &dev->enable_cnt) > 1) return 0; /* already enabled */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) + for (i = 0; i < PCI_ROM_RESOURCE; i++) if (dev->resource[i].flags & flags) bars |= (1 << i); -- cgit From 8c4519456713628cbb457c77bf06684aace67f69 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 29 Nov 2011 19:20:23 +0000 Subject: PCI: fix ats compile failure I get this compile failure on parisc: drivers/pci/ats.c: In function 'ats_alloc_one': drivers/pci/ats.c:29: error: implicit declaration of function 'kzalloc' drivers/pci/ats.c:29: warning: assignment makes pointer from integer without a cast drivers/pci/ats.c: In function 'ats_free_one': drivers/pci/ats.c:45: error: implicit declaration of function 'kfree' Because ats.c is missing linux/slab.h as an include. This patch fixes it Signed-off-by: James Bottomley Signed-off-by: Jesse Barnes --- drivers/pci/ats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 7ec56fb0bd78..b0dd08e6a9da 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "pci.h" -- cgit From 145294c359a690b35c62d27dcff28fe892d02aca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 18:27:25 +0000 Subject: ASoC: Remove references to corgi and spitz from machine driver document They're not currently actively worked on, the hardware being rather obsolete by now. Signed-off-by: Mark Brown --- Documentation/sound/alsa/soc/machine.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt index 3e2ec9cbf397..d50c14df3411 100644 --- a/Documentation/sound/alsa/soc/machine.txt +++ b/Documentation/sound/alsa/soc/machine.txt @@ -50,8 +50,7 @@ Machine DAI Configuration The machine DAI configuration glues all the codec and CPU DAIs together. It can also be used to set up the DAI system clock and for any machine related DAI initialisation e.g. the machine audio map can be connected to the codec audio -map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c -for examples. +map, unconnected codec pins can be set as such. struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. @@ -83,8 +82,7 @@ Machine Power Map The machine driver can optionally extend the codec power map and to become an audio power map of the audio subsystem. This allows for automatic power up/down of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack -sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for -details. +sockets in the machine init function. Machine Controls -- cgit From 8c9b04346c0ae302d8b7b7df16cc19ddff77742e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 5 Dec 2011 14:47:48 +0100 Subject: gpio: fix a build failure on KS8695 GPIO I screwed up by compiling that driver for the machine rather than the arch. Correcting this fixes the build error. Cc: Grant Likely Reported-by: Mike Frysinger Signed-off-by: Linus Walleij Signed-off-by: Linus Torvalds --- drivers/gpio/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dbcb0bcfd8da..4e018d6a7639 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o -obj-$(CONFIG_MACH_KS8695) += gpio-ks8695.o +obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o -- cgit From 811fd3010cf512f2e23e6c4c912aad54516dc706 Mon Sep 17 00:00:00 2001 From: françois romieu Date: Sun, 4 Dec 2011 20:30:45 +0000 Subject: r8169: Rx FIFO overflow fixes. Realtek has specified that the post 8168c gigabit chips and the post 8105e fast ethernet chips recover automatically from a Rx FIFO overflow. The driver does not need to clear the RxFIFOOver bit of IntrStatus and it should rather avoid messing it. The implementation deserves some explanation: 1. events outside of the intr_event bit mask are now ignored. It enforces a no-processing policy for the events that either should not be there or should be ignored. 2. RxFIFOOver was already ignored in rtl_cfg_infos[RTL_CFG_1] for the whole 8168 line of chips with two exceptions: - RTL_GIGA_MAC_VER_22 since b5ba6d12bdac21bc0620a5089e0f24e362645efd ("use RxFIFO overflow workaround for 8168c chipset."). This one should now be correctly handled. - RTL_GIGA_MAC_VER_11 (8168b) which requires a different Rx FIFO overflow processing. Though it does not conform to Realtek suggestion above, the updated driver includes no change for RTL_GIGA_MAC_VER_12 and RTL_GIGA_MAC_VER_17. Both are 8168b. RTL_GIGA_MAC_VER_12 is common and a bit old so I'd rather wait for experimental evidence that the change suggested by Realtek really helps or does not hurt in unexpected ways. Removed case statements in rtl8169_interrupt are only 8168 relevant. 3. RxFIFOOver is masked for post 8105e 810x chips, namely the sole 8105e (RTL_GIGA_MAC_VER_30) itself. Signed-off-by: Francois Romieu Cc: hayeswang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 42 +++++++++++++++--------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 6f06aa10f0d7..7a1e3a69f193 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1183,11 +1183,13 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) return value; } -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) +static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) { - RTL_W16(IntrMask, 0x0000); + void __iomem *ioaddr = tp->mmio_addr; - RTL_W16(IntrStatus, 0xffff); + RTL_W16(IntrMask, 0x0000); + RTL_W16(IntrStatus, tp->intr_event); + RTL_R8(ChipCmd); } static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) @@ -4339,7 +4341,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); + rtl8169_irq_mask_and_ack(tp); rtl_rx_close(tp); @@ -4885,8 +4887,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11 || - tp->mac_version == RTL_GIGA_MAC_VER_22) { + if (tp->mac_version == RTL_GIGA_MAC_VER_11) { tp->intr_event |= RxFIFOOver | PCSTimeout; tp->intr_event &= ~RxOverflow; } @@ -5076,6 +5077,11 @@ static void rtl_hw_start_8101(struct net_device *dev) void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; + if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { + tp->intr_event &= ~RxFIFOOver; + tp->napi_event &= ~RxFIFOOver; + } + if (tp->mac_version == RTL_GIGA_MAC_VER_13 || tp->mac_version == RTL_GIGA_MAC_VER_16) { int cap = pci_pcie_cap(pdev); @@ -5342,7 +5348,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) /* Wait for any pending NAPI task to complete */ napi_disable(&tp->napi); - rtl8169_irq_mask_and_ack(ioaddr); + rtl8169_irq_mask_and_ack(tp); tp->intr_mask = 0xffff; RTL_W16(IntrMask, tp->intr_event); @@ -5804,6 +5810,10 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) */ status = RTL_R16(IntrStatus); while (status && status != 0xffff) { + status &= tp->intr_event; + if (!status) + break; + handled = 1; /* Handle all of the error cases first. These will reset @@ -5818,27 +5828,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) switch (tp->mac_version) { /* Work around for rx fifo overflow */ case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_26: netif_stop_queue(dev); rtl8169_tx_timeout(dev); goto done; - /* Testers needed. */ - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - /* Experimental science. Pktgen proof. */ - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_25: - if (status == RxFIFOOver) - goto done; - break; default: break; } -- cgit From c7c2c39be8ed4e503e987151f4599455060e219a Mon Sep 17 00:00:00 2001 From: françois romieu Date: Sun, 4 Dec 2011 20:30:52 +0000 Subject: r8169: fix Rx index race between FIFO overflow recovery and NAPI handler. Since 92fc43b4159b518f5baae57301f26d770b0834c9, rtl8169_tx_timeout ends up resetting Rx and Tx indexes and thus racing with the NAPI handler via -> rtl8169_hw_reset -> rtl_hw_reset -> rtl8169_init_ring_indexes What about returning to the original state ? rtl_hw_reset is only used by rtl8169_hw_reset and rtl8169_init_one. The latter does not need rtl8169_init_ring_indexes because the indexes still contain their original values from the newly allocated network device private data area (i.e. 0). rtl8169_hw_reset is used by: 1. rtl8169_down Helper for rtl8169_close. rtl8169_open explicitely inits the indexes anyway. 2. rtl8169_pcierr_interrupt Indexes are set by rtl8169_reinit_task. 3. rtl8169_interrupt rtl8169_hw_reset is needed when the device goes down. See 1. 4. rtl_shutdown System shutdown handler. Indexes are irrelevant. 5. rtl8169_reset_task Indexes must be set before rtl_hw_start is called. 6. rtl8169_tx_timeout Indexes should not be set. This is the job of rtl8169_reset_task anyway. The removal of rtl8169_hw_reset in rtl8169_tx_timeout and its move in rtl8169_reset_task do not change the analysis. Signed-off-by: Francois Romieu Cc: hayeswang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 7a1e3a69f193..67bf07819992 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3935,8 +3935,6 @@ static void rtl_hw_reset(struct rtl8169_private *tp) break; udelay(100); } - - rtl8169_init_ring_indexes(tp); } static int __devinit @@ -5395,14 +5393,16 @@ static void rtl8169_reset_task(struct work_struct *work) if (!netif_running(dev)) goto out_unlock; + rtl8169_hw_reset(tp); + rtl8169_wait_for_quiescence(dev); for (i = 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); rtl8169_tx_clear(tp); + rtl8169_init_ring_indexes(tp); - rtl8169_hw_reset(tp); rtl_hw_start(dev); netif_wake_queue(dev); rtl8169_check_link_status(dev, tp, tp->mmio_addr); @@ -5413,11 +5413,6 @@ out_unlock: static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_hw_reset(tp); - - /* Let's wait a bit while any (async) irq lands on */ rtl8169_schedule_work(dev, rtl8169_reset_task); } -- cgit From 6b84bd167458545f0806d5a1a8a102004365d44e Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 5 Dec 2011 06:57:44 +0000 Subject: netback: Fix alert message. The original message in netback_init was 'kthread_run() fails', which should be 'kthread_create() fails'. Signed-off-by: Wei Liu Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 1ae270eed51a..15e332d08c8d 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1668,7 +1668,7 @@ static int __init netback_init(void) "netback/%u", group); if (IS_ERR(netbk->task)) { - printk(KERN_ALERT "kthread_run() fails at netback\n"); + printk(KERN_ALERT "kthread_create() fails at netback\n"); del_timer(&netbk->net_timer); rc = PTR_ERR(netbk->task); goto failed_init; -- cgit From 65e9d805e96c7e6a15c1e3b0c00a842d2249bab8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 5 Dec 2011 19:44:22 +0000 Subject: pasemi_mac: Fix building as module Commit ded19addf9c937d83b9bfb4d73a836732569041b ('pasemic_mac*: Move the PA Semi driver') inadvertently split pasemi_mac into two separate modules with unresolved symbols. Change it back into a single module. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/pasemi/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/pasemi/Makefile b/drivers/net/ethernet/pasemi/Makefile index 05db5434bafc..90497ffb1ac3 100644 --- a/drivers/net/ethernet/pasemi/Makefile +++ b/drivers/net/ethernet/pasemi/Makefile @@ -2,4 +2,5 @@ # Makefile for the A Semi network device drivers. # -obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o pasemi_mac_ethtool.o +obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o +pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o -- cgit From 03e98c9eb916f3f0868c1dc344dde2a60287ff72 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 4 Nov 2011 02:36:16 -0700 Subject: target: Address legacy PYX_TRANSPORT_* return code breakage This patch removes legacy usage of PYX_TRANSPORT_* return codes in a number of locations and addresses cases where transport_generic_request_failure() was returning the incorrect sense upon CHECK_CONDITION status after the v3.1 converson to use errno return codes. This includes the conversion of transport_generic_request_failure() to process cmd->scsi_sense_reason and handle extra TCM_RESERVATION_CONFLICT before calling transport_send_check_condition_and_sense() to queue up response status. It also drops PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES legacy usgae, and returns TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE w/ a response for these cases. transport_generic_allocate_tasks(), transport_generic_new_cmd(), backend SCF_SCSI_DATA_SG_IO_CDB ->do_task(), and emulated ->execute_task() have all been updated to set se_cmd->scsi_sense_reason and return errno codes universally upon failure. This includes cmd->scsi_sense_reason assignment in target_core_alua.c, target_core_pr.c and target_core_cdb.c emulation code. Finally it updates fabric modules to remove the legacy usage, and for TFO->new_cmd_map() callers forwards return values outside of fabric code. iscsi-target has also been updated to remove a handful of special cases related to the cleanup and signaling QUEUE_FULL handling w/ ft_write_pending() (v2: Drop extra SCF_SCSI_CDB_EXCEPTION check during failure from transport_generic_new_cmd, and re-add missing task->task_error_status assignment in transport_complete_task) Cc: Christoph Hellwig Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 9 +- drivers/target/iscsi/iscsi_target_erl1.c | 3 +- drivers/target/loopback/tcm_loop.c | 24 +--- drivers/target/target_core_alua.c | 25 ++-- drivers/target/target_core_cdb.c | 18 ++- drivers/target/target_core_device.c | 2 +- drivers/target/target_core_file.c | 6 +- drivers/target/target_core_iblock.c | 14 +- drivers/target/target_core_pr.c | 240 ++++++++++++++++++++----------- drivers/target/target_core_pscsi.c | 28 ++-- drivers/target/target_core_rd.c | 3 +- drivers/target/target_core_tmr.c | 4 - drivers/target/target_core_transport.c | 178 +++++++---------------- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/target/target_core_base.h | 4 +- include/target/target_core_transport.h | 24 ---- 16 files changed, 281 insertions(+), 303 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 0fd96c10271d..4d81e1007c92 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1017,11 +1017,6 @@ done: " non-existent or non-exported iSCSI LUN:" " 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); } - if (ret == PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); - send_check_condition = 1; goto attach_cmd; } @@ -1123,7 +1118,7 @@ attach_cmd: * the backend memory allocation. */ ret = transport_generic_new_cmd(&cmd->se_cmd); - if ((ret < 0) || (cmd->se_cmd.se_cmd_flags & SCF_SE_CMD_FAILED)) { + if (ret < 0) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; dump_immediate_data = 1; goto after_immediate_data; @@ -1341,7 +1336,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) spin_lock_irqsave(&se_cmd->t_state_lock, flags); if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) || - (se_cmd->se_cmd_flags & SCF_SE_CMD_FAILED)) + (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) dump_unsolicited_data = 1; spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index c4c68da3e500..101b1beb3bca 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -938,8 +938,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well. */ if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { - if (se_cmd->se_cmd_flags & - SCF_SCSI_RESERVATION_CONFLICT) { + if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { cmd->i_state = ISTATE_SEND_STATUS; spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 3df1c9b8ae6b..cbf5e4513741 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -148,22 +148,8 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) * Allocate the necessary tasks to complete the received CDB+data */ ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd); - if (ret == -ENOMEM) { - /* Out of Resources */ - return PYX_TRANSPORT_LU_COMM_FAILURE; - } else if (ret == -EINVAL) { - /* - * Handle case for SAM_STAT_RESERVATION_CONFLICT - */ - if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) - return PYX_TRANSPORT_RESERVATION_CONFLICT; - /* - * Otherwise, return SAM_STAT_CHECK_CONDITION and return - * sense data. - */ - return PYX_TRANSPORT_USE_SENSE_REASON; - } - + if (ret != 0) + return ret; /* * For BIDI commands, pass in the extra READ buffer * to transport_generic_map_mem_to_cmd() below.. @@ -194,12 +180,8 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) } /* Tell the core about our preallocated memory */ - ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), + return transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), scsi_sg_count(sc), sgl_bidi, sgl_bidi_count); - if (ret < 0) - return PYX_TRANSPORT_LU_COMM_FAILURE; - - return 0; } /* diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 88f2ad43ec8b..cd61331c1482 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -191,9 +191,10 @@ int target_emulate_set_target_port_groups(struct se_task *task) int alua_access_state, primary = 0, rc; u16 tg_pt_id, rtpi; - if (!l_port) - return PYX_TRANSPORT_LU_COMM_FAILURE; - + if (!l_port) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; + } buf = transport_kmap_first_data_page(cmd); /* @@ -203,7 +204,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; if (!l_tg_pt_gp_mem) { pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); - rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + rc = -EINVAL; goto out; } spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); @@ -211,7 +213,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) if (!l_tg_pt_gp) { spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); - rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + rc = -EINVAL; goto out; } rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); @@ -220,7 +223,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) if (!rc) { pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICT_ALUA is disabled\n"); - rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + rc = -EINVAL; goto out; } @@ -245,7 +249,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) * REQUEST, and the additional sense code set to INVALID * FIELD IN PARAMETER LIST. */ - rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + rc = -EINVAL; goto out; } rc = -1; @@ -298,7 +303,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) * throw an exception with ASCQ: INVALID_PARAMETER_LIST */ if (rc != 0) { - rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + rc = -EINVAL; goto out; } } else { @@ -335,7 +341,8 @@ int target_emulate_set_target_port_groups(struct se_task *task) * INVALID_PARAMETER_LIST */ if (rc != 0) { - rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + rc = -EINVAL; goto out; } } diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 683ba02b8247..8013a5a7bf64 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -703,6 +703,7 @@ int target_emulate_inquiry(struct se_task *task) if (cmd->data_length < 4) { pr_err("SCSI Inquiry payload length: %u" " too small for EVPD=1\n", cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return -EINVAL; } @@ -719,6 +720,7 @@ int target_emulate_inquiry(struct se_task *task) } pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; ret = -EINVAL; out_unmap: @@ -969,7 +971,8 @@ int target_emulate_modesense(struct se_task *task) default: pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", cdb[2] & 0x3f, cdb[3]); - return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; + cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; + return -EINVAL; } offset += length; @@ -1027,7 +1030,8 @@ int target_emulate_request_sense(struct se_task *task) if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" " supported\n"); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -ENOSYS; } buf = transport_kmap_first_data_page(cmd); @@ -1100,7 +1104,8 @@ int target_emulate_unmap(struct se_task *task) if (!dev->transport->do_discard) { pr_err("UNMAP emulation not supported for: %s\n", dev->transport->name); - return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + return -ENOSYS; } /* First UNMAP block descriptor starts at 8 byte offset */ @@ -1157,7 +1162,8 @@ int target_emulate_write_same(struct se_task *task) if (!dev->transport->do_discard) { pr_err("WRITE_SAME emulation not supported" " for: %s\n", dev->transport->name); - return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + return -ENOSYS; } if (cmd->t_task_cdb[0] == WRITE_SAME) @@ -1193,11 +1199,13 @@ int target_emulate_write_same(struct se_task *task) int target_emulate_synchronize_cache(struct se_task *task) { struct se_device *dev = task->task_se_cmd->se_dev; + struct se_cmd *cmd = task->task_se_cmd; if (!dev->transport->do_sync_cache) { pr_err("SYNCHRONIZE_CACHE emulation not supported" " for: %s\n", dev->transport->name); - return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + return -ENOSYS; } dev->transport->do_sync_cache(task); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index ba5edec2c5f8..07953284ea6f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -708,7 +708,7 @@ done: se_task->task_scsi_status = GOOD; transport_complete_task(se_task, 1); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } /* se_release_device_for_hba(): diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 67cd6fe05bfa..cdd47e8c7366 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -449,13 +449,15 @@ static int fd_do_task(struct se_task *task) } - if (ret < 0) + if (ret < 0) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return ret; + } if (ret) { task->task_scsi_status = GOOD; transport_complete_task(task, 1); } - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } /* fd_free_task(): (Part of se_subsystem_api_t template) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7698efe29262..c670b8c2c994 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -554,12 +554,15 @@ static int iblock_do_task(struct se_task *task) else { pr_err("Unsupported SCSI -> BLOCK LBA conversion:" " %u\n", dev->se_sub_dev->se_dev_attrib.block_size); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOSYS; } bio = iblock_get_bio(task, block_lba, sg_num); - if (!bio) - return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; + if (!bio) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; + } bio_list_init(&list); bio_list_add(&list, bio); @@ -588,12 +591,13 @@ static int iblock_do_task(struct se_task *task) submit_bio(rw, bio); blk_finish_plug(&plug); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; fail: while ((bio = bio_list_pop(&list))) bio_put(bio); - return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; } static u32 iblock_get_device_rev(struct se_device *dev) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 5a4ebfc3a54f..95dee7074aeb 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -191,7 +191,7 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd, int *ret) pr_err("Received legacy SPC-2 RESERVE/RELEASE" " while active SPC-3 registrations exist," " returning RESERVATION_CONFLICT\n"); - *ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return true; } @@ -252,7 +252,8 @@ int target_scsi2_reservation_reserve(struct se_task *task) (cmd->t_task_cdb[1] & 0x02)) { pr_err("LongIO and Obselete Bits set, returning" " ILLEGAL_REQUEST\n"); - ret = PYX_TRANSPORT_ILLEGAL_REQUEST; + cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + ret = -EINVAL; goto out; } /* @@ -277,7 +278,8 @@ int target_scsi2_reservation_reserve(struct se_task *task) " from %s \n", cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + ret = -EINVAL; goto out_unlock; } @@ -1510,7 +1512,8 @@ static int core_scsi3_decode_spec_i_port( tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); if (!tidh_new) { pr_err("Unable to allocate tidh_new\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = tpg; @@ -1522,7 +1525,8 @@ static int core_scsi3_decode_spec_i_port( sa_res_key, all_tg_pt, aptpl); if (!local_pr_reg) { kfree(tidh_new); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; } tidh_new->dest_pr_reg = local_pr_reg; /* @@ -1548,7 +1552,8 @@ static int core_scsi3_decode_spec_i_port( pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" " does not equal CDB data_length: %u\n", tpdl, cmd->data_length); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } /* @@ -1598,7 +1603,9 @@ static int core_scsi3_decode_spec_i_port( " for tmp_tpg\n"); atomic_dec(&tmp_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -EINVAL; goto out; } /* @@ -1628,7 +1635,9 @@ static int core_scsi3_decode_spec_i_port( atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_tpg_undepend_item(tmp_tpg); - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -EINVAL; goto out; } @@ -1646,7 +1655,8 @@ static int core_scsi3_decode_spec_i_port( if (!dest_tpg) { pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" " dest_tpg\n"); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } #if 0 @@ -1660,7 +1670,8 @@ static int core_scsi3_decode_spec_i_port( " %u for Transport ID: %s\n", tid_len, ptr); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } /* @@ -1678,7 +1689,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } @@ -1690,7 +1702,9 @@ static int core_scsi3_decode_spec_i_port( smp_mb__after_atomic_dec(); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -EINVAL; goto out; } #if 0 @@ -1727,7 +1741,9 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -ENOMEM; goto out; } INIT_LIST_HEAD(&tidh_new->dest_list); @@ -1759,7 +1775,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); kfree(tidh_new); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } tidh_new->dest_pr_reg = dest_pr_reg; @@ -2098,7 +2115,8 @@ static int core_scsi3_emulate_pro_register( if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } se_tpg = se_sess->se_tpg; se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; @@ -2117,13 +2135,14 @@ static int core_scsi3_emulate_pro_register( if (res_key) { pr_warn("SPC-3 PR: Reservation Key non-zero" " for SA REGISTER, returning CONFLICT\n"); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * Do nothing but return GOOD status. */ if (!sa_res_key) - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; if (!spec_i_pt) { /* @@ -2138,7 +2157,8 @@ static int core_scsi3_emulate_pro_register( if (ret != 0) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } } else { /* @@ -2197,14 +2217,16 @@ static int core_scsi3_emulate_pro_register( " 0x%016Lx\n", res_key, pr_reg->pr_res_key); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } } if (spec_i_pt) { pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" " set while sa_res_key=0\n"); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } /* * An existing ALL_TG_PT=1 registration being released @@ -2215,7 +2237,8 @@ static int core_scsi3_emulate_pro_register( " registration exists, but ALL_TG_PT=1 bit not" " present in received PROUT\n"); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } /* * Allocate APTPL metadata buffer used for UNREGISTER ops @@ -2227,7 +2250,9 @@ static int core_scsi3_emulate_pro_register( pr_err("Unable to allocate" " pr_aptpl_buf\n"); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } } /* @@ -2241,7 +2266,8 @@ static int core_scsi3_emulate_pro_register( if (pr_holder < 0) { kfree(pr_aptpl_buf); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } spin_lock(&pr_tmpl->registration_lock); @@ -2405,7 +2431,8 @@ static int core_scsi3_pro_reserve( if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } se_tpg = se_sess->se_tpg; se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; @@ -2417,7 +2444,8 @@ static int core_scsi3_pro_reserve( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RESERVE\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2433,7 +2461,8 @@ static int core_scsi3_pro_reserve( " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2448,7 +2477,8 @@ static int core_scsi3_pro_reserve( if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } /* * See if we have an existing PR reservation holder pointer at @@ -2480,7 +2510,8 @@ static int core_scsi3_pro_reserve( spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2503,7 +2534,8 @@ static int core_scsi3_pro_reserve( spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2517,7 +2549,7 @@ static int core_scsi3_pro_reserve( */ spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } /* * Otherwise, our *pr_reg becomes the PR reservation holder for said @@ -2574,7 +2606,8 @@ static int core_scsi3_emulate_pro_reserve( default: pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" " 0x%02x\n", type); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } return ret; @@ -2630,7 +2663,8 @@ static int core_scsi3_emulate_pro_release( if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2639,7 +2673,8 @@ static int core_scsi3_emulate_pro_release( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RELEASE\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } /* * From spc4r17 Section 5.7.11.2 Releasing: @@ -2661,7 +2696,7 @@ static int core_scsi3_emulate_pro_release( */ spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) @@ -2675,7 +2710,7 @@ static int core_scsi3_emulate_pro_release( */ spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } /* * From spc4r17 Section 5.7.11.2 Releasing: @@ -2697,7 +2732,8 @@ static int core_scsi3_emulate_pro_release( " 0x%016Lx\n", res_key, pr_reg->pr_res_key); spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * From spc4r17 Section 5.7.11.2 Releasing and above: @@ -2719,7 +2755,8 @@ static int core_scsi3_emulate_pro_release( spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * In response to a persistent reservation release request from the @@ -2802,7 +2839,8 @@ static int core_scsi3_emulate_pro_clear( if (!pr_reg_n) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for CLEAR\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } /* * From spc4r17 section 5.7.11.6, Clearing: @@ -2821,7 +2859,8 @@ static int core_scsi3_emulate_pro_clear( " existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); core_scsi3_put_pr_reg(pr_reg_n); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * a) Release the persistent reservation, if any; @@ -2979,8 +3018,10 @@ static int core_scsi3_pro_preempt( int all_reg = 0, calling_it_nexus = 0, released_regs = 0; int prh_type = 0, prh_scope = 0, ret; - if (!se_sess) - return PYX_TRANSPORT_LU_COMM_FAILURE; + if (!se_sess) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; + } se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, @@ -2989,16 +3030,19 @@ static int core_scsi3_pro_preempt( pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } if (pr_reg_n->pr_res_key != res_key) { core_scsi3_put_pr_reg(pr_reg_n); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); core_scsi3_put_pr_reg(pr_reg_n); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } INIT_LIST_HEAD(&preempt_and_abort_list); @@ -3012,7 +3056,8 @@ static int core_scsi3_pro_preempt( if (!all_reg && !sa_res_key) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } /* * From spc4r17, section 5.7.11.4.4 Removing Registrations: @@ -3106,7 +3151,8 @@ static int core_scsi3_pro_preempt( if (!released_regs) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * For an existing all registrants type reservation @@ -3297,7 +3343,8 @@ static int core_scsi3_emulate_pro_preempt( default: pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } return ret; @@ -3331,7 +3378,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } memset(dest_iport, 0, 64); memset(i_buf, 0, PR_REG_ISID_ID_LEN); @@ -3349,7 +3397,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" " *pr_reg for REGISTER_AND_MOVE\n"); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } /* * The provided reservation key much match the existing reservation key @@ -3360,7 +3409,8 @@ static int core_scsi3_emulate_pro_register_and_move( " res_key: 0x%016Lx does not match existing SA REGISTER" " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } /* * The service active reservation key needs to be non zero @@ -3369,7 +3419,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" " sa_res_key\n"); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } /* @@ -3392,7 +3443,8 @@ static int core_scsi3_emulate_pro_register_and_move( " does not equal CDB data_length: %u\n", tid_len, cmd->data_length); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } spin_lock(&dev->se_port_lock); @@ -3417,7 +3469,8 @@ static int core_scsi3_emulate_pro_register_and_move( atomic_dec(&dest_se_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; } spin_lock(&dev->se_port_lock); @@ -3430,7 +3483,8 @@ static int core_scsi3_emulate_pro_register_and_move( " fabric ops from Relative Target Port Identifier:" " %hu\n", rtpi); core_scsi3_put_pr_reg(pr_reg); - return PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; } buf = transport_kmap_first_data_page(cmd); @@ -3445,14 +3499,16 @@ static int core_scsi3_emulate_pro_register_and_move( " from fabric: %s\n", proto_ident, dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_tf_ops->get_fabric_name()); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" " containg a valid tpg_parse_pr_out_transport_id" " function pointer\n"); - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -EINVAL; goto out; } initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, @@ -3460,7 +3516,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!initiator_str) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " initiator_str from Transport ID\n"); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } @@ -3489,7 +3546,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" " matches: %s on received I_T Nexus\n", initiator_str, pr_reg_nacl->initiatorname); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { @@ -3497,7 +3555,8 @@ static int core_scsi3_emulate_pro_register_and_move( " matches: %s %s on received I_T Nexus\n", initiator_str, iport_ptr, pr_reg_nacl->initiatorname, pr_reg->pr_reg_isid); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } after_iport_check: @@ -3517,7 +3576,8 @@ after_iport_check: pr_err("Unable to locate %s dest_node_acl for" " TransportID%s\n", dest_tf_ops->get_fabric_name(), initiator_str); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } ret = core_scsi3_nodeacl_depend_item(dest_node_acl); @@ -3527,7 +3587,8 @@ after_iport_check: atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); dest_node_acl = NULL; - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } #if 0 @@ -3543,7 +3604,8 @@ after_iport_check: if (!dest_se_deve) { pr_err("Unable to locate %s dest_se_deve from RTPI:" " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } @@ -3553,7 +3615,8 @@ after_iport_check: atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); dest_se_deve = NULL; - ret = PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = -EINVAL; goto out; } #if 0 @@ -3572,7 +3635,8 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" " currently held\n"); spin_unlock(&dev->dev_reservation_lock); - ret = PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = -EINVAL; goto out; } /* @@ -3585,7 +3649,8 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" " Nexus is not reservation holder\n"); spin_unlock(&dev->dev_reservation_lock); - ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + ret = -EINVAL; goto out; } /* @@ -3603,7 +3668,8 @@ after_iport_check: " reservation for type: %s\n", core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); spin_unlock(&dev->dev_reservation_lock); - ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + ret = -EINVAL; goto out; } pr_res_nacl = pr_res_holder->pr_reg_nacl; @@ -3640,7 +3706,8 @@ after_iport_check: sa_res_key, 0, aptpl, 2, 1); if (ret != 0) { spin_unlock(&dev->dev_reservation_lock); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, @@ -3771,7 +3838,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - ret = PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + ret = EINVAL; goto out; } @@ -3779,13 +3847,16 @@ int target_scsi3_emulate_pr_out(struct se_task *task) * FIXME: A NULL struct se_session pointer means an this is not coming from * a $FABRIC_MOD's nexus, but from internal passthrough ops. */ - if (!cmd->se_sess) - return PYX_TRANSPORT_LU_COMM_FAILURE; + if (!cmd->se_sess) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -EINVAL; + } if (cmd->data_length < 24) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } /* @@ -3820,7 +3891,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) * SPEC_I_PT=1 is only valid for Service action: REGISTER */ if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } @@ -3837,7 +3909,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) (cmd->data_length != 24)) { pr_warn("SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); - ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST; + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; goto out; } /* @@ -3878,7 +3951,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) default: pr_err("Unknown PERSISTENT_RESERVE_OUT service" " action: 0x%02x\n", cdb[1] & 0x1f); - ret = PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = -EINVAL; break; } @@ -3906,7 +3980,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" " too small\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } buf = transport_kmap_first_data_page(cmd); @@ -3965,7 +4040,8 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" " too small\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } buf = transport_kmap_first_data_page(cmd); @@ -4047,7 +4123,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" " %u too small\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } buf = transport_kmap_first_data_page(cmd); @@ -4108,7 +4185,8 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" " too small\n", cmd->data_length); - return PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; } buf = transport_kmap_first_data_page(cmd); @@ -4255,7 +4333,8 @@ int target_scsi3_emulate_pr_in(struct se_task *task) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - return PYX_TRANSPORT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EINVAL; } switch (cmd->t_task_cdb[1] & 0x1f) { @@ -4274,7 +4353,8 @@ int target_scsi3_emulate_pr_in(struct se_task *task) default: pr_err("Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - ret = PYX_TRANSPORT_INVALID_CDB_FIELD; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = -EINVAL; break; } diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index ed32e1efe429..8b15e56b0384 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -963,6 +963,7 @@ static inline struct bio *pscsi_get_bio(int sg_num) static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg, struct bio **hbio) { + struct se_cmd *cmd = task->task_se_cmd; struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr; u32 task_sg_num = task->task_sg_nents; struct bio *bio = NULL, *tbio = NULL; @@ -971,7 +972,7 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg, u32 data_len = task->task_size, i, len, bytes, off; int nr_pages = (task->task_size + task_sg[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; - int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; + int nr_vecs = 0, rc; int rw = (task->task_data_direction == DMA_TO_DEVICE); *hbio = NULL; @@ -1058,11 +1059,13 @@ fail: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - return ret; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; } static int pscsi_do_task(struct se_task *task) { + struct se_cmd *cmd = task->task_se_cmd; struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr; struct pscsi_plugin_task *pt = PSCSI_TASK(task); struct request *req; @@ -1078,7 +1081,9 @@ static int pscsi_do_task(struct se_task *task) if (!req || IS_ERR(req)) { pr_err("PSCSI: blk_get_request() failed: %ld\n", req ? IS_ERR(req) : -ENOMEM); - return PYX_TRANSPORT_LU_COMM_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENODEV; } } else { BUG_ON(!task->task_size); @@ -1087,8 +1092,11 @@ static int pscsi_do_task(struct se_task *task) * Setup the main struct request for the task->task_sg[] payload */ ret = pscsi_map_sg(task, task->task_sg, &hbio); - if (ret < 0) - return PYX_TRANSPORT_LU_COMM_FAILURE; + if (ret < 0) { + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return ret; + } req = blk_make_request(pdv->pdv_sd->request_queue, hbio, GFP_KERNEL); @@ -1115,7 +1123,7 @@ static int pscsi_do_task(struct se_task *task) (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), pscsi_req_done); - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; fail: while (hbio) { @@ -1124,7 +1132,8 @@ fail: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; } /* pscsi_get_sense_buffer(): @@ -1198,9 +1207,8 @@ static inline void pscsi_process_SAM_status( " 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0], pt->pscsi_result); task->task_scsi_status = SAM_STAT_CHECK_CONDITION; - task->task_error_status = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; - task->task_se_cmd->transport_error_status = - PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + task->task_se_cmd->scsi_sense_reason = + TCM_UNSUPPORTED_SCSI_OPCODE; transport_complete_task(task, 0); break; } diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 5158d3846f19..6d8a6881cfff 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -603,8 +603,7 @@ static int rd_MEMCPY_do_task(struct se_task *task) task->task_scsi_status = GOOD; transport_complete_task(task, 1); - - return PYX_TRANSPORT_SENT_TO_TRANSPORT; + return 0; } /* rd_free_task(): (Part of se_subsystem_api_t template) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 217e29df6297..684522805a1f 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -345,10 +345,6 @@ static void core_tmr_drain_cmd_list( " %d t_fe_count: %d\n", (preempt_and_abort_list) ? "Preempt" : "", cmd, cmd->t_state, atomic_read(&cmd->t_fe_count)); - /* - * Signal that the command has failed via cmd->se_cmd_flags, - */ - transport_new_cmd_failure(cmd); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, atomic_read(&cmd->t_fe_count)); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3400ae6e93f8..a997fde9ffcb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -82,7 +82,7 @@ static int transport_generic_get_mem(struct se_cmd *cmd); static void transport_put_cmd(struct se_cmd *cmd); static void transport_remove_cmd_from_queue(struct se_cmd *cmd); static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq); -static void transport_generic_request_failure(struct se_cmd *, int, int); +static void transport_generic_request_failure(struct se_cmd *); static void target_complete_ok_work(struct work_struct *work); int init_se_kmem_caches(void) @@ -680,9 +680,9 @@ void transport_complete_sync_cache(struct se_cmd *cmd, int good) task->task_scsi_status = GOOD; } else { task->task_scsi_status = SAM_STAT_CHECK_CONDITION; - task->task_error_status = PYX_TRANSPORT_ILLEGAL_REQUEST; - task->task_se_cmd->transport_error_status = - PYX_TRANSPORT_ILLEGAL_REQUEST; + task->task_se_cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } transport_complete_task(task, good); @@ -693,7 +693,7 @@ static void target_complete_failure_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - transport_generic_request_failure(cmd, 1, 1); + transport_generic_request_failure(cmd); } /* transport_complete_task(): @@ -755,10 +755,11 @@ void transport_complete_task(struct se_task *task, int success) if (cmd->t_tasks_failed) { if (!task->task_error_status) { task->task_error_status = - PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; - cmd->transport_error_status = - PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } + INIT_WORK(&cmd->work, target_complete_failure_work); } else { atomic_set(&cmd->t_transport_complete, 1); @@ -1573,6 +1574,8 @@ int transport_generic_allocate_tasks( pr_err("Received SCSI CDB with command_size: %d that" " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return -EINVAL; } /* @@ -1588,6 +1591,9 @@ int transport_generic_allocate_tasks( " %u > sizeof(cmd->__t_task_cdb): %lu ops\n", scsi_command_size(cdb), (unsigned long)sizeof(cmd->__t_task_cdb)); + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -ENOMEM; } } else @@ -1658,11 +1664,9 @@ int transport_handle_cdb_direct( * and call transport_generic_request_failure() if necessary.. */ ret = transport_generic_new_cmd(cmd); - if (ret < 0) { - cmd->transport_error_status = ret; - transport_generic_request_failure(cmd, 0, - (cmd->data_direction != DMA_TO_DEVICE)); - } + if (ret < 0) + transport_generic_request_failure(cmd); + return 0; } EXPORT_SYMBOL(transport_handle_cdb_direct); @@ -1798,20 +1802,16 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) /* * Handle SAM-esque emulation for generic transport request failures. */ -static void transport_generic_request_failure( - struct se_cmd *cmd, - int complete, - int sc) +static void transport_generic_request_failure(struct se_cmd *cmd) { int ret = 0; pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), cmd->t_task_cdb[0]); - pr_debug("-----[ i_state: %d t_state: %d transport_error_status: %d\n", + pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", cmd->se_tfo->get_cmd_state(cmd), - cmd->t_state, - cmd->transport_error_status); + cmd->t_state, cmd->scsi_sense_reason); pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d" " t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --" " t_transport_active: %d t_transport_stop: %d" @@ -1829,46 +1829,19 @@ static void transport_generic_request_failure( if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) transport_complete_task_attr(cmd); - if (complete) { - cmd->transport_error_status = PYX_TRANSPORT_LU_COMM_FAILURE; - } - - switch (cmd->transport_error_status) { - case PYX_TRANSPORT_UNKNOWN_SAM_OPCODE: - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - break; - case PYX_TRANSPORT_REQ_TOO_MANY_SECTORS: - cmd->scsi_sense_reason = TCM_SECTOR_COUNT_TOO_MANY; - break; - case PYX_TRANSPORT_INVALID_CDB_FIELD: - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - break; - case PYX_TRANSPORT_INVALID_PARAMETER_LIST: - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - break; - case PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES: - if (!sc) - transport_new_cmd_failure(cmd); - /* - * Currently for PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES, - * we force this session to fall back to session - * recovery. - */ - cmd->se_tfo->fall_back_to_erl0(cmd->se_sess); - cmd->se_tfo->stop_session(cmd->se_sess, 0, 0); - - goto check_stop; - case PYX_TRANSPORT_LU_COMM_FAILURE: - case PYX_TRANSPORT_ILLEGAL_REQUEST: - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - break; - case PYX_TRANSPORT_UNKNOWN_MODE_PAGE: - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - break; - case PYX_TRANSPORT_WRITE_PROTECTED: - cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; + switch (cmd->scsi_sense_reason) { + case TCM_NON_EXISTENT_LUN: + case TCM_UNSUPPORTED_SCSI_OPCODE: + case TCM_INVALID_CDB_FIELD: + case TCM_INVALID_PARAMETER_LIST: + case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: + case TCM_UNKNOWN_MODE_PAGE: + case TCM_WRITE_PROTECTED: + case TCM_CHECK_CONDITION_ABORT_CMD: + case TCM_CHECK_CONDITION_UNIT_ATTENTION: + case TCM_CHECK_CONDITION_NOT_READY: break; - case PYX_TRANSPORT_RESERVATION_CONFLICT: + case TCM_RESERVATION_CONFLICT: /* * No SENSE Data payload for this case, set SCSI Status * and queue the response to $FABRIC_MOD. @@ -1893,15 +1866,9 @@ static void transport_generic_request_failure( if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; goto check_stop; - case PYX_TRANSPORT_USE_SENSE_REASON: - /* - * struct se_cmd->scsi_sense_reason already set - */ - break; default: pr_err("Unknown transport error for CDB 0x%02x: %d\n", - cmd->t_task_cdb[0], - cmd->transport_error_status); + cmd->t_task_cdb[0], cmd->scsi_sense_reason); cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; break; } @@ -1912,14 +1879,10 @@ static void transport_generic_request_failure( * transport_send_check_condition_and_sense() after handling * possible unsoliticied write data payloads. */ - if (!sc && !cmd->se_tfo->new_cmd_map) - transport_new_cmd_failure(cmd); - else { - ret = transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); - if (ret == -EAGAIN || ret == -ENOMEM) - goto queue_full; - } + ret = transport_send_check_condition_and_sense(cmd, + cmd->scsi_sense_reason, 0); + if (ret == -EAGAIN || ret == -ENOMEM) + goto queue_full; check_stop: transport_lun_remove_cmd(cmd); @@ -2077,8 +2040,8 @@ static int transport_execute_tasks(struct se_cmd *cmd) int add_tasks; if (se_dev_check_online(cmd->se_orig_obj_ptr) != 0) { - cmd->transport_error_status = PYX_TRANSPORT_LU_COMM_FAILURE; - transport_generic_request_failure(cmd, 0, 1); + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + transport_generic_request_failure(cmd); return 0; } @@ -2163,14 +2126,13 @@ check_depth: else error = dev->transport->do_task(task); if (error != 0) { - cmd->transport_error_status = error; spin_lock_irqsave(&cmd->t_state_lock, flags); task->task_flags &= ~TF_ACTIVE; spin_unlock_irqrestore(&cmd->t_state_lock, flags); atomic_set(&cmd->t_transport_sent, 0); transport_stop_tasks_for_cmd(cmd); atomic_inc(&dev->depth_left); - transport_generic_request_failure(cmd, 0, 1); + transport_generic_request_failure(cmd); } goto check_depth; @@ -2178,19 +2140,6 @@ check_depth: return 0; } -void transport_new_cmd_failure(struct se_cmd *se_cmd) -{ - unsigned long flags; - /* - * Any unsolicited data will get dumped for failed command inside of - * the fabric plugin - */ - spin_lock_irqsave(&se_cmd->t_state_lock, flags); - se_cmd->se_cmd_flags |= SCF_SE_CMD_FAILED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); -} - static inline u32 transport_get_sectors_6( unsigned char *cdb, struct se_cmd *cmd, @@ -2460,27 +2409,6 @@ static int transport_get_sense_data(struct se_cmd *cmd) return -1; } -static int -transport_handle_reservation_conflict(struct se_cmd *cmd) -{ - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - /* - * For UA Interlock Code 11b, a RESERVATION CONFLICT will - * establish a UNIT ATTENTION with PREVIOUS RESERVATION - * CONFLICT STATUS. - * - * See spc4r17, section 7.4.6 Control Mode Page, Table 349 - */ - if (cmd->se_sess && - cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) - core_scsi3_ua_allocate(cmd->se_sess->se_node_acl, - cmd->orig_fe_lun, 0x2C, - ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); - return -EINVAL; -} - static inline long long transport_dev_end_lba(struct se_device *dev) { return dev->transport->get_blocks(dev) + 1; @@ -2595,8 +2523,12 @@ static int transport_generic_cmd_sequencer( */ if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) { if (su_dev->t10_pr.pr_ops.t10_seq_non_holder( - cmd, cdb, pr_reg_type) != 0) - return transport_handle_reservation_conflict(cmd); + cmd, cdb, pr_reg_type) != 0) { + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return -EBUSY; + } /* * This means the CDB is allowed for the SCSI Initiator port * when said port is *NOT* holding the legacy SPC-2 or @@ -3813,7 +3745,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) cmd->data_length) { ret = transport_generic_get_mem(cmd); if (ret < 0) - return ret; + goto out_fail; } /* @@ -3929,7 +3861,7 @@ static int transport_generic_write_pending(struct se_cmd *cmd) else if (ret < 0) return ret; - return PYX_TRANSPORT_WRITE_PENDING; + return 1; queue_full: pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); @@ -4602,9 +4534,6 @@ void transport_send_task_abort(struct se_cmd *cmd) if (cmd->se_tfo->write_pending_status(cmd) != 0) { atomic_inc(&cmd->t_transport_aborted); smp_mb__after_atomic_inc(); - cmd->scsi_status = SAM_STAT_TASK_ABORTED; - transport_new_cmd_failure(cmd); - return; } } cmd->scsi_status = SAM_STAT_TASK_ABORTED; @@ -4698,18 +4627,13 @@ get_cmd: } ret = cmd->se_tfo->new_cmd_map(cmd); if (ret < 0) { - cmd->transport_error_status = ret; - transport_generic_request_failure(cmd, - 0, (cmd->data_direction != - DMA_TO_DEVICE)); + transport_generic_request_failure(cmd); break; } ret = transport_generic_new_cmd(cmd); if (ret < 0) { - cmd->transport_error_status = ret; - transport_generic_request_failure(cmd, - 0, (cmd->data_direction != - DMA_TO_DEVICE)); + transport_generic_request_failure(cmd); + break; } break; case TRANSPORT_PROCESS_WRITE: diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 4fac37c4c615..71fc9cea5dc9 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -200,7 +200,7 @@ int ft_write_pending(struct se_cmd *se_cmd) lport = ep->lp; fp = fc_frame_alloc(lport, sizeof(*txrdy)); if (!fp) - return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES; + return -ENOMEM; /* Signal QUEUE_FULL */ txrdy = fc_frame_payload_get(fp, sizeof(*txrdy)); memset(txrdy, 0, sizeof(*txrdy)); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7f5fed3c89e1..4d0cb6b8c478 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -103,7 +103,6 @@ enum se_cmd_flags_table { SCF_SCSI_NON_DATA_CDB = 0x00000040, SCF_SCSI_CDB_EXCEPTION = 0x00000080, SCF_SCSI_RESERVATION_CONFLICT = 0x00000100, - SCF_SE_CMD_FAILED = 0x00000400, SCF_SE_LUN_CMD = 0x00000800, SCF_SE_ALLOW_EOO = 0x00001000, SCF_SENT_CHECK_CONDITION = 0x00004000, @@ -154,6 +153,7 @@ enum tcm_sense_reason_table { TCM_CHECK_CONDITION_ABORT_CMD = 0x0d, TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, TCM_CHECK_CONDITION_NOT_READY = 0x0f, + TCM_RESERVATION_CONFLICT = 0x10, }; struct se_obj { @@ -422,8 +422,6 @@ struct se_cmd { int sam_task_attr; /* Transport protocol dependent state, see transport_state_table */ enum transport_state_table t_state; - /* Transport specific error status */ - int transport_error_status; /* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */ int check_release:1; int cmd_wait_set:1; diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index c16e9431dd01..dac4f2d859fd 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -10,29 +10,6 @@ #define PYX_TRANSPORT_STATUS_INTERVAL 5 /* In seconds */ -#define PYX_TRANSPORT_SENT_TO_TRANSPORT 0 -#define PYX_TRANSPORT_WRITE_PENDING 1 - -#define PYX_TRANSPORT_UNKNOWN_SAM_OPCODE -1 -#define PYX_TRANSPORT_HBA_QUEUE_FULL -2 -#define PYX_TRANSPORT_REQ_TOO_MANY_SECTORS -3 -#define PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES -4 -#define PYX_TRANSPORT_INVALID_CDB_FIELD -5 -#define PYX_TRANSPORT_INVALID_PARAMETER_LIST -6 -#define PYX_TRANSPORT_LU_COMM_FAILURE -7 -#define PYX_TRANSPORT_UNKNOWN_MODE_PAGE -8 -#define PYX_TRANSPORT_WRITE_PROTECTED -9 -#define PYX_TRANSPORT_RESERVATION_CONFLICT -10 -#define PYX_TRANSPORT_ILLEGAL_REQUEST -11 -#define PYX_TRANSPORT_USE_SENSE_REASON -12 - -#ifndef SAM_STAT_RESERVATION_CONFLICT -#define SAM_STAT_RESERVATION_CONFLICT 0x18 -#endif - -#define TRANSPORT_PLUGIN_FREE 0 -#define TRANSPORT_PLUGIN_REGISTERED 1 - #define TRANSPORT_PLUGIN_PHBA_PDEV 1 #define TRANSPORT_PLUGIN_VHBA_PDEV 2 #define TRANSPORT_PLUGIN_VHBA_VDEV 3 @@ -158,7 +135,6 @@ extern int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); extern int transport_handle_cdb_direct(struct se_cmd *); extern int transport_generic_handle_cdb_map(struct se_cmd *); extern int transport_generic_handle_data(struct se_cmd *); -extern void transport_new_cmd_failure(struct se_cmd *); extern int transport_generic_handle_tmr(struct se_cmd *); extern bool target_stop_task(struct se_task *task, unsigned long *flags); extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, -- cgit From 0957627a99604f379d35831897a2aa15272528fc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 4 Nov 2011 11:36:38 -0700 Subject: iscsi-target: Fix sess allocation leak in iscsi_login_zero_tsih_s1 This patch adds missing kfree() for an allocation in iscsi_login_zero_tsih_s1() code, and make transport_init_session() check for IS_ERR() returns. Reported-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index daad362a93ce..d734bdec24f9 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -224,7 +224,7 @@ static int iscsi_login_zero_tsih_s1( iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); pr_err("Could not allocate memory for session\n"); - return -1; + return -ENOMEM; } iscsi_login_set_conn_values(sess, conn, pdu->cid); @@ -250,7 +250,8 @@ static int iscsi_login_zero_tsih_s1( pr_err("idr_pre_get() for sess_idr failed\n"); iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); - return -1; + kfree(sess); + return -ENOMEM; } spin_lock(&sess_idr_lock); idr_get_new(&sess_idr, NULL, &sess->session_index); @@ -270,14 +271,16 @@ static int iscsi_login_zero_tsih_s1( ISCSI_LOGIN_STATUS_NO_RESOURCES); pr_err("Unable to allocate memory for" " struct iscsi_sess_ops.\n"); - return -1; + kfree(sess); + return -ENOMEM; } sess->se_sess = transport_init_session(); - if (!sess->se_sess) { + if (IS_ERR(sess->se_sess)) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); - return -1; + kfree(sess); + return -ENOMEM; } return 0; -- cgit From 330694a50f5b80e983136237c10516810fb427a9 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 6 Nov 2011 18:37:23 +0100 Subject: target: Improve system responsivity during I/O While testing ib_srpt I noticed that the target system became rather unresponsive during intensive I/O. The patch below made my target system responsive again during I/O without decreasing performance. Signed-off-by: Bart Van Assche Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index a997fde9ffcb..06cce8178fcf 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -4599,8 +4599,6 @@ static int transport_processing_thread(void *param) struct se_cmd *cmd; struct se_device *dev = (struct se_device *) param; - set_user_nice(current, -20); - while (!kthread_should_stop()) { ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq, atomic_read(&dev->dev_queue_obj.queue_cnt) || -- cgit From 5f655e8d2a7cdc41943f929e86054051d7441ec5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 8 Nov 2011 20:46:29 +0100 Subject: target: Avoid compiler warnings about signed one-bit bitfields Convert to unsigned bit fields for active I/O shutdown fields. Signed-off-by: Bart Van Assche Signed-off-by: Nicholas Bellinger --- include/target/target_core_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 4d0cb6b8c478..36a06f79c973 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -423,8 +423,8 @@ struct se_cmd { /* Transport protocol dependent state, see transport_state_table */ enum transport_state_table t_state; /* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */ - int check_release:1; - int cmd_wait_set:1; + unsigned check_release:1; + unsigned cmd_wait_set:1; /* See se_cmd_flags_table */ u32 se_cmd_flags; u32 se_ordered_id; @@ -560,7 +560,7 @@ struct se_node_acl { } ____cacheline_aligned; struct se_session { - int sess_tearing_down:1; + unsigned sess_tearing_down:1; u64 sess_bin_isid; struct se_node_acl *se_node_acl; struct se_portal_group *se_tpg; -- cgit From 97c34f3b04978799fd6eada69e1a8d84b74d9599 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 10 Nov 2011 11:22:47 -0800 Subject: target: Get rid of unused se_cmd_cache Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 06cce8178fcf..b4073d283408 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -61,7 +61,6 @@ static int sub_api_initialized; static struct workqueue_struct *target_completion_wq; -static struct kmem_cache *se_cmd_cache; static struct kmem_cache *se_sess_cache; struct kmem_cache *se_tmr_req_cache; struct kmem_cache *se_ua_cache; @@ -87,19 +86,13 @@ static void target_complete_ok_work(struct work_struct *work); int init_se_kmem_caches(void) { - se_cmd_cache = kmem_cache_create("se_cmd_cache", - sizeof(struct se_cmd), __alignof__(struct se_cmd), 0, NULL); - if (!se_cmd_cache) { - pr_err("kmem_cache_create for struct se_cmd failed\n"); - goto out; - } se_tmr_req_cache = kmem_cache_create("se_tmr_cache", sizeof(struct se_tmr_req), __alignof__(struct se_tmr_req), 0, NULL); if (!se_tmr_req_cache) { pr_err("kmem_cache_create() for struct se_tmr_req" " failed\n"); - goto out_free_cmd_cache; + goto out; } se_sess_cache = kmem_cache_create("se_sess_cache", sizeof(struct se_session), __alignof__(struct se_session), @@ -182,8 +175,6 @@ out_free_sess_cache: kmem_cache_destroy(se_sess_cache); out_free_tmr_req_cache: kmem_cache_destroy(se_tmr_req_cache); -out_free_cmd_cache: - kmem_cache_destroy(se_cmd_cache); out: return -ENOMEM; } @@ -191,7 +182,6 @@ out: void release_se_kmem_caches(void) { destroy_workqueue(target_completion_wq); - kmem_cache_destroy(se_cmd_cache); kmem_cache_destroy(se_tmr_req_cache); kmem_cache_destroy(se_sess_cache); kmem_cache_destroy(se_ua_cache); -- cgit From 6297b07cbc42eb6b53eb88fce70a4727ea230797 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 12 Nov 2011 09:29:51 -0800 Subject: target: Drop config_item_name usage in fabric TFO->free_wwn() This patch removes config_item_name() informational usage of TFO->free_wwn() treewide in loopback, tcm_fc, ib_srpt and tcm_vhost module code. Using v4 target_core_fabric_configfs.c logic, a fabric call for config_item_name() in TFO->drop_wwn() context returns NULL as target_fabric_drop_wwn() invoking config_item_put() -> config_group_put() will release fabric_port->port_wwn.wwn_group before the last config_item_put() -> TFO->drop_wwn() is invoked. Reported-by: Bart Van Assche Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 9 ++++----- drivers/target/tcm_fc/tfc_conf.c | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index cbf5e4513741..0ca89f02e26f 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -1342,17 +1342,16 @@ void tcm_loop_drop_scsi_hba( { struct tcm_loop_hba *tl_hba = container_of(wwn, struct tcm_loop_hba, tl_hba_wwn); - int host_no = tl_hba->sh->host_no; + + pr_debug("TCM_Loop_ConfigFS: Deallocating emulated Target" + " SAS Address: %s at Linux/SCSI Host ID: %d\n", + tl_hba->tl_wwn_address, tl_hba->sh->host_no); /* * Call device_unregister() on the original tl_hba->dev. * tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will * release *tl_hba; */ device_unregister(&tl_hba->dev); - - pr_debug("TCM_Loop_ConfigFS: Deallocated emulated Target" - " SAS Address: %s at Linux/SCSI Host ID: %d\n", - config_item_name(&wwn->wwn_group.cg_item), host_no); } /* Start items for tcm_loop_cit */ diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index 5f770412ca40..9402b7387cac 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c @@ -436,8 +436,7 @@ static void ft_del_lport(struct se_wwn *wwn) struct ft_lport_acl *lacl = container_of(wwn, struct ft_lport_acl, fc_lport_wwn); - pr_debug("del lport %s\n", - config_item_name(&wwn->wwn_group.cg_item)); + pr_debug("del lport %s\n", lacl->name); mutex_lock(&ft_lport_lock); list_del(&lacl->list); mutex_unlock(&ft_lport_lock); -- cgit From 58a2801a4b9ad97d3685bb7a3344e17d60292908 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Nov 2011 11:36:27 -0500 Subject: target: remove the se_obj_ptr and se_orig_obj_ptr se_cmd fields We already have a perfectly valid se_device pointer in the command, so remove the mostly useless duplicates. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 3 --- drivers/target/target_core_transport.c | 2 +- include/target/target_core_base.h | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 07953284ea6f..dd5adb82e3df 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -104,7 +104,6 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) se_cmd->se_lun = deve->se_lun; se_cmd->pr_res_key = deve->pr_res_key; se_cmd->orig_fe_lun = unpacked_lun; - se_cmd->se_orig_obj_ptr = se_cmd->se_lun->lun_se_dev; se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; } spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); @@ -137,7 +136,6 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_cmd->orig_fe_lun = 0; - se_cmd->se_orig_obj_ptr = se_cmd->se_lun->lun_se_dev; se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; } /* @@ -200,7 +198,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) se_lun = deve->se_lun; se_cmd->pr_res_key = deve->pr_res_key; se_cmd->orig_fe_lun = unpacked_lun; - se_cmd->se_orig_obj_ptr = se_cmd->se_dev; } spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b4073d283408..db2271c18030 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2029,7 +2029,7 @@ static int transport_execute_tasks(struct se_cmd *cmd) { int add_tasks; - if (se_dev_check_online(cmd->se_orig_obj_ptr) != 0) { + if (se_dev_check_online(cmd->se_dev) != 0) { cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; transport_generic_request_failure(cmd); return 0; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 36a06f79c973..f63997316dab 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -444,8 +444,6 @@ struct se_cmd { struct list_head se_qf_node; struct se_device *se_dev; struct se_dev_entry *se_deve; - struct se_device *se_obj_ptr; - struct se_device *se_orig_obj_ptr; struct se_lun *se_lun; /* Only used for internal passthrough and legacy TCM fabric modules */ struct se_session *se_sess; -- cgit From aad13ca20d960ab74b739d7bbe876dac4502f546 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Nov 2011 11:36:28 -0500 Subject: target: remove the se_ordered_node se_cmd field We never walk ordered_cmd_list in the se_device, so remove all code related to supporting it. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 11 ----------- include/target/target_core_base.h | 3 --- 2 files changed, 14 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index db2271c18030..a66050ec2c2f 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1332,12 +1332,10 @@ struct se_device *transport_add_device_to_core_hba( INIT_LIST_HEAD(&dev->dev_tmr_list); INIT_LIST_HEAD(&dev->execute_task_list); INIT_LIST_HEAD(&dev->delayed_cmd_list); - INIT_LIST_HEAD(&dev->ordered_cmd_list); INIT_LIST_HEAD(&dev->state_task_list); INIT_LIST_HEAD(&dev->qf_cmd_list); spin_lock_init(&dev->execute_task_lock); spin_lock_init(&dev->delayed_cmd_lock); - spin_lock_init(&dev->ordered_cmd_lock); spin_lock_init(&dev->state_task_lock); spin_lock_init(&dev->dev_alua_lock); spin_lock_init(&dev->dev_reservation_lock); @@ -1498,7 +1496,6 @@ void transport_init_se_cmd( { INIT_LIST_HEAD(&cmd->se_lun_node); INIT_LIST_HEAD(&cmd->se_delayed_node); - INIT_LIST_HEAD(&cmd->se_ordered_node); INIT_LIST_HEAD(&cmd->se_qf_node); INIT_LIST_HEAD(&cmd->se_queue_node); INIT_LIST_HEAD(&cmd->se_cmd_list); @@ -1963,11 +1960,6 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) cmd->se_ordered_id); return 1; } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { - spin_lock(&cmd->se_dev->ordered_cmd_lock); - list_add_tail(&cmd->se_ordered_node, - &cmd->se_dev->ordered_cmd_list); - spin_unlock(&cmd->se_dev->ordered_cmd_lock); - atomic_inc(&cmd->se_dev->dev_ordered_sync); smp_mb__after_atomic_inc(); @@ -3100,11 +3092,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd) " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id); } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { - spin_lock(&dev->ordered_cmd_lock); - list_del(&cmd->se_ordered_node); atomic_dec(&dev->dev_ordered_sync); smp_mb__after_atomic_dec(); - spin_unlock(&dev->ordered_cmd_lock); dev->dev_cur_ordered_id++; pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:" diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index f63997316dab..29773342f2c6 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -439,7 +439,6 @@ struct se_cmd { /* Used for sense data */ void *sense_buffer; struct list_head se_delayed_node; - struct list_head se_ordered_node; struct list_head se_lun_node; struct list_head se_qf_node; struct se_device *se_dev; @@ -730,7 +729,6 @@ struct se_device { struct se_obj dev_export_obj; struct se_queue_obj dev_queue_obj; spinlock_t delayed_cmd_lock; - spinlock_t ordered_cmd_lock; spinlock_t execute_task_lock; spinlock_t state_task_lock; spinlock_t dev_alua_lock; @@ -756,7 +754,6 @@ struct se_device { struct task_struct *dev_mgmt_thread; struct work_struct qf_work_queue; struct list_head delayed_cmd_list; - struct list_head ordered_cmd_list; struct list_head execute_task_list; struct list_head state_task_list; struct list_head qf_cmd_list; -- cgit From 2d3a4b51df4db2ee0415f42a63b9629a7977b975 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Nov 2011 11:36:29 -0500 Subject: target: remove the t_tasks_fua se_cmd field And use a SCF_FUA flag instead. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 2 +- drivers/target/target_core_iblock.c | 2 +- drivers/target/target_core_transport.c | 15 ++++++++++----- include/target/target_core_base.h | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index cdd47e8c7366..38211322415e 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -438,7 +438,7 @@ static int fd_do_task(struct se_task *task) if (ret > 0 && dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 && dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && - cmd->t_tasks_fua) { + (cmd->se_cmd_flags & SCF_FUA)) { /* * We might need to be a bit smarter here * and return some sense data to let the initiator diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index c670b8c2c994..4aa992204438 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -531,7 +531,7 @@ static int iblock_do_task(struct se_task *task) */ if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 || (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && - task->task_se_cmd->t_tasks_fua)) + (cmd->se_cmd_flags & SCF_FUA))) rw = WRITE_FUA; else rw = WRITE; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index a66050ec2c2f..866af5d5869f 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2572,7 +2572,8 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_32(cdb); - cmd->t_tasks_fua = (cdb[1] & 0x8); + if (cdb[1] & 0x8) + cmd->se_cmd_flags |= SCF_FUA; cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; break; case WRITE_12: @@ -2581,7 +2582,8 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_32(cdb); - cmd->t_tasks_fua = (cdb[1] & 0x8); + if (cdb[1] & 0x8) + cmd->se_cmd_flags |= SCF_FUA; cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; break; case WRITE_16: @@ -2590,7 +2592,8 @@ static int transport_generic_cmd_sequencer( goto out_unsupported_cdb; size = transport_get_size(sectors, cdb, cmd); cmd->t_task_lba = transport_lba_64(cdb); - cmd->t_tasks_fua = (cdb[1] & 0x8); + if (cdb[1] & 0x8) + cmd->se_cmd_flags |= SCF_FUA; cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; break; case XDWRITEREAD_10: @@ -2614,7 +2617,8 @@ static int transport_generic_cmd_sequencer( * Setup BIDI XOR callback to be run after I/O completion. */ cmd->transport_complete_callback = &transport_xor_callback; - cmd->t_tasks_fua = (cdb[1] & 0x8); + if (cdb[1] & 0x8) + cmd->se_cmd_flags |= SCF_FUA; break; case VARIABLE_LENGTH_CMD: service_action = get_unaligned_be16(&cdb[8]); @@ -2642,7 +2646,8 @@ static int transport_generic_cmd_sequencer( * completion. */ cmd->transport_complete_callback = &transport_xor_callback; - cmd->t_tasks_fua = (cdb[10] & 0x8); + if (cdb[1] & 0x8) + cmd->se_cmd_flags |= SCF_FUA; break; case WRITE_SAME_32: sectors = transport_get_sectors_32(cdb, cmd, §or_ret); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 29773342f2c6..357af4546d25 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -103,6 +103,7 @@ enum se_cmd_flags_table { SCF_SCSI_NON_DATA_CDB = 0x00000040, SCF_SCSI_CDB_EXCEPTION = 0x00000080, SCF_SCSI_RESERVATION_CONFLICT = 0x00000100, + SCF_FUA = 0x00000200, SCF_SE_LUN_CMD = 0x00000800, SCF_SE_ALLOW_EOO = 0x00001000, SCF_SENT_CHECK_CONDITION = 0x00004000, @@ -458,7 +459,6 @@ struct se_cmd { unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; unsigned long long t_task_lba; int t_tasks_failed; - int t_tasks_fua; bool t_tasks_bidi; u32 t_tasks_sg_chained_no; atomic_t t_fe_count; -- cgit From 33c3fafc43e56a22be60ebe67bec5ba763d51010 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Nov 2011 11:36:30 -0500 Subject: target: remove the t_tasks_bidi se_cmd field And use a SCF_BIDI flag instead. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 8 +++----- drivers/target/target_core_transport.c | 2 +- include/target/target_core_base.h | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 0ca89f02e26f..81d5832fbbd5 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -113,11 +113,9 @@ static struct se_cmd *tcm_loop_allocate_core_cmd( scsi_bufflen(sc), sc->sc_data_direction, sam_task_attr, &tl_cmd->tl_sense_buf[0]); - /* - * Signal BIDI usage with T_TASK(cmd)->t_tasks_bidi - */ if (scsi_bidi_cmnd(sc)) - se_cmd->t_tasks_bidi = 1; + se_cmd->se_cmd_flags |= SCF_BIDI; + /* * Locate the struct se_lun pointer and attach it to struct se_cmd */ @@ -154,7 +152,7 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) * For BIDI commands, pass in the extra READ buffer * to transport_generic_map_mem_to_cmd() below.. */ - if (se_cmd->t_tasks_bidi) { + if (se_cmd->se_cmd_flags & SCF_BIDI) { struct scsi_data_buffer *sdb = scsi_in(sc); sgl_bidi = sdb->table.sgl; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 866af5d5869f..8f29f472c50b 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2598,7 +2598,7 @@ static int transport_generic_cmd_sequencer( break; case XDWRITEREAD_10: if ((cmd->data_direction != DMA_TO_DEVICE) || - !(cmd->t_tasks_bidi)) + !(cmd->se_cmd_flags & SCF_BIDI)) goto out_invalid_cdb_field; sectors = transport_get_sectors_10(cdb, cmd, §or_ret); if (sector_ret) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 357af4546d25..3f9e4da5bd9f 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -106,6 +106,7 @@ enum se_cmd_flags_table { SCF_FUA = 0x00000200, SCF_SE_LUN_CMD = 0x00000800, SCF_SE_ALLOW_EOO = 0x00001000, + SCF_BIDI = 0x00002000, SCF_SENT_CHECK_CONDITION = 0x00004000, SCF_OVERFLOW_BIT = 0x00008000, SCF_UNDERFLOW_BIT = 0x00010000, @@ -459,7 +460,6 @@ struct se_cmd { unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; unsigned long long t_task_lba; int t_tasks_failed; - bool t_tasks_bidi; u32 t_tasks_sg_chained_no; atomic_t t_fe_count; atomic_t t_se_count; -- cgit From 6fd126ffebef3897d8fca98644a9fd1cc5c7a5e3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Nov 2011 11:36:31 -0500 Subject: target: remove the unused t_task_pt_sgl and t_task_pt_sgl_num se_cmd fields Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- include/target/target_core_base.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 3f9e4da5bd9f..3a21e2234d2b 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -484,14 +484,6 @@ struct se_cmd { struct work_struct work; - /* - * Used for pre-registered fabric SGL passthrough WRITE and READ - * with the special SCF_PASSTHROUGH_CONTIG_TO_SG case for TCM_Loop - * and other HW target mode fabric modules. - */ - struct scatterlist *t_task_pt_sgl; - u32 t_task_pt_sgl_num; - struct scatterlist *t_data_sg; unsigned int t_data_nents; struct scatterlist *t_bidi_data_sg; -- cgit From fef58a6096770ed6ab49103a430cc755254a74d9 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 15 Nov 2011 22:13:24 -0800 Subject: target: Reject SCSI data overflow for fabrics using transport_generic_map_mem_to_cmd This patch changes transport_generic_map_mem_to_cmd() to reject SCSI data overflow and to send exception status with CHECK_CONDITION + TCM_INVALID_CDB_FIELD for fabrics that are passing a pre-populated struct scatterlist (eg: tcm_loop and iscsi-target) being mapped into se_cmd->t_data_sg and se_cmd->t_data_nents. This addresses an OOPs where transport_allocate_data_tasks() would walk the incorrect post OVERFLOW cmd->data_length value beyond the end of the passed scatterlist. Cc: Christoph Hellwig Cc: Andy Grover Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 8f29f472c50b..0bdb6badbf99 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3411,6 +3411,18 @@ int transport_generic_map_mem_to_cmd( if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) || (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) { + /* + * Reject SCSI data overflow with map_mem_to_cmd() as incoming + * scatterlists already have been set to follow what the fabric + * passes for the original expected data transfer length. + */ + if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { + pr_warn("Rejecting SCSI DATA overflow for fabric using" + " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } cmd->t_data_sg = sgl; cmd->t_data_nents = sgl_count; -- cgit From 7e46cf02687e40197ae07c623e660be2a2720064 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 15 Nov 2011 23:59:00 -0800 Subject: iscsi-target: Fix residual count hanlding + remove iscsi_cmd->residual_count This patch fixes iscsi-target handling of underflow where residual data is causing an OOPs by using the incorrect iscsi_cmd_t->data_length initially assigned in iscsit_allocate_se_cmd(). It resets iscsi_cmd_t->data_length from se_cmd_t->data_length after transport_generic_allocate_tasks() has been invoked in iscsit_handle_scsi_cmd() RX context, and converts iscsi_cmd->residual_count usage to access iscsi_cmd->se_cmd.residual_count to get the proper residual count set by target-core. Reported-by: Cc: Christoph Hellwig Cc: Andy Grover Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 10 ++++++---- drivers/target/iscsi/iscsi_target_core.h | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4d81e1007c92..26834eff8960 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1039,6 +1039,8 @@ done: */ send_check_condition = 1; } else { + cmd->data_length = cmd->se_cmd.data_length; + if (iscsit_decide_list_to_build(cmd, payload_length) < 0) return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, @@ -2508,10 +2510,10 @@ static int iscsit_send_data_in( if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW; - hdr->residual_count = cpu_to_be32(cmd->residual_count); + hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW; - hdr->residual_count = cpu_to_be32(cmd->residual_count); + hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); } } hton24(hdr->dlength, datain.length); @@ -3013,10 +3015,10 @@ static int iscsit_send_status( hdr->flags |= ISCSI_FLAG_CMD_FINAL; if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW; - hdr->residual_count = cpu_to_be32(cmd->residual_count); + hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW; - hdr->residual_count = cpu_to_be32(cmd->residual_count); + hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); } hdr->response = cmd->iscsi_response; hdr->cmd_status = cmd->se_cmd.scsi_status; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 3723d90d5ae5..0e96a6b13174 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -398,7 +398,6 @@ struct iscsi_cmd { u32 pdu_send_order; /* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */ u32 pdu_start; - u32 residual_count; /* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */ u32 seq_send_order; /* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */ -- cgit From 7ae0b1038f9f7d4c91e9afd4dbbc98210bf1a241 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 27 Nov 2011 22:25:14 -0800 Subject: iscsi-target: Add missing F_BIT for iscsi_tm_rsp This patch sets the missing ISCSI_FLAG_CMD_FINAL bit in iscsit_send_task_mgt_rsp() for a struct iscsi_tm_rsp PDU. This usage is hardcoded for all TM response PDUs in RFC-3720 section 10.6. Reported-by: whucecil Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 26834eff8960..02de527940de 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3130,6 +3130,7 @@ static int iscsit_send_task_mgt_rsp( hdr = (struct iscsi_tm_rsp *) cmd->pdu; memset(hdr, 0, ISCSI_HDR_LEN); hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; + hdr->flags = ISCSI_FLAG_CMD_FINAL; hdr->response = iscsit_convert_tcm_tmr_rsp(se_tmr); hdr->itt = cpu_to_be32(cmd->init_task_tag); cmd->stat_sn = conn->stat_sn++; -- cgit From 1c3d5794fc4a2afd2258b3aa6406377934a36663 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 23:43:40 +0100 Subject: iscsi-target: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 6 ++---- drivers/target/iscsi/iscsi_target_nego.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 02de527940de..8599545cdf9e 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -614,13 +614,12 @@ int iscsit_add_reject( hdr = (struct iscsi_reject *) cmd->pdu; hdr->reason = reason; - cmd->buf_ptr = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL); + cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); if (!cmd->buf_ptr) { pr_err("Unable to allocate memory for cmd->buf_ptr\n"); iscsit_release_cmd(cmd); return -1; } - memcpy(cmd->buf_ptr, buf, ISCSI_HDR_LEN); spin_lock_bh(&conn->cmd_lock); list_add_tail(&cmd->i_list, &conn->conn_cmd_list); @@ -661,13 +660,12 @@ int iscsit_add_reject_from_cmd( hdr = (struct iscsi_reject *) cmd->pdu; hdr->reason = reason; - cmd->buf_ptr = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL); + cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); if (!cmd->buf_ptr) { pr_err("Unable to allocate memory for cmd->buf_ptr\n"); iscsit_release_cmd(cmd); return -1; } - memcpy(cmd->buf_ptr, buf, ISCSI_HDR_LEN); if (add_to_conn) { spin_lock_bh(&conn->cmd_lock); diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 426cd4bf6a9a..98936cb7c294 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -981,14 +981,13 @@ struct iscsi_login *iscsi_target_init_negotiation( return NULL; } - login->req = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL); + login->req = kmemdup(login_pdu, ISCSI_HDR_LEN, GFP_KERNEL); if (!login->req) { pr_err("Unable to allocate memory for Login Request.\n"); iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); goto out; } - memcpy(login->req, login_pdu, ISCSI_HDR_LEN); login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL); if (!login->req_buf) { -- cgit From 410f670202f0f13cdac8459b9c3effeeead135d1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 22 Nov 2011 13:51:32 -0800 Subject: target: Don't return an error status for 0-length READ and WRITE IO commands with a TRANSFER LENGTH of 0 are not an error; for example, for READ (10) and WRITE (10), SBC-3 says: A TRANSFER LENGTH field set to zero specifies that no logical blocks shall be read. This condition shall not be considered an error. In case we have nothing to do, just complete the command with good status. Signed-off-by: Roland Dreier Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0bdb6badbf99..1b760a0b1109 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3770,8 +3770,15 @@ int transport_generic_new_cmd(struct se_cmd *cmd) task_cdbs = transport_allocate_control_task(cmd); } - if (task_cdbs <= 0) + if (task_cdbs < 0) goto out_fail; + else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) { + cmd->t_state = TRANSPORT_COMPLETE; + atomic_set(&cmd->t_transport_active, 1); + INIT_WORK(&cmd->work, target_complete_ok_work); + queue_work(target_completion_wq, &cmd->work); + return 0; + } if (set_counts) { atomic_inc(&cmd->t_fe_count); -- cgit From 9b5cd7f37e1e018432111333e2a67f78ba41edfe Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 22 Nov 2011 13:51:33 -0800 Subject: target: Handle 0 correctly in transport_get_sectors_6() SBC-3 says: A TRANSFER LENGTH field set to zero specifies that 256 logical blocks shall be written. Any other value specifies the number of logical blocks that shall be written. The old code was always just returning the value in the TRANSFER LENGTH byte. Fix this to return 256 if the byte is 0. Signed-off-by: Roland Dreier Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 1b760a0b1109..9faaaae78b0a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2144,10 +2144,15 @@ static inline u32 transport_get_sectors_6( /* * Everything else assume TYPE_DISK Sector CDB location. - * Use 8-bit sector value. + * Use 8-bit sector value. SBC-3 says: + * + * A TRANSFER LENGTH field set to zero specifies that 256 + * logical blocks shall be written. Any other value + * specifies the number of logical blocks that shall be + * written. */ type_disk: - return (u32)cdb[4]; + return cdb[4] ? : 256; } static inline u32 transport_get_sectors_10( -- cgit From 1289a0571c037b4757f60597d646aedb70361ec3 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 22 Nov 2011 13:51:34 -0800 Subject: target: Fix page length in emulated INQUIRY VPD page 86h The LSB of the page length is at offset 3, not 2. Signed-off-by: Roland Dreier Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 8013a5a7bf64..831468b3163d 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -478,7 +478,7 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) if (cmd->data_length < 60) return 0; - buf[2] = 0x3c; + buf[3] = 0x3c; /* Set HEADSUP, ORDSUP, SIMPSUP */ buf[5] = 0x07; -- cgit From 5c73b678f729ea087ef57b59a5d7b5dd3a97042b Mon Sep 17 00:00:00 2001 From: Jörn Engel Date: Thu, 24 Nov 2011 02:04:16 +0100 Subject: target: remove unused struct fields Some are never used, some are set but never read, dev_hoq_count is incremented and decremented, but never read. Signed-off-by: Joern Engel Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_core.h | 2 -- drivers/target/target_core_alua.c | 2 -- drivers/target/target_core_transport.c | 8 -------- include/target/target_core_base.h | 18 ------------------ 4 files changed, 30 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 0e96a6b13174..f1a02dad05a0 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -534,7 +534,6 @@ struct iscsi_conn { atomic_t connection_exit; atomic_t connection_recovery; atomic_t connection_reinstatement; - atomic_t connection_wait; atomic_t connection_wait_rcfr; atomic_t sleep_on_conn_wait_comp; atomic_t transport_failed; @@ -642,7 +641,6 @@ struct iscsi_session { atomic_t session_reinstatement; atomic_t session_stop_active; atomic_t sleep_on_sess_wait_comp; - atomic_t transport_wait_cmds; /* connection list */ struct list_head sess_conn_list; struct list_head cr_active_list; diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index cd61331c1482..1dcbef499d6a 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -1191,7 +1191,6 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) * struct t10_alua_lu_gp. */ spin_lock(&lu_gps_lock); - atomic_set(&lu_gp->lu_gp_shutdown, 1); list_del(&lu_gp->lu_gp_node); alua_lu_gps_count--; spin_unlock(&lu_gps_lock); @@ -1445,7 +1444,6 @@ struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( tg_pt_gp_mem->tg_pt = port; port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem; - atomic_set(&port->sep_tg_pt_gp_active, 1); return tg_pt_gp_mem; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 9faaaae78b0a..0257658e2e3e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1326,7 +1326,6 @@ struct se_device *transport_add_device_to_core_hba( dev->se_hba = hba; dev->se_sub_dev = se_dev; dev->transport = transport; - atomic_set(&dev->active_cmds, 0); INIT_LIST_HEAD(&dev->dev_list); INIT_LIST_HEAD(&dev->dev_sep_list); INIT_LIST_HEAD(&dev->dev_tmr_list); @@ -1336,11 +1335,8 @@ struct se_device *transport_add_device_to_core_hba( INIT_LIST_HEAD(&dev->qf_cmd_list); spin_lock_init(&dev->execute_task_lock); spin_lock_init(&dev->delayed_cmd_lock); - spin_lock_init(&dev->state_task_lock); - spin_lock_init(&dev->dev_alua_lock); spin_lock_init(&dev->dev_reservation_lock); spin_lock_init(&dev->dev_status_lock); - spin_lock_init(&dev->dev_status_thr_lock); spin_lock_init(&dev->se_port_lock); spin_lock_init(&dev->se_tmr_lock); spin_lock_init(&dev->qf_cmd_lock); @@ -1952,8 +1948,6 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) * to allow the passed struct se_cmd list of tasks to the front of the list. */ if (cmd->sam_task_attr == MSG_HEAD_TAG) { - atomic_inc(&cmd->se_dev->dev_hoq_count); - smp_mb__after_atomic_inc(); pr_debug("Added HEAD_OF_QUEUE for CDB:" " 0x%02x, se_ordered_id: %u\n", cmd->t_task_cdb[0], @@ -3095,8 +3089,6 @@ static void transport_complete_task_attr(struct se_cmd *cmd) " SIMPLE: %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id); } else if (cmd->sam_task_attr == MSG_HEAD_TAG) { - atomic_dec(&dev->dev_hoq_count); - smp_mb__after_atomic_dec(); dev->dev_cur_ordered_id++; pr_debug("Incremented dev_cur_ordered_id: %u for" " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 3a21e2234d2b..098a15611aba 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -213,7 +213,6 @@ struct t10_alua_lu_gp { u16 lu_gp_id; int lu_gp_valid_id; u32 lu_gp_members; - atomic_t lu_gp_shutdown; atomic_t lu_gp_ref_cnt; spinlock_t lu_gp_lock; struct config_group lu_gp_group; @@ -679,9 +678,6 @@ struct se_subsystem_dev { } ____cacheline_aligned; struct se_device { - /* Set to 1 if thread is NOT sleeping on thread_sem */ - u8 thread_active; - u8 dev_status_timer_flags; /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ @@ -706,14 +702,10 @@ struct se_device { u64 write_bytes; spinlock_t stats_lock; /* Active commands on this virtual SE device */ - atomic_t active_cmds; atomic_t simple_cmds; atomic_t depth_left; atomic_t dev_ordered_id; - atomic_t dev_tur_active; atomic_t execute_tasks; - atomic_t dev_status_thr_count; - atomic_t dev_hoq_count; atomic_t dev_ordered_sync; atomic_t dev_qf_count; struct se_obj dev_obj; @@ -722,12 +714,8 @@ struct se_device { struct se_queue_obj dev_queue_obj; spinlock_t delayed_cmd_lock; spinlock_t execute_task_lock; - spinlock_t state_task_lock; - spinlock_t dev_alua_lock; spinlock_t dev_reservation_lock; - spinlock_t dev_state_lock; spinlock_t dev_status_lock; - spinlock_t dev_status_thr_lock; spinlock_t se_port_lock; spinlock_t se_tmr_lock; spinlock_t qf_cmd_lock; @@ -739,11 +727,8 @@ struct se_device { struct t10_pr_registration *dev_pr_res_holder; struct list_head dev_sep_list; struct list_head dev_tmr_list; - struct timer_list dev_status_timer; /* Pointer to descriptor for processing thread */ struct task_struct *process_thread; - pid_t process_thread_pid; - struct task_struct *dev_mgmt_thread; struct work_struct qf_work_queue; struct list_head delayed_cmd_list; struct list_head execute_task_list; @@ -756,8 +741,6 @@ struct se_device { struct se_subsystem_api *transport; /* Linked list for struct se_hba struct se_device list */ struct list_head dev_list; - /* Linked list for struct se_global->g_se_dev_list */ - struct list_head g_se_dev_list; } ____cacheline_aligned; struct se_hba { @@ -819,7 +802,6 @@ struct se_port { u32 sep_index; struct scsi_port_stats sep_stats; /* Used for ALUA Target Port Groups membership */ - atomic_t sep_tg_pt_gp_active; atomic_t sep_tg_pt_secondary_offline; /* Used for PR ALL_TG_PT=1 */ atomic_t sep_tg_pt_ref_cnt; -- cgit From 9649fa1b8764f64c8cc4293e197e14cd46fe7205 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 28 Nov 2011 12:33:10 +0100 Subject: target/file: walk properly over sg list This patch changes fileio to use for_each_sg() when walking se_task->task_sg memory passed into from loopback LLD struct scsi_cmnd scatterlist memory. This addresses an issue where FILEIO backends with loopback where hitting the following OOPs with mkfs.ext2: |kernel BUG at include/linux/scatterlist.h:97! |invalid opcode: 0000 [#1] PREEMPT SMP |Modules linked in: sd_mod tcm_loop target_core_stgt scsi_tgt target_core_pscsi target_core_file target_core_iblock target_core_mod configfs scsi_mod | |Pid: 671, comm: LIO_fileio Not tainted 3.1.0-rc10+ #139 Bochs Bochs |EIP: 0060:[] EFLAGS: 00010202 CPU: 0 |EIP is at fd_do_task+0x396/0x420 [target_core_file] | [] __transport_execute_tasks+0xd4/0x190 [target_core_mod] | [] transport_execute_tasks+0x3c/0xf0 [target_core_mod] |EIP: [] fd_do_task+0x396/0x420 [target_core_file] SS:ESP 0068:dea47e90 Signed-off-by: Sebastian Andrzej Siewior Cc: Christoph Hellwig Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 38211322415e..b4864fba4ef0 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -289,9 +289,9 @@ static int fd_do_readv(struct se_task *task) return -ENOMEM; } - for (i = 0; i < task->task_sg_nents; i++) { - iov[i].iov_len = sg[i].length; - iov[i].iov_base = sg_virt(&sg[i]); + for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { + iov[i].iov_len = sg->length; + iov[i].iov_base = sg_virt(sg); } old_fs = get_fs(); @@ -342,9 +342,9 @@ static int fd_do_writev(struct se_task *task) return -ENOMEM; } - for (i = 0; i < task->task_sg_nents; i++) { - iov[i].iov_len = sg[i].length; - iov[i].iov_base = sg_virt(&sg[i]); + for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { + iov[i].iov_len = sg->length; + iov[i].iov_base = sg_virt(sg); } old_fs = get_fs(); -- cgit From 6f21475576dde397cd2580262209d4080fbd5458 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Nov 2011 03:29:59 -0500 Subject: target: remove the unused se_dev_list Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 11 ----------- drivers/target/target_core_device.c | 1 - include/target/target_core_base.h | 1 - 3 files changed, 13 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index e0c1e8a8dd4e..93d4f6a1b798 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -67,9 +67,6 @@ static struct config_group target_core_hbagroup; static struct config_group alua_group; static struct config_group alua_lu_gps_group; -static DEFINE_SPINLOCK(se_device_lock); -static LIST_HEAD(se_dev_list); - static inline struct se_hba * item_to_hba(struct config_item *item) { @@ -2741,7 +2738,6 @@ static struct config_group *target_core_make_subdev( " struct se_subsystem_dev\n"); goto unlock; } - INIT_LIST_HEAD(&se_dev->se_dev_node); INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); @@ -2777,9 +2773,6 @@ static struct config_group *target_core_make_subdev( " from allocate_virtdevice()\n"); goto out; } - spin_lock(&se_device_lock); - list_add_tail(&se_dev->se_dev_node, &se_dev_list); - spin_unlock(&se_device_lock); config_group_init_type_name(&se_dev->se_dev_group, name, &target_core_dev_cit); @@ -2874,10 +2867,6 @@ static void target_core_drop_subdev( mutex_lock(&hba->hba_access_mutex); t = hba->transport; - spin_lock(&se_device_lock); - list_del(&se_dev->se_dev_node); - spin_unlock(&se_device_lock); - dev_stat_grp = &se_dev->dev_stat_grps.stat_group; for (i = 0; dev_stat_grp->default_groups[i]; i++) { df_item = &dev_stat_grp->default_groups[i]->cg_item; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index dd5adb82e3df..e2be1f510da8 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1584,7 +1584,6 @@ int core_dev_setup_virtual_lun0(void) ret = -ENOMEM; goto out; } - INIT_LIST_HEAD(&se_dev->se_dev_node); INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 098a15611aba..6873c7dd9145 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -669,7 +669,6 @@ struct se_subsystem_dev { struct t10_reservation t10_pr; spinlock_t se_dev_lock; void *se_dev_su_ptr; - struct list_head se_dev_node; struct config_group se_dev_group; /* For T10 Reservations */ struct config_group se_dev_pr_group; -- cgit From 5bff9e8584fbcdb361dada5a0425724b9e31e608 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 25 Nov 2011 22:18:45 +0100 Subject: target/rd: simplify the page/offset computation Breakout rd_MEMCPY_do_task() usage of do_div() to tmp value during rd_request->rd_page assignment. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_rd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6d8a6881cfff..6119ed5a3311 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -583,14 +583,12 @@ static int rd_MEMCPY_do_task(struct se_task *task) { struct se_device *dev = task->task_se_cmd->se_dev; struct rd_request *req = RD_REQ(task); - unsigned long long lba; + u64 tmp; int ret; - req->rd_page = (task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size) / PAGE_SIZE; - lba = task->task_lba; - req->rd_offset = (do_div(lba, - (PAGE_SIZE / dev->se_sub_dev->se_dev_attrib.block_size))) * - dev->se_sub_dev->se_dev_attrib.block_size; + tmp = task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size; + req->rd_offset = do_div(tmp, PAGE_SIZE); + req->rd_page = tmp; req->rd_size = task->task_size; if (task->task_data_direction == DMA_FROM_DEVICE) -- cgit From 65b0c78d5a0ca2cb82b7b9f54f855896e0d7fc10 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 30 Nov 2011 10:48:30 +0100 Subject: target/rd: fix or rewrite the copy routine So the code assumes that the sg list is only a array while in reality loopback SGL memory via scsi_cmnd into target-core may be already chained. This patch converts ramdisk code to use sg_miter logic from scatterlist.h in order to properly support passthrough SGL usage with transport_generic_map_mem_to_cmd() via loopback. With this patch the bug goes away. However after umount/mount of the device my files are gone. So something is still not right. After looking at it for a while I decided to rewrite the that part of the code and now things do work for me. For reference: - http://article.gmane.org/gmane.linux.scsi.target.devel/595 the sg_next() conversion - http://article.gmane.org/gmane.linux.scsi.target.devel/602 the rewrite of the copy code (nab: Fix compile warning in rd_MEMCPY) Signed-off-by: Sebastian Andrzej Siewior Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_rd.c | 245 +++++++--------------------------------- 1 file changed, 40 insertions(+), 205 deletions(-) diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6119ed5a3311..02e51faa2f4e 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -343,235 +343,74 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) return NULL; } -/* rd_MEMCPY_read(): - * - * - */ -static int rd_MEMCPY_read(struct rd_request *req) +static int rd_MEMCPY(struct rd_request *req, u32 read_rd) { struct se_task *task = &req->rd_task; struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr; struct rd_dev_sg_table *table; - struct scatterlist *sg_d, *sg_s; - void *dst, *src; - u32 i = 0, j = 0, dst_offset = 0, src_offset = 0; - u32 length, page_end = 0, table_sg_end; + struct scatterlist *rd_sg; + struct sg_mapping_iter m; u32 rd_offset = req->rd_offset; + u32 src_len; table = rd_get_sg_table(dev, req->rd_page); if (!table) return -EINVAL; - table_sg_end = (table->page_end_offset - req->rd_page); - sg_d = task->task_sg; - sg_s = &table->sg_table[req->rd_page - table->page_start_offset]; + rd_sg = &table->sg_table[req->rd_page - table->page_start_offset]; - pr_debug("RD[%u]: Read LBA: %llu, Size: %u Page: %u, Offset:" - " %u\n", dev->rd_dev_id, task->task_lba, req->rd_size, - req->rd_page, req->rd_offset); - - src_offset = rd_offset; + pr_debug("RD[%u]: %s LBA: %llu, Size: %u Page: %u, Offset: %u\n", + dev->rd_dev_id, read_rd ? "Read" : "Write", + task->task_lba, req->rd_size, req->rd_page, + rd_offset); + src_len = PAGE_SIZE - rd_offset; + sg_miter_start(&m, task->task_sg, task->task_sg_nents, + read_rd ? SG_MITER_TO_SG : SG_MITER_FROM_SG); while (req->rd_size) { - if ((sg_d[i].length - dst_offset) < - (sg_s[j].length - src_offset)) { - length = (sg_d[i].length - dst_offset); - - pr_debug("Step 1 - sg_d[%d]: %p length: %d" - " offset: %u sg_s[%d].length: %u\n", i, - &sg_d[i], sg_d[i].length, sg_d[i].offset, j, - sg_s[j].length); - pr_debug("Step 1 - length: %u dst_offset: %u" - " src_offset: %u\n", length, dst_offset, - src_offset); - - if (length > req->rd_size) - length = req->rd_size; - - dst = sg_virt(&sg_d[i++]) + dst_offset; - BUG_ON(!dst); - - src = sg_virt(&sg_s[j]) + src_offset; - BUG_ON(!src); - - dst_offset = 0; - src_offset = length; - page_end = 0; - } else { - length = (sg_s[j].length - src_offset); - - pr_debug("Step 2 - sg_d[%d]: %p length: %d" - " offset: %u sg_s[%d].length: %u\n", i, - &sg_d[i], sg_d[i].length, sg_d[i].offset, - j, sg_s[j].length); - pr_debug("Step 2 - length: %u dst_offset: %u" - " src_offset: %u\n", length, dst_offset, - src_offset); - - if (length > req->rd_size) - length = req->rd_size; - - dst = sg_virt(&sg_d[i]) + dst_offset; - BUG_ON(!dst); - - if (sg_d[i].length == length) { - i++; - dst_offset = 0; - } else - dst_offset = length; - - src = sg_virt(&sg_s[j++]) + src_offset; - BUG_ON(!src); - - src_offset = 0; - page_end = 1; - } + u32 len; + void *rd_addr; - memcpy(dst, src, length); + sg_miter_next(&m); + len = min((u32)m.length, src_len); + m.consumed = len; - pr_debug("page: %u, remaining size: %u, length: %u," - " i: %u, j: %u\n", req->rd_page, - (req->rd_size - length), length, i, j); + rd_addr = sg_virt(rd_sg) + rd_offset; - req->rd_size -= length; - if (!req->rd_size) - return 0; + if (read_rd) + memcpy(m.addr, rd_addr, len); + else + memcpy(rd_addr, m.addr, len); - if (!page_end) + req->rd_size -= len; + if (!req->rd_size) continue; - if (++req->rd_page <= table->page_end_offset) { - pr_debug("page: %u in same page table\n", - req->rd_page); + src_len -= len; + if (src_len) { + rd_offset += len; continue; } - pr_debug("getting new page table for page: %u\n", - req->rd_page); - - table = rd_get_sg_table(dev, req->rd_page); - if (!table) - return -EINVAL; - - sg_s = &table->sg_table[j = 0]; - } - - return 0; -} - -/* rd_MEMCPY_write(): - * - * - */ -static int rd_MEMCPY_write(struct rd_request *req) -{ - struct se_task *task = &req->rd_task; - struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr; - struct rd_dev_sg_table *table; - struct scatterlist *sg_d, *sg_s; - void *dst, *src; - u32 i = 0, j = 0, dst_offset = 0, src_offset = 0; - u32 length, page_end = 0, table_sg_end; - u32 rd_offset = req->rd_offset; - - table = rd_get_sg_table(dev, req->rd_page); - if (!table) - return -EINVAL; - - table_sg_end = (table->page_end_offset - req->rd_page); - sg_d = &table->sg_table[req->rd_page - table->page_start_offset]; - sg_s = task->task_sg; - - pr_debug("RD[%d] Write LBA: %llu, Size: %u, Page: %u," - " Offset: %u\n", dev->rd_dev_id, task->task_lba, req->rd_size, - req->rd_page, req->rd_offset); - - dst_offset = rd_offset; - - while (req->rd_size) { - if ((sg_s[i].length - src_offset) < - (sg_d[j].length - dst_offset)) { - length = (sg_s[i].length - src_offset); - - pr_debug("Step 1 - sg_s[%d]: %p length: %d" - " offset: %d sg_d[%d].length: %u\n", i, - &sg_s[i], sg_s[i].length, sg_s[i].offset, - j, sg_d[j].length); - pr_debug("Step 1 - length: %u src_offset: %u" - " dst_offset: %u\n", length, src_offset, - dst_offset); - - if (length > req->rd_size) - length = req->rd_size; - - src = sg_virt(&sg_s[i++]) + src_offset; - BUG_ON(!src); - - dst = sg_virt(&sg_d[j]) + dst_offset; - BUG_ON(!dst); - - src_offset = 0; - dst_offset = length; - page_end = 0; - } else { - length = (sg_d[j].length - dst_offset); - - pr_debug("Step 2 - sg_s[%d]: %p length: %d" - " offset: %d sg_d[%d].length: %u\n", i, - &sg_s[i], sg_s[i].length, sg_s[i].offset, - j, sg_d[j].length); - pr_debug("Step 2 - length: %u src_offset: %u" - " dst_offset: %u\n", length, src_offset, - dst_offset); - - if (length > req->rd_size) - length = req->rd_size; - - src = sg_virt(&sg_s[i]) + src_offset; - BUG_ON(!src); - - if (sg_s[i].length == length) { - i++; - src_offset = 0; - } else - src_offset = length; - - dst = sg_virt(&sg_d[j++]) + dst_offset; - BUG_ON(!dst); - - dst_offset = 0; - page_end = 1; - } - - memcpy(dst, src, length); - - pr_debug("page: %u, remaining size: %u, length: %u," - " i: %u, j: %u\n", req->rd_page, - (req->rd_size - length), length, i, j); - - req->rd_size -= length; - if (!req->rd_size) - return 0; - - if (!page_end) - continue; - - if (++req->rd_page <= table->page_end_offset) { - pr_debug("page: %u in same page table\n", - req->rd_page); + /* rd page completed, next one please */ + req->rd_page++; + rd_offset = 0; + src_len = PAGE_SIZE; + if (req->rd_page <= table->page_end_offset) { + rd_sg++; continue; } - pr_debug("getting new page table for page: %u\n", - req->rd_page); - table = rd_get_sg_table(dev, req->rd_page); - if (!table) + if (!table) { + sg_miter_stop(&m); return -EINVAL; + } - sg_d = &table->sg_table[j = 0]; + /* since we increment, the first sg entry is correct */ + rd_sg = table->sg_table; } - + sg_miter_stop(&m); return 0; } @@ -591,11 +430,7 @@ static int rd_MEMCPY_do_task(struct se_task *task) req->rd_page = tmp; req->rd_size = task->task_size; - if (task->task_data_direction == DMA_FROM_DEVICE) - ret = rd_MEMCPY_read(req); - else - ret = rd_MEMCPY_write(req); - + ret = rd_MEMCPY(req, task->task_data_direction == DMA_FROM_DEVICE); if (ret != 0) return ret; -- cgit From c638830d040696ff2bae07785fd4277e7e3fe7c4 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Wed, 30 Nov 2011 12:11:50 -0800 Subject: target: Don't return an error if disabling unsupported features If an attribute is present (but not yet supported) it should be OK to write 0 (a no-op) to the attribute. This is an issue because userspace should be able to save and restore all set attribute values without error. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e2be1f510da8..9b8639425472 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -954,8 +954,12 @@ int se_dev_set_emulate_dpo(struct se_device *dev, int flag) return -EINVAL; } - pr_err("dpo_emulated not supported\n"); - return -EINVAL; + if (flag) { + pr_err("dpo_emulated not supported\n"); + return -EINVAL; + } + + return 0; } int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) @@ -965,7 +969,7 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) return -EINVAL; } - if (dev->transport->fua_write_emulated == 0) { + if (flag && dev->transport->fua_write_emulated == 0) { pr_err("fua_write_emulated not supported\n"); return -EINVAL; } @@ -982,8 +986,12 @@ int se_dev_set_emulate_fua_read(struct se_device *dev, int flag) return -EINVAL; } - pr_err("ua read emulated not supported\n"); - return -EINVAL; + if (flag) { + pr_err("ua read emulated not supported\n"); + return -EINVAL; + } + + return 0; } int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) @@ -992,7 +1000,7 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) pr_err("Illegal value %d\n", flag); return -EINVAL; } - if (dev->transport->write_cache_emulated == 0) { + if (flag && dev->transport->write_cache_emulated == 0) { pr_err("write_cache_emulated not supported\n"); return -EINVAL; } @@ -1053,7 +1061,7 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag) * We expect this value to be non-zero when generic Block Layer * Discard supported is detected iblock_create_virtdevice(). */ - if (!dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { pr_err("Generic Block Discard not supported\n"); return -ENOSYS; } @@ -1074,7 +1082,7 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag) * We expect this value to be non-zero when generic Block Layer * Discard supported is detected iblock_create_virtdevice(). */ - if (!dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { pr_err("Generic Block Discard not supported\n"); return -ENOSYS; } -- cgit From ddca8f3ed36c5d25363dab6762829868af09cb02 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 6 Dec 2011 05:24:19 +0000 Subject: iscsi-target: Fix hex2bin warn_unused compile message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile warning with hex2bin() usage: drivers/target/iscsi/iscsi_target_auth.c: In function ‘chap_string_to_hex’: drivers/target/iscsi/iscsi_target_auth.c:35: warning: ignoring return value of ‘hex2bin’, declared with attribute warn_unused_result Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index beb39469e7f1..1cd6ce373b83 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -30,9 +30,11 @@ static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len) { - int j = DIV_ROUND_UP(len, 2); + int j = DIV_ROUND_UP(len, 2), rc; - hex2bin(dst, src, j); + rc = hex2bin(dst, src, j); + if (rc < 0) + pr_debug("CHAP string contains non hex digit symbols\n"); dst[j] = '\0'; return j; -- cgit From 75fc2d3797c47f5f70ca71c41c342c352845cd06 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 5 Dec 2011 17:27:08 +0100 Subject: MAINTAINERS: Update tip.git related git trees Update the six major subsystem trees hosted in the tip tree to the new location (or add the location if it was missing). Acked-by: Thomas Gleixner Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-w0z98as3kwy9bo1o3k2mmuvi@git.kernel.org Signed-off-by: Ingo Molnar --- MAINTAINERS | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 447560284996..9706a21edcbd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3118,6 +3118,7 @@ F: include/linux/hid* HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS M: Thomas Gleixner +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core S: Maintained F: Documentation/timers/ F: kernel/hrtimer.c @@ -3627,7 +3628,7 @@ F: net/irda/ IRQ SUBSYSTEM M: Thomas Gleixner S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git irq/core +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core F: kernel/irq/ ISAPNP @@ -4115,7 +4116,7 @@ F: drivers/hwmon/lm90.c LOCKDEP AND LOCKSTAT M: Peter Zijlstra M: Ingo Molnar -T: git git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/locking S: Maintained F: Documentation/lockdep*.txt F: Documentation/lockstat.txt @@ -5102,6 +5103,7 @@ M: Peter Zijlstra M: Paul Mackerras M: Ingo Molnar M: Arnaldo Carvalho de Melo +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core S: Supported F: kernel/events/* F: include/linux/perf_event.h @@ -5181,6 +5183,7 @@ F: drivers/scsi/pm8001/ POSIX CLOCKS and TIMERS M: Thomas Gleixner +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core S: Supported F: fs/timerfd.c F: include/linux/timer* @@ -5696,6 +5699,7 @@ F: drivers/dma/dw_dmac.c TIMEKEEPING, NTP M: John Stultz M: Thomas Gleixner +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core S: Supported F: include/linux/clocksource.h F: include/linux/time.h @@ -5720,6 +5724,7 @@ F: drivers/watchdog/sc1200wdt.c SCHEDULER M: Ingo Molnar M: Peter Zijlstra +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core S: Maintained F: kernel/sched* F: include/linux/sched.h @@ -6647,7 +6652,7 @@ TRACING M: Steven Rostedt M: Frederic Weisbecker M: Ingo Molnar -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git perf/core +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core S: Maintained F: Documentation/trace/ftrace.txt F: arch/*/*/*/ftrace.h @@ -7397,7 +7402,7 @@ M: Thomas Gleixner M: Ingo Molnar M: "H. Peter Anvin" M: x86@kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core S: Maintained F: Documentation/x86/ F: arch/x86/ -- cgit From cefcc03ffc9527dde56807339edb1719c8dbae5f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 20:50:45 +0000 Subject: ASoC: Provide a more complete DMA driver stub Allow userspace applications to do more parameter setting by providing a more complete stub DMA driver specifying a wildcard set of formats and channels and essentially random values for the DMA parameters. This is required for useful runtime operation of the dummy DMA driver until we are able to figure out how to power up links and do hw_params() from DAPM. Sending to stable as without this the dummy driver is not terribly useful. Reported-by: Kyung-Kwee Ryu Tested-by: Kyung-Kwee Ryu Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/soc-utils.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 0c12b98484bd..4220bb0f2730 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -58,7 +58,36 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) } EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); -static struct snd_soc_platform_driver dummy_platform; +static const struct snd_pcm_hardware dummy_dma_hardware = { + .formats = 0xffffffff, + .channels_min = 1, + .channels_max = UINT_MAX, + + /* Random values to keep userspace happy when checking constraints */ + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .buffer_bytes_max = 128*1024, + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = PAGE_SIZE*2, + .periods_min = 2, + .periods_max = 128, +}; + +static int dummy_dma_open(struct snd_pcm_substream *substream) +{ + snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); + + return 0; +} + +static struct snd_pcm_ops dummy_dma_ops = { + .open = dummy_dma_open, + .ioctl = snd_pcm_lib_ioctl, +}; + +static struct snd_soc_platform_driver dummy_platform = { + .ops = &dummy_dma_ops, +}; static __devinit int snd_soc_dummy_probe(struct platform_device *pdev) { -- cgit From 96f176a310e447966e45112fe4511b9d9fa0caf4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 6 Dec 2011 11:17:34 +0100 Subject: iommu/msm: Fix compile error in mach-msm/devices-iommu.c Fix compile error due to missing include. Signed-off-by: Joerg Roedel --- arch/arm/mach-msm/devices-iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c index 24030d0da6e3..0fb7a17df398 100644 --- a/arch/arm/mach-msm/devices-iommu.c +++ b/arch/arm/mach-msm/devices-iommu.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include -- cgit From dd13752537d36cc6c145cb040f71ce7acda31e6e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 5 Dec 2011 23:14:39 +0000 Subject: x86/intel_mid: Fix the Kconfig for MID selection We currently fail to build on CONFIG_X86_INTEL_MID=y and CONFIG_X86_MRST unset. We could build all the bits to make generic MID work if you picked MID platform alone but that's really silly. Instead use select and two variables. This looks a bit daft right now but once we add a Medfield selection it'll start to look a good deal more sensible. Reported-by: Ingo Molnar Reported-by: Stanislaw Gruszka Signed-off-by: Alan Cox Link: http://lkml.kernel.org/r/20111205231433.28811.51297.stgit@bob.linux.org.uk Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cb9a1044a771..5553f9f1a70d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -390,7 +390,7 @@ config X86_INTEL_CE This option compiles in support for the CE4100 SOC for settop boxes and media devices. -config X86_INTEL_MID +config X86_WANT_INTEL_MID bool "Intel MID platform support" depends on X86_32 depends on X86_EXTENDED_PLATFORM @@ -399,7 +399,7 @@ config X86_INTEL_MID systems which do not have the PCI legacy interfaces (Moorestown, Medfield). If you are building for a PC class system say N here. -if X86_INTEL_MID +if X86_WANT_INTEL_MID config X86_MRST bool "Moorestown MID platform" @@ -411,6 +411,7 @@ config X86_MRST select SPI select INTEL_SCU_IPC select X86_PLATFORM_DEVICES + select X86_INTEL_MID ---help--- Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin Internet Device(MID) platform. Moorestown consists of two chips: -- cgit From d68fb11c3dae75c8331538dcf083a65e697cc034 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 5 Dec 2011 21:16:06 +0100 Subject: ptp: Fix clock_getres() implementation The clock_getres() function must return the resolution in the timespec argument and return 0 for success. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: stable@kernel.org Cc: Richard Cochran --- drivers/ptp/ptp_clock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index cf3f9997546d..10451a15e828 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -101,7 +101,9 @@ static s32 scaled_ppm_to_ppb(long ppm) static int ptp_clock_getres(struct posix_clock *pc, struct timespec *tp) { - return 1; /* always round timer functions to one nanosecond */ + tp->tv_sec = 0; + tp->tv_nsec = 1; + return 0; } static int ptp_clock_settime(struct posix_clock *pc, const struct timespec *tp) -- cgit From c9c024b3f3e07d087974db4c0dc46217fff3a6c0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 5 Dec 2011 21:20:23 +0100 Subject: alarmtimers: Fix time comparison The expiry function compares the timer against current time and does not expire the timer when the expiry time is >= now. That's wrong. If the timer is set for now, then it must expire. Make the condition expiry > now for breaking out the loop. Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: stable@kernel.org --- kernel/time/alarmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index c436e790b21b..8a46f5d64504 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -195,7 +195,7 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) struct alarm *alarm; ktime_t expired = next->expires; - if (expired.tv64 >= now.tv64) + if (expired.tv64 > now.tv64) break; alarm = container_of(next, struct alarm, node); -- cgit From 68bfcafaaeebdf23fba0edb4e0964bef7d08f92a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 6 Dec 2011 15:19:00 +0800 Subject: ASoC: Include linux/io.h for jz4740 codec Include linux/io.h to fix below build errors: CC sound/soc/codecs/jz4740.o sound/soc/codecs/jz4740.c: In function 'jz4740_codec_read': sound/soc/codecs/jz4740.c:82: error: implicit declaration of function 'readl' sound/soc/codecs/jz4740.c: In function 'jz4740_codec_write': sound/soc/codecs/jz4740.c:92: error: implicit declaration of function 'writel' sound/soc/codecs/jz4740.c: In function 'jz4740_codec_probe': sound/soc/codecs/jz4740.c:373: error: implicit declaration of function 'ioremap' sound/soc/codecs/jz4740.c:373: warning: assignment makes pointer from integer without a cast sound/soc/codecs/jz4740.c:393: error: implicit declaration of function 'iounmap' make[3]: *** [sound/soc/codecs/jz4740.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/jz4740.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index e373f8f06907..3e1f4e172bfb 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -15,6 +15,7 @@ #include #include #include +#include #include -- cgit From f8f626f537aee0da878d287e0d7694b7b76d599a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 6 Dec 2011 15:38:51 +0800 Subject: ASoC: Fix build dependency for SND_SOC_JZ4740_CODEC Currently SND_SOC_JZ4740_CODEC depends on SOC_JZ4740 but SOC_JZ4740 is not defined in any Kconfig. Thus the codec driver will not be built when select "Build all ASoC CODEC drivers". (Unless it is selected by SND_JZ4740_SOC_QI_LB60). Remove the dependency with SOC_JZ4740, then this code driver can be built when select "Build all ASoC CODEC drivers". Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4584514d93d4..fa787d45d74a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -33,7 +33,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CX20442 select SND_SOC_DA7210 if I2C select SND_SOC_DFBMCS320 - select SND_SOC_JZ4740_CODEC if SOC_JZ4740 + select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C select SND_SOC_MAX98088 if I2C select SND_SOC_MAX98095 if I2C -- cgit From 974c07249b06d948154be3275bf4f6e55b585300 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 2 Dec 2011 23:09:42 +0100 Subject: ARM: 7186/1: fix Kconfig issue with PHYS_OFFSET and !MMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1b9f95f8ade9 (ARM: prepare for removal of a bunch of files) introduced CONFIG_PHYS_OFFSET but the Kconfig hex prompt did not provide a default value. This has the undesired side effect of breaking a reportedly used trick for updating defconfigs on the fly for routine buildtesting across all arch and all platforms, i.e. cp /path/to/somedefconfig .config ; yes "" | make oldconfig because the config system will endlessly loop until a valid address is provided. However we can't just pick a random default value since it is likely to be wrong for the majority of the boards as the right answer for this option is quite varied. So the fact that the config system insists on having a proper value be entered is actually a good thing. It turns out that only at91x40_defconfig has this problem because it has CONFIG_MMU=n. However, in the !MMU case, there is already a CONFIG_DRAM_BASE value that can be used here. So let's use that as a default in that case and suppress the redundant CONFIG_PHYS_OFFSET prompt. Eventually the DRAM_BASE config option could simply be replaced by PHYS_OFFSET directly, but that's a larger change better suited for later. Reported-by: Paul Gortmaker Signed-off-by: Nicolas Pitre Acked-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e084b7e981e8..776d76b8cb69 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -220,8 +220,9 @@ config NEED_MACH_MEMORY_H be avoided when possible. config PHYS_OFFSET - hex "Physical address of main memory" + hex "Physical address of main memory" if MMU depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H + default DRAM_BASE if !MMU help Please provide the physical address corresponding to the location of main memory in your system. -- cgit From de66a979012dbc66b1ec0125795a3f79ee667b8a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 5 Dec 2011 09:39:59 +0100 Subject: ARM: 7187/1: fix unwinding for XIP kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The linker places the unwind tables in readonly sections. So when using an XIP kernel these are located in ROM and cannot be modified. For that reason the current approach to convert the relative offsets in the unwind index to absolute addresses early in the boot process doesn't work with XIP. The offsets in the unwind index section are signed 31 bit numbers and the structs are sorted by this offset. So it first has offsets between 0x40000000 and 0x7fffffff (i.e. the negative offsets) and then offsets between 0x00000000 and 0x3fffffff. When seperating these two blocks the numbers are sorted even when interpreting the offsets as unsigned longs. So determine the first non-negative entry once and track that using the new origin pointer. The actual bisection can then use a plain unsigned long comparison. The only thing that makes the new bisection more complicated is that the offsets are relative to their position in the index section, so the key to search needs to be adapted accordingly in each step. Moreover several consts are added to catch future writes and rename the member "addr" of struct unwind_idx to "addr_offset" to better match the new semantic. (This has the additional benefit of breaking eventual users at compile time to make them aware of the change.) In my tests the new algorithm was a tad faster than the original and has the additional upside of not needing the initial conversion and so saves some boot time and it's possible to unwind even earlier. Acked-by: Catalin Marinas Acked-by: Nicolas Pitre Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/include/asm/unwind.h | 16 ++---- arch/arm/kernel/setup.c | 2 - arch/arm/kernel/unwind.c | 129 +++++++++++++++++++++++++++--------------- 3 files changed, 88 insertions(+), 59 deletions(-) diff --git a/arch/arm/include/asm/unwind.h b/arch/arm/include/asm/unwind.h index a5edf421005c..d1c3f3a71c94 100644 --- a/arch/arm/include/asm/unwind.h +++ b/arch/arm/include/asm/unwind.h @@ -30,14 +30,15 @@ enum unwind_reason_code { }; struct unwind_idx { - unsigned long addr; + unsigned long addr_offset; unsigned long insn; }; struct unwind_table { struct list_head list; - struct unwind_idx *start; - struct unwind_idx *stop; + const struct unwind_idx *start; + const struct unwind_idx *origin; + const struct unwind_idx *stop; unsigned long begin_addr; unsigned long end_addr; }; @@ -49,15 +50,6 @@ extern struct unwind_table *unwind_table_add(unsigned long start, extern void unwind_table_del(struct unwind_table *tab); extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk); -#ifdef CONFIG_ARM_UNWIND -extern int __init unwind_init(void); -#else -static inline int __init unwind_init(void) -{ - return 0; -} -#endif - #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_ARM_UNWIND diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 3448a3f9cc8c..1bdd0adbb7dd 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -895,8 +895,6 @@ void __init setup_arch(char **cmdline_p) { struct machine_desc *mdesc; - unwind_init(); - setup_processor(); mdesc = setup_machine_fdt(__atags_pointer); if (!mdesc) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index e7e8365795c3..3f03fe0c3269 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); struct unwind_ctrl_block { unsigned long vrs[16]; /* virtual register set */ - unsigned long *insn; /* pointer to the current instructions word */ + const unsigned long *insn; /* pointer to the current instructions word */ int entries; /* number of entries left to interpret */ int byte; /* current byte number in the instructions word */ }; @@ -83,8 +83,9 @@ enum regs { PC = 15 }; -extern struct unwind_idx __start_unwind_idx[]; -extern struct unwind_idx __stop_unwind_idx[]; +extern const struct unwind_idx __start_unwind_idx[]; +static const struct unwind_idx *__origin_unwind_idx; +extern const struct unwind_idx __stop_unwind_idx[]; static DEFINE_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); @@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables); }) /* - * Binary search in the unwind index. The entries entries are + * Binary search in the unwind index. The entries are * guaranteed to be sorted in ascending order by the linker. + * + * start = first entry + * origin = first entry with positive offset (or stop if there is no such entry) + * stop - 1 = last entry */ -static struct unwind_idx *search_index(unsigned long addr, - struct unwind_idx *first, - struct unwind_idx *last) +static const struct unwind_idx *search_index(unsigned long addr, + const struct unwind_idx *start, + const struct unwind_idx *origin, + const struct unwind_idx *stop) { - pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last); + unsigned long addr_prel31; + + pr_debug("%s(%08lx, %p, %p, %p)\n", + __func__, addr, start, origin, stop); + + /* + * only search in the section with the matching sign. This way the + * prel31 numbers can be compared as unsigned longs. + */ + if (addr < (unsigned long)start) + /* negative offsets: [start; origin) */ + stop = origin; + else + /* positive offsets: [origin; stop) */ + start = origin; + + /* prel31 for address relavive to start */ + addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; - if (addr < first->addr) { + while (start < stop - 1) { + const struct unwind_idx *mid = start + ((stop - start) >> 1); + + /* + * As addr_prel31 is relative to start an offset is needed to + * make it relative to mid. + */ + if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < + mid->addr_offset) + stop = mid; + else { + /* keep addr_prel31 relative to start */ + addr_prel31 -= ((unsigned long)mid - + (unsigned long)start); + start = mid; + } + } + + if (likely(start->addr_offset <= addr_prel31)) + return start; + else { pr_warning("unwind: Unknown symbol address %08lx\n", addr); return NULL; - } else if (addr >= last->addr) - return last; + } +} - while (first < last - 1) { - struct unwind_idx *mid = first + ((last - first + 1) >> 1); +static const struct unwind_idx *unwind_find_origin( + const struct unwind_idx *start, const struct unwind_idx *stop) +{ + pr_debug("%s(%p, %p)\n", __func__, start, stop); + while (start < stop - 1) { + const struct unwind_idx *mid = start + ((stop - start) >> 1); - if (addr < mid->addr) - last = mid; + if (mid->addr_offset >= 0x40000000) + /* negative offset */ + start = mid; else - first = mid; + /* positive offset */ + stop = mid; } - - return first; + pr_debug("%s -> %p\n", __func__, stop); + return stop; } -static struct unwind_idx *unwind_find_idx(unsigned long addr) +static const struct unwind_idx *unwind_find_idx(unsigned long addr) { - struct unwind_idx *idx = NULL; + const struct unwind_idx *idx = NULL; unsigned long flags; pr_debug("%s(%08lx)\n", __func__, addr); - if (core_kernel_text(addr)) + if (core_kernel_text(addr)) { + if (unlikely(!__origin_unwind_idx)) + __origin_unwind_idx = + unwind_find_origin(__start_unwind_idx, + __stop_unwind_idx); + /* main unwind table */ idx = search_index(addr, __start_unwind_idx, - __stop_unwind_idx - 1); - else { + __origin_unwind_idx, + __stop_unwind_idx); + } else { /* module unwind tables */ struct unwind_table *table; @@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr) if (addr >= table->begin_addr && addr < table->end_addr) { idx = search_index(addr, table->start, - table->stop - 1); + table->origin, + table->stop); /* Move-to-front to exploit common traces */ list_move(&table->list, &unwind_tables); break; @@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) int unwind_frame(struct stackframe *frame) { unsigned long high, low; - struct unwind_idx *idx; + const struct unwind_idx *idx; struct unwind_ctrl_block ctrl; /* only go to a higher address on the stack */ @@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, unsigned long text_size) { unsigned long flags; - struct unwind_idx *idx; struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, @@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, if (!tab) return tab; - tab->start = (struct unwind_idx *)start; - tab->stop = (struct unwind_idx *)(start + size); + tab->start = (const struct unwind_idx *)start; + tab->stop = (const struct unwind_idx *)(start + size); + tab->origin = unwind_find_origin(tab->start, tab->stop); tab->begin_addr = text_addr; tab->end_addr = text_addr + text_size; - /* Convert the symbol addresses to absolute values */ - for (idx = tab->start; idx < tab->stop; idx++) - idx->addr = prel31_to_addr(&idx->addr); - spin_lock_irqsave(&unwind_lock, flags); list_add_tail(&tab->list, &unwind_tables); spin_unlock_irqrestore(&unwind_lock, flags); @@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_table *tab) kfree(tab); } - -int __init unwind_init(void) -{ - struct unwind_idx *idx; - - /* Convert the symbol addresses to absolute values */ - for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++) - idx->addr = prel31_to_addr(&idx->addr); - - pr_debug("unwind: ARM stack unwinding initialised\n"); - - return 0; -} -- cgit From 6340cfed48c478cf67451ddcd2daa3438e642632 Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Mon, 28 Nov 2011 12:03:29 +0300 Subject: perf header: Use event_name() to get an event name perf_evsel.name may be not initialized Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Arun Sharma Cc: devel@openvz.org Link: http://lkml.kernel.org/r/1322471015-107825-2-git-send-email-avagin@openvz.org Signed-off-by: Andrew Vagin Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index bcd05d05b4f0..33c17a2b2a81 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -388,7 +388,7 @@ static int write_event_desc(int fd, struct perf_header *h __used, /* * write event string as passed on cmdline */ - ret = do_write_string(fd, attr->name); + ret = do_write_string(fd, event_name(attr)); if (ret < 0) return ret; /* -- cgit From f1a73746c6664442082e3d53e1804f46e1910436 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 4 Dec 2011 13:44:06 +0100 Subject: ALSA: hda - Fix GPIO LED setup for IDT 92HD75 codecs Some HP laptops with IDT 92HD75 codecs may use a GPIO > 4 for the mute LED, but currently the driver doesn't check this properly, and confuses the mute LED behavior. This ended up with the silent output on some HP laptops due to having another GPIO used as external amp control. This patch fixes the problem by checking the max GPIO count and comparing with the given value from DMI entry instead of magic fixed value 4 and 8, and adding a new field to indicate the VREF mute-LED behavior. Reported-and-tested-by: Vitaliy Kulikov Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 45 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548e..e035cf6de278 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -215,6 +215,7 @@ struct sigmatel_spec { unsigned int gpio_mute; unsigned int gpio_led; unsigned int gpio_led_polarity; + unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ unsigned int vref_led; /* stream */ @@ -4318,12 +4319,10 @@ static void stac_store_hints(struct hda_codec *codec) spec->eapd_switch = val; get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { - if (spec->gpio_led <= 8) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - if (spec->gpio_led_polarity) - spec->gpio_data |= spec->gpio_led; - } + spec->gpio_mask |= spec->gpio_led; + spec->gpio_dir |= spec->gpio_led; + if (spec->gpio_led_polarity) + spec->gpio_data |= spec->gpio_led; } } @@ -4913,8 +4912,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &spec->gpio_led_polarity, &spec->gpio_led) == 2) { - if (spec->gpio_led < 4) + unsigned int max_gpio; + max_gpio = snd_hda_param_read(codec, codec->afg, + AC_PAR_GPIO_CAP); + max_gpio &= AC_GPIO_IO_COUNT; + if (spec->gpio_led < max_gpio) spec->gpio_led = 1 << spec->gpio_led; + else + spec->vref_mute_led_nid = spec->gpio_led; return 1; } if (sscanf(dev->name, "HP_Mute_LED_%d", @@ -5043,15 +5048,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; /* sync mute LED */ - if (spec->gpio_led) { - if (spec->gpio_led <= 8) { - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - } else { - stac_vrefout_set(codec, - spec->gpio_led, spec->vref_led); - } - } + if (spec->vref_mute_led_nid) + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); + else if (spec->gpio_led) + stac_gpio_set(codec, spec->gpio_mask, + spec->gpio_dir, spec->gpio_data); return 0; } @@ -5076,7 +5078,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, struct sigmatel_spec *spec = codec->spec; if (power_state == AC_PWRST_D3) { - if (spec->gpio_led > 8) { + if (spec->vref_mute_led_nid) { /* with vref-out pin used for mute led control * codec AFG is prevented from D3 state */ @@ -5129,7 +5131,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) } } /*polarity defines *not* muted state level*/ - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else @@ -5147,7 +5149,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) muted_lvl = spec->gpio_led_polarity ? AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; - stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); } return 0; } @@ -5661,7 +5664,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; @@ -5976,7 +5979,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; -- cgit From a020428364485751b607105c8f5a608f9b1fd38b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Dec 2011 13:17:23 +0100 Subject: ALSA: hda - Fix remaining VREF mute-LED NID check in post-3.1 changes Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ea1f157ca38b..eeb25d529e30 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4442,7 +4442,7 @@ static int stac92xx_init(struct hda_codec *codec) /* power on when no jack detection is available */ /* or when the VREF is used for controlling LED */ if (!spec->hp_detect || - (spec->gpio_led > 8 && spec->gpio_led == nid)) { + spec->vref_mute_led_nid == nid) { stac_toggle_power_map(codec, nid, 1); continue; } -- cgit From 6bd054096dce061560cee0e016e292e588dc438f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 Dec 2011 18:16:01 +0100 Subject: ARM: 7185/1: perf: don't assign platform_device on unsupported CPUs In the unlikely case that a platform registers a PMU platform_device when running on a CPU that is unsupported by perf, we will encounter a NULL dereference when trying to assign the platform_device to the cpu_pmu structure. This patch checks that the CPU is supported by perf before assigning the platform_device. Reported-by: Pawel Moll Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/perf_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 8e9c98edc068..88b0941ce51e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -640,6 +640,9 @@ static struct platform_device_id armpmu_plat_device_ids[] = { static int __devinit armpmu_device_probe(struct platform_device *pdev) { + if (!cpu_pmu) + return -ENODEV; + cpu_pmu->plat_device = pdev; return 0; } -- cgit From 4e2b1c4f56227c742bbd2ea8e8f559567eb80c3f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 6 Dec 2011 13:28:22 +0000 Subject: x86/intel_mid: Kconfig select fix If we select a symbol it should have a type declared first otherwise in some situations the config tools get upset. They are currently perhaps a bit too resilient which is why this wasn't noticed initially. Signed-off-by: Alan Cox Link: http://lkml.kernel.org/r/20111206132811.4041.32549.stgit@bob.linux.org.uk Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5553f9f1a70d..efb42949cc09 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -401,6 +401,9 @@ config X86_WANT_INTEL_MID if X86_WANT_INTEL_MID +config X86_INTEL_MID + bool + config X86_MRST bool "Moorestown MID platform" depends on PCI -- cgit From 89e0b9a3fd66d72f2d7b7f2d6d86fa56997cde27 Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Mon, 5 Dec 2011 23:08:32 +0100 Subject: iommu/amd: Fix typo in kernel-parameters.txt Signed-off-by: Sedat Dilek Signed-off-by: Joerg Roedel --- Documentation/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a0c5c5f4fce6..da5037766eed 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -320,7 +320,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. on: enable for both 32- and 64-bit processes off: disable for both 32- and 64-bit processes - amd_iommu= [HW,X86-84] + amd_iommu= [HW,X86-64] Pass parameters to the AMD IOMMU driver in the system. Possible values are: fullflush - enable flushing of IO/TLB entries when -- cgit From c29f7d457ac63311feb11928a866efd2fe153d74 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 30 Nov 2011 08:58:18 +0000 Subject: xfs: fix nfs export of 64-bit inodes numbers on 32-bit kernels The i_ino field in the VFS inode is of type unsigned long and thus can't hold the full 64-bit inode number on 32-bit kernels. We have the full inode number in the XFS inode, so use that one for nfs exports. Note that I've also switched the 32-bit file handles types to it, just to make the code more consistent and copy & paste errors less likely to happen. Reported-by: Guoquan Yang Reported-by: Hank Peng Signed-off-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_export.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index da108977b21f..558910f5e3c0 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -98,22 +98,22 @@ xfs_fs_encode_fh( switch (fileid_type) { case FILEID_INO32_GEN_PARENT: spin_lock(&dentry->d_lock); - fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino; + fid->i32.parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; spin_unlock(&dentry->d_lock); /*FALLTHRU*/ case FILEID_INO32_GEN: - fid->i32.ino = inode->i_ino; + fid->i32.ino = XFS_I(inode)->i_ino; fid->i32.gen = inode->i_generation; break; case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: spin_lock(&dentry->d_lock); - fid64->parent_ino = dentry->d_parent->d_inode->i_ino; + fid64->parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; fid64->parent_gen = dentry->d_parent->d_inode->i_generation; spin_unlock(&dentry->d_lock); /*FALLTHRU*/ case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: - fid64->ino = inode->i_ino; + fid64->ino = XFS_I(inode)->i_ino; fid64->gen = inode->i_generation; break; } -- cgit From a33caeb118198286309859f014c0662f3ed54ed4 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 9 Nov 2011 16:04:51 +0800 Subject: lockdep, kmemcheck: Annotate ->lock in lockdep_init_map() Since commit f59de89 ("lockdep: Clear whole lockdep_map on initialization"), lockdep_init_map() will clear all the struct. But it will break lock_set_class()/lock_set_subclass(). A typical race condition is like below: CPU A CPU B lock_set_subclass(lockA); lock_set_class(lockA); lockdep_init_map(lockA); /* lockA->name is cleared */ memset(lockA); __lock_acquire(lockA); /* lockA->class_cache[] is cleared */ register_lock_class(lockA); look_up_lock_class(lockA); WARN_ON_ONCE(class->name != lock->name); lock->name = name; So restore to what we have done before commit f59de89 but annotate ->lock with kmemcheck_mark_initialized() to suppress the kmemcheck warning reported in commit f59de89. Reported-by: Sergey Senozhatsky Reported-by: Borislav Petkov Suggested-by: Vegard Nossum Signed-off-by: Yong Zhang Cc: Tejun Heo Cc: David Rientjes Cc: Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111109080451.GB8124@zhy Signed-off-by: Ingo Molnar --- kernel/lockdep.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index e69434b070da..b2e08c932d91 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -2948,7 +2949,12 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, void lockdep_init_map(struct lockdep_map *lock, const char *name, struct lock_class_key *key, int subclass) { - memset(lock, 0, sizeof(*lock)); + int i; + + kmemcheck_mark_initialized(lock, sizeof(*lock)); + + for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++) + lock->class_cache[i] = NULL; #ifdef CONFIG_LOCK_STAT lock->cpu = raw_smp_processor_id(); -- cgit From 99b53bdd810611cc178e1a86bc112d8f4f56a1e9 Mon Sep 17 00:00:00 2001 From: "Peter Pan(潘卫平)" Date: Mon, 5 Dec 2011 21:39:41 +0000 Subject: ipv4:correct description for tcp_max_syn_backlog Since commit c5ed63d66f24(tcp: fix three tcp sysctls tuning), sysctl_max_syn_backlog is determined by tcp_hashinfo->ehash_mask, and the minimal value is 128, and it will increase in proportion to the memory of machine. The original description for tcp_max_syn_backlog and sysctl_max_syn_backlog are out of date. Changelog: V2: update description for sysctl_max_syn_backlog Signed-off-by: Weiping Pan Reviewed-by: Shan Wei Acked-by: Neil Horman Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 10 +++++----- net/core/request_sock.c | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index f049a1ca186f..589f2da5d545 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -282,11 +282,11 @@ tcp_max_ssthresh - INTEGER Default: 0 (off) tcp_max_syn_backlog - INTEGER - Maximal number of remembered connection requests, which are - still did not receive an acknowledgment from connecting client. - Default value is 1024 for systems with more than 128Mb of memory, - and 128 for low memory machines. If server suffers of overload, - try to increase this number. + Maximal number of remembered connection requests, which have not + received an acknowledgment from connecting client. + The minimal value is 128 for low memory machines, and it will + increase in proportion to the memory of machine. + If server suffers from overload, try increasing this number. tcp_max_tw_buckets - INTEGER Maximal number of timewait sockets held by system simultaneously. diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 182236b2510a..9b570a6a33c5 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -26,10 +26,11 @@ * but then some measure against one socket starving all other sockets * would be needed. * - * It was 128 by default. Experiments with real servers show, that + * The minimum value of it is 128. Experiments with real servers show that * it is absolutely not enough even at 100conn/sec. 256 cures most - * of problems. This value is adjusted to 128 for very small machines - * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb). + * of problems. + * This value is adjusted to 128 for low memory machines, + * and it will increase in proportion to the memory of machine. * Note : Dont forget somaxconn that may limit backlog too. */ int sysctl_max_syn_backlog = 256; -- cgit From 4af3ce0de0c12e5c17811eaefad36ab8e146c0fd Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 6 Dec 2011 10:47:37 -0800 Subject: IB/mlx4: Fix shutdown crash accessing a non-existent bitmap Commit cfcde11c3d7a ("IB/mlx4: Use flow counters on IBoE ports") added code that sets elements of counters[] to -1 if no counter is allocated, but then goes ahead and passes every entry to mlx4_counter_free() on shutdown. This is a bad idea, especially if MLX4_DEV_CAP_FLAG_COUNTERS isn't set so there isn't even an underlying bitmap to free from. Tested-by: Sean Hefty Cc: Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 77f3dbc0aaa1..18836cdf1e10 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1244,7 +1244,8 @@ err_reg: err_counter: for (; i; --i) - mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]); + if (ibdev->counters[i - 1] != -1) + mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]); err_map: iounmap(ibdev->uar_map); @@ -1275,7 +1276,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) } iounmap(ibdev->uar_map); for (p = 0; p < ibdev->num_ports; ++p) - mlx4_counter_free(ibdev->dev, ibdev->counters[p]); + if (ibdev->counters[p] != -1) + mlx4_counter_free(ibdev->dev, ibdev->counters[p]); mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB) mlx4_CLOSE_PORT(dev, p); -- cgit From 681090902eeb459a829f6f93d378a82011af3c89 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 6 Dec 2011 08:04:40 +0000 Subject: net: Silence seq_scale() unused warning On a CONFIG_NET=y build net/core/secure_seq.c:22: warning: 'seq_scale' defined but not used Signed-off-by: Stephen Boyd Signed-off-by: David S. Miller --- net/core/secure_seq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 025233de25f9..925991ae6f52 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -19,6 +19,7 @@ static int __init net_secret_init(void) } late_initcall(net_secret_init); +#ifdef CONFIG_INET static u32 seq_scale(u32 seq) { /* @@ -33,6 +34,7 @@ static u32 seq_scale(u32 seq) */ return seq + (ktime_to_ns(ktime_get_real()) >> 6); } +#endif #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, -- cgit From 03fc3070457dc0e6a717a2e732af93ef1cb2ae51 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 4 Dec 2011 12:26:50 +0100 Subject: batman-adv: in case of roaming mark the client with TT_CLIENT_ROAM In case of a client roaming from node A to node B, the latter have to mark the corresponding global entry with TT_CLIENT_ROAM (instead of TT_CLIENT_PENDING). Marking a global entry with TT_CLIENT_PENDING will end up in keeping such entry forever (because this flag is only meant to be used with local entries and it is never checked on global ones). In the worst case (all the clients roaming to the same node A) the local and the global table will contain exactly the same clients. Batman-adv will continue to work, but the memory usage is duplicated. Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c7aafc7c5ed4..c46b1407c885 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -245,9 +245,11 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, if (tt_global_entry) { /* This node is probably going to update its tt table */ tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as PENDING and has to be + /* The global entry has to be marked as ROAMING and has to be * kept for consistency purpose */ - tt_global_entry->flags |= TT_CLIENT_PENDING; + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + send_roam_adv(bat_priv, tt_global_entry->addr, tt_global_entry->orig_node); } -- cgit From 797399b415b78dacdbcaffdb89e46e369ec88b98 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 4 Dec 2011 22:38:27 +0100 Subject: batman-adv: delete global entry in case of roaming When receiving a DEL change for a client due to a roaming event (change is marked with TT_CLIENT_ROAM), each node has to check if the client roamed to itself or somewhere else. In the latter case the global entry is kept to avoid having no route at all otherwise we can safely delete the global entry Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c46b1407c885..5f09a578d49d 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -696,6 +696,7 @@ void tt_global_del(struct bat_priv *bat_priv, const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; + struct tt_local_entry *tt_local_entry = NULL; tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) @@ -703,15 +704,29 @@ void tt_global_del(struct bat_priv *bat_priv, if (tt_global_entry->orig_node == orig_node) { if (roaming) { - tt_global_entry->flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; + /* if we are deleting a global entry due to a roam + * event, there are two possibilities: + * 1) the client roamed from node A to node B => we mark + * it with TT_CLIENT_ROAM, we start a timer and we + * wait for node B to claim it. In case of timeout + * the entry is purged. + * 2) the client roamed to us => we can directly delete + * the global entry, since it is useless now. */ + tt_local_entry = tt_local_hash_find(bat_priv, + tt_global_entry->addr); + if (!tt_local_entry) { + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + goto out; + } } _tt_global_del(bat_priv, tt_global_entry, message); } out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); } void tt_global_del_orig(struct bat_priv *bat_priv, -- cgit From 5bf1e97dc34bf09643815ed48be3d1761a5985e1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Nov 2011 22:22:49 +0100 Subject: m68k: Wire up process_vm_{read,write}v Signed-off-by: Geert Uytterhoeven Acked-by: Greg Ungerer --- arch/m68k/include/asm/unistd.h | 4 +++- arch/m68k/kernel/syscalltable.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 43f984e93970..303192fc9260 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -350,10 +350,12 @@ #define __NR_clock_adjtime 342 #define __NR_syncfs 343 #define __NR_setns 344 +#define __NR_process_vm_readv 345 +#define __NR_process_vm_writev 346 #ifdef __KERNEL__ -#define NR_syscalls 345 +#define NR_syscalls 347 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index c468f2edaa85..ce827b376110 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -365,4 +365,6 @@ ENTRY(sys_call_table) .long sys_clock_adjtime .long sys_syncfs .long sys_setns + .long sys_process_vm_readv /* 345 */ + .long sys_process_vm_writev -- cgit From 162d12de656bc76786ba5fad6dac7bd238de9657 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 4 Dec 2011 08:38:54 +0100 Subject: ath9k: fix check for antenna diversity support fixes a regression on single-stream chips introduced in commit 43c3528430bd29f5e52438cad7cf7c0c62bf4583 "ath9k: implement .get_antenna and .set_antenna" Signed-off-by: Felix Fietkau Reported-by: Marek Lindner Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 93fbe6f40898..d2348a5a7809 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -286,7 +286,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath_start_ani(common); } - if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) { + if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { struct ath_hw_antcomb_conf div_ant_conf; u8 lna_conf; -- cgit From 9f9c19ec1a59422c7687b11847ed3408128aa0d6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Nov 2011 08:17:36 +0000 Subject: xfs: fix the logspace waiting algorithm Apply the scheme used in log_regrant_write_log_space to wake up any other threads waiting for log space before the newly added one to log_regrant_write_log_space as well, and factor the code into readable helpers. For each of the queues we have add two helpers: - one to try to wake up all waiting threads. This helper will also be usable by xfs_log_move_tail once we remove the current opportunistic wakeups in it. - one to sleep on t_wait until enough log space is available, loosely modelled after Linux waitqueues. And use them to reimplement the guts of log_regrant_write_log_space and log_regrant_write_log_space. These two function now use one and the same algorithm for waiting on log space instead of subtly different ones before, with an option to completely unify them in the near future. Also move the filesystem shutdown handling to the common caller given that we had to touch it anyway. Based on hard debugging and an earlier patch from Chandra Seetharaman . Signed-off-by: Christoph Hellwig Reviewed-by: Chandra Seetharaman Tested-by: Chandra Seetharaman Signed-off-by: Ben Myers --- fs/xfs/xfs_log.c | 348 ++++++++++++++++++++++++++--------------------------- fs/xfs/xfs_trace.h | 12 +- 2 files changed, 177 insertions(+), 183 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index a14cd89fe465..34817adf4b9e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -150,6 +150,117 @@ xlog_grant_add_space( } while (head_val != old); } +STATIC bool +xlog_reserveq_wake( + struct log *log, + int *free_bytes) +{ + struct xlog_ticket *tic; + int need_bytes; + + list_for_each_entry(tic, &log->l_reserveq, t_queue) { + if (tic->t_flags & XLOG_TIC_PERM_RESERV) + need_bytes = tic->t_unit_res * tic->t_cnt; + else + need_bytes = tic->t_unit_res; + + if (*free_bytes < need_bytes) + return false; + *free_bytes -= need_bytes; + + trace_xfs_log_grant_wake_up(log, tic); + wake_up(&tic->t_wait); + } + + return true; +} + +STATIC bool +xlog_writeq_wake( + struct log *log, + int *free_bytes) +{ + struct xlog_ticket *tic; + int need_bytes; + + list_for_each_entry(tic, &log->l_writeq, t_queue) { + ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); + + need_bytes = tic->t_unit_res; + + if (*free_bytes < need_bytes) + return false; + *free_bytes -= need_bytes; + + trace_xfs_log_regrant_write_wake_up(log, tic); + wake_up(&tic->t_wait); + } + + return true; +} + +STATIC int +xlog_reserveq_wait( + struct log *log, + struct xlog_ticket *tic, + int need_bytes) +{ + list_add_tail(&tic->t_queue, &log->l_reserveq); + + do { + if (XLOG_FORCED_SHUTDOWN(log)) + goto shutdown; + xlog_grant_push_ail(log, need_bytes); + + XFS_STATS_INC(xs_sleep_logspace); + trace_xfs_log_grant_sleep(log, tic); + + xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); + trace_xfs_log_grant_wake(log, tic); + + spin_lock(&log->l_grant_reserve_lock); + if (XLOG_FORCED_SHUTDOWN(log)) + goto shutdown; + } while (xlog_space_left(log, &log->l_grant_reserve_head) < need_bytes); + + list_del_init(&tic->t_queue); + return 0; +shutdown: + list_del_init(&tic->t_queue); + return XFS_ERROR(EIO); +} + +STATIC int +xlog_writeq_wait( + struct log *log, + struct xlog_ticket *tic, + int need_bytes) +{ + list_add_tail(&tic->t_queue, &log->l_writeq); + + do { + if (XLOG_FORCED_SHUTDOWN(log)) + goto shutdown; + xlog_grant_push_ail(log, need_bytes); + + XFS_STATS_INC(xs_sleep_logspace); + trace_xfs_log_regrant_write_sleep(log, tic); + + xlog_wait(&tic->t_wait, &log->l_grant_write_lock); + trace_xfs_log_regrant_write_wake(log, tic); + + spin_lock(&log->l_grant_write_lock); + if (XLOG_FORCED_SHUTDOWN(log)) + goto shutdown; + } while (xlog_space_left(log, &log->l_grant_write_head) < need_bytes); + + list_del_init(&tic->t_queue); + return 0; +shutdown: + list_del_init(&tic->t_queue); + return XFS_ERROR(EIO); +} + static void xlog_tic_reset_res(xlog_ticket_t *tic) { @@ -350,8 +461,19 @@ xfs_log_reserve( retval = xlog_grant_log_space(log, internal_ticket); } + if (unlikely(retval)) { + /* + * If we are failing, make sure the ticket doesn't have any + * current reservations. We don't want to add this back + * when the ticket/ transaction gets cancelled. + */ + internal_ticket->t_curr_res = 0; + /* ungrant will give back unit_res * t_cnt. */ + internal_ticket->t_cnt = 0; + } + return retval; -} /* xfs_log_reserve */ +} /* @@ -2481,8 +2603,8 @@ restart: /* * Atomically get the log space required for a log ticket. * - * Once a ticket gets put onto the reserveq, it will only return after - * the needed reservation is satisfied. + * Once a ticket gets put onto the reserveq, it will only return after the + * needed reservation is satisfied. * * This function is structured so that it has a lock free fast path. This is * necessary because every new transaction reservation will come through this @@ -2490,113 +2612,53 @@ restart: * every pass. * * As tickets are only ever moved on and off the reserveq under the - * l_grant_reserve_lock, we only need to take that lock if we are going - * to add the ticket to the queue and sleep. We can avoid taking the lock if the - * ticket was never added to the reserveq because the t_queue list head will be - * empty and we hold the only reference to it so it can safely be checked - * unlocked. + * l_grant_reserve_lock, we only need to take that lock if we are going to add + * the ticket to the queue and sleep. We can avoid taking the lock if the ticket + * was never added to the reserveq because the t_queue list head will be empty + * and we hold the only reference to it so it can safely be checked unlocked. */ STATIC int -xlog_grant_log_space(xlog_t *log, - xlog_ticket_t *tic) +xlog_grant_log_space( + struct log *log, + struct xlog_ticket *tic) { - int free_bytes; - int need_bytes; + int free_bytes, need_bytes; + int error = 0; -#ifdef DEBUG - if (log->l_flags & XLOG_ACTIVE_RECOVERY) - panic("grant Recovery problem"); -#endif + ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY)); trace_xfs_log_grant_enter(log, tic); + /* + * If there are other waiters on the queue then give them a chance at + * logspace before us. Wake up the first waiters, if we do not wake + * up all the waiters then go to sleep waiting for more free space, + * otherwise try to get some space for this transaction. + */ need_bytes = tic->t_unit_res; if (tic->t_flags & XFS_LOG_PERM_RESERV) need_bytes *= tic->t_ocnt; - - /* something is already sleeping; insert new transaction at end */ - if (!list_empty_careful(&log->l_reserveq)) { - spin_lock(&log->l_grant_reserve_lock); - /* recheck the queue now we are locked */ - if (list_empty(&log->l_reserveq)) { - spin_unlock(&log->l_grant_reserve_lock); - goto redo; - } - list_add_tail(&tic->t_queue, &log->l_reserveq); - - trace_xfs_log_grant_sleep1(log, tic); - - /* - * Gotta check this before going to sleep, while we're - * holding the grant lock. - */ - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return; - - XFS_STATS_INC(xs_sleep_logspace); - xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); - - /* - * If we got an error, and the filesystem is shutting down, - * we'll catch it down below. So just continue... - */ - trace_xfs_log_grant_wake1(log, tic); - } - -redo: - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return_unlocked; - free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); - if (free_bytes < need_bytes) { + if (!list_empty_careful(&log->l_reserveq)) { spin_lock(&log->l_grant_reserve_lock); - if (list_empty(&tic->t_queue)) - list_add_tail(&tic->t_queue, &log->l_reserveq); - - trace_xfs_log_grant_sleep2(log, tic); - - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return; - - xlog_grant_push_ail(log, need_bytes); - - XFS_STATS_INC(xs_sleep_logspace); - xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); - - trace_xfs_log_grant_wake2(log, tic); - goto redo; - } - - if (!list_empty(&tic->t_queue)) { + if (!xlog_reserveq_wake(log, &free_bytes) || + free_bytes < need_bytes) + error = xlog_reserveq_wait(log, tic, need_bytes); + spin_unlock(&log->l_grant_reserve_lock); + } else if (free_bytes < need_bytes) { spin_lock(&log->l_grant_reserve_lock); - list_del_init(&tic->t_queue); + error = xlog_reserveq_wait(log, tic, need_bytes); spin_unlock(&log->l_grant_reserve_lock); } + if (error) + return error; - /* we've got enough space */ xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); trace_xfs_log_grant_exit(log, tic); xlog_verify_grant_tail(log); return 0; - -error_return_unlocked: - spin_lock(&log->l_grant_reserve_lock); -error_return: - list_del_init(&tic->t_queue); - spin_unlock(&log->l_grant_reserve_lock); - trace_xfs_log_grant_error(log, tic); - - /* - * If we are failing, make sure the ticket doesn't have any - * current reservations. We don't want to add this back when - * the ticket/transaction gets cancelled. - */ - tic->t_curr_res = 0; - tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ - return XFS_ERROR(EIO); -} /* xlog_grant_log_space */ - +} /* * Replenish the byte reservation required by moving the grant write head. @@ -2605,10 +2667,12 @@ error_return: * free fast path. */ STATIC int -xlog_regrant_write_log_space(xlog_t *log, - xlog_ticket_t *tic) +xlog_regrant_write_log_space( + struct log *log, + struct xlog_ticket *tic) { - int free_bytes, need_bytes; + int free_bytes, need_bytes; + int error = 0; tic->t_curr_res = tic->t_unit_res; xlog_tic_reset_res(tic); @@ -2616,104 +2680,38 @@ xlog_regrant_write_log_space(xlog_t *log, if (tic->t_cnt > 0) return 0; -#ifdef DEBUG - if (log->l_flags & XLOG_ACTIVE_RECOVERY) - panic("regrant Recovery problem"); -#endif + ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY)); trace_xfs_log_regrant_write_enter(log, tic); - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return_unlocked; - /* If there are other waiters on the queue then give them a - * chance at logspace before us. Wake up the first waiters, - * if we do not wake up all the waiters then go to sleep waiting - * for more free space, otherwise try to get some space for - * this transaction. + /* + * If there are other waiters on the queue then give them a chance at + * logspace before us. Wake up the first waiters, if we do not wake + * up all the waiters then go to sleep waiting for more free space, + * otherwise try to get some space for this transaction. */ need_bytes = tic->t_unit_res; - if (!list_empty_careful(&log->l_writeq)) { - struct xlog_ticket *ntic; - - spin_lock(&log->l_grant_write_lock); - free_bytes = xlog_space_left(log, &log->l_grant_write_head); - list_for_each_entry(ntic, &log->l_writeq, t_queue) { - ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); - - if (free_bytes < ntic->t_unit_res) - break; - free_bytes -= ntic->t_unit_res; - wake_up(&ntic->t_wait); - } - - if (ntic != list_first_entry(&log->l_writeq, - struct xlog_ticket, t_queue)) { - if (list_empty(&tic->t_queue)) - list_add_tail(&tic->t_queue, &log->l_writeq); - trace_xfs_log_regrant_write_sleep1(log, tic); - - xlog_grant_push_ail(log, need_bytes); - - XFS_STATS_INC(xs_sleep_logspace); - xlog_wait(&tic->t_wait, &log->l_grant_write_lock); - trace_xfs_log_regrant_write_wake1(log, tic); - } else - spin_unlock(&log->l_grant_write_lock); - } - -redo: - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return_unlocked; - free_bytes = xlog_space_left(log, &log->l_grant_write_head); - if (free_bytes < need_bytes) { + if (!list_empty_careful(&log->l_writeq)) { spin_lock(&log->l_grant_write_lock); - if (list_empty(&tic->t_queue)) - list_add_tail(&tic->t_queue, &log->l_writeq); - - if (XLOG_FORCED_SHUTDOWN(log)) - goto error_return; - - xlog_grant_push_ail(log, need_bytes); - - XFS_STATS_INC(xs_sleep_logspace); - trace_xfs_log_regrant_write_sleep2(log, tic); - xlog_wait(&tic->t_wait, &log->l_grant_write_lock); - - trace_xfs_log_regrant_write_wake2(log, tic); - goto redo; - } - - if (!list_empty(&tic->t_queue)) { + if (!xlog_writeq_wake(log, &free_bytes) || + free_bytes < need_bytes) + error = xlog_writeq_wait(log, tic, need_bytes); + spin_unlock(&log->l_grant_write_lock); + } else if (free_bytes < need_bytes) { spin_lock(&log->l_grant_write_lock); - list_del_init(&tic->t_queue); + error = xlog_writeq_wait(log, tic, need_bytes); spin_unlock(&log->l_grant_write_lock); } - /* we've got enough space */ + if (error) + return error; + xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); trace_xfs_log_regrant_write_exit(log, tic); xlog_verify_grant_tail(log); return 0; - - - error_return_unlocked: - spin_lock(&log->l_grant_write_lock); - error_return: - list_del_init(&tic->t_queue); - spin_unlock(&log->l_grant_write_lock); - trace_xfs_log_regrant_write_error(log, tic); - - /* - * If we are failing, make sure the ticket doesn't have any - * current reservations. We don't want to add this back when - * the ticket/transaction gets cancelled. - */ - tic->t_curr_res = 0; - tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ - return XFS_ERROR(EIO); -} /* xlog_regrant_write_log_space */ - +} /* The first cnt-1 times through here we don't need to * move the grant write head because the permanent diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index f1d2802b2f07..494035798873 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -834,18 +834,14 @@ DEFINE_LOGGRANT_EVENT(xfs_log_umount_write); DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter); DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit); DEFINE_LOGGRANT_EVENT(xfs_log_grant_error); -DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep1); -DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake1); -DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep2); -DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake2); +DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep); +DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake); DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); -DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep1); -DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake1); -DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep2); -DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake2); +DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep); +DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake_up); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); -- cgit From 02125a826459a6ad142f8d91c5b6357562f96615 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 5 Dec 2011 08:43:34 -0500 Subject: fix apparmor dereferencing potentially freed dentry, sanitize __d_path() API __d_path() API is asking for trouble and in case of apparmor d_namespace_path() getting just that. The root cause is that when __d_path() misses the root it had been told to look for, it stores the location of the most remote ancestor in *root. Without grabbing references. Sure, at the moment of call it had been pinned down by what we have in *path. And if we raced with umount -l, we could have very well stopped at vfsmount/dentry that got freed as soon as prepend_path() dropped vfsmount_lock. It is safe to compare these pointers with pre-existing (and known to be still alive) vfsmount and dentry, as long as all we are asking is "is it the same address?". Dereferencing is not safe and apparmor ended up stepping into that. d_namespace_path() really wants to examine the place where we stopped, even if it's not connected to our namespace. As the result, it looked at ->d_sb->s_magic of a dentry that might've been already freed by that point. All other callers had been careful enough to avoid that, but it's really a bad interface - it invites that kind of trouble. The fix is fairly straightforward, even though it's bigger than I'd like: * prepend_path() root argument becomes const. * __d_path() is never called with NULL/NULL root. It was a kludge to start with. Instead, we have an explicit function - d_absolute_root(). Same as __d_path(), except that it doesn't get root passed and stops where it stops. apparmor and tomoyo are using it. * __d_path() returns NULL on path outside of root. The main caller is show_mountinfo() and that's precisely what we pass root for - to skip those outside chroot jail. Those who don't want that can (and do) use d_path(). * __d_path() root argument becomes const. Everyone agrees, I hope. * apparmor does *NOT* try to use __d_path() or any of its variants when it sees that path->mnt is an internal vfsmount. In that case it's definitely not mounted anywhere and dentry_path() is exactly what we want there. Handling of sysctl()-triggered weirdness is moved to that place. * if apparmor is asked to do pathname relative to chroot jail and __d_path() tells it we it's not in that jail, the sucker just calls d_absolute_path() instead. That's the other remaining caller of __d_path(), BTW. * seq_path_root() does _NOT_ return -ENAMETOOLONG (it's stupid anyway - the normal seq_file logics will take care of growing the buffer and redoing the call of ->show() just fine). However, if it gets path not reachable from root, it returns SEQ_SKIP. The only caller adjusted (i.e. stopped ignoring the return value as it used to do). Reviewed-by: John Johansen ACKed-by: John Johansen Signed-off-by: Al Viro Cc: stable@vger.kernel.org --- fs/dcache.c | 71 ++++++++++++++++++++++++++++------------------ fs/namespace.c | 20 +++++++------ fs/seq_file.c | 6 ++-- include/linux/dcache.h | 3 +- include/linux/fs.h | 1 + security/apparmor/path.c | 65 ++++++++++++++++++++++++------------------ security/tomoyo/realpath.c | 3 +- 7 files changed, 100 insertions(+), 69 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 10ba92def3f6..89509b5a090e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2439,16 +2439,14 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) /** * prepend_path - Prepend path string to a buffer * @path: the dentry/vfsmount to report - * @root: root vfsmnt/dentry (may be modified by this function) + * @root: root vfsmnt/dentry * @buffer: pointer to the end of the buffer * @buflen: pointer to buffer length * * Caller holds the rename_lock. - * - * If path is not reachable from the supplied root, then the value of - * root is changed (without modifying refcounts). */ -static int prepend_path(const struct path *path, struct path *root, +static int prepend_path(const struct path *path, + const struct path *root, char **buffer, int *buflen) { struct dentry *dentry = path->dentry; @@ -2483,10 +2481,10 @@ static int prepend_path(const struct path *path, struct path *root, dentry = parent; } -out: if (!error && !slash) error = prepend(buffer, buflen, "/", 1); +out: br_read_unlock(vfsmount_lock); return error; @@ -2500,15 +2498,17 @@ global_root: WARN(1, "Root dentry has weird name <%.*s>\n", (int) dentry->d_name.len, dentry->d_name.name); } - root->mnt = vfsmnt; - root->dentry = dentry; + if (!slash) + error = prepend(buffer, buflen, "/", 1); + if (!error) + error = vfsmnt->mnt_ns ? 1 : 2; goto out; } /** * __d_path - return the path of a dentry * @path: the dentry/vfsmount to report - * @root: root vfsmnt/dentry (may be modified by this function) + * @root: root vfsmnt/dentry * @buf: buffer to return value in * @buflen: buffer length * @@ -2519,10 +2519,10 @@ global_root: * * "buflen" should be positive. * - * If path is not reachable from the supplied root, then the value of - * root is changed (without modifying refcounts). + * If the path is not reachable from the supplied root, return %NULL. */ -char *__d_path(const struct path *path, struct path *root, +char *__d_path(const struct path *path, + const struct path *root, char *buf, int buflen) { char *res = buf + buflen; @@ -2533,7 +2533,28 @@ char *__d_path(const struct path *path, struct path *root, error = prepend_path(path, root, &res, &buflen); write_sequnlock(&rename_lock); - if (error) + if (error < 0) + return ERR_PTR(error); + if (error > 0) + return NULL; + return res; +} + +char *d_absolute_path(const struct path *path, + char *buf, int buflen) +{ + struct path root = {}; + char *res = buf + buflen; + int error; + + prepend(&res, &buflen, "\0", 1); + write_seqlock(&rename_lock); + error = prepend_path(path, &root, &res, &buflen); + write_sequnlock(&rename_lock); + + if (error > 1) + error = -EINVAL; + if (error < 0) return ERR_PTR(error); return res; } @@ -2541,8 +2562,9 @@ char *__d_path(const struct path *path, struct path *root, /* * same as __d_path but appends "(deleted)" for unlinked files. */ -static int path_with_deleted(const struct path *path, struct path *root, - char **buf, int *buflen) +static int path_with_deleted(const struct path *path, + const struct path *root, + char **buf, int *buflen) { prepend(buf, buflen, "\0", 1); if (d_unlinked(path->dentry)) { @@ -2579,7 +2601,6 @@ char *d_path(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; - struct path tmp; int error; /* @@ -2594,9 +2615,8 @@ char *d_path(const struct path *path, char *buf, int buflen) get_fs_root(current->fs, &root); write_seqlock(&rename_lock); - tmp = root; - error = path_with_deleted(path, &tmp, &res, &buflen); - if (error) + error = path_with_deleted(path, &root, &res, &buflen); + if (error < 0) res = ERR_PTR(error); write_sequnlock(&rename_lock); path_put(&root); @@ -2617,7 +2637,6 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; - struct path tmp; int error; if (path->dentry->d_op && path->dentry->d_op->d_dname) @@ -2625,9 +2644,8 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) get_fs_root(current->fs, &root); write_seqlock(&rename_lock); - tmp = root; - error = path_with_deleted(path, &tmp, &res, &buflen); - if (!error && !path_equal(&tmp, &root)) + error = path_with_deleted(path, &root, &res, &buflen); + if (error > 0) error = prepend_unreachable(&res, &buflen); write_sequnlock(&rename_lock); path_put(&root); @@ -2758,19 +2776,18 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) write_seqlock(&rename_lock); if (!d_unlinked(pwd.dentry)) { unsigned long len; - struct path tmp = root; char *cwd = page + PAGE_SIZE; int buflen = PAGE_SIZE; prepend(&cwd, &buflen, "\0", 1); - error = prepend_path(&pwd, &tmp, &cwd, &buflen); + error = prepend_path(&pwd, &root, &cwd, &buflen); write_sequnlock(&rename_lock); - if (error) + if (error < 0) goto out; /* Unreachable from current root */ - if (!path_equal(&tmp, &root)) { + if (error > 0) { error = prepend_unreachable(&cwd, &buflen); if (error) goto out; diff --git a/fs/namespace.c b/fs/namespace.c index 6d3a1963879b..cfc6d4448aa5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1048,15 +1048,12 @@ static int show_mountinfo(struct seq_file *m, void *v) if (err) goto out; seq_putc(m, ' '); - seq_path_root(m, &mnt_path, &root, " \t\n\\"); - if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { - /* - * Mountpoint is outside root, discard that one. Ugly, - * but less so than trying to do that in iterator in a - * race-free way (due to renames). - */ - return SEQ_SKIP; - } + + /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ + err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); + if (err) + goto out; + seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); show_mnt_opts(m, mnt); @@ -2776,3 +2773,8 @@ void kern_unmount(struct vfsmount *mnt) } } EXPORT_SYMBOL(kern_unmount); + +bool our_mnt(struct vfsmount *mnt) +{ + return check_mnt(mnt); +} diff --git a/fs/seq_file.c b/fs/seq_file.c index 05d6b0e78c95..dba43c3ea3af 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -449,8 +449,6 @@ EXPORT_SYMBOL(seq_path); /* * Same as seq_path, but relative to supplied root. - * - * root may be changed, see __d_path(). */ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, char *esc) @@ -463,6 +461,8 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, char *p; p = __d_path(path, root, buf, size); + if (!p) + return SEQ_SKIP; res = PTR_ERR(p); if (!IS_ERR(p)) { char *end = mangle_path(buf, p, esc); @@ -474,7 +474,7 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, } seq_commit(m, res); - return res < 0 ? res : 0; + return res < 0 && res != -ENAMETOOLONG ? res : 0; } /* diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 4df926199369..ed9f74f6c519 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -339,7 +339,8 @@ extern int d_validate(struct dentry *, struct dentry *); */ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char *__d_path(const struct path *path, struct path *root, char *, int); +extern char *__d_path(const struct path *, const struct path *, char *, int); +extern char *d_absolute_path(const struct path *, char *, int); extern char *d_path(const struct path *, char *, int); extern char *d_path_with_unreachable(const struct path *, char *, int); extern char *dentry_path_raw(struct dentry *, char *, int); diff --git a/include/linux/fs.h b/include/linux/fs.h index e3130220ce3e..019dc558df1a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1942,6 +1942,7 @@ extern int fd_statfs(int, struct kstatfs *); extern int statfs_by_dentry(struct dentry *, struct kstatfs *); extern int freeze_super(struct super_block *super); extern int thaw_super(struct super_block *super); +extern bool our_mnt(struct vfsmount *mnt); extern int current_umask(void); diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 36cc0cc39e78..b566eba4a65c 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c @@ -57,23 +57,44 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen) static int d_namespace_path(struct path *path, char *buf, int buflen, char **name, int flags) { - struct path root, tmp; char *res; - int connected, error = 0; + int error = 0; + int connected = 1; + + if (path->mnt->mnt_flags & MNT_INTERNAL) { + /* it's not mounted anywhere */ + res = dentry_path(path->dentry, buf, buflen); + *name = res; + if (IS_ERR(res)) { + *name = buf; + return PTR_ERR(res); + } + if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC && + strncmp(*name, "/sys/", 5) == 0) { + /* TODO: convert over to using a per namespace + * control instead of hard coded /proc + */ + return prepend(name, *name - buf, "/proc", 5); + } + return 0; + } - /* Get the root we want to resolve too, released below */ + /* resolve paths relative to chroot?*/ if (flags & PATH_CHROOT_REL) { - /* resolve paths relative to chroot */ + struct path root; get_fs_root(current->fs, &root); - } else { - /* resolve paths relative to namespace */ - root.mnt = current->nsproxy->mnt_ns->root; - root.dentry = root.mnt->mnt_root; - path_get(&root); + res = __d_path(path, &root, buf, buflen); + if (res && !IS_ERR(res)) { + /* everything's fine */ + *name = res; + path_put(&root); + goto ok; + } + path_put(&root); + connected = 0; } - tmp = root; - res = __d_path(path, &tmp, buf, buflen); + res = d_absolute_path(path, buf, buflen); *name = res; /* handle error conditions - and still allow a partial path to @@ -84,7 +105,10 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, *name = buf; goto out; } + if (!our_mnt(path->mnt)) + connected = 0; +ok: /* Handle two cases: * 1. A deleted dentry && profile is not allowing mediation of deleted * 2. On some filesystems, newly allocated dentries appear to the @@ -97,10 +121,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, goto out; } - /* Determine if the path is connected to the expected root */ - connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt; - - /* If the path is not connected, + /* If the path is not connected to the expected root, * check if it is a sysctl and handle specially else remove any * leading / that __d_path may have returned. * Unless @@ -112,17 +133,9 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, * namespace root. */ if (!connected) { - /* is the disconnect path a sysctl? */ - if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC && - strncmp(*name, "/sys/", 5) == 0) { - /* TODO: convert over to using a per namespace - * control instead of hard coded /proc - */ - error = prepend(name, *name - buf, "/proc", 5); - } else if (!(flags & PATH_CONNECT_PATH) && + if (!(flags & PATH_CONNECT_PATH) && !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && - (tmp.mnt == current->nsproxy->mnt_ns->root && - tmp.dentry == tmp.mnt->mnt_root))) { + our_mnt(path->mnt))) { /* disconnected path, don't return pathname starting * with '/' */ @@ -133,8 +146,6 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, } out: - path_put(&root); - return error; } diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 738bbdf8d4c7..36fa7c9bedc4 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -101,9 +101,8 @@ static char *tomoyo_get_absolute_path(struct path *path, char * const buffer, { char *pos = ERR_PTR(-ENOMEM); if (buflen >= 256) { - struct path ns_root = { }; /* go to whatever namespace root we are under */ - pos = __d_path(path, &ns_root, buffer, buflen - 1); + pos = d_absolute_path(path, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = path->dentry->d_inode; if (inode && S_ISDIR(inode->i_mode)) { -- cgit From 7148b7999277e2794cec90d8cb47d2a238e0bd0d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 11 Nov 2011 17:06:20 +0000 Subject: mtd: pxa2xx-flash.c: It used to fall back to provided table. Make this work again. Signed-off-by: Jonathan Cameron Acked-by: Dmitry Eremin-Solenikov Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/pxa2xx-flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 411a17df9fc1..2a25b6789af4 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -98,7 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) } info->mtd->owner = THIS_MODULE; - mtd_device_parse_register(info->mtd, probes, 0, NULL, 0); + mtd_device_parse_register(info->mtd, probes, 0, flash->parts, flash->nr_parts); platform_set_drvdata(pdev, info); return 0; -- cgit From dc87cd5c264cb587f16459285565830689ecf7a7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 2 Dec 2011 18:15:27 -0500 Subject: drm/radeon/kms: fix return type for radeon_encoder_get_dp_bridge_encoder_id Seems like something got mis-merged here. Noticed by kallisti5 on IRC. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 06e413e6a920..4b27efa4405b 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -233,13 +233,12 @@ u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder) switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_TRAVIS: case ENCODER_OBJECT_ID_NUTMEG: - return true; + return radeon_encoder->encoder_id; default: - return false; + return ENCODER_OBJECT_ID_NONE; } } - - return false; + return ENCODER_OBJECT_ID_NONE; } void radeon_panel_mode_fixup(struct drm_encoder *encoder, -- cgit From eb1711bb94991e93669c5a1b5f84f11be2d51ea1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 6 Dec 2011 12:12:33 +0100 Subject: drm/i915: fix infinite recursion on unbind due to ilk vt-d w/a The recursion loop goes retire_requests->unbind->gpu_idle->retire_reqeusts. Every time we go through this we need a - active object that can be retired - and there are no other references to that object than the one from the active list, so that it gets unbound and freed immediately. Otherwise the recursion stops. So the recursion is only limited by the number of objects that fit these requirements sitting in the active list any time retire_request is called. Issue exercised by tests/gem_unref_active_buffers from i-g-t. There's been a decent bikeshed discussion whether it wouldn't be better to pass around a flag, but imo this is o.k. for such a limited case that only supports a w/a. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=42180 Signed-Off-by: Daniel Vetter Reviewed-by: Chris Wilson [ickle- we built better bikesheds, but this keeps the rain off for now] Tested-by: Dave Airlie Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8359dc777041..60ff1b63b568 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2026,8 +2026,13 @@ i915_wait_request(struct intel_ring_buffer *ring, * to handle this, the waiter on a request often wants an associated * buffer to have made it to the inactive list, and we would need * a separate wait queue to handle that. + * + * To avoid a recursion with the ilk VT-d workaround (that calls + * gpu_idle when unbinding objects with interruptible==false) don't + * retire requests in that case (because it might call unbind if the + * active list holds the last reference to the object). */ - if (ret == 0) + if (ret == 0 && dev_priv->mm.interruptible) i915_gem_retire_requests_ring(ring); return ret; -- cgit From 24bb5a0ce39c51a2e2602c947f218a19e4b26d7d Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 29 Nov 2011 22:08:00 +0100 Subject: vmwgfx: Use kcalloc instead of kzalloc to allocate array The advantage of kcalloc is, that will prevent integer overflows which could result from the multiplication of number of elements and size and it is also a bit nicer to read. The semantic patch that makes this change is available in https://lkml.org/lkml/2011/11/25/107 Signed-off-by: Thomas Meyer Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 3f6343502d1f..5ff561d4e0b4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -140,7 +140,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, goto out_clips; } - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); + clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); if (clips == NULL) { DRM_ERROR("Failed to allocate clip rect list.\n"); ret = -ENOMEM; @@ -232,7 +232,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, goto out_clips; } - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); + clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); if (clips == NULL) { DRM_ERROR("Failed to allocate clip rect list.\n"); ret = -ENOMEM; -- cgit From 71c7a97289571ef5246b7f20d60b44961144c82f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 14 Nov 2011 04:28:59 -0300 Subject: [media] omap_vout: fix crash if no driver for a display omap_vout crashes on start if a corresponding driver is not loaded for a display device. This patch changes omap_vout init sequence to skip devices without a driver. Signed-off-by: Tomi Valkeinen Acked-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_vout.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 9c5c19f142de..2d2a136e465e 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -2169,6 +2169,14 @@ static int __init omap_vout_probe(struct platform_device *pdev) vid_dev->num_displays = 0; for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); + + if (!dssdev->driver) { + dev_warn(&pdev->dev, "no driver for display: %s\n", + dssdev->name); + omap_dss_put_device(dssdev); + continue; + } + vid_dev->displays[vid_dev->num_displays++] = dssdev; } -- cgit From 86b47c25494b824da655b95f6fdb4fdb3f17aa77 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 22 Nov 2011 16:08:21 +0200 Subject: perf: Do no try to schedule task events if there are none perf_event_sched_in() shouldn't try to schedule task events if there are none otherwise task's ctx->is_active will be set and will not be cleared during sched_out. This will prevent newly added events from being scheduled into the task context. Fixes a boo-boo in commit 1d5f003f5a9 ("perf: Do not set task_ctx pointer in cpuctx if there are no events in the context"). Signed-off-by: Gleb Natapov Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111122140821.GF2557@redhat.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 600c1629b64d..d3b9df5962c2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2174,11 +2174,11 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx, */ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); - perf_event_sched_in(cpuctx, ctx, task); - if (ctx->nr_events) cpuctx->task_ctx = ctx; + perf_event_sched_in(cpuctx, cpuctx->task_ctx, task); + perf_pmu_enable(ctx->pmu); perf_ctx_unlock(cpuctx, ctx); -- cgit From 68264d2a081f4032804adedb9ed9a680f7dade7e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 7 Dec 2011 17:44:47 +0800 Subject: ASoC: Fix a typo in jive_wm8750 Fix a typo in jive_wm8750 that introduces below build error. Also removes an unused err variable. CC sound/soc/samsung/jive_wm8750.o sound/soc/samsung/jive_wm8750.c: In function 'jive_wm8750_init': sound/soc/samsung/jive_wm8750.c:104: warning: unused variable 'err' sound/soc/samsung/jive_wm8750.c: At top level: sound/soc/samsung/jive_wm8750.c:134: error: unknown field 'dapm_widgtets' specified in initializer sound/soc/samsung/jive_wm8750.c:134: warning: initialization from incompatible pointer type make[3]: *** [sound/soc/samsung/jive_wm8750.o] Error 1 make[2]: *** [sound/soc/samsung] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/samsung/jive_wm8750.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 1826acf20f7c..8e523fd9189e 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c @@ -101,7 +101,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* These endpoints are not being used. */ snd_soc_dapm_nc_pin(dapm, "LINPUT2"); @@ -131,7 +130,7 @@ static struct snd_soc_card snd_soc_machine_jive = { .dai_link = &jive_dai, .num_links = 1, - .dapm_widgtets = wm8750_dapm_widgets, + .dapm_widgets = wm8750_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), .dapm_routes = audio_map, .num_dapm_routes = ARRAY_SIZE(audio_map), -- cgit From 974edd30beafdb136cdfc6839a143e23c826dc89 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 7 Dec 2011 17:52:19 +0800 Subject: ASoC: Include linux/module.h for smdk2443_wm9710 Include linux/module.h to fix below build error: CC sound/soc/samsung/smdk2443_wm9710.o sound/soc/samsung/smdk2443_wm9710.c:64: error: expected declaration specifiers or '...' before string constant sound/soc/samsung/smdk2443_wm9710.c:64: warning: data definition has no type or storage class sound/soc/samsung/smdk2443_wm9710.c:64: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' sound/soc/samsung/smdk2443_wm9710.c:64: warning: function declaration isn't a prototype sound/soc/samsung/smdk2443_wm9710.c:65: error: expected declaration specifiers or '...' before string constant sound/soc/samsung/smdk2443_wm9710.c:65: warning: data definition has no type or storage class sound/soc/samsung/smdk2443_wm9710.c:65: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' sound/soc/samsung/smdk2443_wm9710.c:65: warning: function declaration isn't a prototype sound/soc/samsung/smdk2443_wm9710.c:66: error: expected declaration specifiers or '...' before string constant sound/soc/samsung/smdk2443_wm9710.c:66: warning: data definition has no type or storage class sound/soc/samsung/smdk2443_wm9710.c:66: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE' sound/soc/samsung/smdk2443_wm9710.c:66: warning: function declaration isn't a prototype make[3]: *** [sound/soc/samsung/smdk2443_wm9710.o] Error 1 make[2]: *** [sound/soc/samsung] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/samsung/smdk2443_wm9710.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c index 3a0dbfc793f0..8bd1dc5706bf 100644 --- a/sound/soc/samsung/smdk2443_wm9710.c +++ b/sound/soc/samsung/smdk2443_wm9710.c @@ -12,6 +12,7 @@ * */ +#include #include static struct snd_soc_card smdk2443; -- cgit From 766ddee68bf1e4cc2cdcf73b34d243cf6e6f8ab0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 16:55:19 +0100 Subject: ALSA: hda/realtek - Don't create extra controls with channel suffix The multiple headphone or speaker pins are usually provided to output the same stream unlike line-out jacks (which are supposed to be multi-channel surrounds). Thus giving a mixer name like "Headphone Surround" is rather confusing. Instead, when multiple headphone volumes are available, use index with the same "Headphone" name. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a7d1bc4e0d09..96f5da9db5cf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3173,7 +3173,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, } static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac, const char *pfx) + hda_nid_t dac, const char *pfx, + int cidx) { struct alc_spec *spec = codec->spec; hda_nid_t sw, vol; @@ -3189,15 +3190,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); - return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); + return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, pin, dac); - err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); + err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); if (err < 0) return err; - err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); + err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); if (err < 0) return err; return 0; @@ -3238,16 +3239,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; - return alc_auto_create_extra_out(codec, *pins, dac, pfx); + return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ for (i = 0; i < num_pins; i++) { - snprintf(name, sizeof(name), "%s %s", - pfx, channel_name[i]); - err = alc_auto_create_extra_out(codec, pins[i], dacs[i], - name); + if (num_pins >= 3) { + snprintf(name, sizeof(name), "%s %s", + pfx, channel_name[i]); + err = alc_auto_create_extra_out(codec, pins[i], dacs[i], + name, 0); + } else { + err = alc_auto_create_extra_out(codec, pins[i], dacs[i], + pfx, i); + } if (err < 0) return err; } -- cgit From fbabc24619f7298626265a3f973786b471b8c29d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 17:14:20 +0100 Subject: ALSA: hda/realtek - Create "Bass Speaker" for two speaker pins On systems with two speaker pins, the secondary speaker pin is mostly assigned to a bass speaker instead of a surround. Thus it makes more sense to rename the control properly. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 96f5da9db5cf..214d4f91d6af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2631,6 +2631,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, case AUTO_PIN_SPEAKER_OUT: if (cfg->line_outs == 1) return "Speaker"; + if (cfg->line_outs == 2) + return ch ? "Bass Speaker" : "Speaker"; break; case AUTO_PIN_HP_OUT: /* for multi-io case, only the primary out */ -- cgit From 0a34b42b6245ccc710be6759cded5b7fe41ea1f9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 17:20:30 +0100 Subject: ALSA: hda/realtek - Fix lost speaker volume controls When there are the same or more number of HP pins are available, HP pins are used as the primary outputs instead of the speaker pins. But, in some cases (especially with ALC663 & co), some DACs are available only with a later pin and it's assigned to a speaker, and since the driver parses the pins from the lower NID, such a DAC was skipped eventually without assignments. This resulted in a regression, the missing speaker volume control in the new parser. As a workaround for this, now the driver retries the pin->DAC mapping again after restoring the speaker-pins as primary. This is still an ad hoc fix, but it works so far for most of Realtek codecs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 214d4f91d6af..1d07e8fa2433 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2906,7 +2906,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) if (!nid) continue; if (found_in_nid_list(nid, spec->multiout.dac_nids, - spec->multiout.num_dacs)) + ARRAY_SIZE(spec->private_dac_nids))) continue; if (found_in_nid_list(nid, spec->multiout.hp_out_nid, ARRAY_SIZE(spec->multiout.hp_out_nid))) @@ -2927,6 +2927,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) return 0; } +/* return 0 if no possible DAC is found, 1 if one or more found */ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, const hda_nid_t *pins, hda_nid_t *dacs) { @@ -2944,7 +2945,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, if (!dacs[i]) dacs[i] = alc_auto_look_for_dac(codec, pins[i]); } - return 0; + return 1; } static int alc_auto_fill_multi_ios(struct hda_codec *codec, @@ -2954,7 +2955,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_dac_nids(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *cfg = &spec->autocfg; bool redone = false; int i; @@ -2965,6 +2966,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) spec->multiout.extra_out_nid[0] = 0; memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); spec->multiout.dac_nids = spec->private_dac_nids; + spec->multi_ios = 0; /* fill hard-wired DACs first */ if (!redone) { @@ -2998,10 +3000,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) for (i = 0; i < cfg->line_outs; i++) { if (spec->private_dac_nids[i]) spec->multiout.num_dacs++; - else + else { memmove(spec->private_dac_nids + i, spec->private_dac_nids + i + 1, sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); + spec->private_dac_nids[cfg->line_outs - 1] = 0; + } } if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { @@ -3023,9 +3027,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) if (cfg->line_out_type != AUTO_PIN_HP_OUT) alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, spec->multiout.hp_out_nid); - if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) - alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, - spec->multiout.extra_out_nid); + if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, + cfg->speaker_pins, + spec->multiout.extra_out_nid); + /* if no speaker volume is assigned, try again as the primary + * output + */ + if (!err && cfg->speaker_outs > 0 && + cfg->line_out_type == AUTO_PIN_HP_OUT) { + cfg->hp_outs = cfg->line_outs; + memcpy(cfg->hp_pins, cfg->line_out_pins, + sizeof(cfg->hp_pins)); + cfg->line_outs = cfg->speaker_outs; + memcpy(cfg->line_out_pins, cfg->speaker_pins, + sizeof(cfg->speaker_pins)); + cfg->speaker_outs = 0; + memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); + cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; + redone = false; + goto again; + } + } return 0; } -- cgit From 77a7300abad7fe01891b400e88d746f97307ee5a Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 7 Dec 2011 03:16:26 +0400 Subject: of/irq: Get rid of NO_IRQ usage PPC32/64 defines NO_IRQ to zero, so no problems expected. ARM defines NO_IRQ to -1, but OF code relies on IRQ domains support, which returns correct ('0') value in 'no irq' case. So everything should be fine. Other arches might break if some of their OF drivers rely on NO_IRQ being not 0. If so, the drivers must be fixed, finally. [ Rob Herring points out that microblaze should be fixed, and has posted a patch for testing for that. - Linus ] Signed-off-by: Anton Vorontsov Acked-by: Wolfram Sang Signed-off-by: Linus Torvalds --- drivers/of/irq.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 19c0115092dd..0f0cfa3bca30 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -26,11 +26,6 @@ #include #include -/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */ -#ifndef NO_IRQ -#define NO_IRQ 0 -#endif - /** * irq_of_parse_and_map - Parse and map an interrupt into linux virq space * @device: Device node of the device whose interrupt is to be mapped @@ -44,7 +39,7 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) struct of_irq oirq; if (of_irq_map_one(dev, index, &oirq)) - return NO_IRQ; + return 0; return irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -345,7 +340,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) /* Only dereference the resource if both the * resource and the irq are valid. */ - if (r && irq != NO_IRQ) { + if (r && irq) { r->start = r->end = irq; r->flags = IORESOURCE_IRQ; r->name = dev->full_name; @@ -363,7 +358,7 @@ int of_irq_count(struct device_node *dev) { int nr = 0; - while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ) + while (of_irq_to_resource(dev, nr, NULL)) nr++; return nr; @@ -383,7 +378,7 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res, int i; for (i = 0; i < nr_irqs; i++, res++) - if (of_irq_to_resource(dev, i, res) == NO_IRQ) + if (!of_irq_to_resource(dev, i, res)) break; return i; -- cgit From 43af940c54d712ab5e6d6798a82498b25c2af299 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 5 Dec 2011 05:01:15 +0000 Subject: net/fec: fix the use of pdev->id The pdev->id is used in several places for different purpose. All these uses assume it's always the id of fec device which is >= 0. However this is only true for non-DT case. When DT plays, pdev->id is always -1, which will break these pdev->id users. Instead of fixing all these users one by one, this patch introduces a new member 'dev_id' to 'struct fec_enet_private' for holding the correct fec device id, and replaces all the existing uses of pdev->id with this dev_id. Signed-off-by: Shawn Guo Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 1124ce0a1594..c136230d50bb 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -232,6 +232,7 @@ struct fec_enet_private { struct platform_device *pdev; int opened; + int dev_id; /* Phylib and MDIO interface */ struct mii_bus *mii_bus; @@ -837,7 +838,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev) /* Adjust MAC if using macaddr */ if (iap == macaddr) - ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; + ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id; } /* ------------------------------------------------------------------------- */ @@ -953,7 +954,7 @@ static int fec_enet_mii_probe(struct net_device *ndev) char mdio_bus_id[MII_BUS_ID_SIZE]; char phy_name[MII_BUS_ID_SIZE + 3]; int phy_id; - int dev_id = fep->pdev->id; + int dev_id = fep->dev_id; fep->phy_dev = NULL; @@ -1031,7 +1032,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) * mdio interface in board design, and need to be configured by * fec0 mii_bus. */ - if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id > 0) { + if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { /* fec1 uses fec0 mii_bus */ fep->mii_bus = fec0_mii_bus; return 0; @@ -1063,7 +1064,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; @@ -1521,6 +1522,7 @@ fec_probe(struct platform_device *pdev) int i, irq, ret = 0; struct resource *r; const struct of_device_id *of_id; + static int dev_id; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) @@ -1548,6 +1550,7 @@ fec_probe(struct platform_device *pdev) fep->hwp = ioremap(r->start, resource_size(r)); fep->pdev = pdev; + fep->dev_id = dev_id++; if (!fep->hwp) { ret = -ENOMEM; -- cgit From a454daceb78844a09c08b6e2d8badcb76a5d73b9 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Tue, 6 Dec 2011 15:47:12 +0000 Subject: ppp: fix pptp double release_sock in pptp_bind() Signed-off-by: Djalal Harouni Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ppp/pptp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 89f829f5f725..f8a6853b692e 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -423,10 +423,8 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); opt->src_addr = sp->sa_addr.pptp; - if (add_chan(po)) { - release_sock(sk); + if (add_chan(po)) error = -EBUSY; - } release_sock(sk); return error; -- cgit From 81e759fbf7715514c32e563789db1d9d47fd55fb Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Tue, 15 Nov 2011 14:49:53 -0800 Subject: rbd: return an error when an invalid header is read This protects against opening future rbd images that have incompatible format changes. Signed-off-by: Josh Durgin --- drivers/block/rbd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 65cc424359b0..a828c6a276a8 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -461,6 +461,10 @@ static int rbd_header_from_disk(struct rbd_image_header *header, u32 snap_count = le32_to_cpu(ondisk->snap_count); int ret = -ENOMEM; + if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) { + return -ENXIO; + } + init_rwsem(&header->snap_rwsem); header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); header->snapc = kmalloc(sizeof(struct ceph_snap_context) + @@ -1610,8 +1614,13 @@ static int rbd_read_header(struct rbd_device *rbd_dev, goto out_dh; rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL); - if (rc < 0) + if (rc < 0) { + if (rc == -ENXIO) { + pr_warning("unrecognized header format" + " for image %s", rbd_dev->obj); + } goto out_dh; + } if (snap_count != header->total_snaps) { snap_count = header->total_snaps; -- cgit From 51703306b3b9ea7c05728040998521e47358147b Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Mon, 24 Oct 2011 16:28:27 -0700 Subject: rbd: remove buggy rollback functionality This doesn't interact with resizing well, since it doesn't set the size of the device to the size at the snapshot. It's also an expensive operation to be synchronous. Rollback can still be done with the userspace rbd tool. Signed-off-by: Josh Durgin --- Documentation/ABI/testing/sysfs-bus-rbd | 7 --- drivers/block/rbd.c | 90 --------------------------------- 2 files changed, 97 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd index fa72ccb2282e..dbedafb095e2 100644 --- a/Documentation/ABI/testing/sysfs-bus-rbd +++ b/Documentation/ABI/testing/sysfs-bus-rbd @@ -57,13 +57,6 @@ create_snap $ echo > /sys/bus/rbd/devices//snap_create -rollback_snap - - Rolls back data to the specified snapshot. This goes over the entire - list of rados blocks and sends a rollback command to each. - - $ echo > /sys/bus/rbd/devices//snap_rollback - snap_* A directory per each snapshot diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index a828c6a276a8..148ab944378d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -183,10 +183,6 @@ static LIST_HEAD(rbd_client_list); /* clients */ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev); static void rbd_dev_release(struct device *dev); -static ssize_t rbd_snap_rollback(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size); static ssize_t rbd_snap_add(struct device *dev, struct device_attribute *attr, const char *buf, @@ -1359,32 +1355,6 @@ fail: return ret; } -/* - * Request sync osd rollback - */ -static int rbd_req_sync_rollback_obj(struct rbd_device *dev, - u64 snapid, - const char *obj) -{ - struct ceph_osd_req_op *ops; - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0); - if (ret < 0) - return ret; - - ops[0].snap.snapid = snapid; - - ret = rbd_req_sync_op(dev, NULL, - CEPH_NOSNAP, - 0, - CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, - ops, - 1, obj, 0, 0, NULL, NULL, NULL); - - rbd_destroy_ops(ops); - - return ret; -} - /* * Request sync osd read */ @@ -1891,7 +1861,6 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL); static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add); -static DEVICE_ATTR(rollback_snap, S_IWUSR, NULL, rbd_snap_rollback); static struct attribute *rbd_attrs[] = { &dev_attr_size.attr, @@ -1902,7 +1871,6 @@ static struct attribute *rbd_attrs[] = { &dev_attr_current_snap.attr, &dev_attr_refresh.attr, &dev_attr_create_snap.attr, - &dev_attr_rollback_snap.attr, NULL }; @@ -2433,64 +2401,6 @@ err_unlock: return ret; } -static ssize_t rbd_snap_rollback(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct rbd_device *rbd_dev = dev_to_rbd(dev); - int ret; - u64 snapid; - u64 cur_ofs; - char *seg_name = NULL; - char *snap_name = kmalloc(count + 1, GFP_KERNEL); - ret = -ENOMEM; - if (!snap_name) - return ret; - - /* parse snaps add command */ - snprintf(snap_name, count, "%s", buf); - seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); - if (!seg_name) - goto done; - - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - - ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL); - if (ret < 0) - goto done_unlock; - - dout("snapid=%lld\n", snapid); - - cur_ofs = 0; - while (cur_ofs < rbd_dev->header.image_size) { - cur_ofs += rbd_get_segment(&rbd_dev->header, - rbd_dev->obj, - cur_ofs, (u64)-1, - seg_name, NULL); - dout("seg_name=%s\n", seg_name); - - ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name); - if (ret < 0) - pr_warning("could not roll back obj %s err=%d\n", - seg_name, ret); - } - - ret = __rbd_update_snaps(rbd_dev); - if (ret < 0) - goto done_unlock; - - ret = count; - -done_unlock: - mutex_unlock(&ctl_mutex); -done: - kfree(seg_name); - kfree(snap_name); - - return ret; -} - static struct bus_attribute rbd_bus_attrs[] = { __ATTR(add, S_IWUSR, NULL, rbd_add), __ATTR(remove, S_IWUSR, NULL, rbd_remove), -- cgit From be655596b3de5873f994ddbe205751a5ffb4de39 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 30 Nov 2011 09:47:09 -0800 Subject: ceph: use i_ceph_lock instead of i_lock We have been using i_lock to protect all kinds of data structures in the ceph_inode_info struct, including lists of inodes that we need to iterate over while avoiding races with inode destruction. That requires grabbing a reference to the inode with the list lock protected, but igrab() now takes i_lock to check the inode flags. Changing the list lock ordering would be a painful process. However, using a ceph-specific i_ceph_lock in the ceph inode instead of i_lock is a simple mechanical change and avoids the ordering constraints imposed by igrab(). Reported-by: Amon Ott Signed-off-by: Sage Weil --- fs/ceph/addr.c | 8 +-- fs/ceph/caps.c | 187 ++++++++++++++++++++++++++------------------------- fs/ceph/dir.c | 24 +++---- fs/ceph/file.c | 20 +++--- fs/ceph/inode.c | 53 ++++++++------- fs/ceph/ioctl.c | 4 +- fs/ceph/mds_client.c | 32 ++++----- fs/ceph/mds_client.h | 2 +- fs/ceph/snap.c | 16 ++--- fs/ceph/super.h | 31 ++++----- fs/ceph/xattr.c | 42 ++++++------ 11 files changed, 212 insertions(+), 207 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 4144caf2f9d3..173b1d22e59b 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -87,7 +87,7 @@ static int ceph_set_page_dirty(struct page *page) snapc = ceph_get_snap_context(ci->i_snap_realm->cached_context); /* dirty the head */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_head_snapc == NULL) ci->i_head_snapc = ceph_get_snap_context(snapc); ++ci->i_wrbuffer_ref_head; @@ -100,7 +100,7 @@ static int ceph_set_page_dirty(struct page *page) ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1, ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head, snapc, snapc->seq, snapc->num_snaps); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* now adjust page */ spin_lock_irq(&mapping->tree_lock); @@ -391,7 +391,7 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode, struct ceph_snap_context *snapc = NULL; struct ceph_cap_snap *capsnap = NULL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap, capsnap->context, capsnap->dirty_pages); @@ -407,7 +407,7 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode, dout(" head snapc %p has %d dirty pages\n", snapc, ci->i_wrbuffer_ref_head); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return snapc; } diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 0f327c6c9679..8b53193e4f7c 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -309,7 +309,7 @@ void ceph_reservation_status(struct ceph_fs_client *fsc, /* * Find ceph_cap for given mds, if any. * - * Called with i_lock held. + * Called with i_ceph_lock held. */ static struct ceph_cap *__get_cap_for_mds(struct ceph_inode_info *ci, int mds) { @@ -332,9 +332,9 @@ struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, int mds) { struct ceph_cap *cap; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ci, mds); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return cap; } @@ -361,15 +361,16 @@ static int __ceph_get_cap_mds(struct ceph_inode_info *ci) int ceph_get_cap_mds(struct inode *inode) { + struct ceph_inode_info *ci = ceph_inode(inode); int mds; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); mds = __ceph_get_cap_mds(ceph_inode(inode)); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return mds; } /* - * Called under i_lock. + * Called under i_ceph_lock. */ static void __insert_cap_node(struct ceph_inode_info *ci, struct ceph_cap *new) @@ -415,7 +416,7 @@ static void __cap_set_timeouts(struct ceph_mds_client *mdsc, * * If I_FLUSH is set, leave the inode at the front of the list. * - * Caller holds i_lock + * Caller holds i_ceph_lock * -> we take mdsc->cap_delay_lock */ static void __cap_delay_requeue(struct ceph_mds_client *mdsc, @@ -457,7 +458,7 @@ static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc, /* * Cancel delayed work on cap. * - * Caller must hold i_lock. + * Caller must hold i_ceph_lock. */ static void __cap_delay_cancel(struct ceph_mds_client *mdsc, struct ceph_inode_info *ci) @@ -532,14 +533,14 @@ int ceph_add_cap(struct inode *inode, wanted |= ceph_caps_for_mode(fmode); retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ci, mds); if (!cap) { if (new_cap) { cap = new_cap; new_cap = NULL; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); new_cap = get_cap(mdsc, caps_reservation); if (new_cap == NULL) return -ENOMEM; @@ -625,7 +626,7 @@ retry: if (fmode >= 0) __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); wake_up_all(&ci->i_cap_wq); return 0; } @@ -792,7 +793,7 @@ int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) struct rb_node *p; int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { cap = rb_entry(p, struct ceph_cap, ci_node); if (__cap_is_valid(cap) && @@ -801,7 +802,7 @@ int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) break; } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("ceph_caps_revoking %p %s = %d\n", inode, ceph_cap_string(mask), ret); return ret; @@ -855,7 +856,7 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci) } /* - * called under i_lock + * called under i_ceph_lock */ static int __ceph_is_any_caps(struct ceph_inode_info *ci) { @@ -865,7 +866,7 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci) /* * Remove a cap. Take steps to deal with a racing iterate_session_caps. * - * caller should hold i_lock. + * caller should hold i_ceph_lock. * caller will not hold session s_mutex if called from destroy_inode. */ void __ceph_remove_cap(struct ceph_cap *cap) @@ -1028,7 +1029,7 @@ static void __queue_cap_release(struct ceph_mds_session *session, /* * Queue cap releases when an inode is dropped from our cache. Since - * inode is about to be destroyed, there is no need for i_lock. + * inode is about to be destroyed, there is no need for i_ceph_lock. */ void ceph_queue_caps_release(struct inode *inode) { @@ -1049,7 +1050,7 @@ void ceph_queue_caps_release(struct inode *inode) /* * Send a cap msg on the given inode. Update our caps state, then - * drop i_lock and send the message. + * drop i_ceph_lock and send the message. * * Make note of max_size reported/requested from mds, revoked caps * that have now been implemented. @@ -1061,13 +1062,13 @@ void ceph_queue_caps_release(struct inode *inode) * Return non-zero if delayed release, or we experienced an error * such that the caller should requeue + retry later. * - * called with i_lock, then drops it. + * called with i_ceph_lock, then drops it. * caller should hold snap_rwsem (read), s_mutex. */ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, int op, int used, int want, int retain, int flushing, unsigned *pflush_tid) - __releases(cap->ci->vfs_inode->i_lock) + __releases(cap->ci->i_ceph_lock) { struct ceph_inode_info *ci = cap->ci; struct inode *inode = &ci->vfs_inode; @@ -1170,7 +1171,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, xattr_version = ci->i_xattrs.version; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ret = send_cap_msg(session, ceph_vino(inode).ino, cap_id, op, keep, want, flushing, seq, flush_tid, issue_seq, mseq, @@ -1198,13 +1199,13 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, * Unless @again is true, skip cap_snaps that were already sent to * the MDS (i.e., during this session). * - * Called under i_lock. Takes s_mutex as needed. + * Called under i_ceph_lock. Takes s_mutex as needed. */ void __ceph_flush_snaps(struct ceph_inode_info *ci, struct ceph_mds_session **psession, int again) - __releases(ci->vfs_inode->i_lock) - __acquires(ci->vfs_inode->i_lock) + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) { struct inode *inode = &ci->vfs_inode; int mds; @@ -1261,7 +1262,7 @@ retry: session = NULL; } if (!session) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); mutex_lock(&mdsc->mutex); session = __ceph_lookup_mds_session(mdsc, mds); mutex_unlock(&mdsc->mutex); @@ -1275,7 +1276,7 @@ retry: * deletion or migration. retry, and we'll * get a better @mds value next time. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); goto retry; } @@ -1285,7 +1286,7 @@ retry: list_del_init(&capsnap->flushing_item); list_add_tail(&capsnap->flushing_item, &session->s_cap_snaps_flushing); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("flush_snaps %p cap_snap %p follows %lld tid %llu\n", inode, capsnap, capsnap->follows, capsnap->flush_tid); @@ -1302,7 +1303,7 @@ retry: next_follows = capsnap->follows + 1; ceph_put_cap_snap(capsnap); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); goto retry; } @@ -1322,11 +1323,9 @@ out: static void ceph_flush_snaps(struct ceph_inode_info *ci) { - struct inode *inode = &ci->vfs_inode; - - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_flush_snaps(ci, NULL, 0); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -1373,7 +1372,7 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) * Add dirty inode to the flushing list. Assigned a seq number so we * can wait for caps to flush without starving. * - * Called under i_lock. + * Called under i_ceph_lock. */ static int __mark_caps_flushing(struct inode *inode, struct ceph_mds_session *session) @@ -1421,9 +1420,9 @@ static int try_nonblocking_invalidate(struct inode *inode) struct ceph_inode_info *ci = ceph_inode(inode); u32 invalidating_gen = ci->i_rdcache_gen; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); invalidate_mapping_pages(&inode->i_data, 0, -1); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (inode->i_data.nrpages == 0 && invalidating_gen == ci->i_rdcache_gen) { @@ -1470,7 +1469,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, if (mdsc->stopping) is_delayed = 1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_FLUSH) flags |= CHECK_CAPS_FLUSH; @@ -1480,7 +1479,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, __ceph_flush_snaps(ci, &session, 0); goto retry_locked; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); retry_locked: file_wanted = __ceph_caps_file_wanted(ci); used = __ceph_caps_used(ci); @@ -1634,7 +1633,7 @@ ack: if (mutex_trylock(&session->s_mutex) == 0) { dout("inverting session/ino locks on %p\n", session); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (took_snap_rwsem) { up_read(&mdsc->snap_rwsem); took_snap_rwsem = 0; @@ -1648,7 +1647,7 @@ ack: if (down_read_trylock(&mdsc->snap_rwsem) == 0) { dout("inverting snap/in locks on %p\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); down_read(&mdsc->snap_rwsem); took_snap_rwsem = 1; goto retry; @@ -1664,10 +1663,10 @@ ack: mds = cap->mds; /* remember mds, so we don't repeat */ sent++; - /* __send_cap drops i_lock */ + /* __send_cap drops i_ceph_lock */ delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, used, want, retain, flushing, NULL); - goto retry; /* retake i_lock and restart our cap scan. */ + goto retry; /* retake i_ceph_lock and restart our cap scan. */ } /* @@ -1681,7 +1680,7 @@ ack: else if (!is_delayed || force_requeue) __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (queue_invalidate) ceph_queue_invalidate(inode); @@ -1704,7 +1703,7 @@ static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session, int flushing = 0; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); goto out; @@ -1716,7 +1715,7 @@ retry: int delayed; if (!session) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); session = cap->session; mutex_lock(&session->s_mutex); goto retry; @@ -1727,18 +1726,18 @@ retry: flushing = __mark_caps_flushing(inode, session); - /* __send_cap drops i_lock */ + /* __send_cap drops i_ceph_lock */ delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, used, want, cap->issued | cap->implemented, flushing, flush_tid); if (!delayed) goto out_unlocked; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); out_unlocked: if (session && unlock_session) mutex_unlock(&session->s_mutex); @@ -1753,7 +1752,7 @@ static int caps_are_flushed(struct inode *inode, unsigned tid) struct ceph_inode_info *ci = ceph_inode(inode); int i, ret = 1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); for (i = 0; i < CEPH_CAP_BITS; i++) if ((ci->i_flushing_caps & (1 << i)) && ci->i_cap_flush_tid[i] <= tid) { @@ -1761,7 +1760,7 @@ static int caps_are_flushed(struct inode *inode, unsigned tid) ret = 0; break; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -1868,10 +1867,10 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (__ceph_caps_dirty(ci)) __cap_delay_requeue_front(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } return err; } @@ -1894,7 +1893,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode = &ci->vfs_inode; struct ceph_cap *cap; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; if (cap && cap->session == session) { dout("kick_flushing_caps %p cap %p capsnap %p\n", inode, @@ -1904,7 +1903,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, pr_err("%p auth cap %p not mds%d ???\n", inode, cap, session->s_mds); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } @@ -1921,7 +1920,7 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, struct ceph_cap *cap; int delayed = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; if (cap && cap->session == session) { dout("kick_flushing_caps %p cap %p %s\n", inode, @@ -1932,14 +1931,14 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, cap->issued | cap->implemented, ci->i_flushing_caps, NULL); if (delayed) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else { pr_err("%p auth cap %p not mds%d ???\n", inode, cap, session->s_mds); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } } @@ -1952,7 +1951,7 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, struct ceph_cap *cap; int delayed = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; dout("kick_flushing_inode_caps %p flushing %s flush_seq %lld\n", inode, ceph_cap_string(ci->i_flushing_caps), ci->i_cap_flush_seq); @@ -1964,12 +1963,12 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, cap->issued | cap->implemented, ci->i_flushing_caps, NULL); if (delayed) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } @@ -1978,7 +1977,7 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, * Take references to capabilities we hold, so that we don't release * them to the MDS prematurely. * - * Protected by i_lock. + * Protected by i_ceph_lock. */ static void __take_cap_refs(struct ceph_inode_info *ci, int got) { @@ -2016,7 +2015,7 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want, dout("get_cap_refs %p need %s want %s\n", inode, ceph_cap_string(need), ceph_cap_string(want)); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* make sure file is actually open */ file_wanted = __ceph_caps_file_wanted(ci); @@ -2077,7 +2076,7 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want, ceph_cap_string(have), ceph_cap_string(need)); } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("get_cap_refs %p ret %d got %s\n", inode, ret, ceph_cap_string(*got)); return ret; @@ -2094,7 +2093,7 @@ static void check_max_size(struct inode *inode, loff_t endoff) int check = 0; /* do we need to explicitly request a larger max_size? */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if ((endoff >= ci->i_max_size || endoff > (inode->i_size << 1)) && endoff > ci->i_wanted_max_size) { @@ -2103,7 +2102,7 @@ static void check_max_size(struct inode *inode, loff_t endoff) ci->i_wanted_max_size = endoff; check = 1; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (check) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); } @@ -2140,9 +2139,9 @@ retry: */ void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps) { - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); __take_cap_refs(ci, caps); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2160,7 +2159,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) int last = 0, put = 0, flushsnaps = 0, wake = 0; struct ceph_cap_snap *capsnap; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (had & CEPH_CAP_PIN) --ci->i_pin_ref; if (had & CEPH_CAP_FILE_RD) @@ -2193,7 +2192,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) } } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), last ? " last" : "", put ? " put" : ""); @@ -2225,7 +2224,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, int found = 0; struct ceph_cap_snap *capsnap = NULL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_wrbuffer_ref -= nr; last = !ci->i_wrbuffer_ref; @@ -2274,7 +2273,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (last) { ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); @@ -2291,7 +2290,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, * Handle a cap GRANT message from the MDS. (Note that a GRANT may * actually be a revocation if it specifies a smaller cap set.) * - * caller holds s_mutex and i_lock, we drop both. + * caller holds s_mutex and i_ceph_lock, we drop both. * * return value: * 0 - ok @@ -2302,7 +2301,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, struct ceph_mds_session *session, struct ceph_cap *cap, struct ceph_buffer *xattr_buf) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; @@ -2453,7 +2452,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, } BUG_ON(cap->issued & ~cap->implemented); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (writeback) /* * queue inode for writeback: we can't actually call @@ -2483,7 +2482,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, struct ceph_mds_caps *m, struct ceph_mds_session *session, struct ceph_cap *cap) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; @@ -2539,7 +2538,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, wake_up_all(&ci->i_cap_wq); out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (drop) iput(inode); } @@ -2562,7 +2561,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, dout("handle_cap_flushsnap_ack inode %p ci %p mds%d follows %lld\n", inode, ci, session->s_mds, follows); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { if (capsnap->follows == follows) { if (capsnap->flush_tid != flush_tid) { @@ -2585,7 +2584,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, capsnap, capsnap->follows); } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (drop) iput(inode); } @@ -2598,7 +2597,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, static void handle_cap_trunc(struct inode *inode, struct ceph_mds_caps *trunc, struct ceph_mds_session *session) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; @@ -2617,7 +2616,7 @@ static void handle_cap_trunc(struct inode *inode, inode, mds, seq, truncate_size, truncate_seq); queue_trunc = ceph_fill_file_size(inode, issued, truncate_seq, truncate_size, size); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (queue_trunc) ceph_queue_vmtruncate(inode); @@ -2646,7 +2645,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, dout("handle_cap_export inode %p ci %p mds%d mseq %d\n", inode, ci, mds, mseq); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* make sure we haven't seen a higher mseq */ for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { @@ -2690,7 +2689,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, } /* else, we already released it */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2745,9 +2744,9 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, up_read(&mdsc->snap_rwsem); /* make sure we re-request max_size, if necessary */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_requested_max_size = 0; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2762,6 +2761,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, struct ceph_mds_client *mdsc = session->s_mdsc; struct super_block *sb = mdsc->fsc->sb; struct inode *inode; + struct ceph_inode_info *ci; struct ceph_cap *cap; struct ceph_mds_caps *h; int mds = session->s_mds; @@ -2815,6 +2815,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, /* lookup ino */ inode = ceph_find_inode(sb, vino); + ci = ceph_inode(inode); dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino, vino.snap, inode); if (!inode) { @@ -2844,16 +2845,16 @@ void ceph_handle_caps(struct ceph_mds_session *session, } /* the rest require a cap */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ceph_inode(inode), mds); if (!cap) { dout(" no cap on %p ino %llx.%llx from mds%d\n", inode, ceph_ino(inode), ceph_snap(inode), mds); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto flush_cap_releases; } - /* note that each of these drops i_lock for us */ + /* note that each of these drops i_ceph_lock for us */ switch (op) { case CEPH_CAP_OP_REVOKE: case CEPH_CAP_OP_GRANT: @@ -2869,7 +2870,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, break; default: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); pr_err("ceph_handle_caps: unknown cap op %d %s\n", op, ceph_cap_op_name(op)); } @@ -2962,13 +2963,13 @@ void ceph_put_fmode(struct ceph_inode_info *ci, int fmode) struct inode *inode = &ci->vfs_inode; int last = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("put_fmode %p fmode %d %d -> %d\n", inode, fmode, ci->i_nr_by_mode[fmode], ci->i_nr_by_mode[fmode]-1); BUG_ON(ci->i_nr_by_mode[fmode] == 0); if (--ci->i_nr_by_mode[fmode] == 0) last++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (last && ci->i_vino.snap == CEPH_NOSNAP) ceph_check_caps(ci, 0, NULL); @@ -2991,7 +2992,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, int used, dirty; int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); used = __ceph_caps_used(ci); dirty = __ceph_caps_dirty(ci); @@ -3046,7 +3047,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, inode, cap, ceph_cap_string(cap->issued)); } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -3061,7 +3062,7 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry, /* * force an record for the directory caps if we have a dentry lease. - * this is racy (can't take i_lock and d_lock together), but it + * this is racy (can't take i_ceph_lock and d_lock together), but it * doesn't have to be perfect; the mds will revoke anything we don't * release. */ diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index bca3948e9dbf..3eeb97661262 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -281,18 +281,18 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) } /* can we use the dcache? */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if ((filp->f_pos == 2 || fi->dentry) && !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && ceph_snap(inode) != CEPH_SNAPDIR && ceph_dir_test_complete(inode) && __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = __dcache_readdir(filp, dirent, filldir); if (err != -EAGAIN) return err; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } if (fi->dentry) { err = note_last_dentry(fi, fi->dentry->d_name.name, @@ -428,12 +428,12 @@ more: * were released during the whole readdir, and we should have * the complete dir contents in our cache. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_release_count == fi->dir_release_count) { ceph_dir_set_complete(inode); ci->i_max_offset = filp->f_pos; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("readdir %p filp %p done.\n", inode, filp); return 0; @@ -607,7 +607,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, struct ceph_inode_info *ci = ceph_inode(dir); struct ceph_dentry_info *di = ceph_dentry(dentry); - spin_lock(&dir->i_lock); + spin_lock(&ci->i_ceph_lock); dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags); if (strncmp(dentry->d_name.name, fsc->mount_options->snapdir_name, @@ -615,13 +615,13 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, !is_root_ceph_dentry(dir, dentry) && ceph_dir_test_complete(dir) && (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); dout(" dir %p complete, -ENOENT\n", dir); d_add(dentry, NULL); di->lease_shared_gen = ci->i_shared_gen; return NULL; } - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); } op = ceph_snap(dir) == CEPH_SNAPDIR ? @@ -841,12 +841,12 @@ static int drop_caps_for_unlink(struct inode *inode) struct ceph_inode_info *ci = ceph_inode(inode); int drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (inode->i_nlink == 1) { drop |= ~(__ceph_caps_wanted(ci) | CEPH_CAP_PIN); ci->i_ceph_flags |= CEPH_I_NODELAY; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return drop; } @@ -1015,10 +1015,10 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) struct ceph_dentry_info *di = ceph_dentry(dentry); int valid = 0; - spin_lock(&dir->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_shared_gen == di->lease_shared_gen) valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1); - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("dir_lease_is_valid dir %p v%u dentry %p v%u = %d\n", dir, (unsigned)ci->i_shared_gen, dentry, (unsigned)di->lease_shared_gen, valid); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ce549d31eeb7..af187330cc89 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -147,9 +147,9 @@ int ceph_open(struct inode *inode, struct file *file) /* trivially open snapdir */ if (ceph_snap(inode) == CEPH_SNAPDIR) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ceph_init_file(inode, file, fmode); } @@ -158,7 +158,7 @@ int ceph_open(struct inode *inode, struct file *file) * write) or any MDS (for read). Update wanted set * asynchronously. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (__ceph_is_any_real_caps(ci) && (((fmode & CEPH_FILE_MODE_WR) == 0) || ci->i_auth_cap)) { int mds_wanted = __ceph_caps_mds_wanted(ci); @@ -168,7 +168,7 @@ int ceph_open(struct inode *inode, struct file *file) inode, fmode, ceph_cap_string(wanted), ceph_cap_string(issued)); __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* adjust wanted? */ if ((issued & wanted) != wanted && @@ -180,10 +180,10 @@ int ceph_open(struct inode *inode, struct file *file) } else if (ceph_snap(inode) != CEPH_NOSNAP && (ci->i_snap_caps & wanted) == wanted) { __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ceph_init_file(inode, file, fmode); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("open fmode %d wants %s\n", fmode, ceph_cap_string(wanted)); req = prepare_open_request(inode->i_sb, flags, 0); @@ -743,9 +743,9 @@ retry_snap: */ int dirty; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_put_cap_refs(ci, got); ret = generic_file_aio_write(iocb, iov, nr_segs, pos); @@ -764,9 +764,9 @@ retry_snap: if (ret >= 0) { int dirty; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 116f36502f17..87fb132fb330 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -297,6 +297,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb) dout("alloc_inode %p\n", &ci->vfs_inode); + spin_lock_init(&ci->i_ceph_lock); + ci->i_version = 0; ci->i_time_warp_seq = 0; ci->i_ceph_flags = 0; @@ -583,7 +585,7 @@ static int fill_inode(struct inode *inode, iinfo->xattr_len); } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* * provided version will be odd if inode value is projected, @@ -680,7 +682,7 @@ static int fill_inode(struct inode *inode, char *sym; BUG_ON(symlen != inode->i_size); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = -ENOMEM; sym = kmalloc(symlen+1, GFP_NOFS); @@ -689,7 +691,7 @@ static int fill_inode(struct inode *inode, memcpy(sym, iinfo->symlink, symlen); sym[symlen] = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ci->i_symlink) ci->i_symlink = sym; else @@ -715,7 +717,7 @@ static int fill_inode(struct inode *inode, } no_change: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* queue truncate if we saw i_size decrease */ if (queue_trunc) @@ -750,13 +752,13 @@ no_change: info->cap.flags, caps_reservation); } else { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout(" %p got snap_caps %s\n", inode, ceph_cap_string(le32_to_cpu(info->cap.caps))); ci->i_snap_caps |= le32_to_cpu(info->cap.caps); if (cap_fmode >= 0) __ceph_get_fmode(ci, cap_fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else if (cap_fmode >= 0) { pr_warning("mds issued no caps on %llx.%llx\n", @@ -849,19 +851,20 @@ static void ceph_set_dentry_offset(struct dentry *dn) { struct dentry *dir = dn->d_parent; struct inode *inode = dir->d_inode; + struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_dentry_info *di; BUG_ON(!inode); di = ceph_dentry(dn); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ceph_dir_test_complete(inode)) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return; } di->offset = ceph_inode(inode)->i_max_offset++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); spin_lock(&dir->d_lock); spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); @@ -1308,7 +1311,7 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) struct ceph_inode_info *ci = ceph_inode(inode); int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("set_size %p %llu -> %llu\n", inode, inode->i_size, size); inode->i_size = size; inode->i_blocks = (size + (1 << 9) - 1) >> 9; @@ -1318,7 +1321,7 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) (ci->i_reported_size << 1) < ci->i_max_size) ret = 1; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -1376,20 +1379,20 @@ static void ceph_invalidate_work(struct work_struct *work) u32 orig_gen; int check = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("invalidate_pages %p gen %d revoking %d\n", inode, ci->i_rdcache_gen, ci->i_rdcache_revoking); if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { /* nevermind! */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto out; } orig_gen = ci->i_rdcache_gen; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); truncate_inode_pages(&inode->i_data, 0); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (orig_gen == ci->i_rdcache_gen && orig_gen == ci->i_rdcache_revoking) { dout("invalidate_pages %p gen %d successful\n", inode, @@ -1401,7 +1404,7 @@ static void ceph_invalidate_work(struct work_struct *work) inode, orig_gen, ci->i_rdcache_gen, ci->i_rdcache_revoking); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (check) ceph_check_caps(ci, 0, NULL); @@ -1460,10 +1463,10 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) int wrbuffer_refs, wake = 0; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_truncate_pending == 0) { dout("__do_pending_vmtruncate %p none pending\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return; } @@ -1474,7 +1477,7 @@ retry: if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) { dout("__do_pending_vmtruncate %p flushing snaps first\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); filemap_write_and_wait_range(&inode->i_data, 0, inode->i_sb->s_maxbytes); goto retry; @@ -1484,15 +1487,15 @@ retry: wrbuffer_refs = ci->i_wrbuffer_ref; dout("__do_pending_vmtruncate %p (%d) to %lld\n", inode, ci->i_truncate_pending, to); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); truncate_inode_pages(inode->i_mapping, to); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_truncate_pending--; if (ci->i_truncate_pending == 0) wake = 1; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (wrbuffer_refs == 0) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); @@ -1547,7 +1550,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) if (IS_ERR(req)) return PTR_ERR(req); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); issued = __ceph_caps_issued(ci, NULL); dout("setattr %p issued %s\n", inode, ceph_cap_string(issued)); @@ -1695,7 +1698,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) } release &= issued; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (inode_dirty_flags) __mark_inode_dirty(inode, inode_dirty_flags); @@ -1717,7 +1720,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) __ceph_do_pending_vmtruncate(inode); return err; out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_mdsc_put_request(req); return err; } diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 5a14c29cbba6..790914a598dd 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -241,11 +241,11 @@ static long ceph_ioctl_lazyio(struct file *file) struct ceph_inode_info *ci = ceph_inode(inode); if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_nr_by_mode[fi->fmode]--; fi->fmode |= CEPH_FILE_MODE_LAZY; ci->i_nr_by_mode[fi->fmode]++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("ioctl_layzio: file %p marked lazy\n", file); ceph_check_caps(ci, 0, NULL); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 264ab701154f..34bc35084ae3 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -732,21 +732,21 @@ static int __choose_mds(struct ceph_mds_client *mdsc, } } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = NULL; if (mode == USE_AUTH_MDS) cap = ci->i_auth_cap; if (!cap && !RB_EMPTY_ROOT(&ci->i_caps)) cap = rb_entry(rb_first(&ci->i_caps), struct ceph_cap, ci_node); if (!cap) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto random; } mds = cap->session->s_mds; dout("choose_mds %p %llx.%llx mds%d (%scap %p)\n", inode, ceph_vinop(inode), mds, cap == ci->i_auth_cap ? "auth " : "", cap); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return mds; random: @@ -951,7 +951,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, dout("removing cap %p, ci is %p, inode is %p\n", cap, ci, &ci->vfs_inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_remove_cap(cap); if (!__ceph_is_any_real_caps(ci)) { struct ceph_mds_client *mdsc = @@ -984,7 +984,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, } spin_unlock(&mdsc->cap_dirty_lock); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); while (drop--) iput(inode); return 0; @@ -1015,10 +1015,10 @@ static int wake_up_session_cb(struct inode *inode, struct ceph_cap *cap, wake_up_all(&ci->i_cap_wq); if (arg) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_wanted_max_size = 0; ci->i_requested_max_size = 0; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } return 0; } @@ -1151,7 +1151,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) if (session->s_trim_caps <= 0) return -1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); mine = cap->issued | cap->implemented; used = __ceph_caps_used(ci); oissued = __ceph_caps_issued_other(ci, cap); @@ -1170,7 +1170,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) __ceph_remove_cap(cap); } else { /* try to drop referring dentries */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); d_prune_aliases(inode); dout("trim_caps_cb %p cap %p pruned, count now %d\n", inode, cap, atomic_read(&inode->i_count)); @@ -1178,7 +1178,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return 0; } @@ -1296,7 +1296,7 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) i_flushing_item); struct inode *inode = &ci->vfs_inode; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_cap_flush_seq <= want_flush_seq) { dout("check_cap_flush still flushing %p " "seq %lld <= %lld to mds%d\n", inode, @@ -1304,7 +1304,7 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) session->s_mds); ret = 0; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } mutex_unlock(&session->s_mutex); ceph_put_mds_session(session); @@ -2011,10 +2011,10 @@ void ceph_invalidate_dir_request(struct ceph_mds_request *req) struct ceph_inode_info *ci = ceph_inode(inode); dout("invalidate_dir_request %p (D_COMPLETE, lease(s))\n", inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ceph_dir_clear_complete(inode); ci->i_release_count++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (req->r_dentry) ceph_invalidate_dentry_lease(req->r_dentry); @@ -2422,7 +2422,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, if (err) goto out_free; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap->seq = 0; /* reset cap seq */ cap->issue_seq = 0; /* and issue_seq */ @@ -2445,7 +2445,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, rec.v1.pathbase = cpu_to_le64(pathbase); reclen = sizeof(rec.v1); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (recon_state->flock) { int num_fcntl_locks, num_flock_locks; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 4bb239921dbd..a50ca0e39475 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -20,7 +20,7 @@ * * mdsc->snap_rwsem * - * inode->i_lock + * ci->i_ceph_lock * mdsc->snap_flush_lock * mdsc->cap_delay_lock * diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index e26437191333..a559c80f127a 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -446,7 +446,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) return; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); used = __ceph_caps_used(ci); dirty = __ceph_caps_dirty(ci); @@ -528,7 +528,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) kfree(capsnap); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -537,7 +537,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) * * If capsnap can now be flushed, add to snap_flush list, and return 1. * - * Caller must hold i_lock. + * Caller must hold i_ceph_lock. */ int __ceph_finish_cap_snap(struct ceph_inode_info *ci, struct ceph_cap_snap *capsnap) @@ -739,9 +739,9 @@ static void flush_snaps(struct ceph_mds_client *mdsc) inode = &ci->vfs_inode; ihold(inode); spin_unlock(&mdsc->snap_flush_lock); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_flush_snaps(ci, &session, 0); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); iput(inode); spin_lock(&mdsc->snap_flush_lock); } @@ -847,7 +847,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, continue; ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ci->i_snap_realm) goto skip_inode; /* @@ -876,7 +876,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, oldrealm = ci->i_snap_realm; ci->i_snap_realm = realm; spin_unlock(&realm->inodes_with_caps_lock); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_get_snap_realm(mdsc, realm); ceph_put_snap_realm(mdsc, oldrealm); @@ -885,7 +885,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, continue; skip_inode: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); iput(inode); } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 01bf189e08a9..edcbf3774a56 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -220,7 +220,7 @@ struct ceph_dentry_info { * The locking for D_COMPLETE is a bit odd: * - we can clear it at almost any time (see ceph_d_prune) * - it is only meaningful if: - * - we hold dir inode i_lock + * - we hold dir inode i_ceph_lock * - we hold dir FILE_SHARED caps * - the dentry D_COMPLETE is set */ @@ -250,6 +250,8 @@ struct ceph_inode_xattrs_info { struct ceph_inode_info { struct ceph_vino i_vino; /* ceph ino + snap */ + spinlock_t i_ceph_lock; + u64 i_version; u32 i_time_warp_seq; @@ -271,7 +273,7 @@ struct ceph_inode_info { struct ceph_inode_xattrs_info i_xattrs; - /* capabilities. protected _both_ by i_lock and cap->session's + /* capabilities. protected _both_ by i_ceph_lock and cap->session's * s_mutex. */ struct rb_root i_caps; /* cap list */ struct ceph_cap *i_auth_cap; /* authoritative cap, if any */ @@ -437,18 +439,18 @@ static inline void ceph_i_clear(struct inode *inode, unsigned mask) { struct ceph_inode_info *ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_ceph_flags &= ~mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } static inline void ceph_i_set(struct inode *inode, unsigned mask) { struct ceph_inode_info *ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_ceph_flags |= mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } static inline bool ceph_i_test(struct inode *inode, unsigned mask) @@ -456,9 +458,9 @@ static inline bool ceph_i_test(struct inode *inode, unsigned mask) struct ceph_inode_info *ci = ceph_inode(inode); bool r; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); r = (ci->i_ceph_flags & mask) == mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return r; } @@ -508,9 +510,9 @@ extern int __ceph_caps_issued_other(struct ceph_inode_info *ci, static inline int ceph_caps_issued(struct ceph_inode_info *ci) { int issued; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); issued = __ceph_caps_issued(ci, NULL); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return issued; } @@ -518,9 +520,9 @@ static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) { int r; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); r = __ceph_caps_issued_mask(ci, mask, touch); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return r; } @@ -743,10 +745,9 @@ extern int ceph_add_cap(struct inode *inode, extern void __ceph_remove_cap(struct ceph_cap *cap); static inline void ceph_remove_cap(struct ceph_cap *cap) { - struct inode *inode = &cap->ci->vfs_inode; - spin_lock(&inode->i_lock); + spin_lock(&cap->ci->i_ceph_lock); __ceph_remove_cap(cap); - spin_unlock(&inode->i_lock); + spin_unlock(&cap->ci->i_ceph_lock); } extern void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 96c6739a0280..a5e36e4488a7 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -343,8 +343,8 @@ void __ceph_destroy_xattrs(struct ceph_inode_info *ci) } static int __build_xattrs(struct inode *inode) - __releases(inode->i_lock) - __acquires(inode->i_lock) + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) { u32 namelen; u32 numattr = 0; @@ -372,7 +372,7 @@ start: end = p + ci->i_xattrs.blob->vec.iov_len; ceph_decode_32_safe(&p, end, numattr, bad); xattr_version = ci->i_xattrs.version; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); xattrs = kcalloc(numattr, sizeof(struct ceph_xattr *), GFP_NOFS); @@ -387,7 +387,7 @@ start: goto bad_lock; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_xattrs.version != xattr_version) { /* lost a race, retry */ for (i = 0; i < numattr; i++) @@ -418,7 +418,7 @@ start: return err; bad_lock: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); bad: if (xattrs) { for (i = 0; i < numattr; i++) @@ -512,7 +512,7 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, if (vxattrs) vxattr = ceph_match_vxattr(vxattrs, name); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("getxattr %p ver=%lld index_ver=%lld\n", inode, ci->i_xattrs.version, ci->i_xattrs.index_version); @@ -520,14 +520,14 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { goto get_xattr; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* get xattrs from mds (if we don't already have them) */ err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); if (err) return err; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (vxattr && vxattr->readonly) { err = vxattr->getxattr_cb(ci, value, size); @@ -558,7 +558,7 @@ get_xattr: memcpy(value, xattr->val, xattr->val_len); out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return err; } @@ -573,7 +573,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) u32 len; int i; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("listxattr %p ver=%lld index_ver=%lld\n", inode, ci->i_xattrs.version, ci->i_xattrs.index_version); @@ -581,13 +581,13 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { goto list_xattr; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); if (err) return err; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); err = __build_xattrs(inode); if (err < 0) @@ -619,7 +619,7 @@ list_xattr: } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return err; } @@ -739,7 +739,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, if (!xattr) goto out; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); retry: issued = __ceph_caps_issued(ci, NULL); if (!(issued & CEPH_CAP_XATTR_EXCL)) @@ -752,12 +752,12 @@ retry: required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { struct ceph_buffer *blob = NULL; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout(" preaallocating new blob size=%d\n", required_blob_size); blob = ceph_buffer_new(required_blob_size, GFP_NOFS); if (!blob) goto out; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_xattrs.prealloc_blob) ceph_buffer_put(ci->i_xattrs.prealloc_blob); ci->i_xattrs.prealloc_blob = blob; @@ -770,13 +770,13 @@ retry: dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); return err; do_sync: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_sync_setxattr(dentry, name, value, size, flags); out: kfree(newname); @@ -833,7 +833,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) return -EOPNOTSUPP; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __build_xattrs(inode); issued = __ceph_caps_issued(ci, NULL); dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); @@ -846,12 +846,12 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); return err; do_sync: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_send_removexattr(dentry, name); return err; } -- cgit From 28d8ea2d568534026ccda3e8936f5ea1e04a86a1 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 11 Nov 2011 05:10:39 +0000 Subject: fsl_pq_mdio: Clean up tbi address configuration The code for setting the address of the internal TBI PHY was convoluted enough without a maze of ifdefs. Clean it up a bit so we allow the logic to fail down to -ENODEV at the end of the if/else ladder, rather than using ifdefs to repeat the same failure code over and over. Also, remove the support for the auto-configuration. I'm not aware of anyone using it, and it ends up using the bus mutex before it's been initialized. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 53 +++++----------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 52f4e8ad48e7..4d9f84b8ab97 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -183,28 +183,10 @@ void fsl_pq_mdio_bus_name(char *name, struct device_node *np) } EXPORT_SYMBOL_GPL(fsl_pq_mdio_bus_name); -/* Scan the bus in reverse, looking for an empty spot */ -static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) -{ - int i; - - for (i = PHY_MAX_ADDR; i > 0; i--) { - u32 phy_id; - - if (get_phy_id(new_bus, i, &phy_id)) - return -1; - - if (phy_id == 0xffffffff) - break; - } - - return i; -} - -#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) { +#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) struct gfar __iomem *enet_regs; /* @@ -220,15 +202,15 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct devi } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || of_device_is_compatible(np, "fsl,etsec2-tbi")) { return of_iomap(np, 1); - } else - return NULL; -} + } #endif + return NULL; +} -#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) { +#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) struct device_node *np = NULL; int err = 0; @@ -261,9 +243,10 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) return err; else return -EINVAL; -} +#else + return -ENODEV; #endif - +} static int fsl_pq_mdio_probe(struct platform_device *ofdev) { @@ -339,19 +322,13 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) of_device_is_compatible(np, "fsl,etsec2-mdio") || of_device_is_compatible(np, "fsl,etsec2-tbi") || of_device_is_compatible(np, "gianfar")) { -#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) tbipa = get_gfar_tbipa(regs, np); if (!tbipa) { err = -EINVAL; goto err_free_irqs; } -#else - err = -ENODEV; - goto err_free_irqs; -#endif } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || of_device_is_compatible(np, "ucc_geth_phy")) { -#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) u32 id; static u32 mii_mng_master; @@ -364,10 +341,6 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) mii_mng_master = id; ucc_set_qe_mux_mii_mng(id - 1); } -#else - err = -ENODEV; - goto err_free_irqs; -#endif } else { err = -ENODEV; goto err_free_irqs; @@ -386,16 +359,6 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) } if (tbiaddr == -1) { - out_be32(tbipa, 0); - - tbiaddr = fsl_pq_mdio_find_free(new_bus); - } - - /* - * We define TBIPA at 0 to be illegal, opting to fail for boards that - * have PHYs at 1-31, rather than change tbipa and rescan. - */ - if (tbiaddr == 0) { err = -EBUSY; goto err_free_irqs; -- cgit From 15062e6a8524f5977f2cbdf6e3eb2f144262f74e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Dec 2011 09:02:21 +0100 Subject: mac80211: fix another race in aggregation start Emmanuel noticed that when mac80211 stops the queues for aggregation that can leave a packet pending. This packet will be given to the driver after the AMPDU callback, but as a non-aggregated packet which messes up the sequence number etc. I also noticed by looking at the code that if packets are being processed while we clear the WANT_START bit, they might see it cleared already and queue up on tid_tx->pending. If the driver then rejects the new aggregation session we leak the packet. Fix both of these issues by changing this code to not stop the queues at all. Instead, let packets queue up on the tid_tx->pending queue instead of letting them get to the driver, and add code to recover properly in case the driver rejects the session. (The patch looks large because it has to move two functions to before their new use.) Cc: stable@vger.kernel.org Reported-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 86 ++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 331472ce038c..d448f7a3dbc0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -302,6 +302,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) __release(agg_queue); } +/* + * splice packets from the STA's pending to the local pending, + * requires a call to ieee80211_agg_splice_finish later + */ +static void __acquires(agg_queue) +ieee80211_agg_splice_packets(struct ieee80211_local *local, + struct tid_ampdu_tx *tid_tx, u16 tid) +{ + int queue = ieee80211_ac_from_tid(tid); + unsigned long flags; + + ieee80211_stop_queue_agg(local, tid); + + if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" + " from the pending queue\n", tid)) + return; + + if (!skb_queue_empty(&tid_tx->pending)) { + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + /* copy over remaining packets */ + skb_queue_splice_tail_init(&tid_tx->pending, + &local->pending[queue]); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + } +} + +static void __releases(agg_queue) +ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) +{ + ieee80211_wake_queue_agg(local, tid); +} + void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) { struct tid_ampdu_tx *tid_tx; @@ -313,19 +345,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* - * While we're asking the driver about the aggregation, - * stop the AC queue so that we don't have to worry - * about frames that came in while we were doing that, - * which would require us to put them to the AC pending - * afterwards which just makes the code more complex. + * Start queuing up packets for this aggregation session. + * We're going to release them once the driver is OK with + * that. */ - ieee80211_stop_queue_agg(local, tid); - clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); /* - * make sure no packets are being processed to get - * valid starting sequence number + * Make sure no packets are being processed. This ensures that + * we have a valid starting sequence number and that in-flight + * packets have been flushed out and no packets for this TID + * will go into the driver during the ampdu_action call. */ synchronize_net(); @@ -339,17 +369,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); + ieee80211_agg_splice_packets(local, tid_tx, tid); ieee80211_assign_tid_tx(sta, tid, NULL); + ieee80211_agg_splice_finish(local, tid); spin_unlock_bh(&sta->lock); - ieee80211_wake_queue_agg(local, tid); kfree_rcu(tid_tx, rcu_head); return; } - /* we can take packets again now */ - ieee80211_wake_queue_agg(local, tid); - /* activate the timer for the recipient's addBA response */ mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -465,38 +493,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, } EXPORT_SYMBOL(ieee80211_start_tx_ba_session); -/* - * splice packets from the STA's pending to the local pending, - * requires a call to ieee80211_agg_splice_finish later - */ -static void __acquires(agg_queue) -ieee80211_agg_splice_packets(struct ieee80211_local *local, - struct tid_ampdu_tx *tid_tx, u16 tid) -{ - int queue = ieee80211_ac_from_tid(tid); - unsigned long flags; - - ieee80211_stop_queue_agg(local, tid); - - if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" - " from the pending queue\n", tid)) - return; - - if (!skb_queue_empty(&tid_tx->pending)) { - spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - /* copy over remaining packets */ - skb_queue_splice_tail_init(&tid_tx->pending, - &local->pending[queue]); - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - } -} - -static void __releases(agg_queue) -ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) -{ - ieee80211_wake_queue_agg(local, tid); -} - static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { -- cgit From 91ddff8a3b9cc7ac2252aca138220939cf6cc2cf Mon Sep 17 00:00:00 2001 From: Philipp Dreimann Date: Wed, 7 Dec 2011 13:43:31 -0600 Subject: rtl8192{ce,cu,de,se}: avoid problems because of possible ERFOFF -> ERFSLEEP transition In drivers rtl8192ce, rtl8192cu, rtl8192se, and rtl8192de, break statements would allow ppsc->rfpwr_state to be changed to ERFSLEEP even though the device is actually in ERFOFF. Signed-off-by: Philipp Dreimann Signed-off-by: Larry Finger Cc: Stable Cc: Chaoming Li Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192de/phy.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 592a10ac5929..3b585aadabfc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -569,7 +569,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP:{ if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 72852900df84..e49cf2244c75 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -548,7 +548,7 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 3ac7af1c5509..0883349e1c83 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3374,7 +3374,7 @@ bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index f27171af979c..f10ac1ad9087 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -602,7 +602,7 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { -- cgit From 807cc4b1201e82769f7435211310f5691dcb704d Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 16 Nov 2011 20:01:43 +0100 Subject: spi/ath79: fix compile error due to missing include Whithout including 'linux/module.h' spi-ath79 driver fails to compile with the these errors: drivers/spi/spi-ath79.c:273:12: error: 'THIS_MODULE' undeclared here (not in a function) drivers/spi/spi-ath79.c:278:20: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-ath79.c:278:1: warning: data definition has no type or storage class drivers/spi/spi-ath79.c:278:1: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' drivers/spi/spi-ath79.c:278:20: warning: function declaration isn't a prototype drivers/spi/spi-ath79.c:279:15: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-ath79.c:279:1: warning: data definition has no type or storage class drivers/spi/spi-ath79.c:279:1: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' drivers/spi/spi-ath79.c:279:15: warning: function declaration isn't a prototype drivers/spi/spi-ath79.c:280:16: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-ath79.c:280:1: warning: data definition has no type or storage class drivers/spi/spi-ath79.c:280:1: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE' drivers/spi/spi-ath79.c:280:16: warning: function declaration isn't a prototype drivers/spi/spi-ath79.c:281:14: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-ath79.c:281:1: warning: data definition has no type or storage class drivers/spi/spi-ath79.c:281:1: warning: type defaults to 'int' in declaration of 'MODULE_ALIAS' drivers/spi/spi-ath79.c:281:14: warning: function declaration isn't a prototype Signed-off-by: Gabor Juhos Signed-off-by: Wolfram Sang --- drivers/spi/spi-ath79.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 024b48aed5ca..acc88b4d2869 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include -- cgit From 00d2952caa6b0b2cd113494ae39f08c4663f371b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 24 Nov 2011 11:10:51 +0800 Subject: spi/nuc900: Include linux/module.h Include linux/module.h to fix below build error: CC drivers/spi/spi-nuc900.o drivers/spi/spi-nuc900.c:484: error: 'THIS_MODULE' undeclared here (not in a function) drivers/spi/spi-nuc900.c:489: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-nuc900.c:489: warning: data definition has no type or storage class drivers/spi/spi-nuc900.c:489: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' drivers/spi/spi-nuc900.c:489: warning: function declaration isn't a prototype drivers/spi/spi-nuc900.c:490: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-nuc900.c:490: warning: data definition has no type or storage class drivers/spi/spi-nuc900.c:490: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' drivers/spi/spi-nuc900.c:490: warning: function declaration isn't a prototype drivers/spi/spi-nuc900.c:491: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-nuc900.c:491: warning: data definition has no type or storage class drivers/spi/spi-nuc900.c:491: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE' drivers/spi/spi-nuc900.c:491: warning: function declaration isn't a prototype drivers/spi/spi-nuc900.c:492: error: expected declaration specifiers or '...' before string constant drivers/spi/spi-nuc900.c:492: warning: data definition has no type or storage class drivers/spi/spi-nuc900.c:492: warning: type defaults to 'int' in declaration of 'MODULE_ALIAS' drivers/spi/spi-nuc900.c:492: warning: function declaration isn't a prototype make[2]: *** [drivers/spi/spi-nuc900.o] Error 1 make[1]: *** [drivers/spi] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Acked-by: Paul Gortmaker Signed-off-by: Wolfram Sang --- drivers/spi/spi-nuc900.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 21c70b2b8311..182e9c873822 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -8,6 +8,7 @@ * */ +#include #include #include #include -- cgit From d9ddcec35d713dd33dc20dcb4db84db35f9956a6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 7 Dec 2011 21:18:16 +0100 Subject: spi/fsl-espi: disable CONFIG_SPI_FSL_ESPI=m build When spi_fsl_espi is chosen to be built as a module, there is a build error because we test only CONFIG_SPI_FSL_ESPI in declaration of struct mpc8xxx_spi in drivers/spi/spi_fsl_lib.h. Also some called functions are not exported. So we forbid CONFIG_SPI_FSL_ESPI to be tristate here. The error looks like: drivers/spi/spi_fsl_espi.c: In function 'fsl_espi_bufs': drivers/spi/spi_fsl_espi.c:232: error: 'struct mpc8xxx_spi' has no member named 'len' ... Signed-off-by: Jiri Slaby Acked-by: Kumar Gala Cc: Grant Likely Signed-off-by: Wolfram Sang --- drivers/spi/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a1fd73df5416..8ba4510a9519 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -199,7 +199,7 @@ config SPI_FSL_LIB depends on FSL_SOC config SPI_FSL_SPI - tristate "Freescale SPI controller" + bool "Freescale SPI controller" depends on FSL_SOC select SPI_FSL_LIB help @@ -208,7 +208,7 @@ config SPI_FSL_SPI MPC8569 uses the controller in QE mode, MPC8610 in cpu mode. config SPI_FSL_ESPI - tristate "Freescale eSPI controller" + bool "Freescale eSPI controller" depends on FSL_SOC select SPI_FSL_LIB help -- cgit From c65b53ba4f9ca4520078bab23099579da3bf0446 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Sat, 19 Nov 2011 13:08:10 +0100 Subject: spi/gpio: fix section mismatch warning Fixes: The function __devinit spi_gpio_probe() references a function __init spi_gpio_alloc.isra.4(). If spi_gpio_alloc.isra.4 is only used by spi_gpio_probe then annotate spi_gpio_alloc.isra.4 with a matching annotation. [wsa: fix spi_gpio_request(), too] Signed-off-by: Manuel Lauss Signed-off-by: Wolfram Sang --- drivers/spi/spi-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index e093d3ec41ba..0094c645ff0d 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -256,7 +256,7 @@ static void spi_gpio_cleanup(struct spi_device *spi) spi_bitbang_cleanup(spi); } -static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) +static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in) { int value; @@ -270,7 +270,7 @@ static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) return value; } -static int __init +static int __devinit spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label, u16 *res_flags) { -- cgit From fe6b91f47080eb17d21cbf2a39311877d57f6938 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 6 Dec 2011 23:24:52 +0100 Subject: PM / Driver core: leave runtime PM enabled during system shutdown Disabling all runtime PM during system shutdown turns out not to be a good idea, because some devices may need to be woken up from a low-power state at that time. The whole point of disabling runtime PM for system shutdown was to prevent untimely runtime-suspend method calls. This patch (as1504) accomplishes the same result by incrementing the usage count for each device and waiting for ongoing runtime-PM callbacks to finish. This is what we already do during system suspend and hibernation, which makes sense since the shutdown method is pretty much a legacy analog of the pm->poweroff method. This fixes a recent regression on some OMAP systems introduced by commit af8db1508f2c9f3b6e633e2d2d906c6557c617f9 (PM / driver core: disable device's runtime PM during shutdown). Reported-and-tested-by: NeilBrown Signed-off-by: Alan Stern Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/base/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index d8b3d89db043..919daa7cd5b1 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1743,8 +1743,10 @@ void device_shutdown(void) */ list_del_init(&dev->kobj.entry); spin_unlock(&devices_kset->list_lock); - /* Disable all device's runtime power management */ - pm_runtime_disable(dev); + + /* Don't allow any more runtime suspends */ + pm_runtime_get_noresume(dev); + pm_runtime_barrier(dev); if (dev->bus && dev->bus->shutdown) { dev_dbg(dev, "shutdown\n"); -- cgit From 062c05c46bd4358aad7a0e0cb5ffeb98ab935286 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 7 Dec 2011 19:50:42 -0500 Subject: Btrfs: try to allocate from cluster even at LOOP_NO_EMPTY_SIZE If we reach LOOP_NO_EMPTY_SIZE, we won't even try to use a cluster that others might have set up. Odds are that there won't be one, but if someone else succeeded in setting it up, we might as well use it, even if we don't try to set up a cluster again. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 813c6bb96c9a..db0b23b14f20 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5285,15 +5285,10 @@ alloc: spin_unlock(&block_group->free_space_ctl->tree_lock); /* - * Ok we want to try and use the cluster allocator, so lets look - * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will - * have tried the cluster allocator plenty of times at this - * point and not have found anything, so we are likely way too - * fragmented for the clustering stuff to find anything, so lets - * just skip it and let the allocator find whatever block it can - * find + * Ok we want to try and use the cluster allocator, so + * lets look there */ - if (last_ptr && loop < LOOP_NO_EMPTY_SIZE) { + if (last_ptr) { /* * the refill lock keeps out other * people trying to start a new cluster @@ -5342,6 +5337,20 @@ alloc: } spin_unlock(&last_ptr->lock); refill_cluster: + /* If we are on LOOP_NO_EMPTY_SIZE, we can't + * set up a new clusters, so lets just skip it + * and let the allocator find whatever block + * it can find. If we reach this point, we + * will have tried the cluster allocator + * plenty of times and not have found + * anything, so we are likely way too + * fragmented for the clustering stuff to find + * anything. */ + if (loop >= LOOP_NO_EMPTY_SIZE) { + spin_unlock(&last_ptr->refill_lock); + goto unclustered_alloc; + } + /* * this cluster didn't work out, free it and * start over @@ -5389,6 +5398,7 @@ refill_cluster: goto loop; } +unclustered_alloc: offset = btrfs_find_space_for_alloc(block_group, search_start, num_bytes, empty_size); /* -- cgit From d7a4c45ec24b6c6773ff302c3c9cb5ed46c8e211 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 8 Dec 2011 10:07:53 +0900 Subject: ARM: SAMSUNG: remove duplicated header include This patch removes duplicated slab header for pwm backlight. arch/arm/plat-samsung/dev-backlight.c: slab.h is included more than once. Signed-off-by: Jingoo Han Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/dev-backlight.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c index e657305644cc..a976c023b286 100644 --- a/arch/arm/plat-samsung/dev-backlight.c +++ b/arch/arm/plat-samsung/dev-backlight.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include -- cgit From de611dd4078499d5aa5ae9655652687ae630585f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 8 Dec 2011 10:08:38 +0900 Subject: ARM: S5PV210: Set 1000ns as PWM backlight period on SMDKV210 The SMDK board uses LT3591 as backlight LED driver of LTE480WV LCD. According to the LT3591 datasheet, the switching frequency should be 1MHz. So, PWM period is calculated by following formula: PWM period = 1/switching frequency = 1/1MHz = 1000ns Thus, the PWM backlight period should be 1000ns. Signed-off-by: Jingoo Han Signed-off-by: Kukjin Kim --- arch/arm/mach-s5pv210/mach-smdkv210.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index a9106c392398..8662ef6e5681 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -273,6 +273,7 @@ static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = { static struct platform_pwm_backlight_data smdkv210_bl_data = { .pwm_id = 3, + .pwm_period_ns = 1000, }; static void __init smdkv210_map_io(void) -- cgit From e248cd5d5f1c28c82781d4122dddd1b7c3d7b46f Mon Sep 17 00:00:00 2001 From: Amit Daniel Kachhap Date: Thu, 8 Dec 2011 10:07:08 +0900 Subject: ARM: EXYNOS: Fix for stall in case of cpu hotplug or sleep This patch adds remove_irq in place of disable_irq which is correct equivalent function for setup_irq used in exynos4_mct_tick_init. Signed-off-by: Amit Daniel Kachhap Tested-by: Inderpal Singh Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/mct.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 97343df8f132..959f2514796c 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -428,9 +428,13 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt) void local_timer_stop(struct clock_event_device *evt) { + unsigned int cpu = smp_processor_id(); evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); if (mct_int_type == MCT_INT_SPI) - disable_irq(evt->irq); + if (cpu == 0) + remove_irq(evt->irq, &mct_tick0_event_irq); + else + remove_irq(evt->irq, &mct_tick1_event_irq); else disable_percpu_irq(IRQ_MCT_LOCALTIMER); } -- cgit From 991a6c7d94a9be53f0302a1ada06e66a6ebf51e8 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Thu, 8 Dec 2011 10:04:49 +0900 Subject: ARM: EXYNOS: Fix build error without CONFIG_LOCAL_TIMERS arch/arm/mach-exynos/mct.c: In function 'exynos4_timer_resources': arch/arm/mach-exynos/mct.c:450: error: 'exynos4_mct_tick_isr' undeclared (first use in this function) arch/arm/mach-exynos/mct.c:450: error: (Each undeclared identifier is reported only once arch/arm/mach-exynos/mct.c:450: error: for each function it appears in.) make[1]: *** [arch/arm/mach-exynos/mct.o] Error 1 Reported-by: Kyungmin Park Acked-by: Changhwan Youn Signed-off-by: Kukjin Kim Cc: Marc Zyngier --- arch/arm/mach-exynos/mct.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 959f2514796c..85b5527d0918 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -44,8 +44,6 @@ struct mct_clock_event_device { char name[10]; }; -static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); - static void exynos4_mct_write(unsigned int value, void *addr) { void __iomem *stat_addr; @@ -264,6 +262,9 @@ static void exynos4_clockevent_init(void) } #ifdef CONFIG_LOCAL_TIMERS + +static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); + /* Clock event handling */ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt) { @@ -447,6 +448,7 @@ static void __init exynos4_timer_resources(void) clk_rate = clk_get_rate(mct_clk); +#ifdef CONFIG_LOCAL_TIMERS if (mct_int_type == MCT_INT_PPI) { int err; @@ -456,6 +458,7 @@ static void __init exynos4_timer_resources(void) WARN(err, "MCT: can't request IRQ %d (%d)\n", IRQ_MCT_LOCALTIMER, err); } +#endif /* CONFIG_LOCAL_TIMERS */ } static void __init exynos4_timer_init(void) -- cgit From aed21ad28b1323b2807faea019e5ac388a7bc837 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 23 Nov 2011 11:44:41 -0600 Subject: writeback: comment on the bdi dirty threshold We do "floating proportions" to let active devices to grow its target share of dirty pages and stalled/inactive devices to decrease its target share over time. It works well except in the case of "an inactive disk suddenly goes busy", where the initial target share may be too small. To mitigate this, bdi_position_ratio() has the below line to raise a small bdi_thresh when it's safe to do so, so that the disk be feed with enough dirty pages for efficient IO and in turn fast rampup of bdi_thresh: bdi_thresh = max(bdi_thresh, (limit - dirty) / 8); balance_dirty_pages() normally does negative feedback control which adjusts ratelimit to balance the bdi dirty pages around the target. In some extreme cases when that is not enough, it will have to block the tasks completely until the bdi dirty pages drop below bdi_thresh. Acked-by: Jan Kara Acked-by: Peter Zijlstra Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 71252486bc6f..155efca4c123 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -411,8 +411,13 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) * * Returns @bdi's dirty limit in pages. The term "dirty" in the context of * dirty balancing includes all PG_dirty, PG_writeback and NFS unstable pages. - * And the "limit" in the name is not seriously taken as hard limit in - * balance_dirty_pages(). + * + * Note that balance_dirty_pages() will only seriously take it as a hard limit + * when sleeping max_pause per page is not enough to keep the dirty pages under + * control. For example, when the device is completely stalled due to some error + * conditions, or when there are 1000 dd tasks writing to a slow 10MB/s USB key. + * In the other normal situations, it acts more gently by throttling the tasks + * more (rather than completely block them) when the bdi dirty pages go high. * * It allocates high/low dirty limits to fast/slow devices, in order to prevent * - starving fast devices @@ -594,6 +599,13 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, */ if (unlikely(bdi_thresh > thresh)) bdi_thresh = thresh; + /* + * It's very possible that bdi_thresh is close to 0 not because the + * device is slow, but that it has remained inactive for long time. + * Honour such devices a reasonable good (hopefully IO efficient) + * threshold, so that the occasional writes won't be blocked and active + * writes can rampup the threshold quickly. + */ bdi_thresh = max(bdi_thresh, (limit - dirty) / 8); /* * scale global setpoint to bdi's: -- cgit From c5c6343c4d75f9d3226e05a72e7861e967fc8099 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 2 Dec 2011 10:21:33 -0600 Subject: writeback: permit through good bdi even when global dirty exceeded On a system with 1 local mount and 1 NFS mount, if the NFS server becomes not responding when dd to the NFS mount, the NFS dirty pages may exceed the global dirty limit and _every_ task involving writing will be blocked. The whole system appears unresponsive. The workaround is to permit through the bdi's that only has a small number of dirty pages. The number chosen (bdi_stat_error pages) is not enough to enable the local disk to run in optimal throughput, however is enough to make the system responsive on a broken NFS mount. The user can then kill the dirtiers on the NFS mount and increase the global dirty limit to bring up the local disk's throughput. It risks allowing dirty pages to grow much larger than the global dirty limit when there are 1000+ mounts, however that's very unlikely to happen, especially in low memory profiles. Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 155efca4c123..17403e3a7c89 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1148,6 +1148,19 @@ pause: if (task_ratelimit) break; + /* + * In the case of an unresponding NFS server and the NFS dirty + * pages exceeds dirty_thresh, give the other good bdi's a pipe + * to go through, so that tasks on them still remain responsive. + * + * In theory 1 page is enough to keep the comsumer-producer + * pipe going: the flusher cleans 1 page => the task dirties 1 + * more page. However bdi_dirty has accounting errors. So use + * the larger and more IO friendly bdi_stat_error. + */ + if (bdi_dirty <= bdi_stat_error(bdi)) + break; + if (fatal_signal_pending(current)) break; } -- cgit From 82e230a07de3812a5e87a27979f033dad59172e3 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 2 Dec 2011 18:21:51 -0600 Subject: writeback: set max_pause to lowest value on zero bdi_dirty Some trace shows lots of bdi_dirty=0 lines where it's actually some small value if w/o the accounting errors in the per-cpu bdi stats. In this case the max pause time should really be set to the smallest (non-zero) value to avoid IO queue underrun and improve throughput. Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 17403e3a7c89..50f08241f981 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -989,8 +989,7 @@ static unsigned long bdi_max_pause(struct backing_dev_info *bdi, * * 8 serves as the safety ratio. */ - if (bdi_dirty) - t = min(t, bdi_dirty * HZ / (8 * bw + 1)); + t = min(t, bdi_dirty * HZ / (8 * bw + 1)); /* * The pause time will be settled within range (max_pause/4, max_pause). -- cgit From 053bf34f5aff499d7b595c500bbab5cbab3636e7 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Mon, 7 Nov 2011 21:55:11 +0530 Subject: mmc: omap_hsmmc: DMA unmap only once in case of MMC error Reported by Russell King: mmcblk0: error -84 transferring data, sector 149201, nr 64, cmd response 0x900, card status 0xb00 mmcblk0: retrying using single block read WARNING: at lib/dma-debug.c:811 check_unmap omap_hsmmc omap_hsmmc.0: DMA-API: device driver tries to free DMA memory it has not allocated [device address=0x0000000080933000] [size=20480 bytes] In case of an error dma_unmap() is issued in omap_hsmmc_dma_cleanup() and then again in omap_hsmmc_post_req(). Resolve this by clearing the host_cookie to indicate there is no DMA mapped memory to unmap. Signed-off-by: Per Forlin Tested-by: Balaji T K Tested-by: Russell King Signed-off-by: Chris Ball --- drivers/mmc/host/omap_hsmmc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 101cd31c8220..d5fe43d53c51 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1010,6 +1010,7 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) host->data->sg_len, omap_hsmmc_get_dma_dir(host, host->data)); omap_free_dma(dma_ch); + host->data->host_cookie = 0; } host->data = NULL; } @@ -1575,8 +1576,10 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct mmc_data *data = mrq->data; if (host->use_dma) { - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - omap_hsmmc_get_dma_dir(host, data)); + if (data->host_cookie) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); data->host_cookie = 0; } } -- cgit From 1d23f178d56ae1349b4fc5108ac8f4f8cdc92afc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 8 Dec 2011 15:49:12 +1100 Subject: md: refine interpretation of "hold_active == UNTIL_IOCTL". We like md devices to disappear when they really are not needed. However it is not possible to tell from the current state whether it is needed or not. We can only tell from recent history of changes. In particular immediately after we create an md device it looks very similar to immediately after we have finished with it. So we always preserve a newly created md device until something significant happens. This state is stored in 'hold_active'. The normal case is to keep it until an ioctl happens, as that will normally either activate it, or explicitly de-activate it. If it doesn't then it was probably created by mistake and it is now time to get rid of it. We can also modify an array via sysfs (instead of via ioctl) and we currently treat any change via sysfs like an ioctl as a sign that if it now isn't more active, it should be destroyed. However this is not appropriate as changes made via sysfs are more gradual so we should look for a more definitive change. So this patch only clears 'hold_active' from UNTIL_IOCTL to clear when the array_state is changed via sysfs. Other changes via sysfs are ignored. Signed-off-by: NeilBrown --- drivers/md/md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 84acfe7d10e4..93b0da133507 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3788,6 +3788,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) if (err) return err; else { + if (mddev->hold_active == UNTIL_IOCTL) + mddev->hold_active = 0; sysfs_notify_dirent_safe(mddev->sysfs_state); return len; } @@ -4508,8 +4510,6 @@ md_attr_store(struct kobject *kobj, struct attribute *attr, if (!capable(CAP_SYS_ADMIN)) return -EACCES; rv = mddev_lock(mddev); - if (mddev->hold_active == UNTIL_IOCTL) - mddev->hold_active = 0; if (!rv) { rv = entry->store(mddev, page, length); mddev_unlock(mddev); -- cgit From af8a24347f966ab9fae6b0f127d1fbc9d6932d3a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 8 Dec 2011 15:49:46 +1100 Subject: md: take a reference to mddev during sysfs access. When we are accessing an mddev via sysfs we know that the mddev cannot disappear because it has an embedded kobj which is refcounted by sysfs. And we also take the mddev_lock. However this is not enough. The final mddev_put could have been called and the mddev_delayed_delete is waiting for sysfs to let go so it can destroy the kobj and mddev. In this state there are a lot of changes that should not be attempted. To to guard against this we: - initialise mddev->all_mddevs in on last put so the state can be easily detected. - in md_attr_show and md_attr_store, check ->all_mddevs under all_mddevs_lock and mddev_get the mddev if it still appears to be active. This means that if we get to sysfs as the mddev is being deleted we will get -EBUSY. rdev_attr_store and rdev_attr_show are similar but already have sufficient protection. They check that rdev->mddev still points to mddev after taking mddev_lock. As this is cleared before delayed removal which can only be requested under the mddev_lock, this ensure the rdev and mddev are still alive. Signed-off-by: NeilBrown --- drivers/md/md.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 93b0da133507..f97c3b2f2f89 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -570,7 +570,7 @@ static void mddev_put(struct mddev *mddev) mddev->ctime == 0 && !mddev->hold_active) { /* Array is not configured at all, and not held active, * so destroy it */ - list_del(&mddev->all_mddevs); + list_del_init(&mddev->all_mddevs); bs = mddev->bio_set; mddev->bio_set = NULL; if (mddev->gendisk) { @@ -4489,11 +4489,20 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) if (!entry->show) return -EIO; + spin_lock(&all_mddevs_lock); + if (list_empty(&mddev->all_mddevs)) { + spin_unlock(&all_mddevs_lock); + return -EBUSY; + } + mddev_get(mddev); + spin_unlock(&all_mddevs_lock); + rv = mddev_lock(mddev); if (!rv) { rv = entry->show(mddev, page); mddev_unlock(mddev); } + mddev_put(mddev); return rv; } @@ -4509,11 +4518,19 @@ md_attr_store(struct kobject *kobj, struct attribute *attr, return -EIO; if (!capable(CAP_SYS_ADMIN)) return -EACCES; + spin_lock(&all_mddevs_lock); + if (list_empty(&mddev->all_mddevs)) { + spin_unlock(&all_mddevs_lock); + return -EBUSY; + } + mddev_get(mddev); + spin_unlock(&all_mddevs_lock); rv = mddev_lock(mddev); if (!rv) { rv = entry->store(mddev, page, length); mddev_unlock(mddev); } + mddev_put(mddev); return rv; } -- cgit From 52c64152a935e63d9ff73ce823730c9a23dedbff Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 8 Dec 2011 16:22:48 +1100 Subject: md: bad blocks shouldn't cause a Blocked status on a Faulty device. Once a device is marked Faulty the badblocks - whether acknowledged or not - become irrelevant. So they shouldn't cause the device to be marked as Blocked. Without this patch, a process might write "-blocked" to clear the Blocked status, but while that will correctly fail the device, it won't remove the apparent 'blocked' status. Signed-off-by: NeilBrown --- drivers/md/md.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index f97c3b2f2f89..d730e8f513a7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2546,7 +2546,8 @@ state_show(struct md_rdev *rdev, char *page) sep = ","; } if (test_bit(Blocked, &rdev->flags) || - rdev->badblocks.unacked_exist) { + (rdev->badblocks.unacked_exist + && !test_bit(Faulty, &rdev->flags))) { len += sprintf(page+len, "%sblocked", sep); sep = ","; } -- cgit From 8bd2f0a05b361e07d48bb34398593f5f523946b3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 8 Dec 2011 16:26:08 +1100 Subject: md: ensure new badblocks are handled promptly. When we mark blocks as bad we need them to be acknowledged by the metadata handler promptly. For an in-kernel metadata handler that was already being done. But for an external metadata handler we need to alert it of the change by sending a notification through the sysfs file. This adds that notification. Signed-off-by: NeilBrown --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index d730e8f513a7..ee981737edfc 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7858,6 +7858,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, s + rdev->data_offset, sectors, acknowledged); if (rv) { /* Make sure they get written out promptly */ + sysfs_notify_dirent_safe(rdev->sysfs_state); set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags); md_wakeup_thread(rdev->mddev->thread); } -- cgit From 9283d8c5af4cdcb809e655acdf4be368afec8b58 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 8 Dec 2011 16:27:57 +1100 Subject: md/raid5: never wait for bad-block acks on failed device. Once a device is failed we really want to completely ignore it. It should go away soon anyway. In particular the presence of bad blocks on it should not cause us to block as we won't be trying to write there anyway. So as soon as we can check if a device is Faulty, do so and pretend that it is already gone if it is Faulty. Signed-off-by: NeilBrown --- drivers/md/raid5.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 297e26092178..b0dec01028f4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3036,6 +3036,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) if (dev->written) s->written++; rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && test_bit(Faulty, &rdev->flags)) + rdev = NULL; if (rdev) { is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS, &first_bad, &bad_sectors); @@ -3063,7 +3065,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) } } else if (test_bit(In_sync, &rdev->flags)) set_bit(R5_Insync, &dev->flags); - else if (!test_bit(Faulty, &rdev->flags)) { + else { /* in sync if before recovery_offset */ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) set_bit(R5_Insync, &dev->flags); -- cgit From c564a0cb9d0c7f4ac50f1e9ca8bc67fd66cd550f Mon Sep 17 00:00:00 2001 From: "Jett.Zhou" Date: Wed, 30 Nov 2011 14:32:54 +0800 Subject: ARM: sa1100: fix build error arm-eabi-4.4.3-ld:--defsym zreladdr=: syntax error make[2]: *** [arch/arm/boot/compressed/vmlinux] Error 1 make[1]: *** [arch/arm/boot/compressed/vmlinux] Error 2 make: *** [uImage] Error 2 Signed-off-by: Haojian Zhuang Signed-off-by: Jett.Zhou --- arch/arm/mach-sa1100/Makefile.boot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-sa1100/Makefile.boot b/arch/arm/mach-sa1100/Makefile.boot index 5a616f6e5612..f7951aa04562 100644 --- a/arch/arm/mach-sa1100/Makefile.boot +++ b/arch/arm/mach-sa1100/Makefile.boot @@ -1,5 +1,5 @@ -ifeq ($(CONFIG_ARCH_SA1100),y) - zreladdr-$(CONFIG_SA1111) += 0xc0208000 +ifeq ($(CONFIG_SA1111),y) + zreladdr-y += 0xc0208000 else zreladdr-y += 0xc0008000 endif -- cgit From 274bd4fb3ed6b72c1d77ef8850511f09fc6b8e4d Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 7 Dec 2011 20:08:40 -0500 Subject: Btrfs: try cluster but don't advance in search list When we find an existing cluster, we switch to its block group as the current block group, possibly skipping multiple blocks in the process. Furthermore, under heavy contention, multiple threads may fail to allocate from a cluster and then release just-created clusters just to proceed to create new ones in a different block group. This patch tries to allocate from an existing cluster regardless of its block group, and doesn't switch to that group, instead proceeding to try to allocate a cluster from the group it was iterating before the attempt. Signed-off-by: Alexandre Oliva Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 74 +++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index db0b23b14f20..05e1386b8bec 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5106,11 +5106,11 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root = orig_root->fs_info->extent_root; struct btrfs_free_cluster *last_ptr = NULL; struct btrfs_block_group_cache *block_group = NULL; + struct btrfs_block_group_cache *used_block_group; int empty_cluster = 2 * 1024 * 1024; int allowed_chunk_alloc = 0; int done_chunk_alloc = 0; struct btrfs_space_info *space_info; - int last_ptr_loop = 0; int loop = 0; int index = 0; int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? @@ -5172,6 +5172,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ideal_cache: block_group = btrfs_lookup_block_group(root->fs_info, search_start); + used_block_group = block_group; /* * we don't want to use the block group if it doesn't match our * allocation bits, or if its not cached. @@ -5209,6 +5210,7 @@ search: u64 offset; int cached; + used_block_group = block_group; btrfs_get_block_group(block_group); search_start = block_group->key.objectid; @@ -5294,49 +5296,33 @@ alloc: * people trying to start a new cluster */ spin_lock(&last_ptr->refill_lock); - if (!last_ptr->block_group || - last_ptr->block_group->ro || - !block_group_bits(last_ptr->block_group, data)) + used_block_group = last_ptr->block_group; + if (used_block_group != block_group && + (!used_block_group || + used_block_group->ro || + !block_group_bits(used_block_group, data))) { + used_block_group = block_group; goto refill_cluster; + } + + if (used_block_group != block_group) + btrfs_get_block_group(used_block_group); - offset = btrfs_alloc_from_cluster(block_group, last_ptr, - num_bytes, search_start); + offset = btrfs_alloc_from_cluster(used_block_group, + last_ptr, num_bytes, used_block_group->key.objectid); if (offset) { /* we have a block, we're done */ spin_unlock(&last_ptr->refill_lock); goto checks; } - spin_lock(&last_ptr->lock); - /* - * whoops, this cluster doesn't actually point to - * this block group. Get a ref on the block - * group is does point to and try again - */ - if (!last_ptr_loop && last_ptr->block_group && - last_ptr->block_group != block_group && - index <= - get_block_group_index(last_ptr->block_group)) { - - btrfs_put_block_group(block_group); - block_group = last_ptr->block_group; - btrfs_get_block_group(block_group); - spin_unlock(&last_ptr->lock); - spin_unlock(&last_ptr->refill_lock); - - last_ptr_loop = 1; - search_start = block_group->key.objectid; - /* - * we know this block group is properly - * in the list because - * btrfs_remove_block_group, drops the - * cluster before it removes the block - * group from the list - */ - goto have_block_group; + WARN_ON(last_ptr->block_group != used_block_group); + if (used_block_group != block_group) { + btrfs_put_block_group(used_block_group); + used_block_group = block_group; } - spin_unlock(&last_ptr->lock); refill_cluster: + BUG_ON(used_block_group != block_group); /* If we are on LOOP_NO_EMPTY_SIZE, we can't * set up a new clusters, so lets just skip it * and let the allocator find whatever block @@ -5357,8 +5343,6 @@ refill_cluster: */ btrfs_return_cluster_to_free_space(NULL, last_ptr); - last_ptr_loop = 0; - /* allocate a cluster in this block group */ ret = btrfs_find_space_cluster(trans, root, block_group, last_ptr, @@ -5425,14 +5409,14 @@ checks: search_start = stripe_align(root, offset); /* move on to the next group */ if (search_start + num_bytes >= search_end) { - btrfs_add_free_space(block_group, offset, num_bytes); + btrfs_add_free_space(used_block_group, offset, num_bytes); goto loop; } /* move on to the next group */ if (search_start + num_bytes > - block_group->key.objectid + block_group->key.offset) { - btrfs_add_free_space(block_group, offset, num_bytes); + used_block_group->key.objectid + used_block_group->key.offset) { + btrfs_add_free_space(used_block_group, offset, num_bytes); goto loop; } @@ -5440,14 +5424,14 @@ checks: ins->offset = num_bytes; if (offset < search_start) - btrfs_add_free_space(block_group, offset, + btrfs_add_free_space(used_block_group, offset, search_start - offset); BUG_ON(offset > search_start); - ret = btrfs_update_reserved_bytes(block_group, num_bytes, + ret = btrfs_update_reserved_bytes(used_block_group, num_bytes, alloc_type); if (ret == -EAGAIN) { - btrfs_add_free_space(block_group, offset, num_bytes); + btrfs_add_free_space(used_block_group, offset, num_bytes); goto loop; } @@ -5456,15 +5440,19 @@ checks: ins->offset = num_bytes; if (offset < search_start) - btrfs_add_free_space(block_group, offset, + btrfs_add_free_space(used_block_group, offset, search_start - offset); BUG_ON(offset > search_start); + if (used_block_group != block_group) + btrfs_put_block_group(used_block_group); btrfs_put_block_group(block_group); break; loop: failed_cluster_refill = false; failed_alloc = false; BUG_ON(index != get_block_group_index(block_group)); + if (used_block_group != block_group) + btrfs_put_block_group(used_block_group); btrfs_put_block_group(block_group); } up_read(&space_info->groups_sem); -- cgit From a5d16333612718569ffd26064270e535cb9c3928 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 7 Dec 2011 20:08:40 -0500 Subject: Btrfs: check if the to-be-added device is writable If we call ioctl(BTRFS_IOC_ADD_DEV) directly, we'll succeed in adding a readonly device to a btrfs filesystem, and btrfs will write to that device, emitting kernel errors: [ 3109.833692] lost page write due to I/O error on loop2 [ 3109.833720] lost page write due to I/O error on loop2 ... Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c37433d3cd82..0a8c8f8304b1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1611,7 +1611,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding) return -EINVAL; - bdev = blkdev_get_by_path(device_path, FMODE_EXCL, + bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL, root->fs_info->bdev_holder); if (IS_ERR(bdev)) return PTR_ERR(bdev); -- cgit From 1cf4ffdb3289624a6462c94f2ce05545b32ef736 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Wed, 7 Dec 2011 20:08:40 -0500 Subject: Btrfs: drop spin lock when memory alloc fails Drop spin lock in convert_extent_bit() when memory alloc fails, otherwise, it will be a deadlock. Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/extent_io.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index be1bf627a14b..49f3c9dc09f4 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -935,8 +935,10 @@ again: node = tree_search(tree, start); if (!node) { prealloc = alloc_extent_state_atomic(prealloc); - if (!prealloc) - return -ENOMEM; + if (!prealloc) { + err = -ENOMEM; + goto out; + } err = insert_state(tree, prealloc, start, end, &bits); prealloc = NULL; BUG_ON(err == -EEXIST); @@ -992,8 +994,10 @@ hit_next: */ if (state->start < start) { prealloc = alloc_extent_state_atomic(prealloc); - if (!prealloc) - return -ENOMEM; + if (!prealloc) { + err = -ENOMEM; + goto out; + } err = split_state(tree, state, prealloc, start); BUG_ON(err == -EEXIST); prealloc = NULL; @@ -1024,8 +1028,10 @@ hit_next: this_end = last_start - 1; prealloc = alloc_extent_state_atomic(prealloc); - if (!prealloc) - return -ENOMEM; + if (!prealloc) { + err = -ENOMEM; + goto out; + } /* * Avoid to free 'prealloc' if it can be merged with @@ -1051,8 +1057,10 @@ hit_next: */ if (state->start <= end && state->end > end) { prealloc = alloc_extent_state_atomic(prealloc); - if (!prealloc) - return -ENOMEM; + if (!prealloc) { + err = -ENOMEM; + goto out; + } err = split_state(tree, state, prealloc, end + 1); BUG_ON(err == -EEXIST); -- cgit From 329456d1ffb416c220813725b7363cda9975c9aa Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 5 Dec 2011 23:19:51 +0100 Subject: ssb: fix init regression with SoCs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a Data bus error on some SoCs. The first fix for this problem did not solve it on all devices. commit 6ae8ec27868bfdbb815287bee8146acbefaee867 Author: Rafał Miłecki Date: Tue Jul 5 17:25:32 2011 +0200 ssb: fix init regression of hostmode PCI core In ssb_pcicore_fix_sprom_core_index() the sprom on the PCI core is accessed, but the sprom only exists when the ssb bus is connected over a PCI bus to the rest of the system and not when the SSB Bus is the main system bus. SoCs sometimes have a PCI host controller and there this code will not be executed, but there are some old SoCs with an PCI controller in client mode around and ssb_pcicore_fix_sprom_core_index() should not be called on these devices too. The PCI controller on these devices are unused, but without this fix it results in an Data bus error when it gets initialized. Cc: Michael Buesch Cc: Rafał Miłecki Signed-off-by: Hauke Mehrtens Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index e6ac3177fbbe..32c535f5ce31 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -516,10 +516,14 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) { - ssb_pcicore_fix_sprom_core_index(pc); + struct ssb_device *pdev = pc->dev; + struct ssb_bus *bus = pdev->bus; + + if (bus->bustype == SSB_BUSTYPE_PCI) + ssb_pcicore_fix_sprom_core_index(pc); /* Disable PCI interrupts. */ - ssb_write32(pc->dev, SSB_INTVEC, 0); + ssb_write32(pdev, SSB_INTVEC, 0); /* Additional PCIe always once-executed workarounds */ if (pc->dev->id.coreid == SSB_DEV_PCIE) { -- cgit From 2ded6e6a94c98ea453a156748cb7fabaf39a76b9 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Fri, 18 Nov 2011 16:33:06 +0100 Subject: x86, hpet: Immediately disable HPET timer 1 if rtc irq is masked When HPET is operating in RTC mode, the TN_ENABLE bit on timer1 controls whether the HPET or the RTC delivers interrupts to irq8. When the system goes into suspend, the RTC driver sends a signal to the HPET driver so that the HPET releases control of irq8, allowing the RTC to wake the system from suspend. The switchover is accomplished by a write to the HPET configuration registers which currently only occurs while servicing the HPET interrupt. On some systems, I have seen the system suspend before an HPET interrupt occurs, preventing the write to the HPET configuration register and leaving the HPET in control of the irq8. As the HPET is not active during suspend, it does not generate a wake signal and RTC alarms do not work. This patch forces the HPET driver to immediately transfer control of the irq8 channel to the RTC instead of waiting until the next interrupt event. Signed-off-by: Mark Langsdorf Link: http://lkml.kernel.org/r/20111118153306.GB16319@alberich.amd.com Tested-by: Andreas Herrmann Signed-off-by: Andreas Herrmann Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org --- arch/x86/kernel/hpet.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index b946a9eac7d9..1bb0bf4d92cd 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -1049,6 +1049,14 @@ int hpet_rtc_timer_init(void) } EXPORT_SYMBOL_GPL(hpet_rtc_timer_init); +static void hpet_disable_rtc_channel(void) +{ + unsigned long cfg; + cfg = hpet_readl(HPET_T1_CFG); + cfg &= ~HPET_TN_ENABLE; + hpet_writel(cfg, HPET_T1_CFG); +} + /* * The functions below are called from rtc driver. * Return 0 if HPET is not being used. @@ -1060,6 +1068,9 @@ int hpet_mask_rtc_irq_bit(unsigned long bit_mask) return 0; hpet_rtc_flags &= ~bit_mask; + if (unlikely(!hpet_rtc_flags)) + hpet_disable_rtc_channel(); + return 1; } EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit); @@ -1125,15 +1136,11 @@ EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq); static void hpet_rtc_timer_reinit(void) { - unsigned int cfg, delta; + unsigned int delta; int lost_ints = -1; - if (unlikely(!hpet_rtc_flags)) { - cfg = hpet_readl(HPET_T1_CFG); - cfg &= ~HPET_TN_ENABLE; - hpet_writel(cfg, HPET_T1_CFG); - return; - } + if (unlikely(!hpet_rtc_flags)) + hpet_disable_rtc_channel(); if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) delta = hpet_default_delta; -- cgit From 1418a3e5ad4d01b1d4abf2c479c50b0cedd59e3f Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 8 Dec 2011 21:24:06 +0900 Subject: TOMOYO: Fix pathname handling of disconnected paths. Current tomoyo_realpath_from_path() implementation returns strange pathname when calculating pathname of a file which belongs to lazy unmounted tree. Use local pathname rather than strange absolute pathname in that case. Also, this patch fixes a regression by commit 02125a82 "fix apparmor dereferencing potentially freed dentry, sanitize __d_path() API". Signed-off-by: Tetsuo Handa Acked-by: Al Viro Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds --- security/tomoyo/realpath.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 36fa7c9bedc4..d9f3ced8756e 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -293,8 +293,16 @@ char *tomoyo_realpath_from_path(struct path *path) pos = tomoyo_get_local_path(path->dentry, buf, buf_len - 1); /* Get absolute name for the rest. */ - else + else { pos = tomoyo_get_absolute_path(path, buf, buf_len - 1); + /* + * Fall back to local name if absolute name is not + * available. + */ + if (pos == ERR_PTR(-EINVAL)) + pos = tomoyo_get_local_path(path->dentry, buf, + buf_len - 1); + } encode: if (IS_ERR(pos)) continue; -- cgit From 5d8c71f9e5fbdd95650be00294d238e27a363b5c Mon Sep 17 00:00:00 2001 From: Adam Kwolek Date: Fri, 9 Dec 2011 14:26:11 +1100 Subject: md: raid5 crash during degradation NULL pointer access causes crash in raid5 module. Signed-off-by: Adam Kwolek Signed-off-by: NeilBrown --- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b0dec01028f4..31670f8d6b65 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3070,7 +3070,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) set_bit(R5_Insync, &dev->flags); } - if (test_bit(R5_WriteError, &dev->flags)) { + if (rdev && test_bit(R5_WriteError, &dev->flags)) { clear_bit(R5_Insync, &dev->flags); if (!test_bit(Faulty, &rdev->flags)) { s->handle_bad_blocks = 1; @@ -3078,7 +3078,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) } else clear_bit(R5_WriteError, &dev->flags); } - if (test_bit(R5_MadeGood, &dev->flags)) { + if (rdev && test_bit(R5_MadeGood, &dev->flags)) { if (!test_bit(Faulty, &rdev->flags)) { s->handle_bad_blocks = 1; atomic_inc(&rdev->nr_pending); -- cgit From 9a5101c8968c7b3e7de5564af6358d7332cf9a6b Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Mon, 7 Nov 2011 16:11:24 +0300 Subject: CIFS: Add descriptions to the brlock cache functions Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/file.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index cf0b1539b321..4dd9283885e7 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -702,6 +702,13 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, lock->type, lock->netfid, conf_lock); } +/* + * Check if there is another lock that prevents us to set the lock (mandatory + * style). If such a lock exists, update the flock structure with its + * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks + * or leave it the same if we can't. Returns 0 if we don't need to request to + * the server or 1 otherwise. + */ static int cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, __u8 type, __u16 netfid, struct file_lock *flock) @@ -739,6 +746,12 @@ cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) mutex_unlock(&cinode->lock_mutex); } +/* + * Set the byte-range lock (mandatory style). Returns: + * 1) 0, if we set the lock and don't need to request to the server; + * 2) 1, if no locks prevent us but we need to request to the server; + * 3) -EACCESS, if there is a lock that prevents us and wait is false. + */ static int cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, bool wait) @@ -778,6 +791,13 @@ try_again: return rc; } +/* + * Check if there is another lock that prevents us to set the lock (posix + * style). If such a lock exists, update the flock structure with its + * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks + * or leave it the same if we can't. Returns 0 if we don't need to request to + * the server or 1 otherwise. + */ static int cifs_posix_lock_test(struct file *file, struct file_lock *flock) { @@ -800,6 +820,12 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) return rc; } +/* + * Set the byte-range lock (posix style). Returns: + * 1) 0, if we set the lock and don't need to request to the server; + * 2) 1, if we need to request to the server; + * 3) <0, if the error occurs while setting the lock. + */ static int cifs_posix_lock_set(struct file *file, struct file_lock *flock) { -- cgit From 59edb63ad08e4f3a9477223c9aaf3fba753085bf Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 10 Nov 2011 12:48:20 -0600 Subject: cifs: Fix sparse warning when calling cifs_strtoUCS Fix sparse endian check warning while calling cifs_strtoUCS CHECK fs/cifs/smbencrypt.c fs/cifs/smbencrypt.c:216:37: warning: incorrect type in argument 1 (different base types) fs/cifs/smbencrypt.c:216:37: expected restricted __le16 [usertype] * fs/cifs/smbencrypt.c:216:37: got unsigned short * Signed-off-by: Steve French Acked-by: Shirish Pargaonkar Date: Thu, 1 Dec 2011 20:22:41 -0500 Subject: cifs: attempt to freeze while looping on a receive attempt In the recent overhaul of the demultiplex thread receive path, I neglected to ensure that we attempt to freeze on each pass through the receive loop. Reported-and-Tested-by: Woody Suwalski Reported-and-Tested-by: Adam Williamson Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d6a972df0338..8cd4b52d4217 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -441,6 +441,8 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, smb_msg.msg_controllen = 0; for (total_read = 0; to_read; total_read += length, to_read -= length) { + try_to_freeze(); + if (server_unresponsive(server)) { total_read = -EAGAIN; break; -- cgit From 7023676f9ee851d94f0942e879243fc1f9081c47 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 1 Dec 2011 20:23:34 -0500 Subject: cifs: check for NULL last_entry before calling cifs_save_resume_key Prior to commit eaf35b1, cifs_save_resume_key had some NULL pointer checks at the top. It turns out that at least one of those NULL pointer checks is needed after all. When the LastNameOffset in a FIND reply appears to be beyond the end of the buffer, CIFSFindFirst and CIFSFindNext will set srch_inf.last_entry to NULL. Since eaf35b1, the code will now oops in this situation. Fix this by having the callers check for a NULL last entry pointer before calling cifs_save_resume_key. No change is needed for the call site in cifs_readdir as it's not reachable with a NULL current_entry pointer. This should fix: https://bugzilla.redhat.com/show_bug.cgi?id=750247 Cc: stable@vger.kernel.org Cc: Christoph Hellwig Reported-by: Adam G. Metzler Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/readdir.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 5de03ec20144..a090bbe6ee29 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -554,7 +554,10 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, rc); return rc; } - cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + /* FindFirst/Next set last_entry to NULL on malformed reply */ + if (cifsFile->srch_inf.last_entry) + cifs_save_resume_key(cifsFile->srch_inf.last_entry, + cifsFile); } while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && @@ -562,7 +565,10 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, cFYI(1, "calling findnext2"); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); - cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + /* FindFirst/Next set last_entry to NULL on malformed reply */ + if (cifsFile->srch_inf.last_entry) + cifs_save_resume_key(cifsFile->srch_inf.last_entry, + cifsFile); if (rc) return -ENOENT; } -- cgit From 905ad269c55fc62bee3da29f7b1d1efeba8aa1e1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Dec 2011 23:20:45 -0500 Subject: procfs: fix a vfsmount longterm reference leak kern_mount() doesn't pair with plain mntput()... Signed-off-by: Al Viro --- fs/proc/root.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/proc/root.c b/fs/proc/root.c index 9a8a2b77b874..03102d978180 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -91,20 +91,18 @@ static struct file_system_type proc_fs_type = { void __init proc_root_init(void) { - struct vfsmount *mnt; int err; proc_init_inodecache(); err = register_filesystem(&proc_fs_type); if (err) return; - mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); - if (IS_ERR(mnt)) { + err = pid_ns_prepare_proc(&init_pid_ns); + if (err) { unregister_filesystem(&proc_fs_type); return; } - init_pid_ns.proc_mnt = mnt; proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); @@ -209,5 +207,5 @@ int pid_ns_prepare_proc(struct pid_namespace *ns) void pid_ns_release_proc(struct pid_namespace *ns) { - mntput(ns->proc_mnt); + kern_unmount(ns->proc_mnt); } -- cgit From 6f686574cccc2ef66fb38e41f19cedd81e7b4504 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Dec 2011 00:38:50 -0500 Subject: ... and the same kind of leak for mqueue Signed-off-by: Al Viro --- ipc/mqueue.c | 8 +++----- ipc/msgutil.c | 5 ----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 2e0ecfcc881d..5b4293d9819d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1269,7 +1269,7 @@ void mq_clear_sbinfo(struct ipc_namespace *ns) void mq_put_mnt(struct ipc_namespace *ns) { - mntput(ns->mq_mnt); + kern_unmount(ns->mq_mnt); } static int __init init_mqueue_fs(void) @@ -1291,11 +1291,9 @@ static int __init init_mqueue_fs(void) spin_lock_init(&mq_lock); - init_ipc_ns.mq_mnt = kern_mount_data(&mqueue_fs_type, &init_ipc_ns); - if (IS_ERR(init_ipc_ns.mq_mnt)) { - error = PTR_ERR(init_ipc_ns.mq_mnt); + error = mq_init_ns(&init_ipc_ns); + if (error) goto out_filesystem; - } return 0; diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 8b5ce5d3f3ef..5652101cdac0 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -27,11 +27,6 @@ DEFINE_SPINLOCK(mq_lock); */ struct ipc_namespace init_ipc_ns = { .count = ATOMIC_INIT(1), -#ifdef CONFIG_POSIX_MQUEUE - .mq_queues_max = DFLT_QUEUESMAX, - .mq_msg_max = DFLT_MSGMAX, - .mq_msgsize_max = DFLT_MSGSIZEMAX, -#endif .user_ns = &init_user_ns, }; -- cgit From e8c7106280a305e1ff2a3a8a4dfce141469fb039 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 18 Nov 2011 13:09:11 +0000 Subject: x86, efi: Calling __pa() with an ioremap()ed address is invalid If we encounter an efi_memory_desc_t without EFI_MEMORY_WB set in ->attribute we currently call set_memory_uc(), which in turn calls __pa() on a potentially ioremap'd address. On CONFIG_X86_32 this is invalid, resulting in the following oops on some machines: BUG: unable to handle kernel paging request at f7f22280 IP: [] reserve_ram_pages_type+0x89/0x210 [...] Call Trace: [] ? page_is_ram+0x1a/0x40 [] reserve_memtype+0xdf/0x2f0 [] set_memory_uc+0x49/0xa0 [] efi_enter_virtual_mode+0x1c2/0x3aa [] start_kernel+0x291/0x2f2 [] ? loglevel+0x1b/0x1b [] i386_start_kernel+0xbf/0xc8 A better approach to this problem is to map the memory region with the correct attributes from the start, instead of modifying it after the fact. The uncached case can be handled by ioremap_nocache() and the cached by ioremap_cache(). Despite first impressions, it's not possible to use ioremap_cache() to map all cached memory regions on CONFIG_X86_64 because EFI_RUNTIME_SERVICES_DATA regions really don't like being mapped into the vmalloc space, as detailed in the following bug report, https://bugzilla.redhat.com/show_bug.cgi?id=748516 Therefore, we need to ensure that any EFI_RUNTIME_SERVICES_DATA regions are covered by the direct kernel mapping table on CONFIG_X86_64. To accomplish this we now map E820_RESERVED_EFI regions via the direct kernel mapping with the initial call to init_memory_mapping() in setup_arch(), whereas previously these regions wouldn't be mapped if they were after the last E820_RAM region until efi_ioremap() was called. Doing it this way allows us to delete efi_ioremap() completely. Signed-off-by: Matt Fleming Cc: H. Peter Anvin Cc: Matthew Garrett Cc: Zhang Rui Cc: Huang Ying Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/1321621751-3650-1-git-send-email-matt@console-pimps.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/e820.h | 8 ++++++++ arch/x86/include/asm/efi.h | 5 ----- arch/x86/kernel/e820.c | 3 ++- arch/x86/kernel/setup.c | 21 ++++++++++++++++++++- arch/x86/platform/efi/efi.c | 29 ++++++++++++++++++----------- arch/x86/platform/efi/efi_64.c | 17 ----------------- 6 files changed, 48 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 908b96957d88..c9547033e38e 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -53,6 +53,13 @@ */ #define E820_RESERVED_KERN 128 +/* + * Address ranges that need to be mapped by the kernel direct + * mapping. This is used to make sure regions such as + * EFI_RUNTIME_SERVICES_DATA are directly mapped. See setup_arch(). + */ +#define E820_RESERVED_EFI 129 + #ifndef __ASSEMBLY__ #include struct e820entry { @@ -115,6 +122,7 @@ static inline void early_memtest(unsigned long start, unsigned long end) } #endif +extern unsigned long e820_end_pfn(unsigned long limit_pfn, unsigned type); extern unsigned long e820_end_of_ram_pfn(void); extern unsigned long e820_end_of_low_ram_pfn(void); extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 7093e4a6a0bc..b8d8bfcd44a9 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -33,8 +33,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) -#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) - #else /* !CONFIG_X86_32 */ extern u64 efi_call0(void *fp); @@ -84,9 +82,6 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) -extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, - u32 type); - #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 303a0e48f076..65ffd110a81b 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -135,6 +135,7 @@ static void __init e820_print_type(u32 type) printk(KERN_CONT "(usable)"); break; case E820_RESERVED: + case E820_RESERVED_EFI: printk(KERN_CONT "(reserved)"); break; case E820_ACPI: @@ -783,7 +784,7 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align) /* * Find the highest page frame number we have available */ -static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) +unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) { int i; unsigned long last_pfn = 0; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cf0ef986cb6d..9a9e40fb091c 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -691,6 +691,8 @@ early_param("reservelow", parse_reservelow); void __init setup_arch(char **cmdline_p) { + unsigned long end_pfn; + #ifdef CONFIG_X86_32 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); visws_early_detect(); @@ -932,7 +934,24 @@ void __init setup_arch(char **cmdline_p) init_gbpages(); /* max_pfn_mapped is updated here */ - max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<>PAGE_SHIFT, E820_RESERVED_EFI); + if (efi_end > max_low_pfn) + end_pfn = efi_end; + } +#endif + + max_low_pfn_mapped = init_memory_mapping(0, end_pfn << PAGE_SHIFT); max_pfn_mapped = max_low_pfn_mapped; #ifdef CONFIG_X86_64 diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 37718f0f053d..c9718a16be15 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -323,10 +323,13 @@ static void __init do_add_efi_memmap(void) case EFI_UNUSABLE_MEMORY: e820_type = E820_UNUSABLE; break; + case EFI_RUNTIME_SERVICES_DATA: + e820_type = E820_RESERVED_EFI; + break; default: /* * EFI_RESERVED_TYPE EFI_RUNTIME_SERVICES_CODE - * EFI_RUNTIME_SERVICES_DATA EFI_MEMORY_MAPPED_IO + * EFI_MEMORY_MAPPED_IO * EFI_MEMORY_MAPPED_IO_PORT_SPACE EFI_PAL_CODE */ e820_type = E820_RESERVED; @@ -671,10 +674,21 @@ void __init efi_enter_virtual_mode(void) end_pfn = PFN_UP(end); if (end_pfn <= max_low_pfn_mapped || (end_pfn > (1UL << (32 - PAGE_SHIFT)) - && end_pfn <= max_pfn_mapped)) + && end_pfn <= max_pfn_mapped)) { va = __va(md->phys_addr); - else - va = efi_ioremap(md->phys_addr, size, md->type); + + if (!(md->attribute & EFI_MEMORY_WB)) { + addr = (u64) (unsigned long)va; + npages = md->num_pages; + memrange_efi_to_native(&addr, &npages); + set_memory_uc(addr, npages); + } + } else { + if (!(md->attribute & EFI_MEMORY_WB)) + va = ioremap_nocache(md->phys_addr, size); + else + va = ioremap_cache(md->phys_addr, size); + } md->virt_addr = (u64) (unsigned long) va; @@ -684,13 +698,6 @@ void __init efi_enter_virtual_mode(void) continue; } - if (!(md->attribute & EFI_MEMORY_WB)) { - addr = md->virt_addr; - npages = md->num_pages; - memrange_efi_to_native(&addr, &npages); - set_memory_uc(addr, npages); - } - systab = (u64) (unsigned long) efi_phys.systab; if (md->phys_addr <= systab && systab < end) { systab += md->virt_addr - md->phys_addr; diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e2654..312250c6b2de 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -80,20 +80,3 @@ void __init efi_call_phys_epilog(void) local_irq_restore(efi_flags); early_code_mapping_set_exec(0); } - -void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, - u32 type) -{ - unsigned long last_map_pfn; - - if (type == EFI_MEMORY_MAPPED_IO) - return ioremap(phys_addr, size); - - last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); - if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { - unsigned long top = last_map_pfn << PAGE_SHIFT; - efi_ioremap(top, size - (top - phys_addr), type); - } - - return (void __iomem *)__va(phys_addr); -} -- cgit From c0d96aed8c6dd925afe9ea35491a0cd458642a86 Mon Sep 17 00:00:00 2001 From: Jason Chen Date: Wed, 30 Nov 2011 11:34:27 +0800 Subject: MXC PWM: should active during DOZE/WAIT/DBG mode Signed-off-by: Jason Chen Signed-off-by: Sascha Hauer Cc: stable@kernel.org --- arch/arm/plat-mxc/pwm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c index 42d74ea59084..845de59f07ed 100644 --- a/arch/arm/plat-mxc/pwm.c +++ b/arch/arm/plat-mxc/pwm.c @@ -32,6 +32,9 @@ #define MX3_PWMSAR 0x0C /* PWM Sample Register */ #define MX3_PWMPR 0x10 /* PWM Period Register */ #define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4) +#define MX3_PWMCR_DOZEEN (1 << 24) +#define MX3_PWMCR_WAITEN (1 << 23) +#define MX3_PWMCR_DBGEN (1 << 22) #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) #define MX3_PWMCR_CLKSRC_IPG (1 << 16) #define MX3_PWMCR_EN (1 << 0) @@ -77,7 +80,9 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR); writel(period_cycles, pwm->mmio_base + MX3_PWMPR); - cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_EN; + cr = MX3_PWMCR_PRESCALER(prescale) | + MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | + MX3_PWMCR_DBGEN | MX3_PWMCR_EN; if (cpu_is_mx25()) cr |= MX3_PWMCR_CLKSRC_IPG; -- cgit From 16b3647d333a18141fc9d172e89a142250be0c57 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sat, 12 Nov 2011 00:09:06 +0800 Subject: ARM: mx5: add __initconst for fec pdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dong Aisheng Acked-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/board-mx53_evk.c | 2 +- arch/arm/mach-mx5/board-mx53_loco.c | 2 +- arch/arm/mach-mx5/board-mx53_smd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index 6bea31ab8f85..64bbfcea6f35 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -106,7 +106,7 @@ static inline void mx53_evk_fec_reset(void) gpio_set_value(MX53_EVK_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_evk_fec_pdata = { +static const struct fec_platform_data mx53_evk_fec_pdata __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 7678f7734db6..237bdecd9331 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -242,7 +242,7 @@ static inline void mx53_loco_fec_reset(void) gpio_set_value(LOCO_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_loco_fec_data = { +static const struct fec_platform_data mx53_loco_fec_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c index 59c0845eb4a6..d42132a80e8f 100644 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ b/arch/arm/mach-mx5/board-mx53_smd.c @@ -104,7 +104,7 @@ static inline void mx53_smd_fec_reset(void) gpio_set_value(SMD_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_smd_fec_data = { +static const struct fec_platform_data mx53_smd_fec_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; -- cgit From 300a47b4378a3b2e7c2a423b0aa4d75fc78987d3 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 9 Dec 2011 10:46:21 +0800 Subject: ARM: imx: fix cpufreq build errors CC arch/arm/plat-mxc/cpufreq.o arch/arm/plat-mxc/cpufreq.c:203: error: expected declaration specifiers or '...' before string constant arch/arm/plat-mxc/cpufreq.c:203: warning: data definition has no type or storage class arch/arm/plat-mxc/cpufreq.c:203: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' arch/arm/plat-mxc/cpufreq.c:203: warning: function declaration isn't a prototype arch/arm/plat-mxc/cpufreq.c:204: error: expected declaration specifiers or '...' before string constant arch/arm/plat-mxc/cpufreq.c:204: warning: data definition has no type or storage class arch/arm/plat-mxc/cpufreq.c:204: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION' arch/arm/plat-mxc/cpufreq.c:204: warning: function declaration isn't a prototype arch/arm/plat-mxc/cpufreq.c:205: error: expected declaration specifiers or '...' before string constant arch/arm/plat-mxc/cpufreq.c:205: warning: data definition has no type or storage class arch/arm/plat-mxc/cpufreq.c:205: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE' arch/arm/plat-mxc/cpufreq.c:205: warning: function declaration isn't a prototype make[1]: *** [arch/arm/plat-mxc/cpufreq.o] Error 1 make: *** [arch/arm/plat-mxc] Error 2 Signed-off-by: Richard Zhao Signed-off-by: Richard Zhao Signed-off-by: Sascha Hauer --- arch/arm/plat-mxc/cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index 74aac96cda20..adbff706ef6f 100644 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -17,6 +17,7 @@ * the CPU clock speed on the fly. */ +#include #include #include #include -- cgit From 847a2ee7392e7d3278f9b82c4b503744c72ee463 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 5 Dec 2011 10:28:11 +0800 Subject: arm/imx: fix power button on imx51 babbage board Since commit 6571534 (plat-mxc: iomux-v3.h: implicitly enable pull-up/down when that's desired) was in, the power button on imx51 babbage board stopped working because it's pulled up by mistake. The patch removes the pull-up setting from the pad configuration for that gpio to make the power button back to work. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/board-mx51_babbage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index 5c837603ff0f..24994bb52147 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -362,7 +362,7 @@ static void __init mx51_babbage_init(void) { iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21, - PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); + PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH); imx51_soc_init(); -- cgit From b2c1639135c0fc1560f3fe9a3a83f2c8265a9e02 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 8 Dec 2011 20:21:40 -0800 Subject: MAINTAINERS: Update amd-iommu F: patterns Commit 29b68415e335 ("x86: amd_iommu: move to drivers/iommu/") moved the files, update the patterns. CC: Ohad Ben-Cohen CC: Joerg Roedel Signed-off-by: Joe Perches Signed-off-by: Joerg Roedel --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4808256446f2..c267601ce9e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -511,8 +511,8 @@ M: Joerg Roedel L: iommu@lists.linux-foundation.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git S: Supported -F: arch/x86/kernel/amd_iommu*.c -F: arch/x86/include/asm/amd_iommu*.h +F: drivers/iommu/amd_iommu*.[ch] +F: include/linux/amd-iommu.h AMD MICROCODE UPDATE SUPPORT M: Andreas Herrmann -- cgit From 635697c663f38106063d5659f0cf2e45afcd4bb5 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Thu, 8 Dec 2011 14:33:51 -0800 Subject: vmscan: fix initial shrinker size handling A shrinker function can return -1, means that it cannot do anything without a risk of deadlock. For example prune_super() does this if it cannot grab a superblock refrence, even if nr_to_scan=0. Currently we interpret this -1 as a ULONG_MAX size shrinker and evaluate `total_scan' according to this. So the next time around this shrinker can cause really big pressure. Let's skip such shrinkers instead. Also make total_scan signed, otherwise the check (total_scan < 0) below never works. Signed-off-by: Konstantin Khlebnikov Cc: Dave Chinner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index a1893c050795..f5255442ae2b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -247,14 +247,18 @@ unsigned long shrink_slab(struct shrink_control *shrink, list_for_each_entry(shrinker, &shrinker_list, list) { unsigned long long delta; - unsigned long total_scan; - unsigned long max_pass; + long total_scan; + long max_pass; int shrink_ret = 0; long nr; long new_nr; long batch_size = shrinker->batch ? shrinker->batch : SHRINK_BATCH; + max_pass = do_shrinker_shrink(shrinker, shrink, 0); + if (max_pass <= 0) + continue; + /* * copy the current shrinker scan count into a local variable * and zero it so that other concurrent shrinker invocations @@ -265,7 +269,6 @@ unsigned long shrink_slab(struct shrink_control *shrink, } while (cmpxchg(&shrinker->nr, nr, 0) != nr); total_scan = nr; - max_pass = do_shrinker_shrink(shrinker, shrink, 0); delta = (4 * nr_pages_scanned) / shrinker->seeks; delta *= max_pass; do_div(delta, lru_pages + 1); -- cgit From 83aeeada7c69f35e5100b27ec354335597a7a488 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Thu, 8 Dec 2011 14:33:54 -0800 Subject: vmscan: use atomic-long for shrinker batching Use atomic-long operations instead of looping around cmpxchg(). [akpm@linux-foundation.org: massage atomic.h inclusions] Signed-off-by: Konstantin Khlebnikov Cc: Dave Chinner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 2 +- include/linux/mm.h | 1 + include/linux/shrinker.h | 2 +- mm/vmscan.c | 17 +++++++---------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 019dc558df1a..e0bc4ffb8e7f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -393,8 +393,8 @@ struct inodes_stat_t { #include #include #include -#include #include +#include #include diff --git a/include/linux/mm.h b/include/linux/mm.h index 3dc3a8c2c485..4baadd18f4ad 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index a83833a1f7a2..07ceb97d53fa 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -35,7 +35,7 @@ struct shrinker { /* These are for internal use */ struct list_head list; - long nr; /* objs pending delete */ + atomic_long_t nr_in_batch; /* objs pending delete */ }; #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ extern void register_shrinker(struct shrinker *); diff --git a/mm/vmscan.c b/mm/vmscan.c index f5255442ae2b..f54a05b7a61d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -183,7 +183,7 @@ static unsigned long zone_nr_lru_pages(struct zone *zone, */ void register_shrinker(struct shrinker *shrinker) { - shrinker->nr = 0; + atomic_long_set(&shrinker->nr_in_batch, 0); down_write(&shrinker_rwsem); list_add_tail(&shrinker->list, &shrinker_list); up_write(&shrinker_rwsem); @@ -264,9 +264,7 @@ unsigned long shrink_slab(struct shrink_control *shrink, * and zero it so that other concurrent shrinker invocations * don't also do this scanning work. */ - do { - nr = shrinker->nr; - } while (cmpxchg(&shrinker->nr, nr, 0) != nr); + nr = atomic_long_xchg(&shrinker->nr_in_batch, 0); total_scan = nr; delta = (4 * nr_pages_scanned) / shrinker->seeks; @@ -328,12 +326,11 @@ unsigned long shrink_slab(struct shrink_control *shrink, * manner that handles concurrent updates. If we exhausted the * scan, there is no need to do an update. */ - do { - nr = shrinker->nr; - new_nr = total_scan + nr; - if (total_scan <= 0) - break; - } while (cmpxchg(&shrinker->nr, nr, new_nr) != nr); + if (total_scan > 0) + new_nr = atomic_long_add_return(total_scan, + &shrinker->nr_in_batch); + else + new_nr = atomic_long_read(&shrinker->nr_in_batch); trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr); } -- cgit From b53fc7c2974a50913f49e1d800fe904a28c338e3 Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Thu, 8 Dec 2011 14:33:56 -0800 Subject: fs/proc/meminfo.c: fix compilation error Fix the error message "directives may not be used inside a macro argument" which appears when the kernel is compiled for the cris architecture. Signed-off-by: Claudio Scordino Cc: Andrea Arcangeli Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/meminfo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 586174168e2a..80e4645f7990 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -131,12 +131,13 @@ static int meminfo_proc_show(struct seq_file *m, void *v) K(i.freeswap), K(global_page_state(NR_FILE_DIRTY)), K(global_page_state(NR_WRITEBACK)), - K(global_page_state(NR_ANON_PAGES) #ifdef CONFIG_TRANSPARENT_HUGEPAGE + K(global_page_state(NR_ANON_PAGES) + global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) * - HPAGE_PMD_NR + HPAGE_PMD_NR), +#else + K(global_page_state(NR_ANON_PAGES)), #endif - ), K(global_page_state(NR_FILE_MAPPED)), K(global_page_state(NR_SHMEM)), K(global_page_state(NR_SLAB_RECLAIMABLE) + -- cgit From 1dfb059b9438633b0546c5431538a47f6ed99028 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 8 Dec 2011 14:33:57 -0800 Subject: thp: reduce khugepaged freezing latency khugepaged can sometimes cause suspend to fail, requiring that the user retry the suspend operation. Use wait_event_freezable_timeout() instead of schedule_timeout_interruptible() to avoid missing freezer wakeups. A try_to_freeze() would have been needed in the khugepaged_alloc_hugepage tight loop too in case of the allocation failing repeatedly, and wait_event_freezable_timeout will provide it too. khugepaged would still freeze just fine by trying again the next minute but it's better if it freezes immediately. Reported-by: Jiri Slaby Signed-off-by: Andrea Arcangeli Tested-by: Jiri Slaby Cc: Tejun Heo Cc: Oleg Nesterov Cc: "Srivatsa S. Bhat" Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/huge_memory.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 4298abaae153..36b3d988b4ef 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2259,12 +2259,8 @@ static void khugepaged_do_scan(struct page **hpage) static void khugepaged_alloc_sleep(void) { - DEFINE_WAIT(wait); - add_wait_queue(&khugepaged_wait, &wait); - schedule_timeout_interruptible( - msecs_to_jiffies( - khugepaged_alloc_sleep_millisecs)); - remove_wait_queue(&khugepaged_wait, &wait); + wait_event_freezable_timeout(khugepaged_wait, false, + msecs_to_jiffies(khugepaged_alloc_sleep_millisecs)); } #ifndef CONFIG_NUMA @@ -2313,14 +2309,10 @@ static void khugepaged_loop(void) if (unlikely(kthread_should_stop())) break; if (khugepaged_has_work()) { - DEFINE_WAIT(wait); if (!khugepaged_scan_sleep_millisecs) continue; - add_wait_queue(&khugepaged_wait, &wait); - schedule_timeout_interruptible( - msecs_to_jiffies( - khugepaged_scan_sleep_millisecs)); - remove_wait_queue(&khugepaged_wait, &wait); + wait_event_freezable_timeout(khugepaged_wait, false, + msecs_to_jiffies(khugepaged_scan_sleep_millisecs)); } else if (khugepaged_enabled()) wait_event_freezable(khugepaged_wait, khugepaged_wait_event()); -- cgit From 1de8ad43d0048963d0a0adf14bb046340426b1e4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 8 Dec 2011 14:34:00 -0800 Subject: CREDITS: update Kees's expired fingerprint and fix details Small clean-up for my CREDITS entry; the GPG fingerprint was not up to date, so I fixed other details at the same time too. Signed-off-by: Kees Cook Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- CREDITS | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CREDITS b/CREDITS index 07e32a87d956..44fce988eaac 100644 --- a/CREDITS +++ b/CREDITS @@ -688,10 +688,13 @@ S: Oxfordshire, UK. N: Kees Cook E: kees@outflux.net -W: http://outflux.net/ -P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30 1975 1FFF 4BA9 1706 3E6D -D: Minor updates to SCSI types, added /proc/pid/maps protection +E: kees@ubuntu.com +E: keescook@chromium.org +W: http://outflux.net/blog/ +P: 4096R/DC6DC026 A5C3 F68F 229D D60F 723E 6E13 8972 F4DF DC6D C026 +D: Various security things, bug fixes, and documentation. S: (ask for current address) +S: Portland, Oregon S: USA N: Robin Cornelius -- cgit From 2dbcd05f1e9e0932833d16dab1696176fc164b07 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Thu, 8 Dec 2011 14:34:02 -0800 Subject: drivers/rtc/rtc-s3c.c: fix driver clock enable/disable balance issues If an error occurs after the clock is enabled, the enable/disable state can become unbalanced. Signed-off-by: Jonghwan Choi Cc: Alessandro Zummo Acked-by: Kukjin Kim Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 7639ab906f02..5b979d9cc332 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -202,7 +202,6 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) void __iomem *base = s3c_rtc_base; int year = tm->tm_year - 100; - clk_enable(rtc_clk); pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -214,6 +213,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) return -EINVAL; } + clk_enable(rtc_clk); writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC); writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN); writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR); -- cgit From c193c82f054195aa352ccbef91afc28446e5a30e Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 8 Dec 2011 14:34:10 -0800 Subject: memcg: update maintainers More players joined to memory cgroup developments and Johannes' great work changed internal design of memory cgroup dramatically. And he will do more works. Michal Hokko did many bug fixes and know memory cgroup very well. Daisuke Nishimura helped us very much but he seems busy now. Thanks to his works. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Acked-by: Johannes Weiner Acked-by: Daisuke Nishimura Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b4f18024f4e7..6751a36f569f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4302,8 +4302,9 @@ F: include/linux/mm.h F: mm/ MEMORY RESOURCE CONTROLLER +M: Johannes Weiner +M: Michal Hocko M: Balbir Singh -M: Daisuke Nishimura M: KAMEZAWA Hiroyuki L: cgroups@vger.kernel.org L: linux-mm@kvack.org -- cgit From 09dc3cf93f7d16fdd37a0ad8486faebb5e2769ec Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 8 Dec 2011 14:34:13 -0800 Subject: printk: avoid double lock acquire Commit 4f2a8d3cf5e ("printk: Fix console_sem vs logbuf_lock unlock race") introduced another silly bug where we would want to acquire an already held lock. Avoid this. Reported-by: Andrea Arcangeli Signed-off-by: Peter Zijlstra Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index 1455a0d4eedd..7982a0a841ea 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1293,10 +1293,11 @@ again: raw_spin_lock(&logbuf_lock); if (con_start != log_end) retry = 1; + raw_spin_unlock_irqrestore(&logbuf_lock, flags); + if (retry && console_trylock()) goto again; - raw_spin_unlock_irqrestore(&logbuf_lock, flags); if (wake_klogd) wake_up_klogd(); } -- cgit From b6999b19120931ede364fa3b685e698a61fed31d Mon Sep 17 00:00:00 2001 From: Youquan Song Date: Thu, 8 Dec 2011 14:34:16 -0800 Subject: thp: add compound tail page _mapcount when mapped With the 3.2-rc kernel, IOMMU 2M pages in KVM works. But when I tried to use IOMMU 1GB pages in KVM, I encountered an oops and the 1GB page failed to be used. The root cause is that 1GB page allocation calls gup_huge_pud() while 2M page calls gup_huge_pmd. If compound pages are used and the page is a tail page, gup_huge_pmd() increases _mapcount to record tail page are mapped while gup_huge_pud does not do that. So when the mapped page is relesed, it will result in kernel oops because the page is not marked mapped. This patch add tail process for compound page in 1GB huge page which keeps the same process as 2M page. Reproduce like: 1. Add grub boot option: hugepagesz=1G hugepages=8 2. mount -t hugetlbfs -o pagesize=1G hugetlbfs /dev/hugepages 3. qemu-kvm -m 2048 -hda os-kvm.img -cpu kvm64 -smp 4 -mem-path /dev/hugepages -net none -device pci-assign,host=07:00.1 kernel BUG at mm/swap.c:114! invalid opcode: 0000 [#1] SMP Call Trace: put_page+0x15/0x37 kvm_release_pfn_clean+0x31/0x36 kvm_iommu_put_pages+0x94/0xb1 kvm_iommu_unmap_memslots+0x80/0xb6 kvm_assign_device+0xba/0x117 kvm_vm_ioctl_assigned_device+0x301/0xa47 kvm_vm_ioctl+0x36c/0x3a2 do_vfs_ioctl+0x49e/0x4e4 sys_ioctl+0x5a/0x7c system_call_fastpath+0x16/0x1b RIP put_compound_page+0xd4/0x168 Signed-off-by: Youquan Song Reviewed-by: Andrea Arcangeli Cc: Andi Kleen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/mm/gup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index ea305856151c..dd74e46828c0 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -201,6 +201,8 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr, do { VM_BUG_ON(compound_head(page) != head); pages[*nr] = page; + if (PageTail(page)) + get_huge_page_tail(page); (*nr)++; page++; refs++; -- cgit From 58a84aa92723d1ac3e1cc4e3b0ff49291663f7e1 Mon Sep 17 00:00:00 2001 From: Youquan Song Date: Thu, 8 Dec 2011 14:34:18 -0800 Subject: thp: set compound tail page _count to zero Commit 70b50f94f1644 ("mm: thp: tail page refcounting fix") keeps all page_tail->_count zero at all times. But the current kernel does not set page_tail->_count to zero if a 1GB page is utilized. So when an IOMMU 1GB page is used by KVM, it wil result in a kernel oops because a tail page's _count does not equal zero. kernel BUG at include/linux/mm.h:386! invalid opcode: 0000 [#1] SMP Call Trace: gup_pud_range+0xb8/0x19d get_user_pages_fast+0xcb/0x192 ? trace_hardirqs_off+0xd/0xf hva_to_pfn+0x119/0x2f2 gfn_to_pfn_memslot+0x2c/0x2e kvm_iommu_map_pages+0xfd/0x1c1 kvm_iommu_map_memslots+0x7c/0xbd kvm_iommu_map_guest+0xaa/0xbf kvm_vm_ioctl_assigned_device+0x2ef/0xa47 kvm_vm_ioctl+0x36c/0x3a2 do_vfs_ioctl+0x49e/0x4e4 sys_ioctl+0x5a/0x7c system_call_fastpath+0x16/0x1b RIP gup_huge_pud+0xf2/0x159 Signed-off-by: Youquan Song Reviewed-by: Andrea Arcangeli Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 1 + mm/page_alloc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index bb28a5f9db8d..73f17c0293c0 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -576,6 +576,7 @@ static void prep_compound_gigantic_page(struct page *page, unsigned long order) __SetPageHead(page); for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) { __SetPageTail(p); + set_page_count(p, 0); p->first_page = page; } } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9dd443d89d8b..850009a7101e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -356,8 +356,8 @@ void prep_compound_page(struct page *page, unsigned long order) __SetPageHead(page); for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - __SetPageTail(p); + set_page_count(p, 0); p->first_page = page; } } -- cgit From 09761333ed47e899cc1482c13090b95f3f711971 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Thu, 8 Dec 2011 14:34:20 -0800 Subject: mm/migrate.c: pair unlock_page() and lock_page() when migrating huge pages Avoid unlocking and unlocked page if we failed to lock it. Signed-off-by: Hillf Danton Cc: Naoya Horiguchi Cc: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/migrate.c b/mm/migrate.c index 578e29174fa6..177aca424a06 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -871,9 +871,9 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (anon_vma) put_anon_vma(anon_vma); -out: unlock_page(hpage); +out: if (rc != -EAGAIN) { list_del(&hpage->lru); put_page(hpage); -- cgit From d021563888312018ca65681096f62e36c20e63cc Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 8 Dec 2011 14:34:27 -0800 Subject: mm: Ensure that pfn_valid() is called once per pageblock when reserving pageblocks setup_zone_migrate_reserve() expects that zone->start_pfn starts at pageblock_nr_pages aligned pfn otherwise we could access beyond an existing memblock resulting in the following panic if CONFIG_HOLES_IN_ZONE is not configured and we do not check pfn_valid: IP: [] setup_zone_migrate_reserve+0xcd/0x180 *pdpt = 0000000000000000 *pde = f000ff53f000ff53 Oops: 0000 [#1] SMP Pid: 1, comm: swapper Not tainted 3.0.7-0.7-pae #1 VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform EIP: 0060:[] EFLAGS: 00010006 CPU: 0 EIP is at setup_zone_migrate_reserve+0xcd/0x180 EAX: 000c0000 EBX: f5801fc0 ECX: 000c0000 EDX: 00000000 ESI: 000c01fe EDI: 000c01fe EBP: 00140000 ESP: f2475f58 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process swapper (pid: 1, ti=f2474000 task=f2472cd0 task.ti=f2474000) Call Trace: [] __setup_per_zone_wmarks+0xec/0x160 [] setup_per_zone_wmarks+0xf/0x20 [] init_per_zone_wmark_min+0x27/0x86 [] do_one_initcall+0x2b/0x160 [] kernel_init+0xbe/0x157 [] kernel_thread_helper+0x6/0xd Code: a5 39 f5 89 f7 0f 46 fd 39 cf 76 40 8b 03 f6 c4 08 74 32 eb 91 90 89 c8 c1 e8 0e 0f be 80 80 2f 86 c0 8b 14 85 60 2f 86 c0 89 c8 <2b> 82 b4 12 00 00 c1 e0 05 03 82 ac 12 00 00 8b 00 f6 c4 08 0f EIP: [] setup_zone_migrate_reserve+0xcd/0x180 SS:ESP 0068:f2475f58 CR2: 00000000000012b4 We crashed in pageblock_is_reserved() when accessing pfn 0xc0000 because highstart_pfn = 0x36ffe. The issue was introduced in 3.0-rc1 by 6d3163ce ("mm: check if any page in a pageblock is reserved before marking it MIGRATE_RESERVE"). Make sure that start_pfn is always aligned to pageblock_nr_pages to ensure that pfn_valid s always called at the start of each pageblock. Architectures with holes in pageblocks will be correctly handled by pfn_valid_within in pageblock_is_reserved. Signed-off-by: Michal Hocko Signed-off-by: Mel Gorman Tested-by: Dang Bo Reviewed-by: KAMEZAWA Hiroyuki Cc: Andrea Arcangeli Cc: David Rientjes Cc: Arve Hjnnevg Cc: KOSAKI Motohiro Cc: John Stultz Cc: Dave Hansen Cc: [3.0+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 850009a7101e..2b8ba3aebf6e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3377,9 +3377,15 @@ static void setup_zone_migrate_reserve(struct zone *zone) unsigned long block_migratetype; int reserve; - /* Get the start pfn, end pfn and the number of blocks to reserve */ + /* + * Get the start pfn, end pfn and the number of blocks to reserve + * We have to be careful to be aligned to pageblock_nr_pages to + * make sure that we always check pfn_valid for the first page in + * the block. + */ start_pfn = zone->zone_start_pfn; end_pfn = start_pfn + zone->spanned_pages; + start_pfn = roundup(start_pfn, pageblock_nr_pages); reserve = roundup(min_wmark_pages(zone), pageblock_nr_pages) >> pageblock_order; -- cgit From 1368edf0647ac112d8cfa6ce47257dc950c50f5c Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Thu, 8 Dec 2011 14:34:30 -0800 Subject: mm: vmalloc: check for page allocation failure before vmlist insertion Commit f5252e00 ("mm: avoid null pointer access in vm_struct via /proc/vmallocinfo") adds newly allocated vm_structs to the vmlist after it is fully initialised. Unfortunately, it did not check that __vmalloc_area_node() successfully populated the area. In the event of allocation failure, the vmalloc area is freed but the pointer to freed memory is inserted into the vmlist leading to a a crash later in get_vmalloc_info(). This patch adds a check for ____vmalloc_area_node() failure within __vmalloc_node_range. It does not use "goto fail" as in the previous error path as a warning was already displayed by __vmalloc_area_node() before it called vfree in its failure path. Credit goes to Luciano Chavez for doing all the real work of identifying exactly where the problem was. Signed-off-by: Mel Gorman Reported-by: Luciano Chavez Tested-by: Luciano Chavez Reviewed-by: Rik van Riel Acked-by: David Rientjes Cc: [3.1.x+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 3231bf332878..1d8b32f07139 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1633,6 +1633,8 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, goto fail; addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller); + if (!addr) + return NULL; /* * In this function, newly allocated vm_struct is not added -- cgit From 2a95ea6c0d129b4568fb64e1deda16ceb20e6636 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 8 Dec 2011 14:34:32 -0800 Subject: procfs: do not overflow get_{idle,iowait}_time for nohz Since commit a25cac5198d4 ("proc: Consider NO_HZ when printing idle and iowait times") we are reporting idle/io_wait time also while a CPU is tickless. We rely on get_{idle,iowait}_time functions to retrieve proper data. These functions, however, use usecs_to_cputime to translate micro seconds time to cputime64_t. This is just an alias to usecs_to_jiffies which reduces the data type from u64 to unsigned int and also checks whether the given parameter overflows jiffies_to_usecs(MAX_JIFFY_OFFSET) and returns MAX_JIFFY_OFFSET in that case. When we overflow depends on CONFIG_HZ but especially for CONFIG_HZ_300 it is quite low (1431649781) so we are getting MAX_JIFFY_OFFSET for >3000s! until we overflow unsigned int. Just for reference CONFIG_HZ_100 has an overflow window around 20s, CONFIG_HZ_250 ~8s and CONFIG_HZ_1000 ~2s. This results in a bug when people saw [h]top going mad reporting 100% CPU usage even though there was basically no CPU load. The reason was simply that /proc/stat stopped reporting idle/io_wait changes (and reported MAX_JIFFY_OFFSET) and so the only change happening was for user system time. Let's use nsecs_to_jiffies64 instead which doesn't reduce the precision to 32b type and it is much more appropriate for cumulative time values (unlike usecs_to_jiffies which intended for timeout calculations). Signed-off-by: Michal Hocko Tested-by: Artem S. Tashkinov Cc: Dave Jones Cc: Arnd Bergmann Cc: Alexey Dobriyan Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/stat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 42b274da92c3..2a30d67dd6b8 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -32,7 +32,7 @@ static cputime64_t get_idle_time(int cpu) idle = kstat_cpu(cpu).cpustat.idle; idle = cputime64_add(idle, arch_idle_time(cpu)); } else - idle = usecs_to_cputime(idle_time); + idle = nsecs_to_jiffies64(1000 * idle_time); return idle; } @@ -46,7 +46,7 @@ static cputime64_t get_iowait_time(int cpu) /* !NO_HZ so we can rely on cpustat.iowait */ iowait = kstat_cpu(cpu).cpustat.iowait; else - iowait = usecs_to_cputime(iowait_time); + iowait = nsecs_to_jiffies64(1000 * iowait_time); return iowait; } -- cgit From ceb96398127f3388cb5815b2ab550196e2be5d68 Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 8 Dec 2011 14:34:35 -0800 Subject: rapidio/tsi721: switch to dma_zalloc_coherent Replace the pair dma_alloc_coherent()+memset() with the new dma_zalloc_coherent() added by Andrew Morton for kernel version 3.2 Signed-off-by: Alexandre Bounine Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/devices/tsi721.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 5225930a10cd..514c28c81420 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -851,14 +851,12 @@ static int tsi721_doorbell_init(struct tsi721_device *priv) INIT_WORK(&priv->idb_work, tsi721_db_dpc); /* Allocate buffer for inbound doorbells queue */ - priv->idb_base = dma_alloc_coherent(&priv->pdev->dev, + priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE, &priv->idb_dma, GFP_KERNEL); if (!priv->idb_base) return -ENOMEM; - memset(priv->idb_base, 0, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE); - dev_dbg(&priv->pdev->dev, "Allocated IDB buffer @ %p (phys = %llx)\n", priv->idb_base, (unsigned long long)priv->idb_dma); @@ -904,7 +902,7 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) */ /* Allocate space for DMA descriptors */ - bd_ptr = dma_alloc_coherent(&priv->pdev->dev, + bd_ptr = dma_zalloc_coherent(&priv->pdev->dev, bd_num * sizeof(struct tsi721_dma_desc), &bd_phys, GFP_KERNEL); if (!bd_ptr) @@ -913,8 +911,6 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) priv->bdma[chnum].bd_phys = bd_phys; priv->bdma[chnum].bd_base = bd_ptr; - memset(bd_ptr, 0, bd_num * sizeof(struct tsi721_dma_desc)); - dev_dbg(&priv->pdev->dev, "DMA descriptors @ %p (phys = %llx)\n", bd_ptr, (unsigned long long)bd_phys); @@ -922,7 +918,7 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ? bd_num : TSI721_DMA_MINSTSSZ; sts_size = roundup_pow_of_two(sts_size); - sts_ptr = dma_alloc_coherent(&priv->pdev->dev, + sts_ptr = dma_zalloc_coherent(&priv->pdev->dev, sts_size * sizeof(struct tsi721_dma_sts), &sts_phys, GFP_KERNEL); if (!sts_ptr) { @@ -938,8 +934,6 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) priv->bdma[chnum].sts_base = sts_ptr; priv->bdma[chnum].sts_size = sts_size; - memset(sts_ptr, 0, sts_size); - dev_dbg(&priv->pdev->dev, "desc status FIFO @ %p (phys = %llx) size=0x%x\n", sts_ptr, (unsigned long long)sts_phys, sts_size); @@ -1400,7 +1394,7 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, /* Outbound message descriptor status FIFO allocation */ priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1); - priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev, + priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev, priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts), &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL); @@ -1412,9 +1406,6 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, goto out_desc; } - memset(priv->omsg_ring[mbox].sts_base, 0, - entries * sizeof(struct tsi721_dma_sts)); - /* * Configure Outbound Messaging Engine */ -- cgit From b439e66f04bff6476c5d4bae6a52ab93fbb9a8f4 Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 8 Dec 2011 14:34:36 -0800 Subject: rapidio/tsi721: fix mailbox resource reporting Bug fix for Tsi721 RapidIO mport driver: Tsi721 supports four RapidIO mailboxes (MBOX0 - MBOX3) as defined by RapidIO specification. Mailbox resources has to be properly reported to allow use of all available mailboxes (initial version reports only MBOX0). This patch is applicable to kernel versions staring from 3.2-rc1. Signed-off-by: Alexandre Bounine Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/devices/tsi721.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 514c28c81420..83ac8728b781 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2107,8 +2107,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) INIT_LIST_HEAD(&mport->dbells); rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); - rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); - rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); + rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); + rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); strcpy(mport->name, "Tsi721 mport"); /* Hook up interrupt handler */ -- cgit From 1cee22b7f385b6c4f716846203a96e1f302132aa Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 8 Dec 2011 14:34:42 -0800 Subject: rapidio/tsi721: modify PCIe capability settings Modify initialization of PCIe capability registers in Tsi721 mport driver: - change Completion Timeout value to avoid unexpected data transfer aborts during intensive traffic. - replace hardcoded offset of PCIe capability block by making it use the common function. This patch is applicable to kernel versions starting from 3.2-rc1. Signed-off-by: Alexandre Bounine Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/devices/tsi721.c | 20 +++++++++++++++----- drivers/rapidio/devices/tsi721.h | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 83ac8728b781..691b1ab1a3d0 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2154,7 +2154,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i; + int i, cap; int err; u32 regval; @@ -2262,10 +2262,20 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Unable to set consistent DMA mask\n"); } - /* Clear "no snoop" and "relaxed ordering" bits. */ - pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, ®val); - regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN); - pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval); + cap = pci_pcie_cap(pdev); + BUG_ON(cap == 0); + + /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, ®val); + regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN | + PCI_EXP_DEVCTL_NOSNOOP_EN); + regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT; + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval); + + /* Adjust PCIe completion timeout. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, ®val); + regval &= ~(0x0f); + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2); /* * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 58be4deb1402..822e54c394d5 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -72,6 +72,8 @@ #define TSI721_MSIXPBA_OFFSET 0x2a000 #define TSI721_PCIECFG_EPCTL 0x400 +#define MAX_READ_REQUEST_SZ_SHIFT 12 + /* * Event Management Registers */ -- cgit From 031af165b1cd295ef04d2bfbcae9bc3cb9180735 Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Thu, 8 Dec 2011 14:34:44 -0800 Subject: sys_getppid: add missing rcu_dereference In order to safely dereference current->real_parent inside an rcu_read_lock, we need an rcu_dereference. Signed-off-by: Mandeep Singh Baines Cc: Thomas Gleixner Cc: Pavel Emelyanov Cc: Oleg Nesterov Cc: Kees Cook Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/timer.c b/kernel/timer.c index dbaa62422b13..9c3c62b0c4bc 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1368,7 +1368,7 @@ SYSCALL_DEFINE0(getppid) int pid; rcu_read_lock(); - pid = task_tgid_vnr(current->real_parent); + pid = task_tgid_vnr(rcu_dereference(current->real_parent)); rcu_read_unlock(); return pid; -- cgit From 5dbc8fca8ef5d719014f22345d990e957dcfc692 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 9 Dec 2011 11:07:37 -0500 Subject: Btrfs: fix btrfs_end_bio to deal with write errors to a single mirror btrfs_end_bio checks the number of errors on a bio against the max number of errors allowed before sending any EIOs up to the higher levels. If we got enough copies of the bio done for a given raid level, it is supposed to clear the bio error flag and return success. We have pointers to the original bio sent down by the higher layers and pointers to any cloned bios we made for raid purposes. If the original bio happens to be the one that got an io error, but not the last one to finish, it might not have the BIO_UPTODATE bit set. Then, when the last bio does finish, we'll call bio_end_io on the original bio. It won't have the uptodate bit set and we'll end up sending EIO to the higher layers. We already had a check for this, it just was conditional on getting the IO error on the very last bio. Make the check unconditional so we eat the EIOs properly. Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0a8c8f8304b1..91ea57a1474a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3258,7 +3258,7 @@ static void btrfs_end_bio(struct bio *bio, int err) */ if (atomic_read(&bbio->error) > bbio->max_errors) { err = -EIO; - } else if (err) { + } else { /* * this bio is actually up to date, we didn't * go over the max number of errors -- cgit From 4b44b40e04a758e2242ff4a3f7c15982801ec8bc Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 9 Dec 2011 16:31:52 -0500 Subject: NFSv4: Ensure correct locking when accessing the 'lock_states' list There are currently 2 places in the state recovery code, where we do not take sufficient precautions before accessing the state->lock_states. In both cases, we should be holding the state->state_lock. Reported-by: Pascal Bouchareine Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index da8d73ed9e0f..6a7107ae6b72 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1156,11 +1156,13 @@ restart: if (status >= 0) { status = nfs4_reclaim_locks(state, ops); if (status >= 0) { + spin_lock(&state->state_lock); list_for_each_entry(lock, &state->lock_states, ls_locks) { if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) printk("%s: Lock reclaim failed!\n", __func__); } + spin_unlock(&state->state_lock); nfs4_put_open_state(state); goto restart; } @@ -1224,10 +1226,12 @@ static void nfs4_clear_open_state(struct nfs4_state *state) clear_bit(NFS_O_RDONLY_STATE, &state->flags); clear_bit(NFS_O_WRONLY_STATE, &state->flags); clear_bit(NFS_O_RDWR_STATE, &state->flags); + spin_lock(&state->state_lock); list_for_each_entry(lock, &state->lock_states, ls_locks) { lock->ls_seqid.flags = 0; lock->ls_flags &= ~NFS_LOCK_INITIALIZED; } + spin_unlock(&state->state_lock); } static void nfs4_reset_seqids(struct nfs_server *server, -- cgit From 9aa7705c966c750dda3d5c8d8a20f8e46668911c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 27 Nov 2011 15:42:15 -0300 Subject: [media] [trivial] omap24xxcam-dma: Fix logical test Likely misuse of & vs &&. Signed-off-by: Joe Perches Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap24xxcam-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/omap24xxcam-dma.c b/drivers/media/video/omap24xxcam-dma.c index 1d54b86c936b..3ea38a8def8e 100644 --- a/drivers/media/video/omap24xxcam-dma.c +++ b/drivers/media/video/omap24xxcam-dma.c @@ -506,7 +506,7 @@ int omap24xxcam_sgdma_queue(struct omap24xxcam_sgdma *sgdma, unsigned long flags; struct sgdma_state *sg_state; - if ((sglen < 0) || ((sglen > 0) & !sglist)) + if ((sglen < 0) || ((sglen > 0) && !sglist)) return -EINVAL; spin_lock_irqsave(&sgdma->lock, flags); -- cgit From dc47ce90c3a822cd7c9e9339fe4d5f61dcb26b50 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 9 Dec 2011 15:09:32 -0800 Subject: Linux 3.2-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 12aafc20efbd..d1ea73f74c2f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit From 652f89f64fabcdae9143ee2b4253cfa838fb0279 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 9 Dec 2011 19:05:58 -0500 Subject: NFSv4: Do not accept delegated opens when a delegation recall is in effect ...and report the servers that try to return a delegation when the client is using the CLAIM_DELEG_CUR open mode. That behaviour is explicitly forbidden in RFC3530. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index be2bbac13817..d9f4d78c3413 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include #include @@ -894,6 +896,8 @@ out: static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode) { + if (delegation == NULL) + return 0; if ((delegation->type & fmode) != fmode) return 0; if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) @@ -1036,8 +1040,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) } rcu_read_lock(); delegation = rcu_dereference(nfsi->delegation); - if (delegation == NULL || - !can_open_delegated(delegation, fmode)) { + if (!can_open_delegated(delegation, fmode)) { rcu_read_unlock(); break; } @@ -1091,7 +1094,12 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data if (delegation) delegation_flags = delegation->flags; rcu_read_unlock(); - if ((delegation_flags & 1UL<o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { + pr_err_ratelimited("NFS: Broken NFSv4 server %s is " + "returning a delegation for " + "OPEN(CLAIM_DELEGATE_CUR)\n", + NFS_CLIENT(inode)->cl_server); + } else if ((delegation_flags & 1UL<inode, data->owner->so_cred, &data->o_res); @@ -1423,11 +1431,9 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) goto out_no_action; rcu_read_lock(); delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); - if (delegation != NULL && - test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) { - rcu_read_unlock(); - goto out_no_action; - } + if (data->o_arg.claim != NFS4_OPEN_CLAIM_DELEGATE_CUR && + can_open_delegated(delegation, data->o_arg.fmode)) + goto unlock_no_action; rcu_read_unlock(); } /* Update sequence id. */ @@ -1444,6 +1450,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) return; rpc_call_start(task); return; +unlock_no_action: + rcu_read_unlock(); out_no_action: task->tk_action = NULL; -- cgit From 6d3e32e63f1fb47b3ba104d13dfac116df7b2bbb Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 8 Dec 2011 12:10:50 +0000 Subject: x86, efi: Make efi_call_phys_{prelog,epilog} CONFIG_RELOCATABLE-aware efi_call_phys_prelog() sets up a 1:1 mapping of the physical address range in swapper_pg_dir. Instead of replacing then restoring entries in swapper_pg_dir we should be using initial_page_table which already contains the 1:1 mapping. It's safe to blindly switch back to swapper_pg_dir in the epilog because the physical EFI routines are only called before efi_enter_virtual_mode(), e.g. before any user processes have been forked. Therefore, we don't need to track which pgd was in %cr3 when we entered the prelog. The previous code actually contained a bug because it assumed that the kernel was loaded at a physical address within the first 8MB of ram, usually at 0x100000. However, this isn't the case with a CONFIG_RELOCATABLE=y kernel which could have been loaded anywhere in the physical address space. Also delete the ancient (and bogus) comments about the page table being restored after the lock is released. There is no locking. Cc: Matthew Garrett Cc: Darrent Hart Signed-off-by: Matt Fleming Link: http://lkml.kernel.org/r/1323346250.3894.74.camel@mfleming-mobl1.ger.corp.intel.com Signed-off-by: H. Peter Anvin --- arch/x86/platform/efi/efi_32.c | 48 ++---------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index e36bf714cb77..40e446941dd7 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -39,43 +39,14 @@ */ static unsigned long efi_rt_eflags; -static pgd_t efi_bak_pg_dir_pointer[2]; void efi_call_phys_prelog(void) { - unsigned long cr4; - unsigned long temp; struct desc_ptr gdt_descr; local_irq_save(efi_rt_eflags); - /* - * If I don't have PAE, I should just duplicate two entries in page - * directory. If I have PAE, I just need to duplicate one entry in - * page directory. - */ - cr4 = read_cr4_safe(); - - if (cr4 & X86_CR4_PAE) { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - swapper_pg_dir[0].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - } else { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - efi_bak_pg_dir_pointer[1].pgd = - swapper_pg_dir[pgd_index(0x400000)].pgd; - swapper_pg_dir[pgd_index(0)].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - temp = PAGE_OFFSET + 0x400000; - swapper_pg_dir[pgd_index(0x400000)].pgd = - swapper_pg_dir[pgd_index(temp)].pgd; - } - - /* - * After the lock is released, the original page table is restored. - */ + load_cr3(initial_page_table); __flush_tlb_all(); gdt_descr.address = __pa(get_cpu_gdt_table(0)); @@ -85,28 +56,13 @@ void efi_call_phys_prelog(void) void efi_call_phys_epilog(void) { - unsigned long cr4; struct desc_ptr gdt_descr; gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); - cr4 = read_cr4_safe(); - - if (cr4 & X86_CR4_PAE) { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - } else { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - swapper_pg_dir[pgd_index(0x400000)].pgd = - efi_bak_pg_dir_pointer[1].pgd; - } - - /* - * After the lock is released, the original page table is restored. - */ + load_cr3(swapper_pg_dir); __flush_tlb_all(); local_irq_restore(efi_rt_eflags); -- cgit From 37d5993c5cc9bc83762ae1b5bd287438022e8afe Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 10 Dec 2011 20:38:32 +0800 Subject: ASoC: Fix WM8996 24.576MHz clock operation Record the clock after the divider as that is what all SYSCLK users see. Without this the other clock configuration in the device comes out at half rate. Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8996.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 645c980d6b80..a33b04d17195 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1968,6 +1968,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, break; case 24576000: ratediv = WM8996_SYSCLK_DIV; + wm8996->sysclk /= 2; case 12288000: snd_soc_update_bits(codec, WM8996_AIF_RATE, WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); -- cgit From e58f516ff4730c4047c3f104b061f7a03e9a263c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 11 Nov 2011 16:28:05 +0100 Subject: mmc: mxcmmc: fix falling back to PIO When we can't configure the dma channel we want to fall back to PIO. We do this by setting host->do_dma to zero. This does not work as do_dma is used to see whether dma can be used for the current transfer. Instead, we have to set host->dma to NULL. Signed-off-by: Sascha Hauer Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/mxcmmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 325ea61e12d3..8e0fbe994047 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -732,6 +732,7 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) "failed to config DMA channel. Falling back to PIO\n"); dma_release_channel(host->dma); host->do_dma = 0; + host->dma = NULL; } } -- cgit From 7833c66b2d764a3c883c2f5cc60cd8a6266dae15 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Fri, 11 Nov 2011 19:54:53 -0500 Subject: mmc: Add module.h include to sdhci-cns3xxx.c Fixes: drivers/mmc/host/sdhci-cns3xxx.c:110: error: 'THIS_MODULE' undeclared here (not in a function) Reported-by: Al Viro Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-cns3xxx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 4b920b7621cf..87b6f079b6e0 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "sdhci-pltfm.h" -- cgit From 6de5fc9cf7de334912de4cfd2d06eb2d744d2afe Mon Sep 17 00:00:00 2001 From: Stefan Nilsson XK Date: Thu, 3 Nov 2011 09:44:12 +0100 Subject: mmc: core: Add quirk for long data read time Adds a quirk that sets the data read timeout to a fixed value instead of relying on the information in the CSD. The timeout value chosen is 300ms since that has proven enough for the problematic cards found, but could be increased if other cards require this. This patch also enables this quirk for certain Micron cards known to have this problem. Signed-off-by: Stefan Nilsson XK Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Cc: Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 8 ++++++++ drivers/mmc/core/core.c | 12 ++++++++++++ include/linux/mmc/card.h | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index a1cb21f95302..1e0e27cbe987 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1606,6 +1606,14 @@ static const struct mmc_fixup blk_fixups[] = MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + + /* + * Some Micron MMC cards needs longer data read timeout than + * indicated in CSD. + */ + MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc, + MMC_QUIRK_LONG_READ_TIME), + END_FIXUP }; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5278ffb20e74..74a012ad2bab 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -529,6 +529,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_clks = 0; } } + + /* + * Some cards require longer data read timeout than indicated in CSD. + * Address this by setting the read timeout to a "reasonably high" + * value. For the cards tested, 300ms has proven enough. If necessary, + * this value can be increased if other problematic cards require this. + */ + if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) { + data->timeout_ns = 300000000; + data->timeout_clks = 0; + } + /* * Some cards need very high timeouts if driven in SPI mode. * The worst observed timeout was 900ms after writing a diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 415f2db414e1..c8ef9bc54d50 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -218,6 +218,7 @@ struct mmc_card { #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ +#define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 @@ -433,6 +434,11 @@ static inline int mmc_card_broken_byte_mode_512(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_BYTE_MODE_512; } +static inline int mmc_card_long_read_time(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_LONG_READ_TIME; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) -- cgit From 96a85d548bf960ec8e8a0c3bca2b2e88e41549db Mon Sep 17 00:00:00 2001 From: Girish K S Date: Fri, 4 Nov 2011 16:22:47 +0530 Subject: mmc: core: Fix setting power notify state variable for non-eMMC This patch skips the setting of the power notify state variable for non eMMC 4.5 devices. Also fixes the problem of omap_hsmmc noisy/broken for suspend resume reported by Kevin Hilman. Signed-off-by: Girish K S Acked-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index dbf421a6279c..90de9ba36d2f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -883,10 +883,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) goto free_card; - } - if (!err) - card->poweroff_notify_state = MMC_POWERED_ON; + /* + * The err can be -EBADMSG or 0, + * so check for success and update the flag + */ + if (!err) + card->poweroff_notify_state = MMC_POWERED_ON; + } /* * Activate high speed (if supported) -- cgit From a80f16276388a177199204aa5b60f328d4464110 Mon Sep 17 00:00:00 2001 From: Girish K S Date: Tue, 15 Nov 2011 11:55:46 +0530 Subject: mmc: core: Fix power_off_notify during suspend The eMMC 4.5 devices respond to only RESET and AWAKE command in the sleep state. Hence the mmc switch command to notify power off state should be sent before the device enters sleep state. This patch fixes the same. Signed-off-by: Girish K S Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 81 ++++++++++++++++++++++++++++++------------------- drivers/mmc/core/mmc.c | 2 +- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 74a012ad2bab..7ee2e07f36f4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1225,6 +1225,46 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) mmc_host_clk_release(host); } +static void mmc_poweroff_notify(struct mmc_host *host) +{ + struct mmc_card *card; + unsigned int timeout; + unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION; + int err = 0; + + card = host->card; + + /* + * Send power notify command only if card + * is mmc and notify state is powered ON + */ + if (card && mmc_card_mmc(card) && + (card->poweroff_notify_state == MMC_POWERED_ON)) { + + if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { + notify_type = EXT_CSD_POWER_OFF_SHORT; + timeout = card->ext_csd.generic_cmd6_time; + card->poweroff_notify_state = MMC_POWEROFF_SHORT; + } else { + notify_type = EXT_CSD_POWER_OFF_LONG; + timeout = card->ext_csd.power_off_longtime; + card->poweroff_notify_state = MMC_POWEROFF_LONG; + } + + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_OFF_NOTIFICATION, + notify_type, timeout); + + if (err && err != -EBADMSG) + pr_err("Device failed to respond within %d poweroff " + "time. Forcefully powering down the device\n", + timeout); + + /* Set the card state to no notification after the poweroff */ + card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; + } +} + /* * Apply power to the MMC stack. This is a two-stage process. * First, we enable power to the card without the clock running. @@ -1281,42 +1321,12 @@ static void mmc_power_up(struct mmc_host *host) void mmc_power_off(struct mmc_host *host) { - struct mmc_card *card; - unsigned int notify_type; - unsigned int timeout; - int err; - mmc_host_clk_hold(host); - card = host->card; host->ios.clock = 0; host->ios.vdd = 0; - if (card && mmc_card_mmc(card) && - (card->poweroff_notify_state == MMC_POWERED_ON)) { - - if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { - notify_type = EXT_CSD_POWER_OFF_SHORT; - timeout = card->ext_csd.generic_cmd6_time; - card->poweroff_notify_state = MMC_POWEROFF_SHORT; - } else { - notify_type = EXT_CSD_POWER_OFF_LONG; - timeout = card->ext_csd.power_off_longtime; - card->poweroff_notify_state = MMC_POWEROFF_LONG; - } - - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout); - - if (err && err != -EBADMSG) - pr_err("Device failed to respond within %d poweroff " - "time. Forcefully powering down the device\n", - timeout); - - /* Set the card state to no notification after the poweroff */ - card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; - } + mmc_poweroff_notify(host); /* * Reset ocr mask to be the highest possible voltage supported for @@ -2314,8 +2324,15 @@ int mmc_suspend_host(struct mmc_host *host) * pre-claim the host. */ if (mmc_try_claim_host(host)) { - if (host->bus_ops->suspend) + if (host->bus_ops->suspend) { + /* + * For eMMC 4.5 device send notify command + * before sleep, because in sleep state eMMC 4.5 + * devices respond to only RESET and AWAKE cmd + */ + mmc_poweroff_notify(host); err = host->bus_ops->suspend(host); + } if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 90de9ba36d2f..d240427c1246 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -876,7 +876,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * set the notification byte in the ext_csd register of device */ if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && - (card->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)) { + (card->ext_csd.rev >= 6)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, -- cgit From c99872a16fa7642987f30c750dc166674b0d8060 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 17 Nov 2011 13:34:33 +0900 Subject: mmc: core: Fix typo at mmc_card_sleep Fix wrong bus_ops->sleep check. (This isn't expected to have real-world consequences, because the mmc core always defines both 'awake' and 'sleep' ops.) Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7ee2e07f36f4..271efeac860b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2218,7 +2218,7 @@ int mmc_card_sleep(struct mmc_host *host) mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) + if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) err = host->bus_ops->sleep(host); mmc_bus_put(host); -- cgit From f6bc41fb08cbd6943df358437e0af90c91a3caa3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 16 Nov 2011 10:10:41 +0100 Subject: mmc: sh_mmcif: fix clock gating on platforms with a .down_pwr() method Do not power down the card in .set_ios(), unless MMC_POWER_OFF is requested. This fixes the MMCIF interface functionality on ecovec boards. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 369366c8e205..d5505f3fe2a1 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -908,7 +908,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->power) { pm_runtime_put(&host->pd->dev); host->power = false; - if (p->down_pwr) + if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) p->down_pwr(host->pd); } host->state = STATE_IDLE; -- cgit From f6b8b52c68f6109db4be02b55660258ff503fc3b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 16 Nov 2011 10:11:45 +0100 Subject: mmc: tmio: fix clock gating on platforms with a .set_pwr() method Do not power down the card in .set_ios(), unless MMC_POWER_OFF is requested. This fixes the SDHI functionality on ecovec. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc_pio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index d85a60cda167..4208b3958069 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -798,7 +798,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* start bus clock */ tmio_mmc_clk_start(host); } else if (ios->power_mode != MMC_POWER_UP) { - if (host->set_pwr) + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) host->set_pwr(host->pdev, 0); if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && pdata->power) { -- cgit From 524bfca2b42a7c9dc43af13e1592b21dd1ce3fcc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 18:00:51 +0000 Subject: mmc: sdhci-s3c: Remove old and misprototyped suspend operations Now that the driver is using dev_pm_ops the suspend operations in the platform_driver structure won't get called so don't need to be there, and certainly shouldn't be the same function as dev_pm_ops since the signatures are different. Signed-off-by: Mark Brown Acked-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-s3c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 3d00e722efc9..cb60c4197e0a 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -644,8 +644,6 @@ static int sdhci_s3c_resume(struct platform_device *dev) static struct platform_driver sdhci_s3c_driver = { .probe = sdhci_s3c_probe, .remove = __devexit_p(sdhci_s3c_remove), - .suspend = sdhci_s3c_suspend, - .resume = sdhci_s3c_resume, .driver = { .owner = THIS_MODULE, .name = "s3c-sdhci", -- cgit From 49df78074963c97e25debc3c67b72f059111607d Mon Sep 17 00:00:00 2001 From: Sujit Reddy Thumma Date: Wed, 23 Nov 2011 08:43:18 +0530 Subject: mmc: core: Fix deadlock when the CONFIG_MMC_UNSAFE_RESUME is not defined mmc_suspend_host() tries to claim host during suspend and release it only when the bus suspend operation is compeleted. If CONFIG_MMC_UNSAFE_RESUME is defined and the host is flagged as removable, mmc_suspend_host() tries to remove the card. In this process, the file system sync can get blocked trying to acquire host which is already claimed by mmc_suspend_host() causing deadlock. Fix this deadlock by releasing host before ->remove() is called. Signed-off-by: Sujit Reddy Thumma Acked-by: Ulf Hansson Acked-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 271efeac860b..950b97d7412a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2333,6 +2333,8 @@ int mmc_suspend_host(struct mmc_host *host) mmc_poweroff_notify(host); err = host->bus_ops->suspend(host); } + mmc_do_release_host(host); + if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. @@ -2347,7 +2349,6 @@ int mmc_suspend_host(struct mmc_host *host) host->pm_flags = 0; err = 0; } - mmc_do_release_host(host); } else { err = -EBUSY; } -- cgit From 06c8eb9a9115dbbf1658a79f19f18a887c18119b Mon Sep 17 00:00:00 2001 From: Lothar Waßmann Date: Fri, 9 Dec 2011 14:38:11 +0100 Subject: ASoC: mxs: Add missing MODULE_LICENSE("GPL") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sound driver refuses to load as module, because of the missing MODULE_LICENSE("GPL"). The file header indicates that the driver is indeed published under the GPL. Signed-off-by: Lothar Waßmann Acked-by: Wolfram Sang Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index dea5aa4aa647..8646913631de 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -357,3 +357,5 @@ static void __exit snd_mxs_pcm_exit(void) platform_driver_unregister(&mxs_pcm_driver); } module_exit(snd_mxs_pcm_exit); + +MODULE_LICENSE("GPL"); -- cgit From 9fd369b193dceddd4e9e7f426c229c6104c80e28 Mon Sep 17 00:00:00 2001 From: Lothar Waßmann Date: Fri, 9 Dec 2011 14:38:12 +0100 Subject: ASoC: mxs: Add appropriate MODULE_ALIAS() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lothar Waßmann Acked-by: Wolfram Sang Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-pcm.c | 1 + sound/soc/mxs/mxs-sgtl5000.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 8646913631de..f39d7dd9fbcb 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -359,3 +359,4 @@ static void __exit snd_mxs_pcm_exit(void) module_exit(snd_mxs_pcm_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mxs-pcm-audio"); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 7fbeaec06eb4..1c57f6630a48 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -171,3 +171,4 @@ module_exit(mxs_sgtl5000_exit); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("MXS ALSA SoC Machine driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mxs-sgtl5000"); -- cgit From 23bbba3411715736ad1942f3bdbb18e1bbe6d45f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 29 Nov 2011 18:21:41 -0300 Subject: [media] au0828: add missing USB ID 2040:7260 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 39fc923fc46b..2e72bbd100af 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -324,6 +324,8 @@ struct usb_device_id au0828_usb_id_table[] = { .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, { USB_DEVICE(0x2040, 0x8200), .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, + { USB_DEVICE(0x2040, 0x7260), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, { }, }; -- cgit From 64a6b6cbfad64dae8230ff999394a4b1b9e82ceb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 29 Nov 2011 18:23:11 -0300 Subject: [media] au0828: add missing USB ID 2040:7213 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 2e72bbd100af..2dba8c1ea096 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -326,6 +326,8 @@ struct usb_device_id au0828_usb_id_table[] = { .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, { USB_DEVICE(0x2040, 0x7260), .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x7213), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, { }, }; -- cgit From 6b536a6ca52ae12b5378de6fb5da305a3c54dbd8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 29 Nov 2011 18:55:04 -0300 Subject: [media] au0828: add missing models 72101, 72201 & 72261 to the model matrix Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 2dba8c1ea096..1c6015a04f96 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -162,11 +162,14 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) switch (tv.model) { case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ break; -- cgit From d1ee8878a142f81ea1b40d602c6360b752829437 Mon Sep 17 00:00:00 2001 From: Gary Thomas Date: Thu, 1 Dec 2011 08:51:09 -0300 Subject: [media] omap_vout: Fix compile error in 3.1 This patch is against the mainline v3.1 release (c3b92c8) and fixes a compile error when building for OMAP3+DSS+VOUT Acked-by: Laurent Pinchart Signed-off-by: Gary Thomas Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_vout.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 2d2a136e465e..ee0d0b39cd17 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include -- cgit From a626f3945208af1d60d3dccf064cac3b15bc54ca Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Mon, 5 Dec 2011 06:12:15 -0300 Subject: [media] s5p_mfc_enc: fix s/H264/H263/ typo Signed-off-by: Peter Korsgaard Aked-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-mfc/s5p_mfc_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c index 1e8cdb77d4b8..dff9dc798795 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c @@ -61,7 +61,7 @@ static struct s5p_mfc_fmt formats[] = { .num_planes = 1, }, { - .name = "H264 Encoded Stream", + .name = "H263 Encoded Stream", .fourcc = V4L2_PIX_FMT_H263, .codec_mode = S5P_FIMV_CODEC_H263_ENC, .type = MFC_FMT_ENC, -- cgit From 4c0b036db808054f10f79e9a3d7928cf90aeb186 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 5 Dec 2011 16:01:13 -0300 Subject: [media] V4L: soc-camera: fix compiler warnings on 64-bit platforms On 64-bit platforms assigning a pointer to a 32-bit variable causes a compiler warning and cannot actually work. Soc-camera currently doesn't support any 64-bit systems, but such platforms can be added in the and in any case compiler warnings should be avoided. Signed-off-by: Guennadi Liakhovetski Acked-by: Janusz Krzysztofik Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov6650.c | 2 +- drivers/media/video/sh_mobile_ceu_camera.c | 34 ++++++++++++++++++------------ drivers/media/video/sh_mobile_csi2.c | 4 ++-- drivers/media/video/soc_camera.c | 3 ++- include/media/soc_camera.h | 7 +++++- 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c index d5b057207a7b..577941fa3831 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/video/ov6650.c @@ -539,7 +539,7 @@ static u8 to_clkrc(struct v4l2_fract *timeperframe, static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); struct soc_camera_sense *sense = icd->sense; struct ov6650 *priv = to_ov6650(client); bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect); diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index f390682629cf..c51decfcae19 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -566,8 +566,10 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) ret = sh_mobile_ceu_soft_reset(pcdev); csi2_sd = find_csi2(pcdev); - if (csi2_sd) - csi2_sd->grp_id = (long)icd; + if (csi2_sd) { + csi2_sd->grp_id = soc_camera_grp_id(icd); + v4l2_set_subdev_hostdata(csi2_sd, icd); + } ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { @@ -768,7 +770,7 @@ static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev, { if (pcdev->csi2_pdev) { struct v4l2_subdev *csi2_sd = find_csi2(pcdev); - if (csi2_sd && csi2_sd->grp_id == (u32)icd) + if (csi2_sd && csi2_sd->grp_id == soc_camera_grp_id(icd)) return csi2_sd; } @@ -1089,8 +1091,9 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int /* Try 2560x1920, 1280x960, 640x480, 320x240 */ mf.width = 2560 >> shift; mf.height = 1920 >> shift; - ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, - s_mbus_fmt, &mf); + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, &mf); if (ret < 0) return ret; shift++; @@ -1389,7 +1392,8 @@ static int client_s_fmt(struct soc_camera_device *icd, bool ceu_1to1; int ret; - ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, s_mbus_fmt, mf); if (ret < 0) return ret; @@ -1426,8 +1430,9 @@ static int client_s_fmt(struct soc_camera_device *icd, tmp_h = min(2 * tmp_h, max_height); mf->width = tmp_w; mf->height = tmp_h; - ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, - s_mbus_fmt, mf); + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, mf); dev_geo(dev, "Camera scaled to %ux%u\n", mf->width, mf->height); if (ret < 0) { @@ -1580,8 +1585,9 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, } if (interm_width < icd->user_width || interm_height < icd->user_height) { - ret = v4l2_device_call_until_err(sd->v4l2_dev, (int)icd, video, - s_mbus_fmt, &mf); + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, &mf); if (ret < 0) return ret; @@ -1867,7 +1873,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, mf.code = xlate->code; mf.colorspace = pix->colorspace; - ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf); + ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), + video, try_mbus_fmt, &mf); if (ret < 0) return ret; @@ -1891,8 +1898,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, */ mf.width = 2560; mf.height = 1920; - ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, - try_mbus_fmt, &mf); + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + try_mbus_fmt, &mf); if (ret < 0) { /* Shouldn't actually happen... */ dev_err(icd->parent, diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c index 37706eb81f25..bd0ca0e04460 100644 --- a/drivers/media/video/sh_mobile_csi2.c +++ b/drivers/media/video/sh_mobile_csi2.c @@ -142,7 +142,7 @@ static int sh_csi2_s_mbus_config(struct v4l2_subdev *sd, const struct v4l2_mbus_config *cfg) { struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); - struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2, .flags = priv->mipi_flags}; @@ -201,7 +201,7 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv) static int sh_csi2_client_connect(struct sh_csi2 *priv) { struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; - struct soc_camera_device *icd = (struct soc_camera_device *)priv->subdev.grp_id; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev); struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); struct device *dev = v4l2_get_subdevdata(&priv->subdev); struct v4l2_mbus_config cfg; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b72580c38957..62e4312515cb 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -1103,7 +1103,8 @@ static int soc_camera_probe(struct soc_camera_device *icd) } sd = soc_camera_to_subdev(icd); - sd->grp_id = (long)icd; + sd->grp_id = soc_camera_grp_id(icd); + v4l2_set_subdev_hostdata(sd, icd); if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler)) goto ectrl; diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index b1377b931eb7..5fb2c3d10c05 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -254,7 +254,7 @@ unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl, static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); return icd ? icd->vdev : NULL; } @@ -279,6 +279,11 @@ static inline struct soc_camera_device *soc_camera_from_vbq(const struct videobu return container_of(vq, struct soc_camera_device, vb_vidq); } +static inline u32 soc_camera_grp_id(const struct soc_camera_device *icd) +{ + return (icd->iface << 8) | (icd->devnum + 1); +} + void soc_camera_lock(struct vb2_queue *vq); void soc_camera_unlock(struct vb2_queue *vq); -- cgit From 08da558ae0aaa488d8273ee44177c86580ba0d5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Nov 2011 15:44:12 -0300 Subject: [media] V4L: mt9t112: use after free in mt9t112_probe() priv gets dereferenced in mt9t112_set_params() so we should return before calling that. Signed-off-by: Dan Carpenter Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9t112.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 32114a3c0ca7..7b34b11daf24 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -1083,8 +1083,10 @@ static int mt9t112_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); ret = mt9t112_camera_probe(client); - if (ret) + if (ret) { kfree(priv); + return ret; + } /* Cannot fail: using the default supported pixel code */ mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); -- cgit From 9c0223b53a26c506ecc7a36ec491afa688eebee1 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 24 Nov 2011 20:16:35 -0300 Subject: [media] V4L: omap1_camera: fix missing include Otherwise compilation breaks with: ... after apparently no longer included recursively from other header files. Signed-off-by: Janusz Krzysztofik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap1_camera.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index e87ae2f634b2..6a6cf388bae4 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include -- cgit From 6b806e30a3149816454a7ab71d50c244ebdb27d1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 3 Nov 2011 08:12:00 -0300 Subject: [media] V4L: mt9m111: fix uninitialised mutex Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m111.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index f023cc092c2b..dda4685166d5 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -954,6 +954,7 @@ static int mt9m111_probe(struct i2c_client *client, mt9m111->rect.height = MT9M111_MAX_HEIGHT; mt9m111->fmt = &mt9m111_colour_fmts[0]; mt9m111->lastpage = -1; + mutex_init(&mt9m111->power_lock); ret = mt9m111_video_probe(client); if (ret) { -- cgit From 5eefb4f09bd8b250421fbd055e67d136d57f4030 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Tue, 6 Dec 2011 22:34:29 -0300 Subject: [media] ati_remote: switch to single-byte scancodes The ati_remote driver currently uses 2-byte scancodes. However, one of those bytes is actually a checksum and therefore shouldn't be considered as part of the scancode. Fix the driver to only use the actual data byte as a scancode and to check the checksum itself. Update the bundled keymaps accordingly. Since ati_remote was only migrated to the rc subsystem for 3.2, the previous scancodes weren't emitted on any stable kernel. Reported-by: George Spelvin Signed-off-by: Anssi Hannula Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ati_remote.c | 111 +++++++++----------- drivers/media/rc/keymaps/rc-ati-x10.c | 96 ++++++++--------- drivers/media/rc/keymaps/rc-medion-x10.c | 128 +++++++++++------------ drivers/media/rc/keymaps/rc-snapstream-firefly.c | 114 ++++++++++---------- 4 files changed, 220 insertions(+), 229 deletions(-) diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 303f22ea04c0..01bb8daf4b09 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -189,7 +189,7 @@ struct ati_remote { dma_addr_t inbuf_dma; dma_addr_t outbuf_dma; - unsigned char old_data[2]; /* Detect duplicate events */ + unsigned char old_data; /* Detect duplicate events */ unsigned long old_jiffies; unsigned long acc_jiffies; /* handle acceleration */ unsigned long first_jiffies; @@ -221,35 +221,35 @@ struct ati_remote { /* Translation table from hardware messages to input events. */ static const struct { short kind; - unsigned char data1, data2; + unsigned char data; int type; unsigned int code; int value; } ati_remote_tbl[] = { /* Directional control pad axes */ - {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ - {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ - {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ - {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ + {KIND_ACCEL, 0x70, EV_REL, REL_X, -1}, /* left */ + {KIND_ACCEL, 0x71, EV_REL, REL_X, 1}, /* right */ + {KIND_ACCEL, 0x72, EV_REL, REL_Y, -1}, /* up */ + {KIND_ACCEL, 0x73, EV_REL, REL_Y, 1}, /* down */ /* Directional control pad diagonals */ - {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ - {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ - {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ - {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ + {KIND_LU, 0x74, EV_REL, 0, 0}, /* left up */ + {KIND_RU, 0x75, EV_REL, 0, 0}, /* right up */ + {KIND_LD, 0x77, EV_REL, 0, 0}, /* left down */ + {KIND_RD, 0x76, EV_REL, 0, 0}, /* right down */ /* "Mouse button" buttons */ - {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ - {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ - {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ - {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ + {KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ + {KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ + {KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ + {KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ /* Artificial "doubleclick" events are generated by the hardware. * They are mapped to the "side" and "extra" mouse buttons here. */ - {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ - {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ + {KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ + {KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ /* Non-mouse events are handled by rc-core */ - {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} + {KIND_END, 0x00, EV_MAX + 1, 0, 0} }; /* Local function prototypes */ @@ -396,25 +396,6 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne return retval; } -/* - * ati_remote_event_lookup - */ -static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) -{ - int i; - - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { - /* - * Decide if the table entry matches the remote input. - */ - if (ati_remote_tbl[i].data1 == d1 && - ati_remote_tbl[i].data2 == d2) - return i; - - } - return -1; -} - /* * ati_remote_compute_accel * @@ -463,7 +444,15 @@ static void ati_remote_input_report(struct urb *urb) int index = -1; int acc; int remote_num; - unsigned char scancode[2]; + unsigned char scancode; + int i; + + /* + * data[0] = 0x14 + * data[1] = data[2] + data[3] + 0xd5 (a checksum byte) + * data[2] = the key code (with toggle bit in MSB with some models) + * data[3] = channel << 4 (the low 4 bits must be zero) + */ /* Deal with strange looking inputs */ if ( (urb->actual_length != 4) || (data[0] != 0x14) || @@ -472,6 +461,13 @@ static void ati_remote_input_report(struct urb *urb) return; } + if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) { + dbginfo(&ati_remote->interface->dev, + "wrong checksum in input: %02x %02x %02x %02x\n", + data[0], data[1], data[2], data[3]); + return; + } + /* Mask unwanted remote channels. */ /* note: remote_num is 0-based, channel 1 on remote == 0 here */ remote_num = (data[3] >> 4) & 0x0f; @@ -482,31 +478,30 @@ static void ati_remote_input_report(struct urb *urb) return; } - scancode[0] = (((data[1] - ((remote_num + 1) << 4)) & 0xf0) | (data[1] & 0x0f)); - /* - * Some devices (e.g. SnapStream Firefly) use 8080 as toggle code, - * so we have to clear them. The first bit is a bit tricky as the - * "non-toggled" state depends on remote_num, so we xor it with the - * second bit which is only used for toggle. + * MSB is a toggle code, though only used by some devices + * (e.g. SnapStream Firefly) */ - scancode[0] ^= (data[2] & 0x80); - - scancode[1] = data[2] & ~0x80; + scancode = data[2] & 0x7f; - /* Look up event code index in mouse translation table. */ - index = ati_remote_event_lookup(remote_num, scancode[0], scancode[1]); + /* Look up event code index in the mouse translation table. */ + for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { + if (scancode == ati_remote_tbl[i].data) { + index = i; + break; + } + } if (index >= 0) { dbginfo(&ati_remote->interface->dev, - "channel 0x%02x; mouse data %02x,%02x; index %d; keycode %d\n", - remote_num, data[1], data[2], index, ati_remote_tbl[index].code); + "channel 0x%02x; mouse data %02x; index %d; keycode %d\n", + remote_num, data[2], index, ati_remote_tbl[index].code); if (!dev) return; /* no mouse device */ } else dbginfo(&ati_remote->interface->dev, - "channel 0x%02x; key data %02x,%02x, scancode %02x,%02x\n", - remote_num, data[1], data[2], scancode[0], scancode[1]); + "channel 0x%02x; key data %02x, scancode %02x\n", + remote_num, data[2], scancode); if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) { @@ -523,8 +518,7 @@ static void ati_remote_input_report(struct urb *urb) unsigned long now = jiffies; /* Filter duplicate events which happen "too close" together. */ - if (ati_remote->old_data[0] == data[1] && - ati_remote->old_data[1] == data[2] && + if (ati_remote->old_data == data[2] && time_before(now, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { ati_remote->repeat_count++; @@ -533,8 +527,7 @@ static void ati_remote_input_report(struct urb *urb) ati_remote->first_jiffies = now; } - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + ati_remote->old_data = data[2]; ati_remote->old_jiffies = now; /* Ensure we skip at least the 4 first duplicate events (generated @@ -549,14 +542,13 @@ static void ati_remote_input_report(struct urb *urb) if (index < 0) { /* Not a mouse event, hand it to rc-core. */ - u32 rc_code = (scancode[0] << 8) | scancode[1]; /* * We don't use the rc-core repeat handling yet as * it would cause ghost repeats which would be a * regression for this driver. */ - rc_keydown_notimeout(ati_remote->rdev, rc_code, + rc_keydown_notimeout(ati_remote->rdev, scancode, data[2]); rc_keyup(ati_remote->rdev); return; @@ -607,8 +599,7 @@ static void ati_remote_input_report(struct urb *urb) input_sync(dev); ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + ati_remote->old_data = data[2]; } } diff --git a/drivers/media/rc/keymaps/rc-ati-x10.c b/drivers/media/rc/keymaps/rc-ati-x10.c index e1b8b2605c48..81506440eded 100644 --- a/drivers/media/rc/keymaps/rc-ati-x10.c +++ b/drivers/media/rc/keymaps/rc-ati-x10.c @@ -27,55 +27,55 @@ #include static struct rc_map_table ati_x10[] = { - { 0xd20d, KEY_1 }, - { 0xd30e, KEY_2 }, - { 0xd40f, KEY_3 }, - { 0xd510, KEY_4 }, - { 0xd611, KEY_5 }, - { 0xd712, KEY_6 }, - { 0xd813, KEY_7 }, - { 0xd914, KEY_8 }, - { 0xda15, KEY_9 }, - { 0xdc17, KEY_0 }, - { 0xc500, KEY_A }, - { 0xc601, KEY_B }, - { 0xde19, KEY_C }, - { 0xe01b, KEY_D }, - { 0xe621, KEY_E }, - { 0xe823, KEY_F }, + { 0x0d, KEY_1 }, + { 0x0e, KEY_2 }, + { 0x0f, KEY_3 }, + { 0x10, KEY_4 }, + { 0x11, KEY_5 }, + { 0x12, KEY_6 }, + { 0x13, KEY_7 }, + { 0x14, KEY_8 }, + { 0x15, KEY_9 }, + { 0x17, KEY_0 }, + { 0x00, KEY_A }, + { 0x01, KEY_B }, + { 0x19, KEY_C }, + { 0x1b, KEY_D }, + { 0x21, KEY_E }, + { 0x23, KEY_F }, - { 0xdd18, KEY_KPENTER }, /* "check" */ - { 0xdb16, KEY_MENU }, /* "menu" */ - { 0xc702, KEY_POWER }, /* Power */ - { 0xc803, KEY_TV }, /* TV */ - { 0xc904, KEY_DVD }, /* DVD */ - { 0xca05, KEY_WWW }, /* WEB */ - { 0xcb06, KEY_BOOKMARKS }, /* "book" */ - { 0xcc07, KEY_EDIT }, /* "hand" */ - { 0xe11c, KEY_COFFEE }, /* "timer" */ - { 0xe520, KEY_FRONT }, /* "max" */ - { 0xe21d, KEY_LEFT }, /* left */ - { 0xe41f, KEY_RIGHT }, /* right */ - { 0xe722, KEY_DOWN }, /* down */ - { 0xdf1a, KEY_UP }, /* up */ - { 0xe31e, KEY_OK }, /* "OK" */ - { 0xce09, KEY_VOLUMEDOWN }, /* VOL + */ - { 0xcd08, KEY_VOLUMEUP }, /* VOL - */ - { 0xcf0a, KEY_MUTE }, /* MUTE */ - { 0xd00b, KEY_CHANNELUP }, /* CH + */ - { 0xd10c, KEY_CHANNELDOWN },/* CH - */ - { 0xec27, KEY_RECORD }, /* ( o) red */ - { 0xea25, KEY_PLAY }, /* ( >) */ - { 0xe924, KEY_REWIND }, /* (<<) */ - { 0xeb26, KEY_FORWARD }, /* (>>) */ - { 0xed28, KEY_STOP }, /* ([]) */ - { 0xee29, KEY_PAUSE }, /* ('') */ - { 0xf02b, KEY_PREVIOUS }, /* (<-) */ - { 0xef2a, KEY_NEXT }, /* (>+) */ - { 0xf22d, KEY_INFO }, /* PLAYING */ - { 0xf32e, KEY_HOME }, /* TOP */ - { 0xf42f, KEY_END }, /* END */ - { 0xf530, KEY_SELECT }, /* SELECT */ + { 0x18, KEY_KPENTER }, /* "check" */ + { 0x16, KEY_MENU }, /* "menu" */ + { 0x02, KEY_POWER }, /* Power */ + { 0x03, KEY_TV }, /* TV */ + { 0x04, KEY_DVD }, /* DVD */ + { 0x05, KEY_WWW }, /* WEB */ + { 0x06, KEY_BOOKMARKS }, /* "book" */ + { 0x07, KEY_EDIT }, /* "hand" */ + { 0x1c, KEY_COFFEE }, /* "timer" */ + { 0x20, KEY_FRONT }, /* "max" */ + { 0x1d, KEY_LEFT }, /* left */ + { 0x1f, KEY_RIGHT }, /* right */ + { 0x22, KEY_DOWN }, /* down */ + { 0x1a, KEY_UP }, /* up */ + { 0x1e, KEY_OK }, /* "OK" */ + { 0x09, KEY_VOLUMEDOWN }, /* VOL + */ + { 0x08, KEY_VOLUMEUP }, /* VOL - */ + { 0x0a, KEY_MUTE }, /* MUTE */ + { 0x0b, KEY_CHANNELUP }, /* CH + */ + { 0x0c, KEY_CHANNELDOWN },/* CH - */ + { 0x27, KEY_RECORD }, /* ( o) red */ + { 0x25, KEY_PLAY }, /* ( >) */ + { 0x24, KEY_REWIND }, /* (<<) */ + { 0x26, KEY_FORWARD }, /* (>>) */ + { 0x28, KEY_STOP }, /* ([]) */ + { 0x29, KEY_PAUSE }, /* ('') */ + { 0x2b, KEY_PREVIOUS }, /* (<-) */ + { 0x2a, KEY_NEXT }, /* (>+) */ + { 0x2d, KEY_INFO }, /* PLAYING */ + { 0x2e, KEY_HOME }, /* TOP */ + { 0x2f, KEY_END }, /* END */ + { 0x30, KEY_SELECT }, /* SELECT */ }; static struct rc_map_list ati_x10_map = { diff --git a/drivers/media/rc/keymaps/rc-medion-x10.c b/drivers/media/rc/keymaps/rc-medion-x10.c index 09e2cc01d110..479cdb897810 100644 --- a/drivers/media/rc/keymaps/rc-medion-x10.c +++ b/drivers/media/rc/keymaps/rc-medion-x10.c @@ -25,70 +25,70 @@ #include static struct rc_map_table medion_x10[] = { - { 0xf12c, KEY_TV }, /* TV */ - { 0xf22d, KEY_VCR }, /* VCR */ - { 0xc904, KEY_DVD }, /* DVD */ - { 0xcb06, KEY_AUDIO }, /* MUSIC */ - - { 0xf32e, KEY_RADIO }, /* RADIO */ - { 0xca05, KEY_DIRECTORY }, /* PHOTO */ - { 0xf42f, KEY_INFO }, /* TV-PREVIEW */ - { 0xf530, KEY_LIST }, /* CHANNEL-LST */ - - { 0xe01b, KEY_SETUP }, /* SETUP */ - { 0xf631, KEY_VIDEO }, /* VIDEO DESKTOP */ - - { 0xcd08, KEY_VOLUMEDOWN }, /* VOL - */ - { 0xce09, KEY_VOLUMEUP }, /* VOL + */ - { 0xd00b, KEY_CHANNELUP }, /* CHAN + */ - { 0xd10c, KEY_CHANNELDOWN }, /* CHAN - */ - { 0xc500, KEY_MUTE }, /* MUTE */ - - { 0xf732, KEY_RED }, /* red */ - { 0xf833, KEY_GREEN }, /* green */ - { 0xf934, KEY_YELLOW }, /* yellow */ - { 0xfa35, KEY_BLUE }, /* blue */ - { 0xdb16, KEY_TEXT }, /* TXT */ - - { 0xd20d, KEY_1 }, - { 0xd30e, KEY_2 }, - { 0xd40f, KEY_3 }, - { 0xd510, KEY_4 }, - { 0xd611, KEY_5 }, - { 0xd712, KEY_6 }, - { 0xd813, KEY_7 }, - { 0xd914, KEY_8 }, - { 0xda15, KEY_9 }, - { 0xdc17, KEY_0 }, - { 0xe11c, KEY_SEARCH }, /* TV/RAD, CH SRC */ - { 0xe520, KEY_DELETE }, /* DELETE */ - - { 0xfb36, KEY_KEYBOARD }, /* RENAME */ - { 0xdd18, KEY_SCREEN }, /* SNAPSHOT */ - - { 0xdf1a, KEY_UP }, /* up */ - { 0xe722, KEY_DOWN }, /* down */ - { 0xe21d, KEY_LEFT }, /* left */ - { 0xe41f, KEY_RIGHT }, /* right */ - { 0xe31e, KEY_OK }, /* OK */ - - { 0xfc37, KEY_SELECT }, /* ACQUIRE IMAGE */ - { 0xfd38, KEY_EDIT }, /* EDIT IMAGE */ - - { 0xe924, KEY_REWIND }, /* rewind (<<) */ - { 0xea25, KEY_PLAY }, /* play ( >) */ - { 0xeb26, KEY_FORWARD }, /* forward (>>) */ - { 0xec27, KEY_RECORD }, /* record ( o) */ - { 0xed28, KEY_STOP }, /* stop ([]) */ - { 0xee29, KEY_PAUSE }, /* pause ('') */ - - { 0xe621, KEY_PREVIOUS }, /* prev */ - { 0xfe39, KEY_SWITCHVIDEOMODE }, /* F SCR */ - { 0xe823, KEY_NEXT }, /* next */ - { 0xde19, KEY_MENU }, /* MENU */ - { 0xff3a, KEY_LANGUAGE }, /* AUDIO */ - - { 0xc702, KEY_POWER }, /* POWER */ + { 0x2c, KEY_TV }, /* TV */ + { 0x2d, KEY_VCR }, /* VCR */ + { 0x04, KEY_DVD }, /* DVD */ + { 0x06, KEY_AUDIO }, /* MUSIC */ + + { 0x2e, KEY_RADIO }, /* RADIO */ + { 0x05, KEY_DIRECTORY }, /* PHOTO */ + { 0x2f, KEY_INFO }, /* TV-PREVIEW */ + { 0x30, KEY_LIST }, /* CHANNEL-LST */ + + { 0x1b, KEY_SETUP }, /* SETUP */ + { 0x31, KEY_VIDEO }, /* VIDEO DESKTOP */ + + { 0x08, KEY_VOLUMEDOWN }, /* VOL - */ + { 0x09, KEY_VOLUMEUP }, /* VOL + */ + { 0x0b, KEY_CHANNELUP }, /* CHAN + */ + { 0x0c, KEY_CHANNELDOWN }, /* CHAN - */ + { 0x00, KEY_MUTE }, /* MUTE */ + + { 0x32, KEY_RED }, /* red */ + { 0x33, KEY_GREEN }, /* green */ + { 0x34, KEY_YELLOW }, /* yellow */ + { 0x35, KEY_BLUE }, /* blue */ + { 0x16, KEY_TEXT }, /* TXT */ + + { 0x0d, KEY_1 }, + { 0x0e, KEY_2 }, + { 0x0f, KEY_3 }, + { 0x10, KEY_4 }, + { 0x11, KEY_5 }, + { 0x12, KEY_6 }, + { 0x13, KEY_7 }, + { 0x14, KEY_8 }, + { 0x15, KEY_9 }, + { 0x17, KEY_0 }, + { 0x1c, KEY_SEARCH }, /* TV/RAD, CH SRC */ + { 0x20, KEY_DELETE }, /* DELETE */ + + { 0x36, KEY_KEYBOARD }, /* RENAME */ + { 0x18, KEY_SCREEN }, /* SNAPSHOT */ + + { 0x1a, KEY_UP }, /* up */ + { 0x22, KEY_DOWN }, /* down */ + { 0x1d, KEY_LEFT }, /* left */ + { 0x1f, KEY_RIGHT }, /* right */ + { 0x1e, KEY_OK }, /* OK */ + + { 0x37, KEY_SELECT }, /* ACQUIRE IMAGE */ + { 0x38, KEY_EDIT }, /* EDIT IMAGE */ + + { 0x24, KEY_REWIND }, /* rewind (<<) */ + { 0x25, KEY_PLAY }, /* play ( >) */ + { 0x26, KEY_FORWARD }, /* forward (>>) */ + { 0x27, KEY_RECORD }, /* record ( o) */ + { 0x28, KEY_STOP }, /* stop ([]) */ + { 0x29, KEY_PAUSE }, /* pause ('') */ + + { 0x21, KEY_PREVIOUS }, /* prev */ + { 0x39, KEY_SWITCHVIDEOMODE }, /* F SCR */ + { 0x23, KEY_NEXT }, /* next */ + { 0x19, KEY_MENU }, /* MENU */ + { 0x3a, KEY_LANGUAGE }, /* AUDIO */ + + { 0x02, KEY_POWER }, /* POWER */ }; static struct rc_map_list medion_x10_map = { diff --git a/drivers/media/rc/keymaps/rc-snapstream-firefly.c b/drivers/media/rc/keymaps/rc-snapstream-firefly.c index ef146520931c..c7f33ec719b4 100644 --- a/drivers/media/rc/keymaps/rc-snapstream-firefly.c +++ b/drivers/media/rc/keymaps/rc-snapstream-firefly.c @@ -22,63 +22,63 @@ #include static struct rc_map_table snapstream_firefly[] = { - { 0xf12c, KEY_ZOOM }, /* Maximize */ - { 0xc702, KEY_CLOSE }, - - { 0xd20d, KEY_1 }, - { 0xd30e, KEY_2 }, - { 0xd40f, KEY_3 }, - { 0xd510, KEY_4 }, - { 0xd611, KEY_5 }, - { 0xd712, KEY_6 }, - { 0xd813, KEY_7 }, - { 0xd914, KEY_8 }, - { 0xda15, KEY_9 }, - { 0xdc17, KEY_0 }, - { 0xdb16, KEY_BACK }, - { 0xdd18, KEY_KPENTER }, /* ent */ - - { 0xce09, KEY_VOLUMEUP }, - { 0xcd08, KEY_VOLUMEDOWN }, - { 0xcf0a, KEY_MUTE }, - { 0xd00b, KEY_CHANNELUP }, - { 0xd10c, KEY_CHANNELDOWN }, - { 0xc500, KEY_VENDOR }, /* firefly */ - - { 0xf32e, KEY_INFO }, - { 0xf42f, KEY_OPTION }, - - { 0xe21d, KEY_LEFT }, - { 0xe41f, KEY_RIGHT }, - { 0xe722, KEY_DOWN }, - { 0xdf1a, KEY_UP }, - { 0xe31e, KEY_OK }, - - { 0xe11c, KEY_MENU }, - { 0xe520, KEY_EXIT }, - - { 0xec27, KEY_RECORD }, - { 0xea25, KEY_PLAY }, - { 0xed28, KEY_STOP }, - { 0xe924, KEY_REWIND }, - { 0xeb26, KEY_FORWARD }, - { 0xee29, KEY_PAUSE }, - { 0xf02b, KEY_PREVIOUS }, - { 0xef2a, KEY_NEXT }, - - { 0xcb06, KEY_AUDIO }, /* Music */ - { 0xca05, KEY_IMAGES }, /* Photos */ - { 0xc904, KEY_DVD }, - { 0xc803, KEY_TV }, - { 0xcc07, KEY_VIDEO }, - - { 0xc601, KEY_HELP }, - { 0xf22d, KEY_MODE }, /* Mouse */ - - { 0xde19, KEY_A }, - { 0xe01b, KEY_B }, - { 0xe621, KEY_C }, - { 0xe823, KEY_D }, + { 0x2c, KEY_ZOOM }, /* Maximize */ + { 0x02, KEY_CLOSE }, + + { 0x0d, KEY_1 }, + { 0x0e, KEY_2 }, + { 0x0f, KEY_3 }, + { 0x10, KEY_4 }, + { 0x11, KEY_5 }, + { 0x12, KEY_6 }, + { 0x13, KEY_7 }, + { 0x14, KEY_8 }, + { 0x15, KEY_9 }, + { 0x17, KEY_0 }, + { 0x16, KEY_BACK }, + { 0x18, KEY_KPENTER }, /* ent */ + + { 0x09, KEY_VOLUMEUP }, + { 0x08, KEY_VOLUMEDOWN }, + { 0x0a, KEY_MUTE }, + { 0x0b, KEY_CHANNELUP }, + { 0x0c, KEY_CHANNELDOWN }, + { 0x00, KEY_VENDOR }, /* firefly */ + + { 0x2e, KEY_INFO }, + { 0x2f, KEY_OPTION }, + + { 0x1d, KEY_LEFT }, + { 0x1f, KEY_RIGHT }, + { 0x22, KEY_DOWN }, + { 0x1a, KEY_UP }, + { 0x1e, KEY_OK }, + + { 0x1c, KEY_MENU }, + { 0x20, KEY_EXIT }, + + { 0x27, KEY_RECORD }, + { 0x25, KEY_PLAY }, + { 0x28, KEY_STOP }, + { 0x24, KEY_REWIND }, + { 0x26, KEY_FORWARD }, + { 0x29, KEY_PAUSE }, + { 0x2b, KEY_PREVIOUS }, + { 0x2a, KEY_NEXT }, + + { 0x06, KEY_AUDIO }, /* Music */ + { 0x05, KEY_IMAGES }, /* Photos */ + { 0x04, KEY_DVD }, + { 0x03, KEY_TV }, + { 0x07, KEY_VIDEO }, + + { 0x01, KEY_HELP }, + { 0x2d, KEY_MODE }, /* Mouse */ + + { 0x19, KEY_A }, + { 0x1b, KEY_B }, + { 0x21, KEY_C }, + { 0x23, KEY_D }, }; static struct rc_map_list snapstream_firefly_map = { -- cgit From a32390d808b5b7a6b1c7f9236673c917b4733f13 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Sat, 15 Oct 2011 18:38:40 -0300 Subject: [media] m5mols: Fix logic in sanity check Detected by "cppcheck". Signed-off-by: Thomas Jarosch Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/m5mols/m5mols_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 68497f8ddcd9..5da8d74df508 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c @@ -333,7 +333,7 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) int ret = -EINVAL; u8 reg; - if (mode < REG_PARAMETER && mode > REG_CAPTURE) + if (mode < REG_PARAMETER || mode > REG_CAPTURE) return ret; ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); -- cgit From 393a23fc9377ac3deaa97c5cc00b5c78746c8570 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 8 Dec 2011 06:56:22 -0300 Subject: [media] s5p-fimc: Fix camera input configuration in subdev operations When using only subdev user-space operations the camera interface input was not configured properly. Fix this by updating the corresponding data structure in set_fmt operation. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-capture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 82d9ab6984eb..2cc3b9166724 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -1242,6 +1242,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, mutex_lock(&fimc->lock); set_frame_bounds(ff, mf->width, mf->height); + fimc->vid_cap.mf = *mf; ff->fmt = ffmt; /* Reset the crop rectangle if required. */ -- cgit From 9811ccdfa94b4773c8030569bd8ec75eafa485ac Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Sun, 11 Dec 2011 20:32:25 +0100 Subject: ARM: 7204/1: arch/arm/kernel/setup.c: initialize arm_dma_zone_size earlier arm_dma_zone_size is used by arm_bootmem_free() which is called by paging_init(). Thus it needs to be set before calling it. Signed-off-by: Arnaud Patard Acked-by: Nicolas Pitre Cc: stable@kernel.org Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1bdd0adbb7dd..8fc2c8fcbdc6 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -902,6 +902,12 @@ void __init setup_arch(char **cmdline_p) machine_desc = mdesc; machine_name = mdesc->name; +#ifdef CONFIG_ZONE_DMA + if (mdesc->dma_zone_size) { + extern unsigned long arm_dma_zone_size; + arm_dma_zone_size = mdesc->dma_zone_size; + } +#endif if (mdesc->soft_reboot) reboot_setup("s"); @@ -932,12 +938,6 @@ void __init setup_arch(char **cmdline_p) tcm_init(); -#ifdef CONFIG_ZONE_DMA - if (mdesc->dma_zone_size) { - extern unsigned long arm_dma_zone_size; - arm_dma_zone_size = mdesc->dma_zone_size; - } -#endif #ifdef CONFIG_MULTI_IRQ_HANDLER handle_arch_irq = mdesc->handle_irq; #endif -- cgit From 62e4a13e602214908341fad068ff91f31aed1a4e Mon Sep 17 00:00:00 2001 From: Jonathan Neuschäfer Date: Sun, 11 Dec 2011 19:15:49 +0100 Subject: ASoC: WM8958: correctly show firmware magic on mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonathan Neuschäfer Signed-off-by: Mark Brown --- sound/soc/codecs/wm8958-dsp2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 0293763debe5..5a14d5c0e0e1 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -60,6 +60,8 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, } if (memcmp(fw->data, "WMFW", 4) != 0) { + memcpy(&data32, fw->data, sizeof(data32)); + data32 = be32_to_cpu(data32); dev_err(codec->dev, "%s: firmware has bad file magic %08x\n", name, data32); goto err; -- cgit From 497d496598f411cb7f0690725a0e8b9029cebdb9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 12 Dec 2011 11:26:00 +0800 Subject: ASoC: Fix hx4700 error handling to free gpios if snd_soc_register_card fails Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/pxa/hx4700.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index 65c124831a00..c664e33fb6d7 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -209,9 +209,10 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev) snd_soc_card_hx4700.dev = &pdev->dev; ret = snd_soc_register_card(&snd_soc_card_hx4700); if (ret) - return ret; + gpio_free_array(hx4700_audio_gpios, + ARRAY_SIZE(hx4700_audio_gpios)); - return 0; + return ret; } static int __devexit hx4700_audio_remove(struct platform_device *pdev) -- cgit From 0d0e3064a88cc8d6bd3a9b43c5ae069ca838fc6e Mon Sep 17 00:00:00 2001 From: Chris Bagwell Date: Sun, 11 Dec 2011 23:50:59 -0800 Subject: Input: wacom - add product id used by Samsung Slate 7 New product ID reported by Harvey Braun on linuxwacom mailing list and also tested this patch with new hardware. Signed-off-by: Chris Bagwell Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index da0d8761e778..2ee47d01a3b4 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1470,6 +1470,9 @@ static const struct wacom_features wacom_features_0xE3 = static const struct wacom_features wacom_features_0xE6 = { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xEC = + { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x47 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -1611,6 +1614,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE3) }, { USB_DEVICE_WACOM(0xE6) }, + { USB_DEVICE_WACOM(0xEC) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_LENOVO(0x6004) }, { } -- cgit From 3a7f8fb1d8c9b6a066b0452cea47c85547c97723 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Sun, 11 Dec 2011 23:40:56 -0800 Subject: Input: cma3000_d0x - fix signedness bug in cma3000_thread_irq() The error check (intr_status < 0) didn't work because intr_status is a u8. Change its type to signed int. Signed-off-by: Xi Wang Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cma3000_d0x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 1633b6342267..09f8f2025580 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -114,8 +114,8 @@ static void decode_mg(struct cma3000_accl_data *data, int *datax, static irqreturn_t cma3000_thread_irq(int irq, void *dev_id) { struct cma3000_accl_data *data = dev_id; - int datax, datay, dataz; - u8 ctrl, mode, range, intr_status; + int datax, datay, dataz, intr_status; + u8 ctrl, mode, range; intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status"); if (intr_status < 0) -- cgit From 8521478f67e95ada4e87970c7b41e504c724b2cf Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 12 Dec 2011 00:05:53 -0800 Subject: Input: synaptics - fix touchpad not working after S2R on Vostro V13 Synaptics touchpads on several Dell laptops, particularly Vostro V13 systems, may not respond properly to PS/2 commands and queries immediately after resuming from suspend to RAM. This leads to unresponsive touchpad after suspend/resume cycle. Adding a 1-second delay after resetting the device allows touchpad to finish initializing (calibrating?) and start reacting properly. Reported-by: Daniel Manrique Tested-by: Daniel Manrique Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index c080b828e5dc..a6dcd18e9adf 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -1220,6 +1221,16 @@ static int synaptics_reconnect(struct psmouse *psmouse) do { psmouse_reset(psmouse); + if (retry) { + /* + * On some boxes, right after resuming, the touchpad + * needs some time to finish initializing (I assume + * it needs time to calibrate) and start responding + * to Synaptics-specific queries, so let's wait a + * bit. + */ + ssleep(1); + } error = synaptics_detect(psmouse, 0); } while (error && ++retry < 3); -- cgit From f6a290b419a2675c4b77a6b0731cd2a64332365e Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 7 Nov 2011 22:05:21 +1100 Subject: [SCSI] mpt2sas: _scsih_smart_predicted_fault uses GFP_KERNEL in interrupt context _scsih_smart_predicted_fault is called in an interrupt and therefore must allocate memory using GFP_ATOMIC. Signed-off-by: Anton Blanchard Cc: Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 4e041f6d808c..d570573b7963 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -4335,7 +4335,7 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) /* insert into event log */ sz = offsetof(Mpi2EventNotificationReply_t, EventData) + sizeof(Mpi2EventDataSasDeviceStatusChange_t); - event_reply = kzalloc(sz, GFP_KERNEL); + event_reply = kzalloc(sz, GFP_ATOMIC); if (!event_reply) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); -- cgit From ad537689c30d8e35300dcc93a109a966b8a89478 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 18 Nov 2011 09:02:09 -0800 Subject: [SCSI] qla2xxx: Remove qla2x00_wait_for_loop_ready function. This function can wait for 5min under certain scenarios. One of them is when the port is down from switch and bus reset is issued. The bus reset used to wait for 5 minutes for the loop and upper layer callers used to hang and give stack trace because of getting stuck for 120 sec. It is legacy code that was used when the driver used to do queuing of the commands. Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 70 +++---------------------------------------- 1 file changed, 4 insertions(+), 66 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fd14c7bfc626..93673d3094e8 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -814,49 +814,6 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) return return_status; } -/* - * qla2x00_wait_for_loop_ready - * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop - * to be in LOOP_READY state. - * Input: - * ha - pointer to host adapter structure - * - * Note: - * Does context switching-Release SPIN_LOCK - * (if any) before calling this routine. - * - * - * Return: - * Success (LOOP_READY) : 0 - * Failed (LOOP_NOT_READY) : 1 - */ -static inline int -qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha) -{ - int return_status = QLA_SUCCESS; - unsigned long loop_timeout ; - struct qla_hw_data *ha = vha->hw; - scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - - /* wait for 5 min at the max for loop to be ready */ - loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); - - while ((!atomic_read(&base_vha->loop_down_timer) && - atomic_read(&base_vha->loop_state) == LOOP_DOWN) || - atomic_read(&base_vha->loop_state) != LOOP_READY) { - if (atomic_read(&base_vha->loop_state) == LOOP_DEAD) { - return_status = QLA_FUNCTION_FAILED; - break; - } - msleep(1000); - if (time_after_eq(jiffies, loop_timeout)) { - return_status = QLA_FUNCTION_FAILED; - break; - } - } - return (return_status); -} - static void sp_get(struct srb *sp) { @@ -1035,12 +992,6 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, "Wait for hba online failed for cmd=%p.\n", cmd); goto eh_reset_failed; } - err = 1; - if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x800b, - "Wait for loop ready failed for cmd=%p.\n", cmd); - goto eh_reset_failed; - } err = 2; if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1) != QLA_SUCCESS) { @@ -1137,10 +1088,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) goto eh_bus_reset_done; } - if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) { - if (qla2x00_loop_reset(vha) == QLA_SUCCESS) - ret = SUCCESS; - } + if (qla2x00_loop_reset(vha) == QLA_SUCCESS) + ret = SUCCESS; + if (ret == FAILED) goto eh_bus_reset_done; @@ -1206,15 +1156,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS) goto eh_host_reset_lock; - /* - * Fixme-may be dpc thread is active and processing - * loop_resync,so wait a while for it to - * be completed and then issue big hammer.Otherwise - * it may cause I/O failure as big hammer marks the - * devices as lost kicking of the port_down_timer - * while dpc is stuck for the mailbox to complete. - */ - qla2x00_wait_for_loop_ready(vha); if (vha != base_vha) { if (qla2x00_vp_abort_isp(vha)) goto eh_host_reset_lock; @@ -1297,16 +1238,13 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); qla2x00_mark_all_devices_lost(vha, 0); - qla2x00_wait_for_loop_ready(vha); } if (ha->flags.enable_lip_reset) { ret = qla2x00_lip_reset(vha); - if (ret != QLA_SUCCESS) { + if (ret != QLA_SUCCESS) ql_dbg(ql_dbg_taskm, vha, 0x802e, "lip_reset failed (%d).\n", ret); - } else - qla2x00_wait_for_loop_ready(vha); } /* Issue marker command only when we are going to start the I/O */ -- cgit From 4e85e3d92fd1b52989882062f5cb143a31375b62 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Fri, 18 Nov 2011 09:02:10 -0800 Subject: [SCSI] qla2xxx: Check for SCSI status on underruns. Signed-off-by: Arun Easi Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2516adf1aeea..7b91b290ffd6 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1741,7 +1741,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) resid, scsi_bufflen(cp)); cp->result = DID_ERROR << 16 | lscsi_status; - break; + goto check_scsi_status; } if (!lscsi_status && -- cgit From be5ea3cfa15ddef0bee9dfbc214c2113119087a2 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 18 Nov 2011 09:02:11 -0800 Subject: [SCSI] qla2xxx: Don't call alloc_fw_dump for ISP82XX. Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f03e915f1877..54ea68cec4c5 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1509,7 +1509,8 @@ enable_82xx_npiv: &ha->fw_xcb_count, NULL, NULL, &ha->max_npiv_vports, NULL); - if (!fw_major_version && ql2xallocfwdump) + if (!fw_major_version && ql2xallocfwdump + && !IS_QLA82XX(ha)) qla2x00_alloc_fw_dump(vha); } } else { -- cgit From 0cd33fcfb54f2eb053ead3cca35ad9775fc01301 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:12 -0800 Subject: [SCSI] qla2xxx: Revert back the request queue mapping to request queue 0. If there is an error creating multiple response queues then we need to revert the request queue mapping back to request queue 0. Signed-off-by: Giridhar Malavali Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 93673d3094e8..01c87004b219 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -423,6 +423,7 @@ fail2: qla25xx_delete_queues(vha); destroy_workqueue(ha->wq); ha->wq = NULL; + vha->req = ha->req_q_map[0]; fail: ha->mqenable = 0; kfree(ha->req_q_map); -- cgit From 841c5e5cee140115b03355c39e4c3f1798ec34bc Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:13 -0800 Subject: [SCSI] qla2xxx: Stop unconditional completion of mailbox commands issued in interrupt mode during firmware hang. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 5 ++++- drivers/scsi/qla2xxx/qla_os.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 94bded5ddce4..d2005c3c8247 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -4075,7 +4075,10 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) ha->flags.isp82xx_fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; - complete(&ha->mbx_intr_comp); + if (test_bit(MBX_INTR_WAIT, + &ha->mbx_cmd_flags)) { + complete(&ha->mbx_intr_comp); + } } break; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 01c87004b219..abec1dd31194 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4014,7 +4014,10 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) ql_dbg(ql_dbg_aer, vha, 0x9001, "Due to pci channel io frozen, doing premature " "completion of mbx command.\n"); - complete(&ha->mbx_intr_comp); + if (test_bit(MBX_INTR_WAIT, + &ha->mbx_cmd_flags)) { + complete(&ha->mbx_intr_comp); + } } } qla2x00_free_irqs(vha); -- cgit From 3aadff356bb80dae1ebb0a2e68974fdbb39fe034 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:14 -0800 Subject: [SCSI] qla2xxx: Enable Minidump by default with default capture mask 0x1f. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index abec1dd31194..71d62593c119 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -201,12 +201,12 @@ MODULE_PARM_DESC(ql2xmdcapmask, "Set the Minidump driver capture mask level. " "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); -int ql2xmdenable; +int ql2xmdenable = 1; module_param(ql2xmdenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xmdenable, "Enable/disable MiniDump. " - "0 (Default) - MiniDump disabled. " - "1 - MiniDump enabled."); + "0 - MiniDump disabled. " + "1 (Default) - MiniDump enabled."); /* * SCSI host template entry points -- cgit From 1806fcd5d3d7644511e57b1d0a397837b0b38623 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 18 Nov 2011 09:02:15 -0800 Subject: [SCSI] qla2xxx: Return the correct value for a mailbox command if 82xx is in reset recovery. We need to return QLA_FUNCTION_TIMEOUT immediately otherwise we mess up the mailbox command state machine. Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3b3cec9f6ac2..f965a57f5d65 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -79,8 +79,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) mcp->mb[0] = MBS_LINK_DOWN_ERROR; ql_log(ql_log_warn, base_vha, 0x1004, "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); - rval = QLA_FUNCTION_FAILED; - goto premature_exit; + return QLA_FUNCTION_TIMEOUT; } /* -- cgit From 10a340e6415d938939724743a4da71fd63f5a95c Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:02:16 -0800 Subject: [SCSI] qla2xxx: Display IPE error message for ISP82xx. [jejb: fixup checkpatch error] Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index d2005c3c8247..8dd96da78704 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3858,6 +3858,11 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) QLA82XX_CRB_PEG_NET_3 + 0x3c), qla82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c)); + if (LSW(MSB(halt_status)) == 0x67) + ql_log(ql_log_warn, vha, 0xb052, + "Firmware aborted with " + "error code 0x00006700. Device is " + "being reset.\n"); if (halt_status & HALT_STATUS_UNRECOVERABLE) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); -- cgit From c8f6544e6d831f05720687f3536d5cbc290ff181 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:02:17 -0800 Subject: [SCSI] qla2xxx: Encapsulate prematurely completing mailbox commands during ISP82xx firmware hang. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 6 +++--- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_nx.c | 33 ++++++++++++++++----------------- drivers/scsi/qla2xxx/qla_os.c | 12 ++---------- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 9df4787715c0..e320d54d2e32 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -17,12 +17,12 @@ * | Queue Command and IO tracing | 0x302e | 0x3008 | * | DPC Thread | 0x401c | | * | Async Events | 0x5059 | | - * | Timer Routines | 0x600d | | + * | Timer Routines | 0x6010 | 0x600e,0x600f | * | User Space Interactions | 0x709d | | - * | Task Management | 0x8041 | | + * | Task Management | 0x8041 | 0x800b | * | AER/EEH | 0x900f | | * | Virtual Port | 0xa007 | | - * | ISP82XX Specific | 0xb051 | | + * | ISP82XX Specific | 0xb052 | | * | MultiQ | 0xc00b | | * | Misc | 0xd00b | | * ---------------------------------------------------------------------- diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ce32d8135c9e..c0c11afb685c 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -578,6 +578,7 @@ extern int qla82xx_check_md_needed(scsi_qla_host_t *); extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); extern int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *, int); extern char *qdev_state(uint32_t); +extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct fc_bsg_job *); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 8dd96da78704..60d999d335c5 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3817,6 +3817,19 @@ exit: return rval; } +void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + + if (ha->flags.mbox_busy) { + ha->flags.mbox_int = 1; + ql_log(ql_log_warn, vha, 0x6010, + "Doing premature completion of mbx command.\n"); + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) + complete(&ha->mbx_intr_comp); + } +} + void qla82xx_watchdog(scsi_qla_host_t *vha) { uint32_t dev_state, halt_status; @@ -3874,16 +3887,8 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) } qla2xxx_wake_dpc(vha); ha->flags.isp82xx_fw_hung = 1; - if (ha->flags.mbox_busy) { - ha->flags.mbox_int = 1; - ql_log(ql_log_warn, vha, 0x6007, - "Due to FW hung, doing " - "premature completion of mbx " - "command.\n"); - if (test_bit(MBX_INTR_WAIT, - &ha->mbx_cmd_flags)) - complete(&ha->mbx_intr_comp); - } + ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n"); + qla82xx_clear_pending_mbx(vha); } } } @@ -4078,13 +4083,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) msleep(1000); if (qla82xx_check_fw_alive(vha)) { ha->flags.isp82xx_fw_hung = 1; - if (ha->flags.mbox_busy) { - ha->flags.mbox_int = 1; - if (test_bit(MBX_INTR_WAIT, - &ha->mbx_cmd_flags)) { - complete(&ha->mbx_intr_comp); - } - } + qla82xx_clear_pending_mbx(vha); break; } } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 71d62593c119..f9e5b85e84d8 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4009,16 +4009,8 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) /* For ISP82XX complete any pending mailbox cmd */ if (IS_QLA82XX(ha)) { ha->flags.isp82xx_fw_hung = 1; - if (ha->flags.mbox_busy) { - ha->flags.mbox_int = 1; - ql_dbg(ql_dbg_aer, vha, 0x9001, - "Due to pci channel io frozen, doing premature " - "completion of mbx command.\n"); - if (test_bit(MBX_INTR_WAIT, - &ha->mbx_cmd_flags)) { - complete(&ha->mbx_intr_comp); - } - } + ql_dbg(ql_dbg_aer, vha, 0x9001, "Pci channel io frozen\n"); + qla82xx_clear_pending_mbx(vha); } qla2x00_free_irqs(vha); pci_disable_device(pdev); -- cgit From 1c89fe3b51a2f8068f2f9faa9c48584151416583 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 12 Dec 2011 14:01:17 +0800 Subject: ALSA: HDA: Set position fix to LPIB for an Atom/Poulsbo based device For the Asus 1101HA, reporting position by reading the DMA position buffer map seems unstable and often wrong. The reporter says that position_fix=LPIB works much better (although not 100%, but this is probably due to other issues). The controller chip is an Intel Poulsbo 8086:811b (rev 07) controller, and complete alsa-info is available here: https://launchpadlibrarian.net/86691768/alsa-info.txt.1TNwyE5Ea7 Cc: stable@kernel.org (3.0+) BugLink: http://bugs.launchpad.net/bugs/825709 Tested-by: Stefano Lodi Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7d98240def0b..84d11d7ed710 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2507,6 +2507,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS 1101HA", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), -- cgit From 8937f2f1c4bc6a9098fd71eb4a7deba5f0683118 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:18 -0800 Subject: [SCSI] qla2xxx: Clear mailbox busy flag during premature mailbox completion for ISP82xx. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 2 ++ drivers/scsi/qla2xxx/qla_nx.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f965a57f5d65..6ff7c3cbd0b5 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -162,6 +162,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) HINT_MBX_INT_PENDING) { spin_unlock_irqrestore(&ha->hardware_lock, flags); + ha->flags.mbox_busy = 0; ql_dbg(ql_dbg_mbx, base_vha, 0x1010, "Pending mailbox timeout, exiting.\n"); rval = QLA_FUNCTION_TIMEOUT; @@ -187,6 +188,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) HINT_MBX_INT_PENDING) { spin_unlock_irqrestore(&ha->hardware_lock, flags); + ha->flags.mbox_busy = 0; ql_dbg(ql_dbg_mbx, base_vha, 0x1012, "Pending mailbox timeout, exiting.\n"); rval = QLA_FUNCTION_TIMEOUT; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 60d999d335c5..54246f934664 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3823,6 +3823,7 @@ void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; + ha->flags.mbox_busy = 0; ql_log(ql_log_warn, vha, 0x6010, "Doing premature completion of mbx command.\n"); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) -- cgit From 631549169801df054210839cfda0aceef78966af Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:19 -0800 Subject: [SCSI] qla2xxx: Disable generating pause frames when firmware hang detected for ISP82xx. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 20 ++++++++++++++++++-- drivers/scsi/qla2xxx/qla_nx.c | 6 +++++- drivers/scsi/qla2xxx/qla_nx.h | 4 ++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index e320d54d2e32..f3cddd5800c3 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -12,7 +12,7 @@ * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- * | Module Init and Probe | 0x0116 | | - * | Mailbox commands | 0x1129 | | + * | Mailbox commands | 0x112b | | * | Device Discovery | 0x2083 | | * | Queue Command and IO tracing | 0x302e | 0x3008 | * | DPC Thread | 0x401c | | diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 6ff7c3cbd0b5..82a33533ed26 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -303,7 +303,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { - + if (IS_QLA82XX(ha)) { + ql_dbg(ql_dbg_mbx, vha, 0x112a, + "disabling pause transmit on port " + "0 & 1.\n"); + qla82xx_wr_32(ha, + QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0| + CRB_NIU_XG_PAUSE_CTL_P1); + } ql_log(ql_log_info, base_vha, 0x101c, "Mailbox cmd timeout occured. " "Scheduling ISP abort eeh_busy=0x%x.\n", @@ -319,7 +327,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { - + if (IS_QLA82XX(ha)) { + ql_dbg(ql_dbg_mbx, vha, 0x112b, + "disabling pause transmit on port " + "0 & 1.\n"); + qla82xx_wr_32(ha, + QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0| + CRB_NIU_XG_PAUSE_CTL_P1); + } ql_log(ql_log_info, base_vha, 0x101e, "Mailbox cmd timeout occured. " "Scheduling ISP abort.\n"); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 54246f934664..03554934b0a5 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3853,9 +3853,13 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) qla2xxx_wake_dpc(vha); } else { if (qla82xx_check_fw_alive(vha)) { + ql_dbg(ql_dbg_timer, vha, 0x6011, + "disabling pause transmit on port 0 & 1.\n"); + qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0|CRB_NIU_XG_PAUSE_CTL_P1); halt_status = qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); - ql_dbg(ql_dbg_timer, vha, 0x6005, + ql_log(ql_log_info, vha, 0x6005, "dumping hw/fw registers:.\n " " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,.\n " " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,.\n " diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 57820c199bc2..57a226be339a 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -1173,4 +1173,8 @@ struct qla82xx_md_entry_queue { static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC }; + +#define CRB_NIU_XG_PAUSE_CTL_P0 0x1 +#define CRB_NIU_XG_PAUSE_CTL_P1 0x8 + #endif -- cgit From 49e85c23beb1f12aba59450126ff7e803fbc767d Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 18 Nov 2011 09:02:20 -0800 Subject: [SCSI] qla2xxx: Correct fc_host port_state display. [jejb: checkpatch fixes] Add more fine grain parsing of vha->loop_state to export a more accurate fc_host port_state. Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ac326c41e931..6465dae5883a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1762,12 +1762,31 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost) scsi_qla_host_t *vha = shost_priv(shost); struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); - if (!base_vha->flags.online) + if (!base_vha->flags.online) { fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; - else if (atomic_read(&base_vha->loop_state) == LOOP_TIMEOUT) - fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; - else + return; + } + + switch (atomic_read(&base_vha->loop_state)) { + case LOOP_UPDATE: + fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; + break; + case LOOP_DOWN: + if (test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags)) + fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; + else + fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; + break; + case LOOP_DEAD: + fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; + break; + case LOOP_READY: fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; + break; + default: + fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; + break; + } } static int -- cgit From 0d2aa38ee9b11be35ef6f91c938dd3441cf64ea4 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:02:21 -0800 Subject: [SCSI] qla2xxx: Submit all chained IOCBs for passthrough commands on request queue 0. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_iocb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index dbec89622a0f..a4b267e60a35 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -120,11 +120,10 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) * Returns a pointer to the continuation type 1 IOCB packet. */ static inline cont_a64_entry_t * -qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha) +qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) { cont_a64_entry_t *cont_pkt; - struct req_que *req = vha->req; /* Adjust ring index. */ req->ring_index++; if (req->ring_index == req->length) { @@ -292,7 +291,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, * Five DSDs are available in the Continuation * Type 1 IOCB. */ - cont_pkt = qla2x00_prep_cont_type1_iocb(vha); + cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; avail_dsds = 5; } @@ -684,7 +683,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, * Five DSDs are available in the Continuation * Type 1 IOCB. */ - cont_pkt = qla2x00_prep_cont_type1_iocb(vha); + cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; avail_dsds = 5; } @@ -2070,7 +2069,8 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) * Five DSDs are available in the Cont. * Type 1 IOCB. */ - cont_pkt = qla2x00_prep_cont_type1_iocb(vha); + cont_pkt = qla2x00_prep_cont_type1_iocb(vha, + vha->hw->req_q_map[0]); cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; avail_dsds = 5; cont_iocb_prsnt = 1; @@ -2096,6 +2096,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) int index; uint16_t tot_dsds; scsi_qla_host_t *vha = sp->fcport->vha; + struct qla_hw_data *ha = vha->hw; struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; int loop_iterartion = 0; int cont_iocb_prsnt = 0; @@ -2141,7 +2142,8 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) * Five DSDs are available in the Cont. * Type 1 IOCB. */ - cont_pkt = qla2x00_prep_cont_type1_iocb(vha); + cont_pkt = qla2x00_prep_cont_type1_iocb(vha, + ha->req_q_map[0]); cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; avail_dsds = 5; cont_iocb_prsnt = 1; -- cgit From 09b4402d2c8e36b8d4270c4da235fd7bb312118d Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:02:22 -0800 Subject: [SCSI] qla2xxx: Update version number to 8.03.07.12-k. Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 13b6357c1fa2..23f33a6d52d7 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.07.07-k" +#define QLA2XXX_VERSION "8.03.07.12-k" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- cgit From f44b915d315ff0a7dd362c5c0eac5fbde4cc4411 Mon Sep 17 00:00:00 2001 From: Yu Xu Date: Sat, 10 Dec 2011 00:03:33 +0800 Subject: usb: gadget: storage: release superspeed descriptors. Release superspeed mass storage descriptors memory when the function is unbind. Signed-off-by: Yu Xu Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_mass_storage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index c39d58860fa0..1a6f415c0d02 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2975,6 +2975,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) fsg_common_put(common); usb_free_descriptors(fsg->function.descriptors); usb_free_descriptors(fsg->function.hs_descriptors); + usb_free_descriptors(fsg->function.ss_descriptors); kfree(fsg); } -- cgit From b95eb7476e7224baae34f67ae9a09042521e97ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Dec 2011 18:23:56 -0800 Subject: usb: renesas_usbhs: typofix: irq_dtch control DTCHE Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 053f86d70009..ad96a3896729 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -349,7 +349,7 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) if (mod->irq_attch) intenb1 |= ATTCHE; - if (mod->irq_attch) + if (mod->irq_dtch) intenb1 |= DTCHE; if (mod->irq_sign) -- cgit From 1115b9e279a23ca0bf7eda7d7697fe20a441304e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Dec 2011 18:24:47 -0800 Subject: usb: renesas_usbhs: add hcd->has_tt for low/full speed Low/Full speed device is not recognized without this patch Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_host.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index bade761a1e52..7955de589951 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1267,6 +1267,7 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) dev_err(dev, "Failed to create hcd\n"); return -ENOMEM; } + hcd->has_tt = 1; /* for low/full speed */ pipe_info = kzalloc(sizeof(*pipe_info) * pipe_size, GFP_KERNEL); if (!pipe_info) { -- cgit From b302545744c031eae04a43fb1c56cc17e00a193a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 12 Dec 2011 12:42:12 +0100 Subject: block/swim3: Locking fixes The old PowerMac swim3 driver has some "interesting" locking issues, using a private lock and failing to lock the queue before completing requests, which triggered WARN_ONs among others. This rips out the private lock, makes everything operate under the block queue lock, and generally makes things simpler. We used to also share a queue between the two possible instances which was problematic since we might pick the wrong controller in some cases, so make the queue and the current request per-instance and use queuedata to point to our private data which is a lot cleaner. We still share the queue lock but then, it's nearly impossible to actually use 2 swim3's simultaneously: one would need to have a Wallstreet PowerBook, the only machine afaik with two of these on the motherboard, and populate both hotswap bays with a floppy drive (the machine ships only with one), so nobody cares... While at it, add a little fix to clear up stale interrupts when loading the driver or plugging a floppy drive in a bay. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Jens Axboe --- drivers/block/swim3.c | 362 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 215 insertions(+), 147 deletions(-) diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index ae3e167e17ad..89ddab127e33 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -16,6 +16,8 @@ * handle GCR disks */ +#undef DEBUG + #include #include #include @@ -36,13 +38,11 @@ #include #include -static DEFINE_MUTEX(swim3_mutex); -static struct request_queue *swim3_queue; -static struct gendisk *disks[2]; -static struct request *fd_req; - #define MAX_FLOPPIES 2 +static DEFINE_MUTEX(swim3_mutex); +static struct gendisk *disks[MAX_FLOPPIES]; + enum swim_state { idle, locating, @@ -177,7 +177,6 @@ struct swim3 { struct floppy_state { enum swim_state state; - spinlock_t lock; struct swim3 __iomem *swim3; /* hardware registers */ struct dbdma_regs __iomem *dma; /* DMA controller registers */ int swim3_intr; /* interrupt number for SWIM3 */ @@ -204,8 +203,20 @@ struct floppy_state { int wanted; struct macio_dev *mdev; char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; + int index; + struct request *cur_req; }; +#define swim3_err(fmt, arg...) dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#define swim3_warn(fmt, arg...) dev_warn(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#define swim3_info(fmt, arg...) dev_info(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) + +#ifdef DEBUG +#define swim3_dbg(fmt, arg...) dev_dbg(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#else +#define swim3_dbg(fmt, arg...) do { } while(0) +#endif + static struct floppy_state floppy_states[MAX_FLOPPIES]; static int floppy_count = 0; static DEFINE_SPINLOCK(swim3_lock); @@ -224,17 +235,8 @@ static unsigned short write_postamble[] = { 0, 0, 0, 0, 0, 0 }; -static void swim3_select(struct floppy_state *fs, int sel); -static void swim3_action(struct floppy_state *fs, int action); -static int swim3_readbit(struct floppy_state *fs, int bit); -static void do_fd_request(struct request_queue * q); -static void start_request(struct floppy_state *fs); -static void set_timeout(struct floppy_state *fs, int nticks, - void (*proc)(unsigned long)); -static void scan_track(struct floppy_state *fs); static void seek_track(struct floppy_state *fs, int n); static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count); -static void setup_transfer(struct floppy_state *fs); static void act(struct floppy_state *fs); static void scan_timeout(unsigned long data); static void seek_timeout(unsigned long data); @@ -254,18 +256,21 @@ static unsigned int floppy_check_events(struct gendisk *disk, unsigned int clearing); static int floppy_revalidate(struct gendisk *disk); -static bool swim3_end_request(int err, unsigned int nr_bytes) +static bool swim3_end_request(struct floppy_state *fs, int err, unsigned int nr_bytes) { - if (__blk_end_request(fd_req, err, nr_bytes)) - return true; + struct request *req = fs->cur_req; + int rc; - fd_req = NULL; - return false; -} + swim3_dbg(" end request, err=%d nr_bytes=%d, cur_req=%p\n", + err, nr_bytes, req); -static bool swim3_end_request_cur(int err) -{ - return swim3_end_request(err, blk_rq_cur_bytes(fd_req)); + if (err) + nr_bytes = blk_rq_cur_bytes(req); + rc = __blk_end_request(req, err, nr_bytes); + if (rc) + return true; + fs->cur_req = NULL; + return false; } static void swim3_select(struct floppy_state *fs, int sel) @@ -303,50 +308,53 @@ static int swim3_readbit(struct floppy_state *fs, int bit) return (stat & DATA) == 0; } -static void do_fd_request(struct request_queue * q) -{ - int i; - - for(i=0; imdev->media_bay && - check_media_bay(fs->mdev->media_bay) != MB_FD) - continue; - start_request(fs); - } -} - static void start_request(struct floppy_state *fs) { struct request *req; unsigned long x; + swim3_dbg("start request, initial state=%d\n", fs->state); + if (fs->state == idle && fs->wanted) { fs->state = available; wake_up(&fs->wait); return; } while (fs->state == idle) { - if (!fd_req) { - fd_req = blk_fetch_request(swim3_queue); - if (!fd_req) + swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req); + if (!fs->cur_req) { + fs->cur_req = blk_fetch_request(disks[fs->index]->queue); + swim3_dbg(" fetched request %p\n", fs->cur_req); + if (!fs->cur_req) break; } - req = fd_req; -#if 0 - printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", - req->rq_disk->disk_name, req->cmd, - (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer); - printk(" errors=%d current_nr_sectors=%u\n", - req->errors, blk_rq_cur_sectors(req)); + req = fs->cur_req; + + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) { + swim3_dbg("%s", " media bay absent, dropping req\n"); + swim3_end_request(fs, -ENODEV, 0); + continue; + } + +#if 0 /* This is really too verbose */ + swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", + req->rq_disk->disk_name, req->cmd, + (long)blk_rq_pos(req), blk_rq_sectors(req), + req->buffer); + swim3_dbg(" errors=%d current_nr_sectors=%u\n", + req->errors, blk_rq_cur_sectors(req)); #endif if (blk_rq_pos(req) >= fs->total_secs) { - swim3_end_request_cur(-EIO); + swim3_dbg(" pos out of bounds (%ld, max is %ld)\n", + (long)blk_rq_pos(req), (long)fs->total_secs); + swim3_end_request(fs, -EIO, 0); continue; } if (fs->ejected) { - swim3_end_request_cur(-EIO); + swim3_dbg("%s", " disk ejected\n"); + swim3_end_request(fs, -EIO, 0); continue; } @@ -354,7 +362,8 @@ static void start_request(struct floppy_state *fs) if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) { - swim3_end_request_cur(-EIO); + swim3_dbg("%s", " try to write, disk write protected\n"); + swim3_end_request(fs, -EIO, 0); continue; } } @@ -369,7 +378,6 @@ static void start_request(struct floppy_state *fs) x = ((long)blk_rq_pos(req)) % fs->secpercyl; fs->head = x / fs->secpertrack; fs->req_sector = x % fs->secpertrack + 1; - fd_req = req; fs->state = do_transfer; fs->retries = 0; @@ -377,12 +385,14 @@ static void start_request(struct floppy_state *fs) } } +static void do_fd_request(struct request_queue * q) +{ + start_request(q->queuedata); +} + static void set_timeout(struct floppy_state *fs, int nticks, void (*proc)(unsigned long)) { - unsigned long flags; - - spin_lock_irqsave(&fs->lock, flags); if (fs->timeout_pending) del_timer(&fs->timeout); fs->timeout.expires = jiffies + nticks; @@ -390,7 +400,6 @@ static void set_timeout(struct floppy_state *fs, int nticks, fs->timeout.data = (unsigned long) fs; add_timer(&fs->timeout); fs->timeout_pending = 1; - spin_unlock_irqrestore(&fs->lock, flags); } static inline void scan_track(struct floppy_state *fs) @@ -442,40 +451,45 @@ static inline void setup_transfer(struct floppy_state *fs) struct swim3 __iomem *sw = fs->swim3; struct dbdma_cmd *cp = fs->dma_cmd; struct dbdma_regs __iomem *dr = fs->dma; + struct request *req = fs->cur_req; - if (blk_rq_cur_sectors(fd_req) <= 0) { - printk(KERN_ERR "swim3: transfer 0 sectors?\n"); + if (blk_rq_cur_sectors(req) <= 0) { + swim3_warn("%s", "Transfer 0 sectors ?\n"); return; } - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) n = 1; else { n = fs->secpertrack - fs->req_sector + 1; - if (n > blk_rq_cur_sectors(fd_req)) - n = blk_rq_cur_sectors(fd_req); + if (n > blk_rq_cur_sectors(req)) + n = blk_rq_cur_sectors(req); } + + swim3_dbg(" setup xfer at sect %d (of %d) head %d for %d\n", + fs->req_sector, fs->secpertrack, fs->head, n); + fs->scount = n; swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); out_8(&sw->sector, fs->req_sector); out_8(&sw->nsect, n); out_8(&sw->gap3, 0); out_le32(&dr->cmdptr, virt_to_bus(cp)); - if (rq_data_dir(fd_req) == WRITE) { + if (rq_data_dir(req) == WRITE) { /* Set up 3 dma commands: write preamble, data, postamble */ init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); ++cp; - init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512); + init_dma(cp, OUTPUT_MORE, req->buffer, 512); ++cp; init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble)); } else { - init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512); + init_dma(cp, INPUT_LAST, req->buffer, n * 512); } ++cp; out_le16(&cp->command, DBDMA_STOP); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); in_8(&sw->error); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) out_8(&sw->control_bis, WRITE_SECTORS); in_8(&sw->intr); out_le32(&dr->control, (RUN << 16) | RUN); @@ -488,12 +502,16 @@ static inline void setup_transfer(struct floppy_state *fs) static void act(struct floppy_state *fs) { for (;;) { + swim3_dbg(" act loop, state=%d, req_cyl=%d, cur_cyl=%d\n", + fs->state, fs->req_cyl, fs->cur_cyl); + switch (fs->state) { case idle: return; /* XXX shouldn't get here */ case locating: if (swim3_readbit(fs, TRACK_ZERO)) { + swim3_dbg("%s", " locate track 0\n"); fs->cur_cyl = 0; if (fs->req_cyl == 0) fs->state = do_transfer; @@ -511,7 +529,7 @@ static void act(struct floppy_state *fs) break; } if (fs->req_cyl == fs->cur_cyl) { - printk("whoops, seeking 0\n"); + swim3_warn("%s", "Whoops, seeking 0\n"); fs->state = do_transfer; break; } @@ -527,7 +545,9 @@ static void act(struct floppy_state *fs) case do_transfer: if (fs->cur_cyl != fs->req_cyl) { if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_err("Wrong cylinder in transfer, want: %d got %d\n", + fs->req_cyl, fs->cur_cyl); + swim3_end_request(fs, -EIO, 0); fs->state = idle; return; } @@ -542,7 +562,7 @@ static void act(struct floppy_state *fs) return; default: - printk(KERN_ERR"swim3: unknown state %d\n", fs->state); + swim3_err("Unknown state %d\n", fs->state); return; } } @@ -552,59 +572,75 @@ static void scan_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* scan timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); fs->cur_cyl = -1; if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); } else { fs->state = jogging; act(fs); } + spin_unlock_irqrestore(&swim3_lock, flags); } static void seek_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* seek timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_8(&sw->control_bic, DO_SEEK); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); - printk(KERN_ERR "swim3: seek timeout\n"); - swim3_end_request_cur(-EIO); + swim3_err("%s", "Seek timeout\n"); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + spin_unlock_irqrestore(&swim3_lock, flags); } static void settle_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* settle timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; if (swim3_readbit(fs, SEEK_COMPLETE)) { out_8(&sw->select, RELAX); fs->state = locating; act(fs); - return; + goto unlock; } out_8(&sw->select, RELAX); if (fs->settle_time < 2*HZ) { ++fs->settle_time; set_timeout(fs, 1, settle_timeout); - return; + goto unlock; } - printk(KERN_ERR "swim3: seek settle timeout\n"); - swim3_end_request_cur(-EIO); + swim3_err("%s", "Seek settle timeout\n"); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + unlock: + spin_unlock_irqrestore(&swim3_lock, flags); } static void xfer_timeout(unsigned long data) @@ -612,8 +648,12 @@ static void xfer_timeout(unsigned long data) struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; struct dbdma_regs __iomem *dr = fs->dma; + unsigned long flags; int n; + swim3_dbg("* xfer timeout, state=%d\n", fs->state); + + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_le32(&dr->control, RUN << 16); /* We must wait a bit for dbdma to stop */ @@ -622,12 +662,13 @@ static void xfer_timeout(unsigned long data) out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); - printk(KERN_ERR "swim3: timeout %sing sector %ld\n", - (rq_data_dir(fd_req)==WRITE? "writ": "read"), - (long)blk_rq_pos(fd_req)); - swim3_end_request_cur(-EIO); + swim3_err("Timeout %sing sector %ld\n", + (rq_data_dir(fs->cur_req)==WRITE? "writ": "read"), + (long)blk_rq_pos(fs->cur_req)); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + spin_unlock_irqrestore(&swim3_lock, flags); } static irqreturn_t swim3_interrupt(int irq, void *dev_id) @@ -638,12 +679,17 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) int stat, resid; struct dbdma_regs __iomem *dr; struct dbdma_cmd *cp; + unsigned long flags; + struct request *req = fs->cur_req; + + swim3_dbg("* interrupt, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); intr = in_8(&sw->intr); err = (intr & ERROR_INTR)? in_8(&sw->error): 0; if ((intr & ERROR_INTR) && fs->state != do_transfer) - printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n", - fs->state, rq_data_dir(fd_req), intr, err); + swim3_err("Non-transfer error interrupt: state=%d, dir=%x, intr=%x, err=%x\n", + fs->state, rq_data_dir(req), intr, err); switch (fs->state) { case locating: if (intr & SEEN_SECTOR) { @@ -653,10 +699,10 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) del_timer(&fs->timeout); fs->timeout_pending = 0; if (sw->ctrack == 0xff) { - printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); + swim3_err("%s", "Seen sector but cyl=ff?\n"); fs->cur_cyl = -1; if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); } else { @@ -668,8 +714,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) fs->cur_cyl = sw->ctrack; fs->cur_sector = sw->csect; if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl) - printk(KERN_ERR "swim3: expected cyl %d, got %d\n", - fs->expect_cyl, fs->cur_cyl); + swim3_err("Expected cyl %d, got %d\n", + fs->expect_cyl, fs->cur_cyl); fs->state = do_transfer; act(fs); } @@ -704,7 +750,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) fs->timeout_pending = 0; dr = fs->dma; cp = fs->dma_cmd; - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) ++cp; /* * Check that the main data transfer has finished. @@ -729,31 +775,32 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) if (intr & ERROR_INTR) { n = fs->scount - 1 - resid / 512; if (n > 0) { - blk_update_request(fd_req, 0, n << 9); + blk_update_request(req, 0, n << 9); fs->req_sector += n; } if (fs->retries < 5) { ++fs->retries; act(fs); } else { - printk("swim3: error %sing block %ld (err=%x)\n", - rq_data_dir(fd_req) == WRITE? "writ": "read", - (long)blk_rq_pos(fd_req), err); - swim3_end_request_cur(-EIO); + swim3_err("Error %sing block %ld (err=%x)\n", + rq_data_dir(req) == WRITE? "writ": "read", + (long)blk_rq_pos(req), err); + swim3_end_request(fs, -EIO, 0); fs->state = idle; } } else { if ((stat & ACTIVE) == 0 || resid != 0) { /* musta been an error */ - printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); - printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n", - fs->state, rq_data_dir(fd_req), intr, err); - swim3_end_request_cur(-EIO); + swim3_err("fd dma error: stat=%x resid=%d\n", stat, resid); + swim3_err(" state=%d, dir=%x, intr=%x, err=%x\n", + fs->state, rq_data_dir(req), intr, err); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); break; } - if (swim3_end_request(0, fs->scount << 9)) { + fs->retries = 0; + if (swim3_end_request(fs, 0, fs->scount << 9)) { fs->req_sector += fs->scount; if (fs->req_sector > fs->secpertrack) { fs->req_sector -= fs->secpertrack; @@ -770,8 +817,9 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) start_request(fs); break; default: - printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state); + swim3_err("Don't know what to do in state %d\n", fs->state); } + spin_unlock_irqrestore(&swim3_lock, flags); return IRQ_HANDLED; } @@ -781,26 +829,31 @@ static void fd_dma_interrupt(int irq, void *dev_id) } */ +/* Called under the mutex to grab exclusive access to a drive */ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible) { unsigned long flags; - spin_lock_irqsave(&fs->lock, flags); - if (fs->state != idle) { + swim3_dbg("%s", "-> grab drive\n"); + + spin_lock_irqsave(&swim3_lock, flags); + if (fs->state != idle && fs->state != available) { ++fs->wanted; while (fs->state != available) { + spin_unlock_irqrestore(&swim3_lock, flags); if (interruptible && signal_pending(current)) { --fs->wanted; - spin_unlock_irqrestore(&fs->lock, flags); return -EINTR; } interruptible_sleep_on(&fs->wait); + spin_lock_irqsave(&swim3_lock, flags); } --fs->wanted; } fs->state = state; - spin_unlock_irqrestore(&fs->lock, flags); + spin_unlock_irqrestore(&swim3_lock, flags); + return 0; } @@ -808,10 +861,12 @@ static void release_drive(struct floppy_state *fs) { unsigned long flags; - spin_lock_irqsave(&fs->lock, flags); + swim3_dbg("%s", "-> release drive\n"); + + spin_lock_irqsave(&swim3_lock, flags); fs->state = idle; start_request(fs); - spin_unlock_irqrestore(&fs->lock, flags); + spin_unlock_irqrestore(&swim3_lock, flags); } static int fd_eject(struct floppy_state *fs) @@ -966,6 +1021,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; + mutex_lock(&swim3_mutex); if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); @@ -1031,30 +1087,48 @@ static const struct block_device_operations floppy_fops = { .revalidate_disk= floppy_revalidate, }; +static void swim3_mb_event(struct macio_dev* mdev, int mb_state) +{ + struct floppy_state *fs = macio_get_drvdata(mdev); + struct swim3 __iomem *sw = fs->swim3; + + if (!fs) + return; + if (mb_state != MB_FD) + return; + + /* Clear state */ + out_8(&sw->intr_enable, 0); + in_8(&sw->intr); + in_8(&sw->error); +} + static int swim3_add_device(struct macio_dev *mdev, int index) { struct device_node *swim = mdev->ofdev.dev.of_node; struct floppy_state *fs = &floppy_states[index]; int rc = -EBUSY; + /* Do this first for message macros */ + memset(fs, 0, sizeof(*fs)); + fs->mdev = mdev; + fs->index = index; + /* Check & Request resources */ if (macio_resource_count(mdev) < 2) { - printk(KERN_WARNING "ifd%d: no address for %s\n", - index, swim->full_name); + swim3_err("%s", "No address in device-tree\n"); return -ENXIO; } - if (macio_irq_count(mdev) < 2) { - printk(KERN_WARNING "fd%d: no intrs for device %s\n", - index, swim->full_name); + if (macio_irq_count(mdev) < 1) { + swim3_err("%s", "No interrupt in device-tree\n"); + return -ENXIO; } if (macio_request_resource(mdev, 0, "swim3 (mmio)")) { - printk(KERN_ERR "fd%d: can't request mmio resource for %s\n", - index, swim->full_name); + swim3_err("%s", "Can't request mmio resource\n"); return -EBUSY; } if (macio_request_resource(mdev, 1, "swim3 (dma)")) { - printk(KERN_ERR "fd%d: can't request dma resource for %s\n", - index, swim->full_name); + swim3_err("%s", "Can't request dma resource\n"); macio_release_resource(mdev, 0); return -EBUSY; } @@ -1063,22 +1137,18 @@ static int swim3_add_device(struct macio_dev *mdev, int index) if (mdev->media_bay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); - memset(fs, 0, sizeof(*fs)); - spin_lock_init(&fs->lock); fs->state = idle; fs->swim3 = (struct swim3 __iomem *) ioremap(macio_resource_start(mdev, 0), 0x200); if (fs->swim3 == NULL) { - printk("fd%d: couldn't map registers for %s\n", - index, swim->full_name); + swim3_err("%s", "Couldn't map mmio registers\n"); rc = -ENOMEM; goto out_release; } fs->dma = (struct dbdma_regs __iomem *) ioremap(macio_resource_start(mdev, 1), 0x200); if (fs->dma == NULL) { - printk("fd%d: couldn't map DMA for %s\n", - index, swim->full_name); + swim3_err("%s", "Couldn't map dma registers\n"); iounmap(fs->swim3); rc = -ENOMEM; goto out_release; @@ -1090,31 +1160,25 @@ static int swim3_add_device(struct macio_dev *mdev, int index) fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; - fs->mdev = mdev; init_waitqueue_head(&fs->wait); fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); + if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD) + swim3_mb_event(mdev, MB_FD); + if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { - printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n", - index, fs->swim3_intr, swim->full_name); + swim3_err("%s", "Couldn't request interrupt\n"); pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); goto out_unmap; return -EBUSY; } -/* - if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { - printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", - fs->dma_intr); - return -EBUSY; - } -*/ init_timer(&fs->timeout); - printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, + swim3_info("SWIM3 floppy controller %s\n", mdev->media_bay ? "in media bay" : ""); return 0; @@ -1132,41 +1196,42 @@ static int swim3_add_device(struct macio_dev *mdev, int index) static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match) { - int i, rc; struct gendisk *disk; + int index, rc; + + index = floppy_count++; + if (index >= MAX_FLOPPIES) + return -ENXIO; /* Add the drive */ - rc = swim3_add_device(mdev, floppy_count); + rc = swim3_add_device(mdev, index); if (rc) return rc; + /* Now register that disk. Same comment about failure handling */ + disk = disks[index] = alloc_disk(1); + if (disk == NULL) + return -ENOMEM; + disk->queue = blk_init_queue(do_fd_request, &swim3_lock); + if (disk->queue == NULL) { + put_disk(disk); + return -ENOMEM; + } + disk->queue->queuedata = &floppy_states[index]; - /* Now create the queue if not there yet */ - if (swim3_queue == NULL) { + if (index == 0) { /* If we failed, there isn't much we can do as the driver is still * too dumb to remove the device, just bail out */ if (register_blkdev(FLOPPY_MAJOR, "fd")) return 0; - swim3_queue = blk_init_queue(do_fd_request, &swim3_lock); - if (swim3_queue == NULL) { - unregister_blkdev(FLOPPY_MAJOR, "fd"); - return 0; - } } - /* Now register that disk. Same comment about failure handling */ - i = floppy_count++; - disk = disks[i] = alloc_disk(1); - if (disk == NULL) - return 0; - disk->major = FLOPPY_MAJOR; - disk->first_minor = i; + disk->first_minor = index; disk->fops = &floppy_fops; - disk->private_data = &floppy_states[i]; - disk->queue = swim3_queue; + disk->private_data = &floppy_states[index]; disk->flags |= GENHD_FL_REMOVABLE; - sprintf(disk->disk_name, "fd%d", i); + sprintf(disk->disk_name, "fd%d", index); set_capacity(disk, 2880); add_disk(disk); @@ -1194,6 +1259,9 @@ static struct macio_driver swim3_driver = .of_match_table = swim3_match, }, .probe = swim3_attach, +#ifdef CONFIG_PMAC_MEDIABAY + .mediabay_event = swim3_mb_event, +#endif #if 0 .suspend = swim3_suspend, .resume = swim3_resume, -- cgit From b5a7e97039a80fae673ccc115ce595d5b88fb4ee Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 12 Dec 2011 10:53:02 -0500 Subject: ext4: fix ext4_end_io_dio() racing against fsync() We need to make sure iocb->private is cleared *before* we put the io_end structure on i_completed_io_list. Otherwise fsync() could potentially run on another CPU and free the iocb structure out from under us. Reported-by: Kent Overstreet Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 848f436df29f..d2c86633811f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2781,10 +2781,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, iocb->private, io_end->inode->i_ino, iocb, offset, size); + iocb->private = NULL; + /* if not aio dio with unwritten extents, just free io and return */ if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { ext4_free_io_end(io_end); - iocb->private = NULL; out: if (is_async) aio_complete(iocb, ret, 0); @@ -2807,7 +2808,6 @@ out: spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); /* queue the work to convert unwritten extents to written */ - iocb->private = NULL; queue_work(wq, &io_end->work); /* XXX: probably should move into the real I/O completion handler */ -- cgit From b4611abfa98af8351bf32e8b9ecc9d3384931c37 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 12 Dec 2011 11:00:56 -0500 Subject: ext4: Fix crash due to getting bogus eh_depth value on big-endian systems Commit 1939dd84b3 ("ext4: cleanup ext4_ext_grow_indepth code") added a reference to ext4_extent_header.eh_depth, but forget to pass the value read through le16_to_cpu. The result is a crash on big-endian machines, such as this crash on a POWER7 server: attempt to access beyond end of device sda8: rw=0, want=776392648163376, limit=168558560 Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6b6bcb Faulting instruction address: 0xc0000000001f5f38 cpu 0x14: Vector: 300 (Data Access) at [c000001bd1aaecf0] pc: c0000000001f5f38: .__brelse+0x18/0x60 lr: c0000000002e07a4: .ext4_ext_drop_refs+0x44/0x80 sp: c000001bd1aaef70 msr: 9000000000009032 dar: 6b6b6b6b6b6b6bcb dsisr: 40000000 current = 0xc000001bd15b8010 paca = 0xc00000000ffe4600 pid = 19911, comm = flush-8:0 enter ? for help [c000001bd1aaeff0] c0000000002e07a4 .ext4_ext_drop_refs+0x44/0x80 [c000001bd1aaf090] c0000000002e0c58 .ext4_ext_find_extent+0x408/0x4c0 [c000001bd1aaf180] c0000000002e145c .ext4_ext_insert_extent+0x2bc/0x14c0 [c000001bd1aaf2c0] c0000000002e3fb8 .ext4_ext_map_blocks+0x628/0x1710 [c000001bd1aaf420] c0000000002b2974 .ext4_map_blocks+0x224/0x310 [c000001bd1aaf4d0] c0000000002b7f2c .mpage_da_map_and_submit+0xbc/0x490 [c000001bd1aaf5a0] c0000000002b8688 .write_cache_pages_da+0x2c8/0x430 [c000001bd1aaf720] c0000000002b8b28 .ext4_da_writepages+0x338/0x670 [c000001bd1aaf8d0] c000000000157280 .do_writepages+0x40/0x90 [c000001bd1aaf940] c0000000001ea830 .writeback_single_inode+0xe0/0x530 [c000001bd1aafa00] c0000000001eb680 .writeback_sb_inodes+0x210/0x300 [c000001bd1aafb20] c0000000001ebc84 .__writeback_inodes_wb+0xd4/0x140 [c000001bd1aafbe0] c0000000001ebfec .wb_writeback+0x2fc/0x3e0 [c000001bd1aafce0] c0000000001ed770 .wb_do_writeback+0x2f0/0x300 [c000001bd1aafdf0] c0000000001ed848 .bdi_writeback_thread+0xc8/0x340 [c000001bd1aafed0] c0000000000c5494 .kthread+0xb4/0xc0 [c000001bd1aaff90] c000000000021f48 .kernel_thread+0x54/0x70 This is due to getting ext_depth(inode) == 0x101 and therefore running off the end of the path array in ext4_ext_drop_refs into following unallocated structures. This fixes it by adding the necessary le16_to_cpu. Signed-off-by: Paul Mackerras Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 61fa9e1614af..61cdb97f338c 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1095,7 +1095,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block), ext4_idx_pblock(EXT_FIRST_INDEX(neh))); - neh->eh_depth = cpu_to_le16(neh->eh_depth + 1); + neh->eh_depth = cpu_to_le16(le16_to_cpu(neh->eh_depth) + 1); ext4_mark_inode_dirty(handle, inode); out: brelse(bh); -- cgit From 0b57d7602b68f7b2786b2f0e22da39cbd4139a95 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 8 Dec 2011 08:04:12 -0500 Subject: hwmon: (jz4740) fix signedness bug wait_for_completion_interruptible_timeout() may return negative value. In this case, checking if (t > 0) will return true if t is unsigned. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Cc: stable@kernel.org (3.0+) Signed-off-by: Guenter Roeck --- drivers/hwmon/jz4740-hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index 7a48b1eb4233..3d7e590d57b7 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c @@ -59,7 +59,7 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, { struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); struct completion *completion = &hwmon->read_completion; - unsigned long t; + long t; unsigned long val; int ret; -- cgit From d6c4f2ac1de3c1ee10796740aa5b7a1e98a05f07 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 8 Dec 2011 08:33:37 -0500 Subject: hwmon: (jz4740) Staticise jz4740_hwmon_driver It is not used outside this driver so no need to make the symbol global. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Guenter Roeck --- drivers/hwmon/jz4740-hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index 3d7e590d57b7..5253d23361d9 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c @@ -203,7 +203,7 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) return 0; } -struct platform_driver jz4740_hwmon_driver = { +static struct platform_driver jz4740_hwmon_driver = { .probe = jz4740_hwmon_probe, .remove = __devexit_p(jz4740_hwmon_remove), .driver = { -- cgit From f1932fc1a6d899c754676b1dd8b17de93b052d43 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 7 Dec 2011 09:10:26 -0800 Subject: crush: fix mapping calculation when force argument doesn't exist If the force argument isn't valid, we should continue calculating a mapping as if it weren't specified. Signed-off-by: Sage Weil --- net/ceph/crush/mapper.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 42599e31dcad..3a94eae7abe9 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -477,7 +477,6 @@ int crush_do_rule(struct crush_map *map, int i, j; int numrep; int firstn; - int rc = -1; BUG_ON(ruleno >= map->max_rules); @@ -491,23 +490,18 @@ int crush_do_rule(struct crush_map *map, * that this may or may not correspond to the specific types * referenced by the crush rule. */ - if (force >= 0) { - if (force >= map->max_devices || - map->device_parents[force] == 0) { - /*dprintk("CRUSH: forcefed device dne\n");*/ - rc = -1; /* force fed device dne */ - goto out; - } - if (!is_out(map, weight, force, x)) { - while (1) { - force_context[++force_pos] = force; - if (force >= 0) - force = map->device_parents[force]; - else - force = map->bucket_parents[-1-force]; - if (force == 0) - break; - } + if (force >= 0 && + force < map->max_devices && + map->device_parents[force] != 0 && + !is_out(map, weight, force, x)) { + while (1) { + force_context[++force_pos] = force; + if (force >= 0) + force = map->device_parents[force]; + else + force = map->bucket_parents[-1-force]; + if (force == 0) + break; } } @@ -600,10 +594,7 @@ int crush_do_rule(struct crush_map *map, BUG_ON(1); } } - rc = result_len; - -out: - return rc; + return result_len; } -- cgit From e1ad783b12ec8b69da83479c5d21a0d8180bc519 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 11 Dec 2011 16:12:42 -0800 Subject: Revert "x86, efi: Calling __pa() with an ioremap()ed address is invalid" This hangs my MacBook Air at boot time; I get no console messages at all. I reverted this on top of -rc5 and my machine boots again. This reverts commit e8c7106280a305e1ff2a3a8a4dfce141469fb039. Signed-off-by: Matt Fleming Signed-off-by: Keith Packard Acked-by: H. Peter Anvin Cc: Matthew Garrett Cc: Zhang Rui Cc: Huang Ying Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/1321621751-3650-1-git-send-email-matt@console Signed-off-by: Ingo Molnar --- arch/x86/include/asm/e820.h | 8 -------- arch/x86/include/asm/efi.h | 5 +++++ arch/x86/kernel/e820.c | 3 +-- arch/x86/kernel/setup.c | 21 +-------------------- arch/x86/platform/efi/efi.c | 29 +++++++++++------------------ arch/x86/platform/efi/efi_64.c | 17 +++++++++++++++++ 6 files changed, 35 insertions(+), 48 deletions(-) diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index c9547033e38e..908b96957d88 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -53,13 +53,6 @@ */ #define E820_RESERVED_KERN 128 -/* - * Address ranges that need to be mapped by the kernel direct - * mapping. This is used to make sure regions such as - * EFI_RUNTIME_SERVICES_DATA are directly mapped. See setup_arch(). - */ -#define E820_RESERVED_EFI 129 - #ifndef __ASSEMBLY__ #include struct e820entry { @@ -122,7 +115,6 @@ static inline void early_memtest(unsigned long start, unsigned long end) } #endif -extern unsigned long e820_end_pfn(unsigned long limit_pfn, unsigned type); extern unsigned long e820_end_of_ram_pfn(void); extern unsigned long e820_end_of_low_ram_pfn(void); extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index b8d8bfcd44a9..7093e4a6a0bc 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -33,6 +33,8 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) +#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) + #else /* !CONFIG_X86_32 */ extern u64 efi_call0(void *fp); @@ -82,6 +84,9 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) +extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, + u32 type); + #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 65ffd110a81b..303a0e48f076 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -135,7 +135,6 @@ static void __init e820_print_type(u32 type) printk(KERN_CONT "(usable)"); break; case E820_RESERVED: - case E820_RESERVED_EFI: printk(KERN_CONT "(reserved)"); break; case E820_ACPI: @@ -784,7 +783,7 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align) /* * Find the highest page frame number we have available */ -unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) +static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) { int i; unsigned long last_pfn = 0; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9a9e40fb091c..cf0ef986cb6d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -691,8 +691,6 @@ early_param("reservelow", parse_reservelow); void __init setup_arch(char **cmdline_p) { - unsigned long end_pfn; - #ifdef CONFIG_X86_32 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); visws_early_detect(); @@ -934,24 +932,7 @@ void __init setup_arch(char **cmdline_p) init_gbpages(); /* max_pfn_mapped is updated here */ - end_pfn = max_low_pfn; - -#ifdef CONFIG_X86_64 - /* - * There may be regions after the last E820_RAM region that we - * want to include in the kernel direct mapping, such as - * EFI_RUNTIME_SERVICES_DATA. - */ - if (efi_enabled) { - unsigned long efi_end; - - efi_end = e820_end_pfn(MAXMEM>>PAGE_SHIFT, E820_RESERVED_EFI); - if (efi_end > max_low_pfn) - end_pfn = efi_end; - } -#endif - - max_low_pfn_mapped = init_memory_mapping(0, end_pfn << PAGE_SHIFT); + max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn< (1UL << (32 - PAGE_SHIFT)) - && end_pfn <= max_pfn_mapped)) { + && end_pfn <= max_pfn_mapped)) va = __va(md->phys_addr); - - if (!(md->attribute & EFI_MEMORY_WB)) { - addr = (u64) (unsigned long)va; - npages = md->num_pages; - memrange_efi_to_native(&addr, &npages); - set_memory_uc(addr, npages); - } - } else { - if (!(md->attribute & EFI_MEMORY_WB)) - va = ioremap_nocache(md->phys_addr, size); - else - va = ioremap_cache(md->phys_addr, size); - } + else + va = efi_ioremap(md->phys_addr, size, md->type); md->virt_addr = (u64) (unsigned long) va; @@ -698,6 +684,13 @@ void __init efi_enter_virtual_mode(void) continue; } + if (!(md->attribute & EFI_MEMORY_WB)) { + addr = md->virt_addr; + npages = md->num_pages; + memrange_efi_to_native(&addr, &npages); + set_memory_uc(addr, npages); + } + systab = (u64) (unsigned long) efi_phys.systab; if (md->phys_addr <= systab && systab < end) { systab += md->virt_addr - md->phys_addr; diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 312250c6b2de..ac3aa54e2654 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -80,3 +80,20 @@ void __init efi_call_phys_epilog(void) local_irq_restore(efi_flags); early_code_mapping_set_exec(0); } + +void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, + u32 type) +{ + unsigned long last_map_pfn; + + if (type == EFI_MEMORY_MAPPED_IO) + return ioremap(phys_addr, size); + + last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); + if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { + unsigned long top = last_map_pfn << PAGE_SHIFT; + efi_ioremap(top, size - (top - phys_addr), type); + } + + return (void __iomem *)__va(phys_addr); +} -- cgit From 4b5d8da88e3fab76700e89488a8c65c54facb9a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 12 Dec 2011 16:02:15 -0200 Subject: Revert "[media] af9015: limit I2C access to keep FW happy" This reverts commit ff83bd82cb343d37b5ab8e402aaad9ef33d03f1e. As requested by Antti: From a talk with him at #linuxtv irc, he strong feeling that some apps like MythTV will do a lot a lot of I2C I/O and now it adds locks, with utimatelly means more delays. This could cause bad effects. There is a new patch for 3.3 that re-writes af9013 in order to limit I2C I/O. and thus those patches could be nice to have together because those user who has has problems are most likely MythTV users. So, let's revert this commit for now. Requested-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 97 -------------------------------------- drivers/media/dvb/dvb-usb/af9015.h | 7 --- 2 files changed, 104 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 033aa8affd8e..c6c275bac08e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1093,80 +1093,9 @@ error: return ret; } -/* override demod callbacks for resource locking */ -static int af9015_af9013_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->set_frontend[adap->id](fe, params); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_read_status(struct dvb_frontend *fe, - fe_status_t *status) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->read_status[adap->id](fe, status); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_init(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->init[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_sleep(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->init[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) { int ret; - struct af9015_state *state = adap->dev->priv; if (adap->id == 1) { /* copy firmware to 2nd demodulator */ @@ -1187,32 +1116,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], &adap->dev->i2c_adap); - /* - * AF9015 firmware does not like if it gets interrupted by I2C adapter - * request on some critical phases. During normal operation I2C adapter - * is used only 2nd demodulator and tuner on dual tuner devices. - * Override demodulator callbacks and use mutex for limit access to - * those "critical" paths to keep AF9015 happy. - * Note: we abuse unused usb_mutex here. - */ - if (adap->fe_adap[0].fe) { - state->set_frontend[adap->id] = - adap->fe_adap[0].fe->ops.set_frontend; - adap->fe_adap[0].fe->ops.set_frontend = - af9015_af9013_set_frontend; - - state->read_status[adap->id] = - adap->fe_adap[0].fe->ops.read_status; - adap->fe_adap[0].fe->ops.read_status = - af9015_af9013_read_status; - - state->init[adap->id] = adap->fe_adap[0].fe->ops.init; - adap->fe_adap[0].fe->ops.init = af9015_af9013_init; - - state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep; - adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep; - } - return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 4a126177e101..6252ea6c1904 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -102,13 +102,6 @@ struct af9015_state { u8 rc_repeat; u32 rc_keycode; u8 rc_last[4]; - - /* for demod callback override */ - int (*set_frontend[2]) (struct dvb_frontend *fe, - struct dvb_frontend_parameters *params); - int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); - int (*init[2]) (struct dvb_frontend *fe); - int (*sleep[2]) (struct dvb_frontend *fe); }; struct af9015_config { -- cgit From 0c8551e5fa3833c6080542da662394817fea4616 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 12 Dec 2011 10:38:26 +0200 Subject: ARM: OMAP: mcbsp: Fix possible memory corruption Commits 09d28d ("ARM: OMAP: mcbsp: Start generalize omap2_mcbsp_set_clks_src") and 7bc0c4 ("ARM: OMAP: mcbsp: Start generalize signal muxing functions") incorrectly set two struct omap_mcbsp_platform_data fields after omap_device_build_ss and kfree calls. Fix this by moving these pdata assignments before those calls. Signed-off-by: Jarkko Nikula Reported-by: NeilBrown Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mcbsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 292eee3be15f..28fcb27005d2 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -145,6 +145,9 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->reg_size = 4; pdata->has_ccr = true; } + pdata->set_clk_src = omap2_mcbsp_set_clk_src; + if (id == 1) + pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; if (oh->class->rev == MCBSP_CONFIG_TYPE3) { if (id == 2) @@ -174,9 +177,6 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) name, oh->name); return PTR_ERR(pdev); } - pdata->set_clk_src = omap2_mcbsp_set_clk_src; - if (id == 1) - pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; omap_mcbsp_count++; return 0; } -- cgit From 123877b80ed62c3b897c53357b622574c023b642 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 8 Dec 2011 15:52:00 -0800 Subject: iwlwifi: do not set the sequence control bit is not needed Check the IEEE80211_TX_CTL_ASSIGN_SEQ flag from mac80211, then decide how to set the TX_CMD_FLG_SEQ_CTL_MSK bit. Setting the wrong bit in BAR frame whill make the firmware to increment the sequence number which is incorrect and cause unknown behavior. CC: stable@vger.kernel.org #3.0+ Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 35a6b71f358c..df1540ca6102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, tx_cmd->tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } else { - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + else + tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); -- cgit From f8c141c3e915e3a040d4c1badde28e23f8cbe255 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 9 Dec 2011 09:35:39 +0300 Subject: nfc: signedness bug in __nci_request() wait_for_completion_interruptible_timeout() returns -ERESTARTSYS if interrupted so completion_rc needs to be signed. The current code probably returns -ETIMEDOUT if we hit this situation, but after this patch is applied it will return -ERESTARTSYS. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- net/nfc/nci/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 4047e29acb3b..25dae3f8f5c2 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -68,7 +68,7 @@ static int __nci_request(struct nci_dev *ndev, __u32 timeout) { int rc = 0; - unsigned long completion_rc; + long completion_rc; ndev->req_status = NCI_REQ_PEND; -- cgit From 10636bc2d60942254bda149827b922c41f4cb4af Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Sat, 10 Dec 2011 18:59:43 +0530 Subject: ath9k: fix max phy rate at rate control init The stations always chooses 1Mbps for all trasmitting frames, whenever the AP is configured to lock the supported rates. As the max phy rate is always set with the 4th from highest phy rate, this assumption might be wrong if we have less than that. Fix that. Cc: stable@kernel.org Cc: Paul Stewart Reported-by: Ajay Gummalla Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8448281dd069..cc5703b853bc 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1270,7 +1270,9 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->max_valid_rate = k; ath_rc_sort_validrates(rate_table, ath_rc_priv); - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; + ath_rc_priv->rate_max_phy = (k > 4) ? + ath_rc_priv->valid_rate_index[k-4] : + ath_rc_priv->valid_rate_index[k-1]; ath_rc_priv->rate_table = rate_table; ath_dbg(common, ATH_DBG_CONFIG, -- cgit From 414b591fd16655871e9f5592a55368b10a3ccc30 Mon Sep 17 00:00:00 2001 From: Alex Hermann Date: Mon, 12 Dec 2011 21:42:23 +0100 Subject: usb: option: Add Huawei E398 controlling interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the controlling interfaces for the Huawei E398. Thanks to Bjørn Mork for extracting the interface numbers from the windows driver. Signed-off-by: Alex Hermann Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e3426602dc82..29907482261f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -664,6 +664,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -- cgit From 6abff5dc4d5a2c90e597137ce8987e7fd439259b Mon Sep 17 00:00:00 2001 From: Krzysztof Hałasa Date: Mon, 12 Dec 2011 14:51:00 +0100 Subject: USB: cdc-acm: add IDs for Motorola H24 HSPA USB module. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add USB IDs for Motorola H24 HSPA USB module. Signed-off-by: Krzysztof Hałasa Acked-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e8c564a53346..a8078d0638fa 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1458,6 +1458,16 @@ static const struct usb_device_id acm_ids[] = { }, { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ }, + /* Motorola H24 HSPA module: */ + { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */ + { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */ + { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */ + { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */ + { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */ + { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */ + { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */ + { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */ + { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on data interface instead of -- cgit From 4af04aba93f47699e7ac33e7cfd4da22550e6114 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Tue, 6 Dec 2011 21:23:45 +0000 Subject: ipv6: Fix for adding multicast route for loopback device automatically. There is no obvious reason to add a default multicast route for loopback devices, otherwise there would be a route entry whose dst.error set to -ENETUNREACH that would blocking all multicast packets. ==================== [ more detailed explanation ] The problem is that the resulting routing table depends on the sequence of interface's initialization and in some situation, that would block all muticast packets. Suppose there are two interfaces on my computer (lo and eth0), if we initailize 'lo' before 'eth0', the resuting routing table(for multicast) would be # ip -6 route show | grep ff00:: unreachable ff00::/8 dev lo metric 256 error -101 ff00::/8 dev eth0 metric 256 When sending multicasting packets, routing subsystem will return the first route entry which with a error set to -101(ENETUNREACH). I know the kernel will set the default ipv6 address for 'lo' when it is up and won't set the default multicast route for it, but there is no reason to stop 'init' program from setting address for 'lo', and that is exactly what systemd did. I am sure there is something wrong with kernel or systemd, currently I preferred kernel caused this problem. ==================== Signed-off-by: Li Wei Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cf88df82e2c2..36806def8cfd 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1805,7 +1805,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) return ERR_PTR(-EACCES); /* Add default multicast route */ - addrconf_add_mroute(dev); + if (!(dev->flags & IFF_LOOPBACK)) + addrconf_add_mroute(dev); /* Add link local route */ addrconf_add_lroute(dev); -- cgit From 72b36015ba43a3cca5303f5534d2c3e1899eae29 Mon Sep 17 00:00:00 2001 From: Ted Feng Date: Thu, 8 Dec 2011 00:46:21 +0000 Subject: ipip, sit: copy parms.name after register_netdevice Same fix as 731abb9cb2 for ipip and sit tunnel. Commit 1c5cae815d removed an explicit call to dev_alloc_name in ipip_tunnel_locate and ipip6_tunnel_locate, because register_netdevice will now create a valid name, however the tunnel keeps a copy of the name in the private parms structure. Fix this by copying the name back after register_netdevice has successfully returned. This shows up if you do a simple tunnel add, followed by a tunnel show: $ sudo ip tunnel add mode ipip remote 10.2.20.211 $ ip tunnel tunl0: ip/ip remote any local any ttl inherit nopmtudisc tunl%d: ip/ip remote 10.2.20.211 local any ttl inherit $ sudo ip tunnel add mode sit remote 10.2.20.212 $ ip tunnel sit0: ipv6/ip remote any local any ttl 64 nopmtudisc 6rd-prefix 2002::/16 sit%d: ioctl 89f8 failed: No such device sit%d: ipv6/ip remote 10.2.20.212 local any ttl inherit Cc: stable@vger.kernel.org Signed-off-by: Ted Feng Signed-off-by: David S. Miller --- net/ipv4/ipip.c | 7 ++++++- net/ipv6/sit.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 065effd8349a..0b2e7329abda 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -285,6 +285,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + strcpy(nt->parms.name, dev->name); + dev_hold(dev); ipip_tunnel_link(ipn, nt); return nt; @@ -759,7 +761,6 @@ static int ipip_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; - strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -825,6 +826,7 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head) static int __net_init ipip_init_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); + struct ip_tunnel *t; int err; ipn->tunnels[0] = ipn->tunnels_wc; @@ -848,6 +850,9 @@ static int __net_init ipip_init_net(struct net *net) if ((err = register_netdev(ipn->fb_tunnel_dev))) goto err_reg_dev; + t = netdev_priv(ipn->fb_tunnel_dev); + + strcpy(t->parms.name, ipn->fb_tunnel_dev->name); return 0; err_reg_dev: diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index a7a18602a046..96f3623618e3 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -263,6 +263,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + strcpy(nt->parms.name, dev->name); + dev_hold(dev); ipip6_tunnel_link(sitn, nt); @@ -1144,7 +1146,6 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; - strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -1207,6 +1208,7 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea static int __net_init sit_init_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); + struct ip_tunnel *t; int err; sitn->tunnels[0] = sitn->tunnels_wc; @@ -1231,6 +1233,9 @@ static int __net_init sit_init_net(struct net *net) if ((err = register_netdev(sitn->fb_tunnel_dev))) goto err_reg_dev; + t = netdev_priv(sitn->fb_tunnel_dev); + + strcpy(t->parms.name, sitn->fb_tunnel_dev->name); return 0; err_reg_dev: -- cgit From 3f1e6d3fd37bd4f25e5b19f1c7ca21850426c33f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 11 Dec 2011 23:42:53 +0000 Subject: sch_gred: should not use GFP_KERNEL while holding a spinlock gred_change_vq() is called under sch_tree_lock(sch). This means a spinlock is held, and we are not allowed to sleep in this context. We might pre-allocate memory using GFP_KERNEL before taking spinlock, but this is not suitable for stable material. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_gred.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index b9493a09a870..6cd8ddfb512d 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -385,7 +385,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, struct gred_sched_data *q; if (table->tab[dp] == NULL) { - table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL); + table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); if (table->tab[dp] == NULL) return -ENOMEM; } -- cgit From fc6cb1cda5db7b2d24bf32890826214b857c728e Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 12 Dec 2011 22:06:18 -0500 Subject: ext4: display the correct mount option in /proc/mounts for [no]init_itable /proc/mounts was showing the mount option [no]init_inode_table when the correct mount option that will be accepted by parse_options() is [no]init_itable. Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/super.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3858767ec672..3e1329e2f826 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1155,9 +1155,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",block_validity"); if (!test_opt(sb, INIT_INODE_TABLE)) - seq_puts(seq, ",noinit_inode_table"); + seq_puts(seq, ",noinit_itable"); else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT) - seq_printf(seq, ",init_inode_table=%u", + seq_printf(seq, ",init_itable=%u", (unsigned) sbi->s_li_wait_mult); ext4_show_quota_options(seq, sb); @@ -1333,8 +1333,7 @@ enum { Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, Opt_inode_readahead_blks, Opt_journal_ioprio, Opt_dioread_nolock, Opt_dioread_lock, - Opt_discard, Opt_nodiscard, - Opt_init_inode_table, Opt_noinit_inode_table, + Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, }; static const match_table_t tokens = { @@ -1407,9 +1406,9 @@ static const match_table_t tokens = { {Opt_dioread_lock, "dioread_lock"}, {Opt_discard, "discard"}, {Opt_nodiscard, "nodiscard"}, - {Opt_init_inode_table, "init_itable=%u"}, - {Opt_init_inode_table, "init_itable"}, - {Opt_noinit_inode_table, "noinit_itable"}, + {Opt_init_itable, "init_itable=%u"}, + {Opt_init_itable, "init_itable"}, + {Opt_noinit_itable, "noinit_itable"}, {Opt_err, NULL}, }; @@ -1892,7 +1891,7 @@ set_qf_format: case Opt_dioread_lock: clear_opt(sb, DIOREAD_NOLOCK); break; - case Opt_init_inode_table: + case Opt_init_itable: set_opt(sb, INIT_INODE_TABLE); if (args[0].from) { if (match_int(&args[0], &option)) @@ -1903,7 +1902,7 @@ set_qf_format: return 0; sbi->s_li_wait_mult = option; break; - case Opt_noinit_inode_table: + case Opt_noinit_itable: clear_opt(sb, INIT_INODE_TABLE); break; default: -- cgit From 13c07b0286d340275f2d97adf085cecda37ede37 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 12 Dec 2011 22:06:55 -0800 Subject: linux/log2.h: Fix rounddown_pow_of_two(1) Exactly like roundup_pow_of_two(1), the rounddown version was buggy for the case of a compile-time constant '1' argument. Probably because it originated from the same code, sharing history with the roundup version from before the bugfix (for that one, see commit 1a06a52ee1b0: "Fix roundup_pow_of_two(1)"). However, unlike the roundup version, the fix for rounddown is to just remove the broken special case entirely. It's simply not needed - the generic code 1UL << ilog2(n) does the right thing for the constant '1' argment too. The only reason roundup needed that special case was because rounding up does so by subtracting one from the argument (and then adding one to the result) causing the obvious problems with "ilog2(0)". But rounddown doesn't do any of that, since ilog2() naturally truncates (ie "rounds down") to the right rounded down value. And without the ilog2(0) case, there's no reason for the special case that had the wrong value. tl;dr: rounddown_pow_of_two(1) should be 1, not 0. Acked-by: Dmitry Torokhov Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- include/linux/log2.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/log2.h b/include/linux/log2.h index 25b808631cd9..fd7ff3d91e6a 100644 --- a/include/linux/log2.h +++ b/include/linux/log2.h @@ -185,7 +185,6 @@ unsigned long __rounddown_pow_of_two(unsigned long n) #define rounddown_pow_of_two(n) \ ( \ __builtin_constant_p(n) ? ( \ - (n == 1) ? 0 : \ (1UL << ilog2(n))) : \ __rounddown_pow_of_two(n) \ ) -- cgit From 48706d0a91583d08c56e7ef2a7602d99c8d4133f Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 13 Dec 2011 10:36:59 +0100 Subject: fuse: fix fuse_retrieve Fix two bugs in fuse_retrieve(): - retrieving more than one page would yield repeated instances of the first page - if more than FUSE_MAX_PAGES_PER_REQ pages were requested than the request page array would overflow fuse_retrieve() was added in 2.6.36 and these bugs had been there since the beginning. Signed-off-by: Miklos Szeredi CC: stable@vger.kernel.org --- fs/fuse/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 5cb8614508c3..2aaf3eaaf13d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1512,7 +1512,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, else if (outarg->offset + num > file_size) num = file_size - outarg->offset; - while (num) { + while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { struct page *page; unsigned int this_num; @@ -1526,6 +1526,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, num -= this_num; total_len += this_num; + index++; } req->misc.retrieve_in.offset = outarg->offset; req->misc.retrieve_in.size = total_len; -- cgit From b48c6af2086ab2ba8a9c9b6ce9ecb34592ce500c Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 13 Dec 2011 10:37:00 +0100 Subject: fuse: fix llseek bug The test in fuse_file_llseek() "not SEEK_CUR or not SEEK_SET" always evaluates to true. This was introduced in 3.1 by commit 06222e49 (fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek) and changed the behavior of SEEK_CUR and SEEK_SET to always retrieve the file attributes. This is a performance regression. Fix the test so that it makes sense. Signed-off-by: Miklos Szeredi CC: stable@vger.kernel.org CC: Josef Bacik CC: Al Viro --- fs/fuse/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 594f07a81c28..19029e97ca2f 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1556,7 +1556,7 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) struct inode *inode = file->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); - if (origin != SEEK_CUR || origin != SEEK_SET) { + if (origin != SEEK_CUR && origin != SEEK_SET) { retval = fuse_update_attributes(inode, NULL, file, NULL); if (retval) goto exit; -- cgit From 73104b6e37f75f822e3dcf016147c322d1f6dad9 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 13 Dec 2011 11:40:59 +0100 Subject: fuse: llseek fix race Fix race between lseek(fd, 0, SEEK_CUR) and read/write. This was fixed in generic code by commit 5b6f1eb97d (vfs: lseek(fd, 0, SEEK_CUR) race condition). Signed-off-by: Miklos Szeredi --- fs/fuse/file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 19029e97ca2f..0c84100acd44 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1567,6 +1567,10 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) offset += i_size_read(inode); break; case SEEK_CUR: + if (offset == 0) { + retval = file->f_pos; + goto exit; + } offset += file->f_pos; break; case SEEK_DATA: -- cgit From e2ef36c688d5844a986424c3194bd33212c968ce Mon Sep 17 00:00:00 2001 From: Gustavo Maciel Dias Vieira Date: Tue, 13 Dec 2011 11:47:22 -0200 Subject: ALSA: hda: fix mute led polarity for HP laptops with buggy BIOS Some HP laptop models do not have a properly filled OEM string used to set the gpio and polarity of the mute led. Make the mute led configuration work for this case. Signed-off-by: Gustavo Maciel Dias Vieira Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index eeb25d529e30..616678fde486 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4929,6 +4929,12 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) set_hp_led_gpio(codec); return 1; } + /* BIOS bug: unfilled OEM string */ + if (strstr(dev->name, "HP_Mute_LED_P_G")) { + set_hp_led_gpio(codec); + spec->gpio_led_polarity = 1; + return 1; + } } /* -- cgit From 935a9fee51c945b8942be2d7b4bae069167b4886 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 12 Dec 2011 12:39:14 -0800 Subject: ibft: Fix finding IBFT ACPI table on UEFI Found one system with UEFI/iBFT, kernel does not detect the iBFT during iscsi_ibft module loading. Root cause: on x86 (UEFI), we are calling of find_ibft_region() much earlier - specifically in setup_arch() before ACPI is enabled. Try to split acpi checking code out and call that later At that time ACPI iBFT already get permanent mapped with ioremap. So isa_virt_to_bus() will get wrong phys from right virt address. We could just skip that phys address printing. For legacy one, print the found address early. -v2: update comments and description according to Konrad. -v3: fix problem about module use case that is found by Konrad. -v4: use acpi_get_table() instead of acpi_table_parse() to handle module use case that is found by Konrad again.. Signed-off-by: Yinghai Lu Signed-off-by: Konrad Rzeszutek Wilk --- drivers/firmware/iscsi_ibft.c | 42 ++++++++++++++++++++++++++++++++++++-- drivers/firmware/iscsi_ibft_find.c | 26 ++--------------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index c811cb107904..2cce44a1d7d0 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -746,6 +746,37 @@ static void __exit ibft_exit(void) ibft_cleanup(); } +#ifdef CONFIG_ACPI +static const struct { + char *sign; +} ibft_signs[] = { + /* + * One spec says "IBFT", the other says "iBFT". We have to check + * for both. + */ + { ACPI_SIG_IBFT }, + { "iBFT" }, +}; + +static void __init acpi_find_ibft_region(void) +{ + int i; + struct acpi_table_header *table = NULL; + + if (acpi_disabled) + return; + + for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) { + acpi_get_table(ibft_signs[i].sign, 0, &table); + ibft_addr = (struct acpi_table_ibft *)table; + } +} +#else +static void __init acpi_find_ibft_region(void) +{ +} +#endif + /* * ibft_init() - creates sysfs tree entries for the iBFT data. */ @@ -753,9 +784,16 @@ static int __init ibft_init(void) { int rc = 0; + /* + As on UEFI systems the setup_arch()/find_ibft_region() + is called before ACPI tables are parsed and it only does + legacy finding. + */ + if (!ibft_addr) + acpi_find_ibft_region(); + if (ibft_addr) { - printk(KERN_INFO "iBFT detected at 0x%llx.\n", - (u64)isa_virt_to_bus(ibft_addr)); + pr_info("iBFT detected.\n"); rc = ibft_check_device(); if (rc) diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index bfe723266fd8..4da4eb9ae926 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -45,13 +45,6 @@ EXPORT_SYMBOL_GPL(ibft_addr); static const struct { char *sign; } ibft_signs[] = { -#ifdef CONFIG_ACPI - /* - * One spec says "IBFT", the other says "iBFT". We have to check - * for both. - */ - { ACPI_SIG_IBFT }, -#endif { "iBFT" }, { "BIFT" }, /* Broadcom iSCSI Offload */ }; @@ -62,14 +55,6 @@ static const struct { #define VGA_MEM 0xA0000 /* VGA buffer */ #define VGA_SIZE 0x20000 /* 128kB */ -#ifdef CONFIG_ACPI -static int __init acpi_find_ibft(struct acpi_table_header *header) -{ - ibft_addr = (struct acpi_table_ibft *)header; - return 0; -} -#endif /* CONFIG_ACPI */ - static int __init find_ibft_in_mem(void) { unsigned long pos; @@ -94,6 +79,7 @@ static int __init find_ibft_in_mem(void) * the table cannot be valid. */ if (pos + len <= (IBFT_END-1)) { ibft_addr = (struct acpi_table_ibft *)virt; + pr_info("iBFT found at 0x%lx.\n", pos); goto done; } } @@ -108,20 +94,12 @@ done: */ unsigned long __init find_ibft_region(unsigned long *sizep) { -#ifdef CONFIG_ACPI - int i; -#endif ibft_addr = NULL; -#ifdef CONFIG_ACPI - for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) - acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft); -#endif /* CONFIG_ACPI */ - /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will * only use ACPI for this */ - if (!ibft_addr && !efi_enabled) + if (!efi_enabled) find_ibft_in_mem(); if (ibft_addr) { -- cgit From 6a82c47aa84ab22cb5969a44105cca5358879d21 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 13 Dec 2011 09:19:26 -0800 Subject: ceph: fix SEEK_CUR, SEEK_SET regression Commit 06222e491e663dac939f04b125c9dc52126a75c4 got the if wrong so that it always evaluates as true. This is semantically harmless, but makes SEEK_CUR and SEEK_SET needlessly query the server. Rewrite the if to explicitly enumerate the cases we DO need a valid i_size to make this code less fragile. Reported-by: Roel Kluin Signed-off-by: Sage Weil --- fs/ceph/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index af187330cc89..ed72428d9c75 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -797,7 +797,8 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) mutex_lock(&inode->i_mutex); __ceph_do_pending_vmtruncate(inode); - if (origin != SEEK_CUR || origin != SEEK_SET) { + + if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) { ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); if (ret < 0) { offset = ret; -- cgit From 5cc361e3b8241989d8240014dbbe6214c9292541 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 12 Dec 2011 23:58:21 -0500 Subject: ubifs: too early register_filesystem() doing that before you are ready to handle mount() is a Bad Idea(tm)... Signed-off-by: Al Viro --- fs/ubifs/super.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 20403dc5d437..ae0e76bb6ebf 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2264,19 +2264,12 @@ static int __init ubifs_init(void) return -EINVAL; } - err = register_filesystem(&ubifs_fs_type); - if (err) { - ubifs_err("cannot register file system, error %d", err); - return err; - } - - err = -ENOMEM; ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab", sizeof(struct ubifs_inode), 0, SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT, &inode_slab_ctor); if (!ubifs_inode_slab) - goto out_reg; + return -ENOMEM; register_shrinker(&ubifs_shrinker_info); @@ -2288,15 +2281,20 @@ static int __init ubifs_init(void) if (err) goto out_compr; + err = register_filesystem(&ubifs_fs_type); + if (err) { + ubifs_err("cannot register file system, error %d", err); + goto out_dbg; + } return 0; +out_dbg: + dbg_debugfs_exit(); out_compr: ubifs_compressors_exit(); out_shrinker: unregister_shrinker(&ubifs_shrinker_info); kmem_cache_destroy(ubifs_inode_slab); -out_reg: - unregister_filesystem(&ubifs_fs_type); return err; } /* late_initcall to let compressors initialize first */ -- cgit From 988f032567eaba3c5896c5de05270b9ff71b2a9d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 13 Dec 2011 12:25:27 -0500 Subject: fuse: register_filesystem() called too early same story as with ubifs Signed-off-by: Al Viro --- fs/fuse/inode.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3e6d72756479..aa83109b9431 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1138,28 +1138,28 @@ static int __init fuse_fs_init(void) { int err; - err = register_filesystem(&fuse_fs_type); - if (err) - goto out; - - err = register_fuseblk(); - if (err) - goto out_unreg; - fuse_inode_cachep = kmem_cache_create("fuse_inode", sizeof(struct fuse_inode), 0, SLAB_HWCACHE_ALIGN, fuse_inode_init_once); err = -ENOMEM; if (!fuse_inode_cachep) - goto out_unreg2; + goto out; + + err = register_fuseblk(); + if (err) + goto out2; + + err = register_filesystem(&fuse_fs_type); + if (err) + goto out3; return 0; - out_unreg2: + out3: unregister_fuseblk(); - out_unreg: - unregister_filesystem(&fuse_fs_type); + out2: + kmem_cache_destroy(fuse_inode_cachep); out: return err; } -- cgit From 7c6455e368bc87ef38df7b6ddba2339a67107bdf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 13 Dec 2011 12:32:42 -0500 Subject: configfs: register_filesystem() called too early Signed-off-by: Al Viro --- fs/configfs/inode.c | 2 +- fs/configfs/mount.c | 36 +++++++++++++++++------------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index ca418aaf6352..9d8715c45f25 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -292,7 +292,7 @@ int __init configfs_inode_init(void) return bdi_init(&configfs_backing_dev_info); } -void __exit configfs_inode_exit(void) +void configfs_inode_exit(void) { bdi_destroy(&configfs_backing_dev_info); } diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index ecc62178beda..276e15cafd58 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -143,28 +143,26 @@ static int __init configfs_init(void) goto out; config_kobj = kobject_create_and_add("config", kernel_kobj); - if (!config_kobj) { - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - goto out; - } + if (!config_kobj) + goto out2; + + err = configfs_inode_init(); + if (err) + goto out3; err = register_filesystem(&configfs_fs_type); - if (err) { - printk(KERN_ERR "configfs: Unable to register filesystem!\n"); - kobject_put(config_kobj); - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - goto out; - } + if (err) + goto out4; - err = configfs_inode_init(); - if (err) { - unregister_filesystem(&configfs_fs_type); - kobject_put(config_kobj); - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - } + return 0; +out4: + printk(KERN_ERR "configfs: Unable to register filesystem!\n"); + configfs_inode_exit(); +out3: + kobject_put(config_kobj); +out2: + kmem_cache_destroy(configfs_dir_cachep); + configfs_dir_cachep = NULL; out: return err; } -- cgit From 02a551c9755b799579e0a093bcc99b80b4dc1453 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Tue, 13 Dec 2011 05:33:02 +0100 Subject: USB: option: Removing one bogus and adding some new Huawei combinations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Huawei use the product code HUAWEI_PRODUCT_E353 (0x1506) for a number of different devices, which each can appear with a number of different descriptor sets. Different types of interfaces can be identified by looking at the subclass and protocol fields Subclass 1 protocol 8 is actually the data interface of a CDC ECM set, with subclass 1 protocol 9 as the control interface. Neither support serial data communcation, and cannot therefore be supported by this driver. At the same time, add a few other sets which appear if the device is configured in "Windows mode" using this modeswitch message: 55534243000000000000000000000011060000000100000000000000000000 Signed-off-by: Bjørn Mork Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 29907482261f..6dd64534fad0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -663,7 +663,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ -- cgit From b2888095feb3c651cba5904b0227622e82777b34 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 9 Dec 2011 16:56:08 -0600 Subject: gpio: pl061: drop extra check for NULL platform_data In adding DT binding support, the check for NULL platform_data got added back in inadvertently, so remove it. Signed-off-by: Rob Herring Signed-off-by: Grant Likely --- drivers/gpio/gpio-pl061.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 093c90bd3c1d..4102f63230fd 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -238,10 +238,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) int ret, irq, i; static DECLARE_BITMAP(init_irq, NR_IRQS); - pdata = dev->dev.platform_data; - if (pdata == NULL) - return -ENODEV; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; -- cgit From f9ea14efa5277c47efec341dee2c408b6b80f854 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 13 Dec 2011 23:53:49 +0800 Subject: gpio-ml-ioh: fix a bug in the interrupt handler GPIO's irq action's dev_id is set to the first struct ioh_gpio chip, so when loop checking the 8 chips, the "chip" should be changed according. Signed-off-by: Feng Tang Signed-off-by: Grant Likely --- drivers/gpio/gpio-ml-ioh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index ea8e73869250..92b6f51a206e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -339,7 +339,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) int i, j; int ret = IRQ_NONE; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++, chip++) { reg_val = ioread32(&chip->reg->regs[i].istatus); for (j = 0; j < num_ports[i]; j++) { if (reg_val & BIT(j)) { -- cgit From 4d052213ff8f71a4a70fc4eed71b773cfde51fcf Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 13 Dec 2011 23:53:50 +0800 Subject: gpio-ml-ioh: Add the irq_disable/irq_enable hooks for ml-ioh irq chip These hooks will be needed by the general disabl/enable_irq(); Signed-off-by: Feng Tang Signed-off-by: Grant Likely --- drivers/gpio/gpio-ml-ioh.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 92b6f51a206e..461958fc2264 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -332,6 +332,34 @@ static void ioh_irq_mask(struct irq_data *d) &chip->reg->regs[chip->ch].imask); } +static void ioh_irq_disable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct ioh_gpio *chip = gc->private; + unsigned long flags; + u32 ien; + + spin_lock_irqsave(&chip->spinlock, flags); + ien = ioread32(&chip->reg->regs[chip->ch].ien); + ien &= ~(1 << (d->irq - chip->irq_base)); + iowrite32(ien, &chip->reg->regs[chip->ch].ien); + spin_unlock_irqrestore(&chip->spinlock, flags); +} + +static void ioh_irq_enable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct ioh_gpio *chip = gc->private; + unsigned long flags; + u32 ien; + + spin_lock_irqsave(&chip->spinlock, flags); + ien = ioread32(&chip->reg->regs[chip->ch].ien); + ien |= 1 << (d->irq - chip->irq_base); + iowrite32(ien, &chip->reg->regs[chip->ch].ien); + spin_unlock_irqrestore(&chip->spinlock, flags); +} + static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) { struct ioh_gpio *chip = dev_id; @@ -370,6 +398,8 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, ct->chip.irq_mask = ioh_irq_mask; ct->chip.irq_unmask = ioh_irq_unmask; ct->chip.irq_set_type = ioh_irq_type; + ct->chip.irq_disable = ioh_irq_disable; + ct->chip.irq_enable = ioh_irq_enable; irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST | IRQ_NOPROBE, 0); -- cgit From 28538df0389a59ede9ccd6f327d2031f0044db87 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 13 Dec 2011 10:12:48 +0100 Subject: gpio: mpc8xxx: don't allow input-only pins to be output for MPC5121 Add a 5121-custom reject if an input-only pin is requested to be output (see 18.3.1.1 in the refman). Also, rewrite mach-specific quirk setup to consume less lines which scales better. Signed-off-by: Wolfram Sang [grant.likely: Fixed build error] Signed-off-by: Grant Likely --- drivers/gpio/gpio-mpc8xxx.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index ec3fcf0a7e12..5cd04b65c556 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -132,6 +132,15 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val return 0; } +static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + /* GPIO 28..31 are input only on MPC5121 */ + if (gpio >= 28) + return -EINVAL; + + return mpc8xxx_gpio_dir_out(gc, gpio, val); +} + static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) { struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); @@ -340,11 +349,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) mm_gc->save_regs = mpc8xxx_gpio_save_regs; gc->ngpio = MPC8XXX_GPIO_PINS; gc->direction_input = mpc8xxx_gpio_dir_in; - gc->direction_output = mpc8xxx_gpio_dir_out; - if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) - gc->get = mpc8572_gpio_get; - else - gc->get = mpc8xxx_gpio_get; + gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ? + mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out; + gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? + mpc8572_gpio_get : mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; gc->to_irq = mpc8xxx_gpio_to_irq; -- cgit From 619a5182d1f38a3d629ee48e04fa182ef9170052 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 13 Dec 2011 00:02:28 +0100 Subject: PCI hotplug: Always allow acpiphp to handle non-PCIe bridges Commit 0d52f54e2ef64c189dedc332e680b2eb4a34590a (PCI / ACPI: Make acpiphp ignore root bridges using PCIe native hotplug) added code that made the acpiphp driver completely ignore PCIe root complexes for which the kernel had been granted control of the native PCIe hotplug feature by the BIOS through _OSC. Unfortunately, however, this was a mistake, because on some systems there were PCI bridges supporting PCI (non-PCIe) hotplug under such root complexes and those bridges should have been handled by acpiphp. For this reason, revert the changes made by the commit mentioned above and make register_slot() in drivers/pci/hotplug/acpiphp_glue.c avoid registering hotplug slots for PCIe ports that belong to root complexes with native PCIe hotplug enabled (which means that the BIOS has granted the kernel control of this feature for the given root complex). This is reported to address the original issue fixed by commit 0d52f54e2ef64c189dedc332e680b2eb4a34590a and to work on the system where that commit broke things. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpiphp_glue.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index fce1c54a0c8d..68360d5b494a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -132,6 +132,18 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) return AE_OK; + pdev = pbus->self; + if (pdev && pci_is_pcie(pdev)) { + tmp = acpi_find_root_bridge_handle(pdev); + if (tmp) { + struct acpi_pci_root *root = acpi_pci_find_root(tmp); + + if (root && (root->osc_control_set & + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) + return AE_OK; + } + } + acpi_evaluate_integer(handle, "_ADR", NULL, &adr); device = (adr >> 16) & 0xffff; function = adr & 0xffff; @@ -459,17 +471,8 @@ static int add_bridge(acpi_handle handle) { acpi_status status; unsigned long long tmp; - struct acpi_pci_root *root; acpi_handle dummy_handle; - /* - * We shouldn't use this bridge if PCIe native hotplug control has been - * granted by the BIOS for it. - */ - root = acpi_pci_find_root(handle); - if (root && (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) - return -ENODEV; - /* if the bridge doesn't have _STA, we assume it is always there */ status = acpi_get_handle(handle, "_STA", &dummy_handle); if (ACPI_SUCCESS(status)) { @@ -1385,19 +1388,11 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, static acpi_status find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { - struct acpi_pci_root *root; int *count = (int *)context; if (!acpi_is_root_bridge(handle)) return AE_OK; - root = acpi_pci_find_root(handle); - if (!root) - return AE_OK; - - if (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) - return AE_OK; - (*count)++; acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, NULL); -- cgit From 9d5a09e659f8414dd3713e2acbfaf8a9e9794aa1 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 13 Dec 2011 09:57:44 -0800 Subject: ceph: add missing spin_unlock at ceph_mdsc_build_path() one of the paths was missing spin_unlock Signed-off-by: Yehuda Sadeh --- fs/ceph/mds_client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 34bc35084ae3..6203d805eb45 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1495,6 +1495,7 @@ retry: pos, temp); } else if (stop_on_nosnap && inode && ceph_snap(inode) == CEPH_NOSNAP) { + spin_unlock(&temp->d_lock); break; } else { pos -= temp->d_name.len; -- cgit From 93b2ec0128c431148b216b8f7337c1a52131ef03 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 9 Dec 2011 09:39:15 +1100 Subject: rtc: Expire alarms after the time is set. If the alarm time programming in the rtc is ever in the past, it won't fire, and any other alarm will be queued after it so they won't fire either. So any time that the alarm might be in the past, we need to trigger the irq handler to ensure the old alarm is cleared and the timer queue is fully in the future. This can happen: - when we first initialise the alarm - when we set the time in the rtc. so follow both of these by scheduling the timer work function. CC: stable@kernel.org Signed-off-by: NeilBrown [Also catch set_mmss case -jstultz] Signed-off-by: John Stultz --- drivers/rtc/interface.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index fa4d9f324189..3bcc7cfcaba7 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -73,6 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) err = -EINVAL; mutex_unlock(&rtc->ops_lock); + /* A timer might have just expired */ + schedule_work(&rtc->irqwork); return err; } EXPORT_SYMBOL_GPL(rtc_set_time); @@ -112,6 +114,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) err = -EINVAL; mutex_unlock(&rtc->ops_lock); + /* A timer might have just expired */ + schedule_work(&rtc->irqwork); return err; } @@ -403,6 +407,8 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); } mutex_unlock(&rtc->ops_lock); + /* maybe that was in the past.*/ + schedule_work(&rtc->irqwork); return err; } EXPORT_SYMBOL_GPL(rtc_initialize_alarm); -- cgit From c3b79770e51ab1fd4201f3b54edf30113b9ce74f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 12 Dec 2011 13:57:52 -0800 Subject: rtc: m41t80: Workaround broken alarm functionality The m41t80 driver can read and set the alarm, but it doesn't seem to have a functional alarm irq. This causes failures when the generic core sees alarm functions, but then cannot use them properly for things like UIE mode. Disabling the alarm functions allows proper error reporting, and possible fallback to emulated modes. Once someone fixes the alarm irq functionality, this can be restored. CC: stable@kernel.org CC: Matt Turner CC: Nico Macrionitis CC: Atsushi Nemoto Reported-by: Matt Turner Reported-by: Nico Macrionitis Tested-by: Nico Macrionitis Signed-off-by: John Stultz --- drivers/rtc/rtc-m41t80.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index eda128fc1d38..64aedd8cc095 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -357,10 +357,19 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) static struct rtc_class_ops m41t80_rtc_ops = { .read_time = m41t80_rtc_read_time, .set_time = m41t80_rtc_set_time, + /* + * XXX - m41t80 alarm functionality is reported broken. + * until it is fixed, don't register alarm functions. + * .read_alarm = m41t80_rtc_read_alarm, .set_alarm = m41t80_rtc_set_alarm, + */ .proc = m41t80_rtc_proc, + /* + * See above comment on broken alarm + * .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, + */ }; #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) -- cgit From e5fe29c7198a1f6616286dfc8602a69da165cb3f Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Thu, 8 Dec 2011 22:23:00 +0200 Subject: ARM: OMAP: rx51: fix USB Commit 10299e2e4e3ed3b16503d4e04edd48b33083f4e2 (ARM: RX-51: Enable isp1704 power on/off) added power management for isp1704. However, the transceiver should be powered on by default, otherwise USB doesn't work at all for networking during boot. All kernels after v3.0 are affected. Cc: stable@kernel.org Signed-off-by: Felipe Contreras Reviewed-by: Sebastian Reichel [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ba1aa07bdb29..c15c5c9c9085 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -193,7 +193,7 @@ static struct platform_device rx51_charger_device = { static void __init rx51_charger_init(void) { WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, - GPIOF_OUT_INIT_LOW, "isp1704_reset")); + GPIOF_OUT_INIT_HIGH, "isp1704_reset")); platform_device_register(&rx51_charger_device); } -- cgit From bb3c36863e8001fc21a88bebfdead4da4c23e848 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 13 Dec 2011 17:35:06 -0500 Subject: ipv6: Check dest prefix length on original route not copied one in rt6_alloc_cow(). After commit 8e2ec639173f325977818c45011ee176ef2b11f6 ("ipv6: don't use inetpeer to store metrics for routes.") the test in rt6_alloc_cow() for setting the ANYCAST flag is now wrong. 'rt' will always now have a plen of 128, because it is set explicitly to 128 by ip6_rt_copy. So to restore the semantics of the test, check the destination prefix length of 'ort'. Signed-off-by: David S. Miller --- net/ipv6/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3399dd326287..b582a0a0f1c5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -728,7 +728,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, int attempts = !in_softirq(); if (!(rt->rt6i_flags&RTF_GATEWAY)) { - if (rt->rt6i_dst.plen != 128 && + if (ort->rt6i_dst.plen != 128 && ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) rt->rt6i_flags |= RTF_ANYCAST; ipv6_addr_copy(&rt->rt6i_gateway, daddr); -- cgit From 0a7e22e61e07a2ea479511f9620858be2f1507e8 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Mon, 14 Nov 2011 20:16:57 -0600 Subject: staging: tidspbridge: include module.h by default Fixes compilation break when compiled as part of the kernel: drivers/staging/tidspbridge/rmgr/drv_interface.c:134: error: expected declaration specifiers or '...' before string constant drivers/staging/tidspbridge/rmgr/drv_interface.c:134: warning: data definition has no type or storage class drivers/staging/tidspbridge/rmgr/drv_interface.c:134: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR' drivers/staging/tidspbridge/rmgr/drv_interface.c:134: warning: function declaration isn't a prototype drivers/staging/tidspbridge/rmgr/drv_interface.c:135: error: expected declaration specifiers or '...' before string constant drivers/staging/tidspbridge/rmgr/drv_interface.c:135: warning: data definition has no type or storage class drivers/staging/tidspbridge/rmgr/drv_interface.c:135: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE' drivers/staging/tidspbridge/rmgr/drv_interface.c:135: warning: function declaration isn't a prototype drivers/staging/tidspbridge/rmgr/drv_interface.c:136: error: expected declaration specifiers or '...' before string constant drivers/staging/tidspbridge/rmgr/drv_interface.c:136: warning: data definition has no type or storage class drivers/staging/tidspbridge/rmgr/drv_interface.c:136: warning: type defaults to 'int' in declaration of 'MODULE_VERSION' drivers/staging/tidspbridge/rmgr/drv_interface.c:136: warning: function declaration isn't a prototype drivers/staging/tidspbridge/rmgr/drv_interface.c: In function 'omap34_xx_bridge_probe': drivers/staging/tidspbridge/rmgr/drv_interface.c:359: error: 'THIS_MODULE' undeclared (first use in this function) drivers/staging/tidspbridge/rmgr/drv_interface.c:359: error: (Each undeclared identifier is reported only once drivers/staging/tidspbridge/rmgr/drv_interface.c:359: error: for each function it appears in.) Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/rmgr/drv_interface.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index c43c7e3421c8..76cfc6edecd9 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -24,11 +24,7 @@ #include #include #include - -#ifdef MODULE #include -#endif - #include #include #include -- cgit From ed625b9143ee53fe610320908c89e22635ee6e87 Mon Sep 17 00:00:00 2001 From: Omar Ramirez Luna Date: Fri, 18 Nov 2011 16:18:54 -0600 Subject: staging: tidspbridge: request dmtimer clocks on init Given that dm timer framework doesn't support request of clocks by soft | hard irqs because some recent changes, tidspbridge needs to request its clocks on init and enable/disable them on demand. This was first seen on 3.2-rc1. Signed-off-by: Omar Ramirez Luna Signed-off-by: Greg Kroah-Hartman --- drivers/staging/tidspbridge/core/dsp-clock.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index 3d1279c424a8..7eb56178fb64 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c @@ -54,6 +54,7 @@ /* Bridge GPT id (1 - 4), DM Timer id (5 - 8) */ #define DMT_ID(id) ((id) + 4) +#define DM_TIMER_CLOCKS 4 /* Bridge MCBSP id (6 - 10), OMAP Mcbsp id (0 - 4) */ #define MCBSP_ID(id) ((id) - 6) @@ -114,8 +115,13 @@ static s8 get_clk_type(u8 id) */ void dsp_clk_exit(void) { + int i; + dsp_clock_disable_all(dsp_clocks); + for (i = 0; i < DM_TIMER_CLOCKS; i++) + omap_dm_timer_free(timer[i]); + clk_put(iva2_clk); clk_put(ssi.sst_fck); clk_put(ssi.ssr_fck); @@ -130,9 +136,13 @@ void dsp_clk_exit(void) void dsp_clk_init(void) { static struct platform_device dspbridge_device; + int i, id; dspbridge_device.dev.bus = &platform_bus_type; + for (i = 0, id = 5; i < DM_TIMER_CLOCKS; i++, id++) + timer[i] = omap_dm_timer_request_specific(id); + iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); if (IS_ERR(iva2_clk)) dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); @@ -204,8 +214,7 @@ int dsp_clk_enable(enum dsp_clk_id clk_id) clk_enable(iva2_clk); break; case GPT_CLK: - timer[clk_id - 1] = - omap_dm_timer_request_specific(DMT_ID(clk_id)); + status = omap_dm_timer_start(timer[clk_id - 1]); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: @@ -281,7 +290,7 @@ int dsp_clk_disable(enum dsp_clk_id clk_id) clk_disable(iva2_clk); break; case GPT_CLK: - omap_dm_timer_free(timer[clk_id - 1]); + status = omap_dm_timer_stop(timer[clk_id - 1]); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: -- cgit From c7caf4d4c56aee40b995f5858ccf1c814f3d2da2 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 11 Dec 2011 10:27:54 -0600 Subject: staging: r8712u: Add new USB ID Add USB ID for Sitecom WLA-2000 v1.001 WLAN. Reported-and-tested-by: Roland Gruber Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_intf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index fb2e89c3056c..5385da2e9cdb 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -89,6 +89,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { {USB_DEVICE(0x0DF6, 0x0045)}, {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */ {USB_DEVICE(0x0DF6, 0x004B)}, + {USB_DEVICE(0x0DF6, 0x005D)}, {USB_DEVICE(0x0DF6, 0x0063)}, /* Sweex */ {USB_DEVICE(0x177F, 0x0154)}, -- cgit From ea51d132dbf9b00063169c1159bee253d9649224 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Tue, 13 Dec 2011 21:41:15 -0500 Subject: ext4: avoid hangs in ext4_da_should_update_i_disksize() If the pte mapping in generic_perform_write() is unmapped between iov_iter_fault_in_readable() and iov_iter_copy_from_user_atomic(), the "copied" parameter to ->end_write can be zero. ext4 couldn't cope with it with delayed allocations enabled. This skips the i_disksize enlargement logic if copied is zero and no new data was appeneded to the inode. gdb> bt #0 0xffffffff811afe80 in ext4_da_should_update_i_disksize (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x1\ 08000, len=0x1000, copied=0x0, page=0xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2467 #1 ext4_da_write_end (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x108000, len=0x1000, copied=0x0, page=0\ xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2512 #2 0xffffffff810d97f1 in generic_perform_write (iocb=, iov=, nr_segs=, pos=0x108000, ppos=0xffff88001e26be40, count=, written=0x0) at mm/filemap.c:2440 #3 generic_file_buffered_write (iocb=, iov=, nr_segs=, p\ os=0x108000, ppos=0xffff88001e26be40, count=, written=0x0) at mm/filemap.c:2482 #4 0xffffffff810db5d1 in __generic_file_aio_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=0x1, ppos=0\ xffff88001e26be40) at mm/filemap.c:2600 #5 0xffffffff810db853 in generic_file_aio_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=, pos=) at mm/filemap.c:2632 #6 0xffffffff811a71aa in ext4_file_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=0x1, pos=0x108000) a\ t fs/ext4/file.c:136 #7 0xffffffff811375aa in do_sync_write (filp=0xffff88003f606a80, buf=, len=, \ ppos=0xffff88001e26bf48) at fs/read_write.c:406 #8 0xffffffff81137e56 in vfs_write (file=0xffff88003f606a80, buf=0x1ec2960
, count=0x4\ 000, pos=0xffff88001e26bf48) at fs/read_write.c:435 #9 0xffffffff8113816c in sys_write (fd=, buf=0x1ec2960
, count=0x\ 4000) at fs/read_write.c:487 #10 #11 0x00007f120077a390 in __brk_reservation_fn_dmi_alloc__ () #12 0x0000000000000000 in ?? () gdb> print offset $22 = 0xffffffffffffffff gdb> print idx $23 = 0xffffffff gdb> print inode->i_blkbits $24 = 0xc gdb> up #1 ext4_da_write_end (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x108000, len=0x1000, copied=0x0, page=0\ xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2512 2512 if (ext4_da_should_update_i_disksize(page, end)) { gdb> print start $25 = 0x0 gdb> print end $26 = 0xffffffffffffffff gdb> print pos $27 = 0x108000 gdb> print new_i_size $28 = 0x108000 gdb> print ((struct ext4_inode_info *)((char *)inode-((int)(&((struct ext4_inode_info *)0)->vfs_inode))))->i_disksize $29 = 0xd9000 gdb> down 2467 for (i = 0; i < idx; i++) gdb> print i $30 = 0xd44acbee This is 100% reproducible with some autonuma development code tuned in a very aggressive manner (not normal way even for knumad) which does "exotic" changes to the ptes. It wouldn't normally trigger but I don't see why it can't happen normally if the page is added to swap cache in between the two faults leading to "copied" being zero (which then hangs in ext4). So it should be fixed. Especially possible with lumpy reclaim (albeit disabled if compaction is enabled) as that would ignore the young bits in the ptes. Signed-off-by: Andrea Arcangeli Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d2c86633811f..b5edc6e4bab9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2508,7 +2508,7 @@ static int ext4_da_write_end(struct file *file, */ new_i_size = pos + copied; - if (new_i_size > EXT4_I(inode)->i_disksize) { + if (copied && new_i_size > EXT4_I(inode)->i_disksize) { if (ext4_da_should_update_i_disksize(page, end)) { down_write(&EXT4_I(inode)->i_data_sem); if (new_i_size > EXT4_I(inode)->i_disksize) { -- cgit From 13a79a4741d37fda2fbafb953f0f301dc007928f Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Tue, 13 Dec 2011 21:51:55 -0500 Subject: ext4: avoid potential hang in mpage_submit_io() when blocksize < pagesize If there is an unwritten but clean buffer in a page and there is a dirty buffer after the buffer, then mpage_submit_io does not write the dirty buffer out. As a result, da_writepages loops forever. This patch fixes the problem by checking dirty flag. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b5edc6e4bab9..cf20e1fe7782 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1339,8 +1339,11 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, clear_buffer_unwritten(bh); } - /* skip page if block allocation undone */ - if (buffer_delay(bh) || buffer_unwritten(bh)) + /* + * skip page if block allocation undone and + * block is dirty + */ + if (ext4_bh_delay_or_unwritten(NULL, bh)) skip_page = 1; bh = bh->b_this_page; block_start += bh->b_size; -- cgit From 093e6e3666f47d29763a235b404c84ee47ba8bb0 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Tue, 13 Dec 2011 22:05:05 -0500 Subject: ext4: correctly handle pages w/o buffers in ext4_discard_partial_buffers() If a page has been read into memory and never been written, it has no buffers, but we should handle the page in truncate or punch hole. VFS code of writing operations has handled holes correctly, so this patch removes the code handling holes in writing operations. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/inode.c | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cf20e1fe7782..92655fd89657 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2390,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, pgoff_t index; struct inode *inode = mapping->host; handle_t *handle; - loff_t page_len; index = pos >> PAGE_CACHE_SHIFT; @@ -2437,13 +2436,6 @@ retry: */ if (pos + len > inode->i_size) ext4_truncate_failed_write(inode); - } else { - page_len = pos & (PAGE_CACHE_SIZE - 1); - if (page_len > 0) { - ret = ext4_discard_partial_page_buffers_no_lock(handle, - inode, page, pos - page_len, page_len, - EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); - } } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) @@ -2486,7 +2478,6 @@ static int ext4_da_write_end(struct file *file, loff_t new_i_size; unsigned long start, end; int write_mode = (int)(unsigned long)fsdata; - loff_t page_len; if (write_mode == FALL_BACK_TO_NONDELALLOC) { if (ext4_should_order_data(inode)) { @@ -2535,16 +2526,6 @@ static int ext4_da_write_end(struct file *file, } ret2 = generic_write_end(file, mapping, pos, len, copied, page, fsdata); - - page_len = PAGE_CACHE_SIZE - - ((pos + copied - 1) & (PAGE_CACHE_SIZE - 1)); - - if (page_len > 0) { - ret = ext4_discard_partial_page_buffers_no_lock(handle, - inode, page, pos + copied - 1, page_len, - EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); - } - copied = ret2; if (ret2 < 0) ret = ret2; @@ -3206,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); - if (!page_has_buffers(page)) { - /* - * If the range to be discarded covers a partial block - * we need to get the page buffers. This is because - * partial blocks cannot be released and the page needs - * to be updated with the contents of the block before - * we write the zeros on top of it. - */ - if ((from & (blocksize - 1)) || - ((from + length) & (blocksize - 1))) { - create_empty_buffers(page, blocksize, 0); - } else { - /* - * If there are no partial blocks, - * there is nothing to update, - * so we can return now - */ - return 0; - } - } + if (!page_has_buffers(page)) + create_empty_buffers(page, blocksize, 0); /* Find the buffer that contains "offset" */ bh = page_buffers(page); -- cgit From 5b5ffa49d4bbb8ca4c41c094261660264f16bd20 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Tue, 13 Dec 2011 22:13:42 -0500 Subject: ext4: remove a wrong BUG_ON in ext4_ext_convert_to_initialized If a file is fallocated on a hole, map->m_lblk + map->m_len may be greater than ee_block + ee_len. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/extents.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 61cdb97f338c..607b1557d292 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2955,7 +2955,6 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, /* Pre-conditions */ BUG_ON(!ext4_ext_is_uninitialized(ex)); BUG_ON(!in_range(map->m_lblk, ee_block, ee_len)); - BUG_ON(map->m_lblk + map->m_len > ee_block + ee_len); /* * Attempt to transfer newly initialized blocks from the currently -- cgit From 5a0dc7365c240795bf190766eba7a27600be3b3e Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Tue, 13 Dec 2011 22:29:12 -0500 Subject: ext4: handle EOF correctly in ext4_bio_write_page() We need to zero out part of a page which beyond EOF before setting uptodate, otherwise, mapread or write will see non-zero data beyond EOF. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Cc: stable@kernel.org --- fs/ext4/page-io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 7ce1d0b19c94..7e106c810c62 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -385,6 +385,18 @@ int ext4_bio_write_page(struct ext4_io_submit *io, block_end = block_start + blocksize; if (block_start >= len) { + /* + * Comments copied from block_write_full_page_endio: + * + * The page straddles i_size. It must be zeroed out on + * each and every writepage invocation because it may + * be mmapped. "A file is mapped in multiples of the + * page size. For a file that is not a multiple of + * the page size, the remaining memory is zeroed when + * mapped, and writes to that region are not written + * out to the file." + */ + zero_user_segment(page, block_start, block_end); clear_buffer_dirty(bh); set_buffer_uptodate(bh); continue; -- cgit From 759c361eb95964d0d786f8962224dd0d9e780e6e Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Tue, 13 Dec 2011 02:47:29 +0100 Subject: fs/ncpfs: fix error paths and goto statements in ncp_fill_super() The label 'out_bdi' should be followed by bdi_destroy() instead of fput() which should be after the 'out_fput' label. If bdi_setup_and_register() fails then jump to the 'out_fput' label instead of the 'out_bdi' one. If fget(data.info_fd) fails then jump to the previously fixed 'out_bdi' label to call bdi_destroy() otherwise the bdi object will not be destroyed. Compile tested only. Signed-off-by: Djalal Harouni Signed-off-by: Al Viro --- fs/ncpfs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 5b5fa33b6b9d..cbd1a61c110a 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -548,7 +548,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); if (error) - goto out_bdi; + goto out_fput; server->ncp_filp = ncp_filp; server->ncp_sock = sock; @@ -559,7 +559,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) error = -EBADF; server->info_filp = fget(data.info_fd); if (!server->info_filp) - goto out_fput; + goto out_bdi; error = -ENOTSOCK; sock_inode = server->info_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) @@ -746,9 +746,9 @@ out_nls: out_fput2: if (server->info_filp) fput(server->info_filp); -out_fput: - bdi_destroy(&server->bdi); out_bdi: + bdi_destroy(&server->bdi); +out_fput: /* 23/12/1998 Marcin Dalecki : * * The previously used put_filp(ncp_filp); was bogus, since -- cgit From ccc080c77cd47fde5eb097058fae930b956096eb Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 13 Dec 2011 10:32:42 +0530 Subject: usb: musb: fix reset issue with full speed device TXMAXP register is not getting programmed correctly for a full speed device as can_bulk_split() have been removed by "0662481: usb: musb: disable double buffering when it's broken" patch. Adding back the case for can_bulk_split() to fix the reset message seen with a full speed stick. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 60ddba8066ea..79cb0af779fa 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -774,6 +774,10 @@ static void musb_ep_program(struct musb *musb, u8 epnum, if (musb->double_buffer_not_ok) musb_writew(epio, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); + else if (can_bulk_split(musb, qh->type)) + musb_writew(epio, MUSB_TXMAXP, packet_sz + | ((hw_ep->max_packet_sz_tx / + packet_sz) - 1) << 11); else musb_writew(epio, MUSB_TXMAXP, qh->maxpacket | -- cgit From 44b7f4b98d8877e2a4427f2a2f2e42ae8227a58f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 13 Dec 2011 20:40:45 +0100 Subject: perf events: Fix ring_buffer_wakeup() brown paperbag bug Commit 10c6db11 ("perf: Fix loss of notification with multi-event") seems to unconditionally dereference event->rb in the wakeup handler, this is wrong, there might not be a buffer attached. Signed-off-by: Will Deacon Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111213152651.GP20297@mudshark.cambridge.arm.com [ minor edits ] Signed-off-by: Ingo Molnar --- kernel/events/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index d3b9df5962c2..58690af323e4 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3558,9 +3558,13 @@ static void ring_buffer_wakeup(struct perf_event *event) rcu_read_lock(); rb = rcu_dereference(event->rb); - list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { + if (!rb) + goto unlock; + + list_for_each_entry_rcu(event, &rb->event_list, rb_entry) wake_up_all(&event->waitq); - } + +unlock: rcu_read_unlock(); } -- cgit From 7e1e7ead88dff75b11b86ee0d5232c4591be1326 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 11 Nov 2011 20:52:01 +0100 Subject: [SCSI] fcoe: Fix preempt count leak in fcoe_filter_frames() The error exit path leaks preempt count. Add the missing put_cpu(). Signed-off-by: Thomas Gleixner Reviewed-by: Yi Zou Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cefbe44bb84a..f3f440c955f3 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1624,6 +1624,7 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, stats->InvalidCRCCount++; if (stats->InvalidCRCCount < 5) printk(KERN_WARNING "fcoe: dropping frame with CRC error\n"); + put_cpu(); return -EINVAL; } -- cgit From 44f747fff6e9f027a4866c1a6864e26ae7c510c8 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Fri, 18 Nov 2011 20:00:40 +0100 Subject: [SCSI] zfcp: return early from slave_destroy if slave_alloc returned early zfcp_scsi_slave_destroy erroneously always tried to finish its task even if the corresponding previous zfcp_scsi_slave_alloc returned early. This can lead to kernel page faults on accessing uninitialized fields of struct zfcp_scsi_dev in zfcp_erp_lun_shutdown_wait. Take the port field of the struct to determine if slave_alloc returned early. This zfcp bug is exposed by 4e6c82b (in turn fixing f7c9c6b to be compatible with 21208ae) which can call slave_destroy for a corresponding previous slave_alloc that did not finish. This patch is based on James Bottomley's fix suggestion in http://www.spinics.net/lists/linux-scsi/msg55449.html. Signed-off-by: Steffen Maier Cc: #2.6.38+ Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 11f07f888223..b79576b64f45 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -55,6 +55,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdev) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + /* if previous slave_alloc returned early, there is nothing to do */ + if (!zfcp_sdev->port) + return; + zfcp_erp_lun_shutdown_wait(sdev, "scssd_1"); put_device(&zfcp_sdev->port->dev); } -- cgit From 13483730a13bef372894aefcf73760f5c6c297be Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 1 Dec 2011 21:38:41 -0600 Subject: [SCSI] qla4xxx: fix flash/ddb support With open-iscsi support, target entries persisted in the FLASH were not login. Added support in the qla4xxx driver to do the login on probe time to the target entries saved in the FLASH by user. With this changes upgrade to the new kernel with open-iscsi support in qla4xxx will ensure users original target entries login on driver load Signed-off-by: Manish Rangankar Signed-off-by: Ravi Anand Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 55 +- drivers/scsi/qla4xxx/ql4_fw.h | 8 + drivers/scsi/qla4xxx/ql4_glbl.h | 16 +- drivers/scsi/qla4xxx/ql4_init.c | 239 ++++++-- drivers/scsi/qla4xxx/ql4_mbx.c | 11 + drivers/scsi/qla4xxx/ql4_os.c | 1081 ++++++++++++++++++++++++++++++++++-- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 7 files changed, 1315 insertions(+), 97 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index ace637bf254e..fd5edc6e166d 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -147,7 +147,7 @@ #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ -#define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ +#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */ /* recovery timeout */ #define LSDW(x) ((u32)((u64)(x))) @@ -173,6 +173,8 @@ #define ISNS_DEREG_TOV 5 #define HBA_ONLINE_TOV 30 #define DISABLE_ACB_TOV 30 +#define IP_CONFIG_TOV 30 +#define LOGIN_TOV 12 #define MAX_RESET_HA_RETRIES 2 @@ -240,6 +242,45 @@ struct ddb_entry { uint16_t fw_ddb_index; /* DDB firmware index */ uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ + uint16_t ddb_type; +#define FLASH_DDB 0x01 + + struct dev_db_entry fw_ddb_entry; + int (*unblock_sess)(struct iscsi_cls_session *cls_session); + int (*ddb_change)(struct scsi_qla_host *ha, uint32_t fw_ddb_index, + struct ddb_entry *ddb_entry, uint32_t state); + + /* Driver Re-login */ + unsigned long flags; /* DDB Flags */ + uint16_t default_relogin_timeout; /* Max time to wait for + * relogin to complete */ + atomic_t retry_relogin_timer; /* Min Time between relogins + * (4000 only) */ + atomic_t relogin_timer; /* Max Time to wait for + * relogin to complete */ + atomic_t relogin_retry_count; /* Num of times relogin has been + * retried */ + uint32_t default_time2wait; /* Default Min time between + * relogins (+aens) */ + +}; + +struct qla_ddb_index { + struct list_head list; + uint16_t fw_ddb_idx; + struct dev_db_entry fw_ddb; +}; + +#define DDB_IPADDR_LEN 64 + +struct ql4_tuple_ddb { + int port; + int tpgt; + char ip_addr[DDB_IPADDR_LEN]; + char iscsi_name[ISCSI_NAME_SIZE]; + uint16_t options; +#define DDB_OPT_IPV6 0x0e0e +#define DDB_OPT_IPV4 0x0f0f }; /* @@ -411,7 +452,7 @@ struct scsi_qla_host { #define AF_FW_RECOVERY 19 /* 0x00080000 */ #define AF_EEH_BUSY 20 /* 0x00100000 */ #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ - +#define AF_BUILD_DDB_LIST 22 /* 0x00400000 */ unsigned long dpc_flags; #define DPC_RESET_HA 1 /* 0x00000002 */ @@ -604,6 +645,7 @@ struct scsi_qla_host { uint16_t bootload_minor; uint16_t bootload_patch; uint16_t bootload_build; + uint16_t def_timeout; /* Default login timeout */ uint32_t flash_state; #define QLFLASH_WAITING 0 @@ -623,6 +665,11 @@ struct scsi_qla_host { uint16_t iscsi_pci_func_cnt; uint8_t model_name[16]; struct completion disable_acb_comp; + struct dma_pool *fw_ddb_dma_pool; +#define DDB_DMA_BLOCK_SIZE 512 + uint16_t pri_ddb_idx; + uint16_t sec_ddb_idx; + int is_reset; }; struct ql4_task_data { @@ -835,6 +882,10 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha) /*---------------------------------------------------------------------------*/ /* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */ + +#define INIT_ADAPTER 0 +#define RESET_ADAPTER 1 + #define PRESERVE_DDB_LIST 0 #define REBUILD_DDB_LIST 1 diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index cbd5a20dbbd1..4ac07f882521 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -12,6 +12,7 @@ #define MAX_PRST_DEV_DB_ENTRIES 64 #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES #define MAX_DEV_DB_ENTRIES 512 +#define MAX_DEV_DB_ENTRIES_40XX 256 /************************************************************************* * @@ -604,6 +605,13 @@ struct addr_ctrl_blk { uint8_t res14[140]; /* 274-2FF */ }; +#define IP_ADDR_COUNT 4 /* Total 4 IP address supported in one interface + * One IPv4, one IPv6 link local and 2 IPv6 + */ + +#define IP_STATE_MASK 0x0F000000 +#define IP_STATE_SHIFT 24 + struct init_fw_ctrl_blk { struct addr_ctrl_blk pri; /* struct addr_ctrl_blk sec;*/ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 160db9d5ea21..d0dd4b330206 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -13,7 +13,7 @@ struct iscsi_cls_conn; int qla4xxx_hw_reset(struct scsi_qla_host *ha); int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb); -int qla4xxx_initialize_adapter(struct scsi_qla_host *ha); +int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset); int qla4xxx_soft_reset(struct scsi_qla_host *ha); irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); @@ -153,10 +153,13 @@ int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index, uint32_t *mbx_sts); int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index); int qla4xxx_send_passthru0(struct iscsi_task *task); +void qla4xxx_free_ddb_index(struct scsi_qla_host *ha); int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, uint16_t stats_size, dma_addr_t stats_dma); void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); +void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry); int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, struct dev_db_entry *fw_ddb_entry, dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index); @@ -169,11 +172,22 @@ int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, uint32_t region, uint32_t field0, uint32_t field1); +int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index); +void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session); +int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session); +int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session); +int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, + struct ddb_entry *ddb_entry, uint32_t state); +int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, + struct ddb_entry *ddb_entry, uint32_t state); +void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); /* BSG Functions */ int qla4xxx_bsg_request(struct bsg_job *bsg_job); int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); +void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry); + extern int ql4xextended_error_logging; extern int ql4xdontresethba; extern int ql4xenablemsix; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 3075fbaef553..0497873a1dd2 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -773,14 +773,14 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha) * be freed so that when login happens from user space there are free DDB * indices available. **/ -static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) +void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) { int max_ddbs; int ret; uint32_t idx = 0, next_idx = 0; uint32_t state = 0, conn_err = 0; - max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : + max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : MAX_DEV_DB_ENTRIES; for (idx = 0; idx < max_ddbs; idx = next_idx) { @@ -804,7 +804,6 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) } } - /** * qla4xxx_initialize_adapter - initiailizes hba * @ha: Pointer to host adapter structure. @@ -812,7 +811,7 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) * This routine parforms all of the steps necessary to initialize the adapter. * **/ -int qla4xxx_initialize_adapter(struct scsi_qla_host *ha) +int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset) { int status = QLA_ERROR; @@ -840,7 +839,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha) if (status == QLA_ERROR) goto exit_init_hba; - qla4xxx_free_ddb_index(ha); + if (is_reset == RESET_ADAPTER) + qla4xxx_build_ddb_list(ha, is_reset); set_bit(AF_ONLINE, &ha->flags); exit_init_hba: @@ -855,38 +855,12 @@ exit_init_hba: return status; } -/** - * qla4xxx_process_ddb_changed - process ddb state change - * @ha - Pointer to host adapter structure. - * @fw_ddb_index - Firmware's device database index - * @state - Device state - * - * This routine processes a Decive Database Changed AEN Event. - **/ -int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, - uint32_t state, uint32_t conn_err) +int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, + struct ddb_entry *ddb_entry, uint32_t state) { - struct ddb_entry * ddb_entry; uint32_t old_fw_ddb_device_state; int status = QLA_ERROR; - /* check for out of range index */ - if (fw_ddb_index >= MAX_DDB_ENTRIES) - goto exit_ddb_event; - - /* Get the corresponging ddb entry */ - ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); - /* Device does not currently exist in our database. */ - if (ddb_entry == NULL) { - ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n", - __func__, fw_ddb_index); - - if (state == DDB_DS_NO_CONNECTION_ACTIVE) - clear_bit(fw_ddb_index, ha->ddb_idx_map); - - goto exit_ddb_event; - } - old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB - old state = 0x%x, new state = 0x%x for " @@ -900,9 +874,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, switch (state) { case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY: - iscsi_conn_start(ddb_entry->conn); - iscsi_conn_login_event(ddb_entry->conn, - ISCSI_CONN_STATE_LOGGED_IN); + ddb_entry->unblock_sess(ddb_entry->sess); qla4xxx_update_session_conn_param(ha, ddb_entry); status = QLA_SUCCESS; break; @@ -936,9 +908,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, switch (state) { case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY: - iscsi_conn_start(ddb_entry->conn); - iscsi_conn_login_event(ddb_entry->conn, - ISCSI_CONN_STATE_LOGGED_IN); + ddb_entry->unblock_sess(ddb_entry->sess); qla4xxx_update_session_conn_param(ha, ddb_entry); status = QLA_SUCCESS; break; @@ -954,7 +924,198 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, __func__)); break; } + return status; +} + +void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry) +{ + /* + * This triggers a relogin. After the relogin_timer + * expires, the relogin gets scheduled. We must wait a + * minimum amount of time since receiving an 0x8014 AEN + * with failed device_state or a logout response before + * we can issue another relogin. + * + * Firmware pads this timeout: (time2wait +1). + * Driver retry to login should be longer than F/W. + * Otherwise F/W will fail + * set_ddb() mbx cmd with 0x4005 since it still + * counting down its time2wait. + */ + atomic_set(&ddb_entry->relogin_timer, 0); + atomic_set(&ddb_entry->retry_relogin_timer, + ddb_entry->default_time2wait + 4); + +} + +int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, + struct ddb_entry *ddb_entry, uint32_t state) +{ + uint32_t old_fw_ddb_device_state; + int status = QLA_ERROR; + + old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: DDB - old state = 0x%x, new state = 0x%x for " + "index [%d]\n", __func__, + ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); + + ddb_entry->fw_ddb_device_state = state; + + switch (old_fw_ddb_device_state) { + case DDB_DS_LOGIN_IN_PROCESS: + case DDB_DS_NO_CONNECTION_ACTIVE: + switch (state) { + case DDB_DS_SESSION_ACTIVE: + ddb_entry->unblock_sess(ddb_entry->sess); + qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry); + status = QLA_SUCCESS; + break; + case DDB_DS_SESSION_FAILED: + iscsi_block_session(ddb_entry->sess); + if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) + qla4xxx_arm_relogin_timer(ddb_entry); + status = QLA_SUCCESS; + break; + } + break; + case DDB_DS_SESSION_ACTIVE: + switch (state) { + case DDB_DS_SESSION_FAILED: + iscsi_block_session(ddb_entry->sess); + if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) + qla4xxx_arm_relogin_timer(ddb_entry); + status = QLA_SUCCESS; + break; + } + break; + case DDB_DS_SESSION_FAILED: + switch (state) { + case DDB_DS_SESSION_ACTIVE: + ddb_entry->unblock_sess(ddb_entry->sess); + qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry); + status = QLA_SUCCESS; + break; + case DDB_DS_SESSION_FAILED: + if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) + qla4xxx_arm_relogin_timer(ddb_entry); + status = QLA_SUCCESS; + break; + } + break; + default: + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n", + __func__)); + break; + } + return status; +} + +/** + * qla4xxx_process_ddb_changed - process ddb state change + * @ha - Pointer to host adapter structure. + * @fw_ddb_index - Firmware's device database index + * @state - Device state + * + * This routine processes a Decive Database Changed AEN Event. + **/ +int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, + uint32_t fw_ddb_index, + uint32_t state, uint32_t conn_err) +{ + struct ddb_entry *ddb_entry; + int status = QLA_ERROR; + + /* check for out of range index */ + if (fw_ddb_index >= MAX_DDB_ENTRIES) + goto exit_ddb_event; + + /* Get the corresponging ddb entry */ + ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); + /* Device does not currently exist in our database. */ + if (ddb_entry == NULL) { + ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n", + __func__, fw_ddb_index); + + if (state == DDB_DS_NO_CONNECTION_ACTIVE) + clear_bit(fw_ddb_index, ha->ddb_idx_map); + + goto exit_ddb_event; + } + + ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state); exit_ddb_event: return status; } + +/** + * qla4xxx_login_flash_ddb - Login to target (DDB) + * @cls_session: Pointer to the session to login + * + * This routine logins to the target. + * Issues setddb and conn open mbx + **/ +void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + struct dev_db_entry *fw_ddb_entry = NULL; + dma_addr_t fw_ddb_dma; + uint32_t mbx_sts = 0; + int ret; + + sess = cls_session->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + + if (!test_bit(AF_LINK_UP, &ha->flags)) + return; + + if (ddb_entry->ddb_type != FLASH_DDB) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "Skipping login to non FLASH DB")); + goto exit_login; + } + + fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, + &fw_ddb_dma); + if (fw_ddb_entry == NULL) { + DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); + goto exit_login; + } + + if (ddb_entry->fw_ddb_index == INVALID_ENTRY) { + ret = qla4xxx_get_ddb_index(ha, &ddb_entry->fw_ddb_index); + if (ret == QLA_ERROR) + goto exit_login; + + ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; + ha->tot_ddbs++; + } + + memcpy(fw_ddb_entry, &ddb_entry->fw_ddb_entry, + sizeof(struct dev_db_entry)); + ddb_entry->sess->target_id = ddb_entry->fw_ddb_index; + + ret = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, + fw_ddb_dma, &mbx_sts); + if (ret == QLA_ERROR) { + DEBUG2(ql4_printk(KERN_ERR, ha, "Set DDB failed\n")); + goto exit_login; + } + + ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS; + ret = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index); + if (ret == QLA_ERROR) { + ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__, + sess->targetname); + goto exit_login; + } + +exit_login: + if (fw_ddb_entry) + dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); +} + diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 4c2b84870392..c2593782fbbe 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -41,6 +41,16 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, return status; } + if (is_qla40XX(ha)) { + if (test_bit(AF_HA_REMOVAL, &ha->flags)) { + DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " + "prematurely completing mbx cmd as " + "adapter removal detected\n", + ha->host_no, __func__)); + return status; + } + } + if (is_qla8022(ha)) { if (test_bit(AF_FW_RECOVERY, &ha->flags)) { DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " @@ -413,6 +423,7 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, memcpy(ha->name_string, init_fw_cb->iscsi_name, min(sizeof(ha->name_string), sizeof(init_fw_cb->iscsi_name))); + ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout); /*memcpy(ha->alias, init_fw_cb->Alias, min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 30f31b127f33..95910c9b4776 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,13 @@ static struct kmem_cache *srb_cachep; /* * Module parameter information and variables */ +int ql4xdisablesysfsboot = 1; +module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ql4xdisablesysfsboot, + "Set to disable exporting boot targets to sysfs\n" + " 0 - Export boot targets\n" + " 1 - Do not export boot targets (Default)"); + int ql4xdontresethba = 0; module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xdontresethba, @@ -63,7 +71,7 @@ static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; module_param(ql4xsess_recovery_tmo, int, S_IRUGO); MODULE_PARM_DESC(ql4xsess_recovery_tmo, "Target Session Recovery Timeout.\n" - " Default: 30 sec."); + " Default: 120 sec."); static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); /* @@ -415,7 +423,7 @@ static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) qla_ep = ep->dd_data; ha = to_qla_host(qla_ep->host); - if (adapter_up(ha)) + if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags)) ret = 1; return ret; @@ -975,6 +983,150 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn, } +int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index) +{ + uint32_t mbx_sts = 0; + uint16_t tmp_ddb_index; + int ret; + +get_ddb_index: + tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES); + + if (tmp_ddb_index >= MAX_DDB_ENTRIES) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "Free DDB index not available\n")); + ret = QLA_ERROR; + goto exit_get_ddb_index; + } + + if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map)) + goto get_ddb_index; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "Found a free DDB index at %d\n", tmp_ddb_index)); + ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts); + if (ret == QLA_ERROR) { + if (mbx_sts == MBOX_STS_COMMAND_ERROR) { + ql4_printk(KERN_INFO, ha, + "DDB index = %d not available trying next\n", + tmp_ddb_index); + goto get_ddb_index; + } + DEBUG2(ql4_printk(KERN_INFO, ha, + "Free FW DDB not available\n")); + } + + *ddb_index = tmp_ddb_index; + +exit_get_ddb_index: + return ret; +} + +static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry, + char *existing_ipaddr, + char *user_ipaddr) +{ + uint8_t dst_ipaddr[IPv6_ADDR_LEN]; + char formatted_ipaddr[DDB_IPADDR_LEN]; + int status = QLA_SUCCESS, ret = 0; + + if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) { + ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, + '\0', NULL); + if (ret == 0) { + status = QLA_ERROR; + goto out_match; + } + ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr); + } else { + ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, + '\0', NULL); + if (ret == 0) { + status = QLA_ERROR; + goto out_match; + } + ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr); + } + + if (strcmp(existing_ipaddr, formatted_ipaddr)) + status = QLA_ERROR; + +out_match: + return status; +} + +static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha, + struct iscsi_cls_conn *cls_conn) +{ + int idx = 0, max_ddbs, rval; + struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn); + struct iscsi_session *sess, *existing_sess; + struct iscsi_conn *conn, *existing_conn; + struct ddb_entry *ddb_entry; + + sess = cls_sess->dd_data; + conn = cls_conn->dd_data; + + if (sess->targetname == NULL || + conn->persistent_address == NULL || + conn->persistent_port == 0) + return QLA_ERROR; + + max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : + MAX_DEV_DB_ENTRIES; + + for (idx = 0; idx < max_ddbs; idx++) { + ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); + if (ddb_entry == NULL) + continue; + + if (ddb_entry->ddb_type != FLASH_DDB) + continue; + + existing_sess = ddb_entry->sess->dd_data; + existing_conn = ddb_entry->conn->dd_data; + + if (existing_sess->targetname == NULL || + existing_conn->persistent_address == NULL || + existing_conn->persistent_port == 0) + continue; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "IQN = %s User IQN = %s\n", + existing_sess->targetname, + sess->targetname)); + + DEBUG2(ql4_printk(KERN_INFO, ha, + "IP = %s User IP = %s\n", + existing_conn->persistent_address, + conn->persistent_address)); + + DEBUG2(ql4_printk(KERN_INFO, ha, + "Port = %d User Port = %d\n", + existing_conn->persistent_port, + conn->persistent_port)); + + if (strcmp(existing_sess->targetname, sess->targetname)) + continue; + rval = qla4xxx_match_ipaddress(ha, ddb_entry, + existing_conn->persistent_address, + conn->persistent_address); + if (rval == QLA_ERROR) + continue; + if (existing_conn->persistent_port != conn->persistent_port) + continue; + break; + } + + if (idx == max_ddbs) + return QLA_ERROR; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "Match found in fwdb sessions\n")); + return QLA_SUCCESS; +} + static struct iscsi_cls_session * qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, uint16_t qdepth, @@ -984,8 +1136,7 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, struct scsi_qla_host *ha; struct qla_endpoint *qla_ep; struct ddb_entry *ddb_entry; - uint32_t ddb_index; - uint32_t mbx_sts = 0; + uint16_t ddb_index; struct iscsi_session *sess; struct sockaddr *dst_addr; int ret; @@ -1000,32 +1151,9 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, dst_addr = (struct sockaddr *)&qla_ep->dst_addr; ha = to_qla_host(qla_ep->host); -get_ddb_index: - ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES); - - if (ddb_index >= MAX_DDB_ENTRIES) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "Free DDB index not available\n")); + ret = qla4xxx_get_ddb_index(ha, &ddb_index); + if (ret == QLA_ERROR) return NULL; - } - - if (test_and_set_bit(ddb_index, ha->ddb_idx_map)) - goto get_ddb_index; - - DEBUG2(ql4_printk(KERN_INFO, ha, - "Found a free DDB index at %d\n", ddb_index)); - ret = qla4xxx_req_ddb_entry(ha, ddb_index, &mbx_sts); - if (ret == QLA_ERROR) { - if (mbx_sts == MBOX_STS_COMMAND_ERROR) { - ql4_printk(KERN_INFO, ha, - "DDB index = %d not available trying next\n", - ddb_index); - goto get_ddb_index; - } - DEBUG2(ql4_printk(KERN_INFO, ha, - "Free FW DDB not available\n")); - return NULL; - } cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host, cmds_max, sizeof(struct ddb_entry), @@ -1040,6 +1168,8 @@ get_ddb_index: ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; ddb_entry->ha = ha; ddb_entry->sess = cls_sess; + ddb_entry->unblock_sess = qla4xxx_unblock_ddb; + ddb_entry->ddb_change = qla4xxx_ddb_change; cls_sess->recovery_tmo = ql4xsess_recovery_tmo; ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; ha->tot_ddbs++; @@ -1109,7 +1239,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) struct iscsi_session *sess; struct ddb_entry *ddb_entry; struct scsi_qla_host *ha; - struct dev_db_entry *fw_ddb_entry; + struct dev_db_entry *fw_ddb_entry = NULL; dma_addr_t fw_ddb_entry_dma; uint32_t mbx_sts = 0; int ret = 0; @@ -1120,12 +1250,25 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) ddb_entry = sess->dd_data; ha = ddb_entry->ha; + /* Check if we have matching FW DDB, if yes then do not + * login to this target. This could cause target to logout previous + * connection + */ + ret = qla4xxx_match_fwdb_session(ha, cls_conn); + if (ret == QLA_SUCCESS) { + ql4_printk(KERN_INFO, ha, + "Session already exist in FW.\n"); + ret = -EEXIST; + goto exit_conn_start; + } + fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), &fw_ddb_entry_dma, GFP_KERNEL); if (!fw_ddb_entry) { ql4_printk(KERN_ERR, ha, "%s: Unable to allocate dma buffer\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto exit_conn_start; } ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts); @@ -1138,9 +1281,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) if (mbx_sts) if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { - iscsi_conn_start(ddb_entry->conn); - iscsi_conn_login_event(ddb_entry->conn, - ISCSI_CONN_STATE_LOGGED_IN); + ddb_entry->unblock_sess(ddb_entry->sess); goto exit_set_param; } @@ -1167,8 +1308,9 @@ exit_set_param: ret = 0; exit_conn_start: - dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), - fw_ddb_entry, fw_ddb_entry_dma); + if (fw_ddb_entry) + dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + fw_ddb_entry, fw_ddb_entry_dma); return ret; } @@ -1344,6 +1486,101 @@ static int qla4xxx_task_xmit(struct iscsi_task *task) return -ENOSYS; } +static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, + struct dev_db_entry *fw_ddb_entry, + struct iscsi_cls_session *cls_sess, + struct iscsi_cls_conn *cls_conn) +{ + int buflen = 0; + struct iscsi_session *sess; + struct iscsi_conn *conn; + char ip_addr[DDB_IPADDR_LEN]; + uint16_t options = 0; + + sess = cls_sess->dd_data; + conn = cls_conn->dd_data; + + conn->max_recv_dlength = BYTE_UNITS * + le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); + + conn->max_xmit_dlength = BYTE_UNITS * + le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); + + sess->initial_r2t_en = + (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options)); + + sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); + + sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options)); + + sess->first_burst = BYTE_UNITS * + le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); + + sess->max_burst = BYTE_UNITS * + le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); + + sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); + + sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); + + conn->persistent_port = le16_to_cpu(fw_ddb_entry->port); + + sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); + + options = le16_to_cpu(fw_ddb_entry->options); + if (options & DDB_OPT_IPV6_DEVICE) + sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr); + else + sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr); + + iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME, + (char *)fw_ddb_entry->iscsi_name, buflen); + iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, + (char *)ha->name_string, buflen); + iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS, + (char *)ip_addr, buflen); +} + +void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry) +{ + struct iscsi_cls_session *cls_sess; + struct iscsi_cls_conn *cls_conn; + uint32_t ddb_state; + dma_addr_t fw_ddb_entry_dma; + struct dev_db_entry *fw_ddb_entry; + + fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + &fw_ddb_entry_dma, GFP_KERNEL); + if (!fw_ddb_entry) { + ql4_printk(KERN_ERR, ha, + "%s: Unable to allocate dma buffer\n", __func__); + goto exit_session_conn_fwddb_param; + } + + if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, + fw_ddb_entry_dma, NULL, NULL, &ddb_state, + NULL, NULL, NULL) == QLA_ERROR) { + DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " + "get_ddb_entry for fw_ddb_index %d\n", + ha->host_no, __func__, + ddb_entry->fw_ddb_index)); + goto exit_session_conn_fwddb_param; + } + + cls_sess = ddb_entry->sess; + + cls_conn = ddb_entry->conn; + + /* Update params */ + qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); + +exit_session_conn_fwddb_param: + if (fw_ddb_entry) + dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + fw_ddb_entry, fw_ddb_entry_dma); +} + void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) { @@ -1360,7 +1597,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, if (!fw_ddb_entry) { ql4_printk(KERN_ERR, ha, "%s: Unable to allocate dma buffer\n", __func__); - return; + goto exit_session_conn_param; } if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, @@ -1370,7 +1607,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, "get_ddb_entry for fw_ddb_index %d\n", ha->host_no, __func__, ddb_entry->fw_ddb_index)); - return; + goto exit_session_conn_param; } cls_sess = ddb_entry->sess; @@ -1379,6 +1616,12 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, cls_conn = ddb_entry->conn; conn = cls_conn->dd_data; + /* Update timers after login */ + ddb_entry->default_relogin_timeout = + le16_to_cpu(fw_ddb_entry->def_timeout); + ddb_entry->default_time2wait = + le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); + /* Update params */ conn->max_recv_dlength = BYTE_UNITS * le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); @@ -1407,6 +1650,11 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, memcpy(sess->initiatorname, ha->name_string, min(sizeof(ha->name_string), sizeof(sess->initiatorname))); + +exit_session_conn_param: + if (fw_ddb_entry) + dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), + fw_ddb_entry, fw_ddb_entry_dma); } /* @@ -1607,6 +1855,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) vfree(ha->chap_list); ha->chap_list = NULL; + if (ha->fw_ddb_dma_pool) + dma_pool_destroy(ha->fw_ddb_dma_pool); + /* release io space registers */ if (is_qla8022(ha)) { if (ha->nx_pcibase) @@ -1689,6 +1940,16 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) goto mem_alloc_error_exit; } + ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev, + DDB_DMA_BLOCK_SIZE, 8, 0); + + if (ha->fw_ddb_dma_pool == NULL) { + ql4_printk(KERN_WARNING, ha, + "%s: fw_ddb_dma_pool allocation failed..\n", + __func__); + goto mem_alloc_error_exit; + } + return QLA_SUCCESS; mem_alloc_error_exit: @@ -1800,6 +2061,60 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) } } +void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) +{ + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + + sess = cls_sess->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + + if (!(ddb_entry->ddb_type == FLASH_DDB)) + return; + + if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) && + !iscsi_is_session_online(cls_sess)) { + if (atomic_read(&ddb_entry->retry_relogin_timer) != + INVALID_ENTRY) { + if (atomic_read(&ddb_entry->retry_relogin_timer) == + 0) { + atomic_set(&ddb_entry->retry_relogin_timer, + INVALID_ENTRY); + set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); + set_bit(DF_RELOGIN, &ddb_entry->flags); + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: index [%d] login device\n", + __func__, ddb_entry->fw_ddb_index)); + } else + atomic_dec(&ddb_entry->retry_relogin_timer); + } + } + + /* Wait for relogin to timeout */ + if (atomic_read(&ddb_entry->relogin_timer) && + (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { + /* + * If the relogin times out and the device is + * still NOT ONLINE then try and relogin again. + */ + if (!iscsi_is_session_online(cls_sess)) { + /* Reset retry relogin timer */ + atomic_inc(&ddb_entry->relogin_retry_count); + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: index[%d] relogin timed out-retrying" + " relogin (%d), retry (%d)\n", __func__, + ddb_entry->fw_ddb_index, + atomic_read(&ddb_entry->relogin_retry_count), + ddb_entry->default_time2wait + 4)); + set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); + atomic_set(&ddb_entry->retry_relogin_timer, + ddb_entry->default_time2wait + 4); + } + } +} + /** * qla4xxx_timer - checks every second for work to do. * @ha: Pointer to host adapter structure. @@ -1809,6 +2124,8 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) int start_dpc = 0; uint16_t w; + iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb); + /* If we are in the middle of AER/EEH processing * skip any processing and reschedule the timer */ @@ -2078,7 +2395,12 @@ static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session) sess = cls_session->dd_data; ddb_entry = sess->dd_data; ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED; - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); + + if (ddb_entry->ddb_type == FLASH_DDB) + iscsi_block_session(ddb_entry->sess); + else + iscsi_session_failure(cls_session->dd_data, + ISCSI_ERR_CONN_FAILED); } /** @@ -2163,7 +2485,7 @@ recover_ha_init_adapter: /* NOTE: AF_ONLINE flag set upon successful completion of * qla4xxx_initialize_adapter */ - status = qla4xxx_initialize_adapter(ha); + status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); } /* Retry failed adapter initialization, if necessary @@ -2245,17 +2567,108 @@ static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session) iscsi_unblock_session(ddb_entry->sess); } else { /* Trigger relogin */ - iscsi_session_failure(cls_session->dd_data, - ISCSI_ERR_CONN_FAILED); + if (ddb_entry->ddb_type == FLASH_DDB) { + if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) + qla4xxx_arm_relogin_timer(ddb_entry); + } else + iscsi_session_failure(cls_session->dd_data, + ISCSI_ERR_CONN_FAILED); } } } +int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + + sess = cls_session->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" + " unblock session\n", ha->host_no, __func__, + ddb_entry->fw_ddb_index); + + iscsi_unblock_session(ddb_entry->sess); + + /* Start scan target */ + if (test_bit(AF_ONLINE, &ha->flags)) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" + " start scan\n", ha->host_no, __func__, + ddb_entry->fw_ddb_index); + scsi_queue_work(ha->host, &ddb_entry->sess->scan_work); + } + return QLA_SUCCESS; +} + +int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + + sess = cls_session->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" + " unblock user space session\n", ha->host_no, __func__, + ddb_entry->fw_ddb_index); + iscsi_conn_start(ddb_entry->conn); + iscsi_conn_login_event(ddb_entry->conn, + ISCSI_CONN_STATE_LOGGED_IN); + + return QLA_SUCCESS; +} + static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) { iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices); } +static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) +{ + uint16_t relogin_timer; + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + + sess = cls_sess->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + + relogin_timer = max(ddb_entry->default_relogin_timeout, + (uint16_t)RELOGIN_TOV); + atomic_set(&ddb_entry->relogin_timer, relogin_timer); + + DEBUG2(ql4_printk(KERN_INFO, ha, + "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no, + ddb_entry->fw_ddb_index, relogin_timer)); + + qla4xxx_login_flash_ddb(cls_sess); +} + +static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess) +{ + struct iscsi_session *sess; + struct ddb_entry *ddb_entry; + struct scsi_qla_host *ha; + + sess = cls_sess->dd_data; + ddb_entry = sess->dd_data; + ha = ddb_entry->ha; + + if (!(ddb_entry->ddb_type == FLASH_DDB)) + return; + + if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) && + !iscsi_is_session_online(cls_sess)) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "relogin issued\n")); + qla4xxx_relogin_flash_ddb(cls_sess); + } +} + void qla4xxx_wake_dpc(struct scsi_qla_host *ha) { if (ha->dpc_thread) @@ -2356,6 +2769,12 @@ dpc_post_reset_ha: if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) qla4xxx_get_dhcp_ip_address(ha); + /* ---- relogin device? --- */ + if (adapter_up(ha) && + test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { + iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin); + } + /* ---- link change? --- */ if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) { if (!test_bit(AF_LINK_UP, &ha->flags)) { @@ -2368,8 +2787,12 @@ dpc_post_reset_ha: * fatal error recovery. Therefore, the driver must * manually relogin to devices when recovering from * connection failures, logouts, expired KATO, etc. */ - - qla4xxx_relogin_all_devices(ha); + if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) { + qla4xxx_build_ddb_list(ha, ha->is_reset); + iscsi_host_for_each_session(ha->host, + qla4xxx_login_flash_ddb); + } else + qla4xxx_relogin_all_devices(ha); } } } @@ -2867,6 +3290,9 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[]) " target ID %d\n", __func__, ddb_index[0], ddb_index[1])); + ha->pri_ddb_idx = ddb_index[0]; + ha->sec_ddb_idx = ddb_index[1]; + exit_boot_info_free: dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma); exit_boot_info: @@ -3034,6 +3460,9 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha) return ret; } + if (ql4xdisablesysfsboot) + return QLA_SUCCESS; + if (ddb_index[0] == 0xffff) goto sec_target; @@ -3066,7 +3495,15 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha) struct iscsi_boot_kobj *boot_kobj; if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS) - return 0; + return QLA_ERROR; + + if (ql4xdisablesysfsboot) { + ql4_printk(KERN_INFO, ha, + "%s: syfsboot disabled - driver will trigger login" + "and publish session for discovery .\n", __func__); + return QLA_SUCCESS; + } + ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no); if (!ha->boot_kset) @@ -3108,7 +3545,7 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha) if (!boot_kobj) goto put_host; - return 0; + return QLA_SUCCESS; put_host: scsi_host_put(ha->host); @@ -3174,9 +3611,507 @@ static void qla4xxx_create_chap_list(struct scsi_qla_host *ha) exit_chap_list: dma_free_coherent(&ha->pdev->dev, chap_size, chap_flash_data, chap_dma); - return; } +static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, + struct ql4_tuple_ddb *tddb) +{ + struct scsi_qla_host *ha; + struct iscsi_cls_session *cls_sess; + struct iscsi_cls_conn *cls_conn; + struct iscsi_session *sess; + struct iscsi_conn *conn; + + DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); + ha = ddb_entry->ha; + cls_sess = ddb_entry->sess; + sess = cls_sess->dd_data; + cls_conn = ddb_entry->conn; + conn = cls_conn->dd_data; + + tddb->tpgt = sess->tpgt; + tddb->port = conn->persistent_port; + strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); + strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); +} + +static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, + struct ql4_tuple_ddb *tddb) +{ + uint16_t options = 0; + + tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); + memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], + min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); + + options = le16_to_cpu(fw_ddb_entry->options); + if (options & DDB_OPT_IPV6_DEVICE) + sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr); + else + sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr); + + tddb->port = le16_to_cpu(fw_ddb_entry->port); +} + +static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, + struct ql4_tuple_ddb *old_tddb, + struct ql4_tuple_ddb *new_tddb) +{ + if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name)) + return QLA_ERROR; + + if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr)) + return QLA_ERROR; + + if (old_tddb->port != new_tddb->port) + return QLA_ERROR; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]", + old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr, + old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt, + new_tddb->ip_addr, new_tddb->iscsi_name)); + + return QLA_SUCCESS; +} + +static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, + struct dev_db_entry *fw_ddb_entry) +{ + struct ddb_entry *ddb_entry; + struct ql4_tuple_ddb *fw_tddb = NULL; + struct ql4_tuple_ddb *tmp_tddb = NULL; + int idx; + int ret = QLA_ERROR; + + fw_tddb = vzalloc(sizeof(*fw_tddb)); + if (!fw_tddb) { + DEBUG2(ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed.\n")); + ret = QLA_SUCCESS; + goto exit_check; + } + + tmp_tddb = vzalloc(sizeof(*tmp_tddb)); + if (!tmp_tddb) { + DEBUG2(ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed.\n")); + ret = QLA_SUCCESS; + goto exit_check; + } + + qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb); + + for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { + ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); + if (ddb_entry == NULL) + continue; + + qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); + if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { + ret = QLA_SUCCESS; /* found */ + goto exit_check; + } + } + +exit_check: + if (fw_tddb) + vfree(fw_tddb); + if (tmp_tddb) + vfree(tmp_tddb); + return ret; +} + +static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha, + struct list_head *list_nt, + struct dev_db_entry *fw_ddb_entry) +{ + struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; + struct ql4_tuple_ddb *fw_tddb = NULL; + struct ql4_tuple_ddb *tmp_tddb = NULL; + int ret = QLA_ERROR; + + fw_tddb = vzalloc(sizeof(*fw_tddb)); + if (!fw_tddb) { + DEBUG2(ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed.\n")); + ret = QLA_SUCCESS; + goto exit_check; + } + + tmp_tddb = vzalloc(sizeof(*tmp_tddb)); + if (!tmp_tddb) { + DEBUG2(ql4_printk(KERN_WARNING, ha, + "Memory Allocation failed.\n")); + ret = QLA_SUCCESS; + goto exit_check; + } + + qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb); + + list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { + qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb); + if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { + ret = QLA_SUCCESS; /* found */ + goto exit_check; + } + } + +exit_check: + if (fw_tddb) + vfree(fw_tddb); + if (tmp_tddb) + vfree(tmp_tddb); + return ret; +} + +static void qla4xxx_free_nt_list(struct list_head *list_nt) +{ + struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; + + /* Free up the normaltargets list */ + list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { + list_del_init(&nt_ddb_idx->list); + vfree(nt_ddb_idx); + } + +} + +static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha, + struct dev_db_entry *fw_ddb_entry) +{ + struct iscsi_endpoint *ep; + struct sockaddr_in *addr; + struct sockaddr_in6 *addr6; + struct sockaddr *dst_addr; + char *ip; + + /* TODO: need to destroy on unload iscsi_endpoint*/ + dst_addr = vmalloc(sizeof(*dst_addr)); + if (!dst_addr) + return NULL; + + if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) { + dst_addr->sa_family = AF_INET6; + addr6 = (struct sockaddr_in6 *)dst_addr; + ip = (char *)&addr6->sin6_addr; + memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); + addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port)); + + } else { + dst_addr->sa_family = AF_INET; + addr = (struct sockaddr_in *)dst_addr; + ip = (char *)&addr->sin_addr; + memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN); + addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port)); + } + + ep = qla4xxx_ep_connect(ha->host, dst_addr, 0); + vfree(dst_addr); + return ep; +} + +static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx) +{ + if (ql4xdisablesysfsboot) + return QLA_SUCCESS; + if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx) + return QLA_ERROR; + return QLA_SUCCESS; +} + +static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry) +{ + ddb_entry->ddb_type = FLASH_DDB; + ddb_entry->fw_ddb_index = INVALID_ENTRY; + ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; + ddb_entry->ha = ha; + ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; + ddb_entry->ddb_change = qla4xxx_flash_ddb_change; + + atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); + atomic_set(&ddb_entry->relogin_timer, 0); + atomic_set(&ddb_entry->relogin_retry_count, 0); + + ddb_entry->default_relogin_timeout = + le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); + ddb_entry->default_time2wait = + le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait); +} + +static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) +{ + uint32_t idx = 0; + uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */ + uint32_t sts[MBOX_REG_COUNT]; + uint32_t ip_state; + unsigned long wtime; + int ret; + + wtime = jiffies + (HZ * IP_CONFIG_TOV); + do { + for (idx = 0; idx < IP_ADDR_COUNT; idx++) { + if (ip_idx[idx] == -1) + continue; + + ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts); + + if (ret == QLA_ERROR) { + ip_idx[idx] = -1; + continue; + } + + ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "Waiting for IP state for idx = %d, state = 0x%x\n", + ip_idx[idx], ip_state)); + if (ip_state == IP_ADDRSTATE_UNCONFIGURED || + ip_state == IP_ADDRSTATE_INVALID || + ip_state == IP_ADDRSTATE_PREFERRED || + ip_state == IP_ADDRSTATE_DEPRICATED || + ip_state == IP_ADDRSTATE_DISABLING) + ip_idx[idx] = -1; + + } + + /* Break if all IP states checked */ + if ((ip_idx[0] == -1) && + (ip_idx[1] == -1) && + (ip_idx[2] == -1) && + (ip_idx[3] == -1)) + break; + schedule_timeout_uninterruptible(HZ); + } while (time_after(wtime, jiffies)); +} + +void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) +{ + int max_ddbs; + int ret; + uint32_t idx = 0, next_idx = 0; + uint32_t state = 0, conn_err = 0; + uint16_t conn_id; + struct dev_db_entry *fw_ddb_entry; + struct ddb_entry *ddb_entry = NULL; + dma_addr_t fw_ddb_dma; + struct iscsi_cls_session *cls_sess; + struct iscsi_session *sess; + struct iscsi_cls_conn *cls_conn; + struct iscsi_endpoint *ep; + uint16_t cmds_max = 32, tmo = 0; + uint32_t initial_cmdsn = 0; + struct list_head list_st, list_nt; /* List of sendtargets */ + struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp; + int fw_idx_size; + unsigned long wtime; + struct qla_ddb_index *nt_ddb_idx; + + if (!test_bit(AF_LINK_UP, &ha->flags)) { + set_bit(AF_BUILD_DDB_LIST, &ha->flags); + ha->is_reset = is_reset; + return; + } + max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : + MAX_DEV_DB_ENTRIES; + + fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, + &fw_ddb_dma); + if (fw_ddb_entry == NULL) { + DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); + goto exit_ddb_list; + } + + INIT_LIST_HEAD(&list_st); + INIT_LIST_HEAD(&list_nt); + fw_idx_size = sizeof(struct qla_ddb_index); + + for (idx = 0; idx < max_ddbs; idx = next_idx) { + ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, + fw_ddb_dma, NULL, + &next_idx, &state, &conn_err, + NULL, &conn_id); + if (ret == QLA_ERROR) + break; + + if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) + goto continue_next_st; + + /* Check if ST, add to the list_st */ + if (strlen((char *) fw_ddb_entry->iscsi_name) != 0) + goto continue_next_st; + + st_ddb_idx = vzalloc(fw_idx_size); + if (!st_ddb_idx) + break; + + st_ddb_idx->fw_ddb_idx = idx; + + list_add_tail(&st_ddb_idx->list, &list_st); +continue_next_st: + if (next_idx == 0) + break; + } + + /* Before issuing conn open mbox, ensure all IPs states are configured + * Note, conn open fails if IPs are not configured + */ + qla4xxx_wait_for_ip_configuration(ha); + + /* Go thru the STs and fire the sendtargets by issuing conn open mbx */ + list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { + qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx); + } + + /* Wait to ensure all sendtargets are done for min 12 sec wait */ + tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout); + DEBUG2(ql4_printk(KERN_INFO, ha, + "Default time to wait for build ddb %d\n", tmo)); + + wtime = jiffies + (HZ * tmo); + do { + list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, + list) { + ret = qla4xxx_get_fwddb_entry(ha, + st_ddb_idx->fw_ddb_idx, + NULL, 0, NULL, &next_idx, + &state, &conn_err, NULL, + NULL); + if (ret == QLA_ERROR) + continue; + + if (state == DDB_DS_NO_CONNECTION_ACTIVE || + state == DDB_DS_SESSION_FAILED) { + list_del_init(&st_ddb_idx->list); + vfree(st_ddb_idx); + } + } + schedule_timeout_uninterruptible(HZ / 10); + } while (time_after(wtime, jiffies)); + + /* Free up the sendtargets list */ + list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { + list_del_init(&st_ddb_idx->list); + vfree(st_ddb_idx); + } + + for (idx = 0; idx < max_ddbs; idx = next_idx) { + ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, + fw_ddb_dma, NULL, + &next_idx, &state, &conn_err, + NULL, &conn_id); + if (ret == QLA_ERROR) + break; + + if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) + goto continue_next_nt; + + /* Check if NT, then add to list it */ + if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) + goto continue_next_nt; + + if (state == DDB_DS_NO_CONNECTION_ACTIVE || + state == DDB_DS_SESSION_FAILED) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "Adding DDB to session = 0x%x\n", + idx)); + if (is_reset == INIT_ADAPTER) { + nt_ddb_idx = vmalloc(fw_idx_size); + if (!nt_ddb_idx) + break; + + nt_ddb_idx->fw_ddb_idx = idx; + + memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry, + sizeof(struct dev_db_entry)); + + if (qla4xxx_is_flash_ddb_exists(ha, &list_nt, + fw_ddb_entry) == QLA_SUCCESS) { + vfree(nt_ddb_idx); + goto continue_next_nt; + } + list_add_tail(&nt_ddb_idx->list, &list_nt); + } else if (is_reset == RESET_ADAPTER) { + if (qla4xxx_is_session_exists(ha, + fw_ddb_entry) == QLA_SUCCESS) + goto continue_next_nt; + } + + /* Create session object, with INVALID_ENTRY, + * the targer_id would get set when we issue the login + */ + cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, + ha->host, cmds_max, + sizeof(struct ddb_entry), + sizeof(struct ql4_task_data), + initial_cmdsn, INVALID_ENTRY); + if (!cls_sess) + goto exit_ddb_list; + + /* + * iscsi_session_setup increments the driver reference + * count which wouldn't let the driver to be unloaded. + * so calling module_put function to decrement the + * reference count. + **/ + module_put(qla4xxx_iscsi_transport.owner); + sess = cls_sess->dd_data; + ddb_entry = sess->dd_data; + ddb_entry->sess = cls_sess; + + cls_sess->recovery_tmo = ql4xsess_recovery_tmo; + memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry, + sizeof(struct dev_db_entry)); + + qla4xxx_setup_flash_ddb_entry(ha, ddb_entry); + + cls_conn = iscsi_conn_setup(cls_sess, + sizeof(struct qla_conn), + conn_id); + if (!cls_conn) + goto exit_ddb_list; + + ddb_entry->conn = cls_conn; + + /* Setup ep, for displaying attributes in sysfs */ + ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry); + if (ep) { + ep->conn = cls_conn; + cls_conn->ep = ep; + } else { + DEBUG2(ql4_printk(KERN_ERR, ha, + "Unable to get ep\n")); + } + + /* Update sess/conn params */ + qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, + cls_conn); + + if (is_reset == RESET_ADAPTER) { + iscsi_block_session(cls_sess); + /* Use the relogin path to discover new devices + * by short-circuting the logic of setting + * timer to relogin - instead set the flags + * to initiate login right away. + */ + set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); + set_bit(DF_RELOGIN, &ddb_entry->flags); + } + } +continue_next_nt: + if (next_idx == 0) + break; + } +exit_ddb_list: + qla4xxx_free_nt_list(&list_nt); + if (fw_ddb_entry) + dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); + + qla4xxx_free_ddb_index(ha); +} + + /** * qla4xxx_probe_adapter - callback function to probe HBA * @pdev: pointer to pci_dev structure @@ -3298,7 +4233,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, * firmware * NOTE: interrupts enabled upon successful completion */ - status = qla4xxx_initialize_adapter(ha); + status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); while ((!test_bit(AF_ONLINE, &ha->flags)) && init_retry_count++ < MAX_INIT_RETRIES) { @@ -3319,7 +4254,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) continue; - status = qla4xxx_initialize_adapter(ha); + status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); } if (!test_bit(AF_ONLINE, &ha->flags)) { @@ -3386,12 +4321,16 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->host_no, ha->firmware_version[0], ha->firmware_version[1], ha->patch_number, ha->build_number); - qla4xxx_create_chap_list(ha); - if (qla4xxx_setup_boot_info(ha)) ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n", __func__); + /* Perform the build ddb list and login to each */ + qla4xxx_build_ddb_list(ha, INIT_ADAPTER); + iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); + + qla4xxx_create_chap_list(ha); + qla4xxx_create_ifaces(ha); return 0; @@ -3449,6 +4388,38 @@ static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha) } } +static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha) +{ + struct ddb_entry *ddb_entry; + int options; + int idx; + + for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { + + ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); + if ((ddb_entry != NULL) && + (ddb_entry->ddb_type == FLASH_DDB)) { + + options = LOGOUT_OPTION_CLOSE_SESSION; + if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) + == QLA_ERROR) + ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", + __func__); + + qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); + /* + * we have decremented the reference count of the driver + * when we setup the session to have the driver unload + * to be seamless without actually destroying the + * session + **/ + try_module_get(qla4xxx_iscsi_transport.owner); + iscsi_destroy_endpoint(ddb_entry->conn->ep); + qla4xxx_free_ddb(ha, ddb_entry); + iscsi_session_teardown(ddb_entry->sess); + } + } +} /** * qla4xxx_remove_adapter - calback function to remove adapter. * @pci_dev: PCI device pointer @@ -3465,9 +4436,11 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) /* destroy iface from sysfs */ qla4xxx_destroy_ifaces(ha); - if (ha->boot_kset) + if ((!ql4xdisablesysfsboot) && ha->boot_kset) iscsi_boot_destroy_kset(ha->boot_kset); + qla4xxx_destroy_fw_ddb_session(ha); + scsi_remove_host(ha->host); qla4xxx_free_adapter(ha); @@ -4115,7 +5088,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) qla4_8xxx_idc_unlock(ha); clear_bit(AF_FW_RECOVERY, &ha->flags); - rval = qla4xxx_initialize_adapter(ha); + rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); qla4_8xxx_idc_lock(ha); if (rval != QLA_SUCCESS) { @@ -4151,7 +5124,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == QLA82XX_DEV_READY)) { clear_bit(AF_FW_RECOVERY, &ha->flags); - rval = qla4xxx_initialize_adapter(ha); + rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); if (rval == QLA_SUCCESS) { ret = qla4xxx_request_irqs(ha); if (ret) { diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c15347d3f532..5254e57968f5 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k8" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k9" -- cgit From e1cd89c507b41e4021ce6fb0d19d230f6a932ccd Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Thu, 1 Dec 2011 21:38:42 -0600 Subject: [SCSI] qla4xxx: a small loop fix When the qla4xxx_get_fwddb_entry returns QLA_ERROR the nex_idx is not updated, for (idx = 0; idx < max_ddbs; idx = next_idx) { ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, &next_idx, &state, &conn_err, NULL, NULL); if (ret == QLA_ERROR) continue; This means there is a risk that the 'idx < max_ddbs' condition will never met and the loop will loop forever. Fix this by explicitly increasing the next_idx in the error condition. Maybe a break instead of continue is more appropriate, leaving the decision on the qlogic maintainer. Signed-off-by: Tomas Henzl Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 0497873a1dd2..1bdfa8120ac8 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -787,8 +787,10 @@ void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, &next_idx, &state, &conn_err, NULL, NULL); - if (ret == QLA_ERROR) + if (ret == QLA_ERROR) { + next_idx++; continue; + } if (state == DDB_DS_NO_CONNECTION_ACTIVE || state == DDB_DS_SESSION_FAILED) { DEBUG2(ql4_printk(KERN_INFO, ha, -- cgit From ff1d0319ac6a5fd859884b30c0a3cb6733b8fb2d Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 1 Dec 2011 21:38:43 -0600 Subject: [SCSI] qla4xxx: check for failed conn setup iscsi_conn_setup can fail so we must check for NULL being returned. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 95910c9b4776..4169c8baa112 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1207,6 +1207,9 @@ qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx) DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_idx); + if (!cls_conn) + return NULL; + sess = cls_sess->dd_data; ddb_entry = sess->dd_data; ddb_entry->conn = cls_conn; -- cgit From cd5cfce856684e13b9b57d46b78bb827e9c4da3c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 12 Dec 2011 09:23:48 -0500 Subject: drm/radeon/kms: add some new pci ids Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=43739 Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- include/drm/drm_pciids.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 4e4fbb820e20..14b6cd022284 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -182,8 +182,11 @@ {0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6759, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x675B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x675D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x675F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6761, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -195,8 +198,10 @@ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x677B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -246,6 +251,7 @@ {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68fa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -488,6 +494,8 @@ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -502,6 +510,8 @@ {0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0, 0, 0} #define r128_PCI_IDS \ -- cgit From a878185c3b93e692ace0d1628a47f3d75504ab4f Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 6 Dec 2011 22:41:21 -0800 Subject: [SCSI] bnx2i: Fixed kernel panic caused by unprotected task->sc->request deref During session recovery, the conn_stop call will trigger a flush to all outstanding SCSI cmds in the xmit queue. This will set all outstanding task->sc to NULL prior to the session_teardown call which frees the task memory. In the bnx2i SCSI response processing path, only the task was being checked for NULL under the session lock before the task->sc->request dereferencing. If there are outstanding SCSI cmd responses pending for process, the following kernel panic can be exposed where task->sc was found to be NULL. Call Trace: [ 69.720205] [] bnx2i_process_new_cqes+0x290/0x3c0 [bnx2i] [ 69.804289] [] bnx2i_fastpath_notification+0x33/0xa0 [bnx2 i] [ 69.891490] [] bnx2i_indicate_kcqe+0xdb/0x330 [bnx2i] [ 69.971427] [] service_kcqes+0x16e/0x1d0 [cnic] [ 70.045132] [] cnic_service_bnx2x_kcq+0x2a/0x50 [cnic] [ 70.126105] [] cnic_service_bnx2x_bh+0x43/0x140 [cnic] [ 70.207081] [] tasklet_action+0x66/0x110 [ 70.273521] [] __do_softirq+0xef/0x220 [ 70.337887] [] call_softirq+0x1c/0x30 This patch adds the !task->sc check and also protects the sc dereferencing under the session lock. Signed-off-by: Eddie Wai Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_hwi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index dba72a4e6a1c..1ad0b8225560 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1906,18 +1906,19 @@ static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session, spin_lock(&session->lock); task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data, cqe->itt & ISCSI_CMD_RESPONSE_INDEX); - if (!task) { + if (!task || !task->sc) { spin_unlock(&session->lock); return -EINVAL; } sc = task->sc; - spin_unlock(&session->lock); if (!blk_rq_cpu_valid(sc->request)) cpu = smp_processor_id(); else cpu = sc->request->cpu; + spin_unlock(&session->lock); + p = &per_cpu(bnx2i_percpu, cpu); spin_lock(&p->p_work_lock); if (unlikely(!p->iothread)) { -- cgit From b51306c63449d7f06ffa689036ba49eb46e898b5 Mon Sep 17 00:00:00 2001 From: Ajaykumar Hotchandani Date: Mon, 12 Dec 2011 13:57:36 +0530 Subject: PCI: Set device power state to PCI_D0 for device without native PM support During test of one IB card with guest VM, found that, msi is not initialized properly. It turns out __write_msi_msg will do nothing if device current_state is not PCI_D0. And, that pci device does not have pm_cap in guest VM. There is an error in setting of power state to PCI_D0 in pci_enable_device(), but error is not returned for this. Following is code flow: pci_enable_device() --> __pci_enable_device_flags() --> do_pci_enable_device() --> pci_set_power_state() --> __pci_start_power_transition() We have following condition inside __pci_start_power_transition(): if (platform_pci_power_manageable(dev)) { error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); } else { error = -ENODEV; /* Fall back to PCI_D0 if native PM is not supported */ if (!dev->pm_cap) dev->current_state = PCI_D0; } Here, from platform_pci_set_power_state(), acpi_pci_set_power_state() is getting called and that is failing with ENODEV because of following condition: if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0",&tmp))) return -ENODEV; Because of that, pci_update_current_state() is not getting called. With this patch, if device power state can not be set via platform_pci_set_power_state and that device does not have native pm support, then PCI device power state will be set to PCI_D0. -v2: This also reverts 47e9037ac16637cd7f12b8790ea7ce6680e42168, as it's not needed after this change. Acked-by: "Rafael J. Wysocki" Signed-off-by: Ajaykumar Hotchandani Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpiphp_glue.c | 1 - drivers/pci/pci.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 68360d5b494a..9ddf69e3bbef 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -225,7 +225,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); if (pdev) { - pdev->current_state = PCI_D0; slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); pci_dev_put(pdev); } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4788413f43d7..faccb8937706 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -664,6 +664,9 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); + /* Fall back to PCI_D0 if native PM is not supported */ + if (!dev->pm_cap) + dev->current_state = PCI_D0; } else { error = -ENODEV; /* Fall back to PCI_D0 if native PM is not supported */ -- cgit From 51e708c1049e721b9c5c48d026bc97ca8497d39a Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Tue, 13 Dec 2011 20:43:16 -0800 Subject: mwifiex: avoid double list_del in command cancel path Command cancel path cancels the current command and moves it to free command queue. While doing that it deletes the command entry from the pending list. This is not correct as the entry has been already deleted from the pending list at 'mwifiex_exec_next_cmd'. Fixing it. Also making sure the stale command pointer is cleaned and unaccessible for later use. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index ac278156d390..6e0a3eaecf70 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; unsigned long cmd_flags; - unsigned long cmd_pending_q_flags; unsigned long scan_pending_q_flags; uint16_t cancel_scan_cmd = false; @@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) cmd_node = adapter->curr_cmd; cmd_node->wait_q_enabled = false; cmd_node->cmd_flag |= CMD_F_CANCELED; - spin_lock_irqsave(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + mwifiex_complete_cmd(adapter, adapter->curr_cmd); + adapter->curr_cmd = NULL; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } @@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } adapter->cmd_wait_q.status = -1; - mwifiex_complete_cmd(adapter, adapter->curr_cmd); } /* -- cgit From 81670a491849127cd5f86defd2cd03cef1b08d07 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 14 Dec 2011 08:22:35 -0800 Subject: iwlwifi: tx_sync only on PAN context Ted reported that he couldn't connect to some APs and bisected it to the tx_sync implementation. Disable it for the BSS context to fix this issue. Reported-by: Ted Ts'o Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bacc06c95e7a..e0e9a3dfbc00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2850,6 +2850,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, int ret; u8 sta_id; + if (ctx->ctxid != IWL_RXON_CTX_PAN) + return 0; + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->shrd->mutex); @@ -2898,6 +2901,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_rxon_context *ctx = vif_priv->ctx; + if (ctx->ctxid != IWL_RXON_CTX_PAN) + return; + IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->shrd->mutex); -- cgit From 78feb35b8161acd95c33a703ed6ab6f554d29387 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 14 Dec 2011 08:22:36 -0800 Subject: iwlwifi: allow to switch to HT40 if not associated My previous patch 34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure HT40 after associated Fix the case of HT40 after association on specified AP, but it break the association for some APs and cause not able to establish connection. We need to address HT40 before and after addociation. CC: stable@vger.kernel.org #3.0+ Reported-by: Andrej Gelenberg Signed-off-by: Wey-Yi Guy Tested-by: Andrej Gelenberg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a7a6def40d05..5c7c17c7166a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) if (ctx->ht.enabled) { /* if HT40 is used, it should not change * after associated except channel switch */ - if (iwl_is_associated_ctx(ctx) && - !ctx->ht.is_40mhz) + if (!ctx->ht.is_40mhz || + !iwl_is_associated_ctx(ctx)) iwlagn_config_ht40(conf, ctx); } else ctx->ht.is_40mhz = false; -- cgit From b1f44e13a525d2ffb7d5afe2273b7169d6f2222e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Dec 2011 10:05:22 -0800 Subject: sparc32: Be less strict in matching %lo part of relocation. The "(insn & 0x01800000) != 0x01800000" test matches 'restore' but that is a legitimate place to see the %lo() part of a 32-bit symbol relocation, particularly in tail calls. Signed-off-by: David S. Miller Tested-by: Sergei Trofimovich --- arch/sparc/mm/btfixup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c index 5175ac2f4820..8a7f81743c12 100644 --- a/arch/sparc/mm/btfixup.c +++ b/arch/sparc/mm/btfixup.c @@ -302,8 +302,7 @@ void __init btfixup(void) case 'i': /* INT */ if ((insn & 0xc1c00000) == 0x01000000) /* %HI */ set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10)); - else if ((insn & 0x80002000) == 0x80002000 && - (insn & 0x01800000) != 0x01800000) /* %LO */ + else if ((insn & 0x80002000) == 0x80002000) /* %LO */ set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff)); else { prom_printf(insn_i, p, addr, insn); -- cgit From 248b122b131202de95aaa3670e48465619bdff14 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 14 Dec 2011 21:59:30 +0200 Subject: usb: dwc3: core: fix cached revision on our structure All our revision macros are defined with the entire 32-bits which we read from GSNPSID register, so we must cache all 32-bits properly rather than masking the top 16-bits. This will fix all revision checks we have on current driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 717ebc9ff941..600d82348511 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -264,7 +264,7 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) ret = -ENODEV; goto err0; } - dwc->revision = reg & DWC3_GSNPSREV_MASK; + dwc->revision = reg; dwc3_core_soft_reset(dwc); -- cgit From 6f6c2aa33b915c574543f176dee89d7aefc115c1 Mon Sep 17 00:00:00 2001 From: john fastabend Date: Fri, 18 Nov 2011 13:35:56 -0800 Subject: [SCSI] fcoe: fix fcoe in a DCB environment by adding DCB notifiers to set skb priority Use DCB notifiers to set the skb priority to allow packets to be steered and tagged correctly over DCB enabled drivers that setup traffic classes. This allows queue_mapping() routines to be removed in these drivers that were previously inspecting the ethertype of every skb to mark FCoE/FIP frames. Signed-off-by: John Fastabend Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 115 ++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/fcoe/fcoe_ctlr.c | 4 ++ include/scsi/libfcoe.h | 3 ++ 3 files changed, 122 insertions(+) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index f3f440c955f3..8d67467dd9ce 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -101,6 +103,8 @@ static int fcoe_ddp_done(struct fc_lport *, u16); static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *, unsigned int); static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); +static int fcoe_dcb_app_notification(struct notifier_block *notifier, + ulong event, void *ptr); static bool fcoe_match(struct net_device *netdev); static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode); @@ -129,6 +133,11 @@ static struct notifier_block fcoe_cpu_notifier = { .notifier_call = fcoe_cpu_callback, }; +/* notification function for DCB events */ +static struct notifier_block dcb_notifier = { + .notifier_call = fcoe_dcb_app_notification, +}; + static struct scsi_transport_template *fcoe_nport_scsi_transport; static struct scsi_transport_template *fcoe_vport_scsi_transport; @@ -1522,6 +1531,8 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) skb_reset_network_header(skb); skb->mac_len = elen; skb->protocol = htons(ETH_P_FCOE); + skb->priority = port->priority; + if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN && fcoe->realdev->features & NETIF_F_HW_VLAN_TX) { skb->vlan_tci = VLAN_TAG_PRESENT | @@ -1747,6 +1758,7 @@ int fcoe_percpu_receive_thread(void *arg) */ static void fcoe_dev_setup(void) { + register_dcbevent_notifier(&dcb_notifier); register_netdevice_notifier(&fcoe_notifier); } @@ -1755,9 +1767,69 @@ static void fcoe_dev_setup(void) */ static void fcoe_dev_cleanup(void) { + unregister_dcbevent_notifier(&dcb_notifier); unregister_netdevice_notifier(&fcoe_notifier); } +static struct fcoe_interface * +fcoe_hostlist_lookup_realdev_port(struct net_device *netdev) +{ + struct fcoe_interface *fcoe; + struct net_device *real_dev; + + list_for_each_entry(fcoe, &fcoe_hostlist, list) { + if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN) + real_dev = vlan_dev_real_dev(fcoe->netdev); + else + real_dev = fcoe->netdev; + + if (netdev == real_dev) + return fcoe; + } + return NULL; +} + +static int fcoe_dcb_app_notification(struct notifier_block *notifier, + ulong event, void *ptr) +{ + struct dcb_app_type *entry = ptr; + struct fcoe_interface *fcoe; + struct net_device *netdev; + struct fcoe_port *port; + int prio; + + if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE) + return NOTIFY_OK; + + netdev = dev_get_by_index(&init_net, entry->ifindex); + if (!netdev) + return NOTIFY_OK; + + fcoe = fcoe_hostlist_lookup_realdev_port(netdev); + dev_put(netdev); + if (!fcoe) + return NOTIFY_OK; + + if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) + prio = ffs(entry->app.priority) - 1; + else + prio = entry->app.priority; + + if (prio < 0) + return NOTIFY_OK; + + if (entry->app.protocol == ETH_P_FIP || + entry->app.protocol == ETH_P_FCOE) + fcoe->ctlr.priority = prio; + + if (entry->app.protocol == ETH_P_FCOE) { + port = lport_priv(fcoe->ctlr.lp); + port->priority = prio; + } + + return NOTIFY_OK; +} + /** * fcoe_device_notification() - Handler for net device events * @notifier: The context of the notification @@ -1965,6 +2037,46 @@ static bool fcoe_match(struct net_device *netdev) return true; } +/** + * fcoe_dcb_create() - Initialize DCB attributes and hooks + * @netdev: The net_device object of the L2 link that should be queried + * @port: The fcoe_port to bind FCoE APP priority with + * @ + */ +static void fcoe_dcb_create(struct fcoe_interface *fcoe) +{ +#ifdef CONFIG_DCB + int dcbx; + u8 fup, up; + struct net_device *netdev = fcoe->realdev; + struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); + struct dcb_app app = { + .priority = 0, + .protocol = ETH_P_FCOE + }; + + /* setup DCB priority attributes. */ + if (netdev && netdev->dcbnl_ops && netdev->dcbnl_ops->getdcbx) { + dcbx = netdev->dcbnl_ops->getdcbx(netdev); + + if (dcbx & DCB_CAP_DCBX_VER_IEEE) { + app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE; + up = dcb_ieee_getapp_mask(netdev, &app); + app.protocol = ETH_P_FIP; + fup = dcb_ieee_getapp_mask(netdev, &app); + } else { + app.selector = DCB_APP_IDTYPE_ETHTYPE; + up = dcb_getapp(netdev, &app); + app.protocol = ETH_P_FIP; + fup = dcb_getapp(netdev, &app); + } + + port->priority = ffs(up) ? ffs(up) - 1 : 0; + fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority; + } +#endif +} + /** * fcoe_create() - Create a fcoe interface * @netdev : The net_device object the Ethernet interface to create on @@ -2008,6 +2120,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) /* Make this the "master" N_Port */ fcoe->ctlr.lp = lport; + /* setup DCB priority attributes. */ + fcoe_dcb_create(fcoe); + /* add to lports list */ fcoe_hostlist_add(lport); diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index c74c4b8e71ef..e7522dcc296e 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -320,6 +320,7 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) skb_put(skb, sizeof(*sol)); skb->protocol = htons(ETH_P_FIP); + skb->priority = fip->priority; skb_reset_mac_header(skb); skb_reset_network_header(skb); fip->send(fip, skb); @@ -474,6 +475,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, } skb_put(skb, len); skb->protocol = htons(ETH_P_FIP); + skb->priority = fip->priority; skb_reset_mac_header(skb); skb_reset_network_header(skb); fip->send(fip, skb); @@ -566,6 +568,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, cap->fip.fip_dl_len = htons(dlen / FIP_BPW); skb->protocol = htons(ETH_P_FIP); + skb->priority = fip->priority; skb_reset_mac_header(skb); skb_reset_network_header(skb); return 0; @@ -1911,6 +1914,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, skb_put(skb, len); skb->protocol = htons(ETH_P_FIP); + skb->priority = fip->priority; skb_reset_mac_header(skb); skb_reset_network_header(skb); diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index d1e95c6ac776..5a35a2a2d3c5 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -147,6 +147,7 @@ struct fcoe_ctlr { u8 map_dest; u8 spma; u8 probe_tries; + u8 priority; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; @@ -301,6 +302,7 @@ struct fcoe_percpu_s { * @lport: The associated local port * @fcoe_pending_queue: The pending Rx queue of skbs * @fcoe_pending_queue_active: Indicates if the pending queue is active + * @priority: Packet priority (DCB) * @max_queue_depth: Max queue depth of pending queue * @min_queue_depth: Min queue depth of pending queue * @timer: The queue timer @@ -316,6 +318,7 @@ struct fcoe_port { struct fc_lport *lport; struct sk_buff_head fcoe_pending_queue; u8 fcoe_pending_queue_active; + u8 priority; u32 max_queue_depth; u32 min_queue_depth; struct timer_list timer; -- cgit From 645e903528ca6cd510f9ac71a6a23de1a4d931e3 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 14 Dec 2011 15:52:30 +0800 Subject: ALSA: HDA: Use LPIB Position fix for Intel SCH Poulsbo Several people with this chipset have reported inconsistent/sloppy values for position reporting when the DMA position buffer is used, and that setting position_fix=1 have fixed their problems. BugLink: https://bugs.launchpad.net/bugs/825709 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 84d11d7ed710..c2f79e63124d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2971,7 +2971,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ + /* ICH */ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_BUFSIZE }, /* ICH6 */ -- cgit From f4a2f4c548296168832ad4ab7e7f7b0cd0bf1214 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 14 Dec 2011 20:12:01 -0500 Subject: Btrfs: fix wrong i_size when truncating a file to a larger size Btrfsck report error 100 after the 83th case of xfstests was run, it means the i_size of the file is wrong. The reason of this bug is that: Btrfs increased i_size of the file at the beginning, but it failed to expand the file, and failed to update the i_size to the old size because there is no enough space in the file system, so we found a wrong i_size. This patch fixes this bug by updating the i_size just when we pass the file expanding and get enough space to update i-node. Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c5ccec23984c..4bbceb928aff 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3370,6 +3370,8 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) static int btrfs_setsize(struct inode *inode, loff_t newsize) { + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); int ret; @@ -3377,16 +3379,20 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return 0; if (newsize > oldsize) { - i_size_write(inode, newsize); - btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); truncate_pagecache(inode, oldsize, newsize); ret = btrfs_cont_expand(inode, oldsize, newsize); - if (ret) { - btrfs_setsize(inode, oldsize); + if (ret) return ret; - } - mark_inode_dirty(inode); + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + i_size_write(inode, newsize); + btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); + ret = btrfs_update_inode(trans, root, inode); + + btrfs_end_transaction_throttle(trans, root); } else { /* -- cgit From 3642320e07444cc46327b24977d752f99706dac2 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 14 Dec 2011 20:12:02 -0500 Subject: Btrfs: fix wrong disk space information of the files Btrfsck report errors after the 83th case of xfstests was run, The error number is 400, it means the used disk space of the file is wrong. The reason of this bug is that: The file truncation may fail when the space of the file system is not enough, and leave some file extents, whose offset are beyond the end of the files. When we want to expand those files, we will drop those file extents, and put in dummy file extents, and then we should update the i-node. But btrfs forgets to do it. This patch adds the forgotten i-node update. Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4bbceb928aff..f1c4bceed072 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3327,7 +3327,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) u64 hint_byte = 0; hole_size = last_byte - cur_offset; - trans = btrfs_start_transaction(root, 2); + trans = btrfs_start_transaction(root, 3); if (IS_ERR(trans)) { err = PTR_ERR(trans); break; @@ -3337,6 +3337,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) cur_offset + hole_size, &hint_byte, 1); if (err) { + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@ -3346,6 +3347,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) 0, hole_size, 0, hole_size, 0, 0, 0); if (err) { + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@ -3353,6 +3355,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) btrfs_drop_extent_cache(inode, hole_start, last_byte - 1, 0); + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); } free_extent_map(em); -- cgit From 39fb26c398ddf8d7794a85e896cfe1a42e55524b Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Wed, 14 Dec 2011 20:12:02 -0500 Subject: Btrfs: fix inaccurate available space on raid0 profile When we use raid0 as the data profile, df command may show us a very inaccurate value of the available space, which may be much less than the real one. It may make the users puzzled. Fix it by changing the calculation of the available space, and making it be more similar to a fake chunk allocation. Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/super.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1a3ce9e0b495..41495dce4db0 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1079,7 +1079,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) u64 avail_space; u64 used_space; u64 min_stripe_size; - int min_stripes = 1; + int min_stripes = 1, num_stripes = 1; int i = 0, nr_devices; int ret; @@ -1093,12 +1093,16 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) /* calc min stripe number for data space alloction */ type = btrfs_get_alloc_profile(root, 1); - if (type & BTRFS_BLOCK_GROUP_RAID0) + if (type & BTRFS_BLOCK_GROUP_RAID0) { min_stripes = 2; - else if (type & BTRFS_BLOCK_GROUP_RAID1) + num_stripes = nr_devices; + } else if (type & BTRFS_BLOCK_GROUP_RAID1) { min_stripes = 2; - else if (type & BTRFS_BLOCK_GROUP_RAID10) + num_stripes = 2; + } else if (type & BTRFS_BLOCK_GROUP_RAID10) { min_stripes = 4; + num_stripes = 4; + } if (type & BTRFS_BLOCK_GROUP_DUP) min_stripe_size = 2 * BTRFS_STRIPE_LEN; @@ -1167,13 +1171,16 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) i = nr_devices - 1; avail_space = 0; while (nr_devices >= min_stripes) { + if (num_stripes > nr_devices) + num_stripes = nr_devices; + if (devices_info[i].max_avail >= min_stripe_size) { int j; u64 alloc_size; - avail_space += devices_info[i].max_avail * min_stripes; + avail_space += devices_info[i].max_avail * num_stripes; alloc_size = devices_info[i].max_avail; - for (j = i + 1 - min_stripes; j <= i; j++) + for (j = i + 1 - num_stripes; j <= i; j++) devices_info[j].max_avail -= alloc_size; } i--; -- cgit From f8e9e0b07be0464e12366631da3da73a1a62449c Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Wed, 14 Dec 2011 20:12:02 -0500 Subject: btrfs: keep orphans for subvolume deletion Since we have the free space caches, btrfs_orphan_cleanup also runs for the tree_root. Unfortunately this also cleans up the orphans used to mark subvol deletions in progress. Currently if a subvol deletion gets interrupted twice by umount/mount, the deletion will not be continued and the space permanently lost, though it would be possible to write a tool to recover those lost subvol deletions. This patch checks if the orphan belongs to a subvol (dead root) and skips the deletion. Signed-off-by: Arne Jansen Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f1c4bceed072..4a31493d97ac 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2158,6 +2158,38 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) if (ret && ret != -ESTALE) goto out; + if (ret == -ESTALE && root == root->fs_info->tree_root) { + struct btrfs_root *dead_root; + struct btrfs_fs_info *fs_info = root->fs_info; + int is_dead_root = 0; + + /* + * this is an orphan in the tree root. Currently these + * could come from 2 sources: + * a) a snapshot deletion in progress + * b) a free space cache inode + * We need to distinguish those two, as the snapshot + * orphan must not get deleted. + * find_dead_roots already ran before us, so if this + * is a snapshot deletion, we should find the root + * in the dead_roots list + */ + spin_lock(&fs_info->trans_lock); + list_for_each_entry(dead_root, &fs_info->dead_roots, + root_list) { + if (dead_root->root_key.objectid == + found_key.objectid) { + is_dead_root = 1; + break; + } + } + spin_unlock(&fs_info->trans_lock); + if (is_dead_root) { + /* prevent this orphan from being found again */ + key.offset = found_key.objectid - 1; + continue; + } + } /* * Inode is already gone but the orphan item is still there, * kill the orphan item. -- cgit From 306424cc880a0fbbdc99eee1f43d056a301a180f Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 14 Dec 2011 20:12:02 -0500 Subject: Btrfs: fix ctime update of on-disk inode To reproduce the bug: # touch /mnt/tmp # stat /mnt/tmp | grep Change Change: 2011-12-09 09:32:23.412105981 +0800 # chattr +i /mnt/tmp # stat /mnt/tmp | grep Change Change: 2011-12-09 09:32:43.198105295 +0800 # umount /mnt # mount /dev/loop1 /mnt # stat /mnt/tmp | grep Change Change: 2011-12-09 09:32:23.412105981 +0800 We should update ctime of in-memory inode before calling btrfs_update_inode(). Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 72d461656f60..40eaa9fdf07c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -252,11 +252,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) trans = btrfs_join_transaction(root); BUG_ON(IS_ERR(trans)); + btrfs_update_iflags(inode); + inode->i_ctime = CURRENT_TIME; ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); - btrfs_update_iflags(inode); - inode->i_ctime = CURRENT_TIME; btrfs_end_transaction(trans, root); mnt_drop_write(file->f_path.mnt); -- cgit From 8f3b65a3d66bcc086e1eb040b7545e70681f2ed1 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Thu, 15 Dec 2011 09:29:43 -0500 Subject: Btrfs: add a cond_resched() into the worker loop If we have a constant stream of end_io completions or crc work, we can hit softlockup messages from the async helper threads. This adds a cond_resched() into the loop to avoid them. Signed-off-by: Chris Mason --- fs/btrfs/async-thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 7ec14097fef1..203e849dc9c9 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -331,7 +331,7 @@ again: run_ordered_completions(worker->workers, work); check_pending_worker_creates(worker); - + cond_resched(); } spin_lock_irq(&worker->lock); -- cgit From ad19db71f498fd858dd84ce603efcf97e321f184 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Thu, 15 Dec 2011 10:09:07 -0500 Subject: BTRFS: Establish i_ops before calling d_instantiate The Smack LSM hook for security_d_instantiate checks the inode's i_op->getxattr value to determine if the containing filesystem supports extended attributes. The BTRFS filesystem sets the inode's i_op value only after it has instantiated the inode. This results in Smack incorrectly giving new BTRFS inodes attributes from the filesystem defaults on the assumption that values can't be stored on the filesystem. This patch moves the assignment of inode operation vectors ahead of the calls to d_instantiate, letting Smack know that the filesystem supports extended attributes. There should be no impact on the performance or behavior of BTRFS. Signed-off-by: Casey Schaufler Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4a31493d97ac..d4a9195c7f0d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4596,11 +4596,18 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + + inode->i_op = &btrfs_special_inode_operations; err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { - inode->i_op = &btrfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); btrfs_update_inode(trans, root, inode); } @@ -4654,14 +4661,21 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - inode->i_fop = &btrfs_file_operations; - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } out_unlock: @@ -7117,14 +7131,21 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - inode->i_fop = &btrfs_file_operations; - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } if (drop_inode) -- cgit From 0dc3b84a73267f47a75468f924f5d58a840e3152 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 18 Nov 2011 14:37:27 -0500 Subject: Btrfs: fix num_workers_starting bug and other bugs in async thread Al pointed out we have some random problems with the way we account for num_workers_starting in the async thread stuff. First of all we need to make sure to decrement num_workers_starting if we fail to start the worker, so make __btrfs_start_workers do this. Also fix __btrfs_start_workers so that it doesn't call btrfs_stop_workers(), there is no point in stopping everybody if we failed to create a worker. Also check_pending_worker_creates needs to call __btrfs_start_work in it's work function since it already increments num_workers_starting. People only start one worker at a time, so get rid of the num_workers argument everywhere, and make btrfs_queue_worker a void since it will always succeed. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/async-thread.c | 115 +++++++++++++++++++++++------------------------- fs/btrfs/async-thread.h | 4 +- fs/btrfs/disk-io.c | 34 ++++++++------ fs/btrfs/scrub.c | 8 +++- 4 files changed, 83 insertions(+), 78 deletions(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 7ec14097fef1..af8e117c8978 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -64,6 +64,8 @@ struct btrfs_worker_thread { int idle; }; +static int __btrfs_start_workers(struct btrfs_workers *workers); + /* * btrfs_start_workers uses kthread_run, which can block waiting for memory * for a very long time. It will actually throttle on page writeback, @@ -88,27 +90,10 @@ static void start_new_worker_func(struct btrfs_work *work) { struct worker_start *start; start = container_of(work, struct worker_start, work); - btrfs_start_workers(start->queue, 1); + __btrfs_start_workers(start->queue); kfree(start); } -static int start_new_worker(struct btrfs_workers *queue) -{ - struct worker_start *start; - int ret; - - start = kzalloc(sizeof(*start), GFP_NOFS); - if (!start) - return -ENOMEM; - - start->work.func = start_new_worker_func; - start->queue = queue; - ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work); - if (ret) - kfree(start); - return ret; -} - /* * helper function to move a thread onto the idle list after it * has finished some requests. @@ -153,12 +138,20 @@ static void check_busy_worker(struct btrfs_worker_thread *worker) static void check_pending_worker_creates(struct btrfs_worker_thread *worker) { struct btrfs_workers *workers = worker->workers; + struct worker_start *start; unsigned long flags; rmb(); if (!workers->atomic_start_pending) return; + start = kzalloc(sizeof(*start), GFP_NOFS); + if (!start) + return; + + start->work.func = start_new_worker_func; + start->queue = workers; + spin_lock_irqsave(&workers->lock, flags); if (!workers->atomic_start_pending) goto out; @@ -170,10 +163,11 @@ static void check_pending_worker_creates(struct btrfs_worker_thread *worker) workers->num_workers_starting += 1; spin_unlock_irqrestore(&workers->lock, flags); - start_new_worker(workers); + btrfs_queue_worker(workers->atomic_worker_start, &start->work); return; out: + kfree(start); spin_unlock_irqrestore(&workers->lock, flags); } @@ -462,56 +456,55 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, * starts new worker threads. This does not enforce the max worker * count in case you need to temporarily go past it. */ -static int __btrfs_start_workers(struct btrfs_workers *workers, - int num_workers) +static int __btrfs_start_workers(struct btrfs_workers *workers) { struct btrfs_worker_thread *worker; int ret = 0; - int i; - for (i = 0; i < num_workers; i++) { - worker = kzalloc(sizeof(*worker), GFP_NOFS); - if (!worker) { - ret = -ENOMEM; - goto fail; - } + worker = kzalloc(sizeof(*worker), GFP_NOFS); + if (!worker) { + ret = -ENOMEM; + goto fail; + } - INIT_LIST_HEAD(&worker->pending); - INIT_LIST_HEAD(&worker->prio_pending); - INIT_LIST_HEAD(&worker->worker_list); - spin_lock_init(&worker->lock); - - atomic_set(&worker->num_pending, 0); - atomic_set(&worker->refs, 1); - worker->workers = workers; - worker->task = kthread_run(worker_loop, worker, - "btrfs-%s-%d", workers->name, - workers->num_workers + i); - if (IS_ERR(worker->task)) { - ret = PTR_ERR(worker->task); - kfree(worker); - goto fail; - } - spin_lock_irq(&workers->lock); - list_add_tail(&worker->worker_list, &workers->idle_list); - worker->idle = 1; - workers->num_workers++; - workers->num_workers_starting--; - WARN_ON(workers->num_workers_starting < 0); - spin_unlock_irq(&workers->lock); + INIT_LIST_HEAD(&worker->pending); + INIT_LIST_HEAD(&worker->prio_pending); + INIT_LIST_HEAD(&worker->worker_list); + spin_lock_init(&worker->lock); + + atomic_set(&worker->num_pending, 0); + atomic_set(&worker->refs, 1); + worker->workers = workers; + worker->task = kthread_run(worker_loop, worker, + "btrfs-%s-%d", workers->name, + workers->num_workers + 1); + if (IS_ERR(worker->task)) { + ret = PTR_ERR(worker->task); + kfree(worker); + goto fail; } + spin_lock_irq(&workers->lock); + list_add_tail(&worker->worker_list, &workers->idle_list); + worker->idle = 1; + workers->num_workers++; + workers->num_workers_starting--; + WARN_ON(workers->num_workers_starting < 0); + spin_unlock_irq(&workers->lock); + return 0; fail: - btrfs_stop_workers(workers); + spin_lock_irq(&workers->lock); + workers->num_workers_starting--; + spin_unlock_irq(&workers->lock); return ret; } -int btrfs_start_workers(struct btrfs_workers *workers, int num_workers) +int btrfs_start_workers(struct btrfs_workers *workers) { spin_lock_irq(&workers->lock); - workers->num_workers_starting += num_workers; + workers->num_workers_starting++; spin_unlock_irq(&workers->lock); - return __btrfs_start_workers(workers, num_workers); + return __btrfs_start_workers(workers); } /* @@ -568,6 +561,7 @@ static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers) struct btrfs_worker_thread *worker; unsigned long flags; struct list_head *fallback; + int ret; again: spin_lock_irqsave(&workers->lock, flags); @@ -584,7 +578,9 @@ again: workers->num_workers_starting++; spin_unlock_irqrestore(&workers->lock, flags); /* we're below the limit, start another worker */ - __btrfs_start_workers(workers, 1); + ret = __btrfs_start_workers(workers); + if (ret) + goto fallback; goto again; } } @@ -665,7 +661,7 @@ void btrfs_set_work_high_prio(struct btrfs_work *work) /* * places a struct btrfs_work into the pending queue of one of the kthreads */ -int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) +void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) { struct btrfs_worker_thread *worker; unsigned long flags; @@ -673,7 +669,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) /* don't requeue something already on a list */ if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) - goto out; + return; worker = find_worker(workers); if (workers->ordered) { @@ -712,7 +708,4 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) if (wake) wake_up_process(worker->task); spin_unlock_irqrestore(&worker->lock, flags); - -out: - return 0; } diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h index 5077746cf85e..f34cc31fa3c9 100644 --- a/fs/btrfs/async-thread.h +++ b/fs/btrfs/async-thread.h @@ -109,8 +109,8 @@ struct btrfs_workers { char *name; }; -int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); -int btrfs_start_workers(struct btrfs_workers *workers, int num_workers); +void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); +int btrfs_start_workers(struct btrfs_workers *workers); int btrfs_stop_workers(struct btrfs_workers *workers); void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, struct btrfs_workers *async_starter); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 94abc25392f6..3f9d5551e582 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2194,19 +2194,27 @@ struct btrfs_root *open_ctree(struct super_block *sb, fs_info->endio_meta_write_workers.idle_thresh = 2; fs_info->readahead_workers.idle_thresh = 2; - btrfs_start_workers(&fs_info->workers, 1); - btrfs_start_workers(&fs_info->generic_worker, 1); - btrfs_start_workers(&fs_info->submit_workers, 1); - btrfs_start_workers(&fs_info->delalloc_workers, 1); - btrfs_start_workers(&fs_info->fixup_workers, 1); - btrfs_start_workers(&fs_info->endio_workers, 1); - btrfs_start_workers(&fs_info->endio_meta_workers, 1); - btrfs_start_workers(&fs_info->endio_meta_write_workers, 1); - btrfs_start_workers(&fs_info->endio_write_workers, 1); - btrfs_start_workers(&fs_info->endio_freespace_worker, 1); - btrfs_start_workers(&fs_info->delayed_workers, 1); - btrfs_start_workers(&fs_info->caching_workers, 1); - btrfs_start_workers(&fs_info->readahead_workers, 1); + /* + * btrfs_start_workers can really only fail because of ENOMEM so just + * return -ENOMEM if any of these fail. + */ + ret = btrfs_start_workers(&fs_info->workers); + ret |= btrfs_start_workers(&fs_info->generic_worker); + ret |= btrfs_start_workers(&fs_info->submit_workers); + ret |= btrfs_start_workers(&fs_info->delalloc_workers); + ret |= btrfs_start_workers(&fs_info->fixup_workers); + ret |= btrfs_start_workers(&fs_info->endio_workers); + ret |= btrfs_start_workers(&fs_info->endio_meta_workers); + ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers); + ret |= btrfs_start_workers(&fs_info->endio_write_workers); + ret |= btrfs_start_workers(&fs_info->endio_freespace_worker); + ret |= btrfs_start_workers(&fs_info->delayed_workers); + ret |= btrfs_start_workers(&fs_info->caching_workers); + ret |= btrfs_start_workers(&fs_info->readahead_workers); + if (ret) { + ret = -ENOMEM; + goto fail_sb_buffer; + } fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index c27bcb67f330..ddf2c90d3fc0 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1535,18 +1535,22 @@ static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) { struct btrfs_fs_info *fs_info = root->fs_info; + int ret = 0; mutex_lock(&fs_info->scrub_lock); if (fs_info->scrub_workers_refcnt == 0) { btrfs_init_workers(&fs_info->scrub_workers, "scrub", fs_info->thread_pool_size, &fs_info->generic_worker); fs_info->scrub_workers.idle_thresh = 4; - btrfs_start_workers(&fs_info->scrub_workers, 1); + ret = btrfs_start_workers(&fs_info->scrub_workers); + if (ret) + goto out; } ++fs_info->scrub_workers_refcnt; +out: mutex_unlock(&fs_info->scrub_lock); - return 0; + return ret; } static noinline_for_stack void scrub_workers_put(struct btrfs_root *root) -- cgit From 22c44fe65adacd20a174f3f54686509ee94ef7be Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 30 Nov 2011 10:45:38 -0500 Subject: Btrfs: deal with enospc from dirtying inodes properly Now that we're properly keeping track of delayed inode space we've been getting a lot of warnings out of btrfs_dirty_inode() when running xfstest 83. This is because a bunch of people call mark_inode_dirty, which is void so we can't return ENOSPC. This needs to be fixed in a few areas 1) file_update_time - this updates the mtime and such when writing to a file, which will call mark_inode_dirty. So copy file_update_time into btrfs so we can call btrfs_dirty_inode directly and return an error if we get one appropriately. 2) fix symlinks to use btrfs_setattr for ->setattr. For some reason we weren't setting ->setattr for symlinks, even though we should have been. This catches one of the cases where we were getting errors in mark_inode_dirty. 3) Fix btrfs_setattr and btrfs_setsize to call btrfs_dirty_inode directly instead of mark_inode_dirty. This lets us return errors properly for truncate and chown/anything related to setattr. 4) Add a new btrfs_fs_dirty_inode which will just call btrfs_dirty_inode and print an error if we have one. The only remaining user we can't control for this is touch_atime(), but we don't really want to keep people from walking down the tree if we don't have space to save the atime update, so just complain but don't worry about it. With this patch xfstests 83 complains a handful of times instead of hundreds of times. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 3 ++- fs/btrfs/file.c | 6 ++++- fs/btrfs/inode.c | 80 ++++++++++++++++++++++++++++++++++++++++++-------------- fs/btrfs/super.c | 13 ++++++++- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 50634abef9b4..67385033323d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2692,7 +2692,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); int btrfs_readpage(struct file *file, struct page *page); void btrfs_evict_inode(struct inode *inode); int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); -void btrfs_dirty_inode(struct inode *inode, int flags); +int btrfs_dirty_inode(struct inode *inode); +int btrfs_update_time(struct file *file); struct inode *btrfs_alloc_inode(struct super_block *sb); void btrfs_destroy_inode(struct inode *inode); int btrfs_drop_inode(struct inode *inode); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f2e928289600..cc7492c823f3 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1387,7 +1387,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, goto out; } - file_update_time(file); + err = btrfs_update_time(file); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } BTRFS_I(inode)->sequence++; start_pos = round_down(pos, root->sectorsize); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c5ccec23984c..eec33b9c953d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -3386,7 +3387,7 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return ret; } - mark_inode_dirty(inode); + ret = btrfs_dirty_inode(inode); } else { /* @@ -3426,9 +3427,9 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid) { setattr_copy(inode, attr); - mark_inode_dirty(inode); + err = btrfs_dirty_inode(inode); - if (attr->ia_valid & ATTR_MODE) + if (!err && attr->ia_valid & ATTR_MODE) err = btrfs_acl_chmod(inode); } @@ -4204,42 +4205,80 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) * FIXME, needs more benchmarking...there are no reasons other than performance * to keep or drop this code. */ -void btrfs_dirty_inode(struct inode *inode, int flags) +int btrfs_dirty_inode(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; int ret; if (BTRFS_I(inode)->dummy_inode) - return; + return 0; trans = btrfs_join_transaction(root); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); if (ret && ret == -ENOSPC) { /* whoops, lets try again with the full transaction */ btrfs_end_transaction(trans, root); trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - printk_ratelimited(KERN_ERR "btrfs: fail to " - "dirty inode %llu error %ld\n", - (unsigned long long)btrfs_ino(inode), - PTR_ERR(trans)); - return; - } + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); - if (ret) { - printk_ratelimited(KERN_ERR "btrfs: fail to " - "dirty inode %llu error %d\n", - (unsigned long long)btrfs_ino(inode), - ret); - } } btrfs_end_transaction(trans, root); if (BTRFS_I(inode)->delayed_node) btrfs_balance_delayed_items(root); + + return ret; +} + +/* + * This is a copy of file_update_time. We need this so we can return error on + * ENOSPC for updating the inode in the case of file write and mmap writes. + */ +int btrfs_update_time(struct file *file) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct timespec now; + int ret; + enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; + + /* First try to exhaust all avenues to not sync */ + if (IS_NOCMTIME(inode)) + return 0; + + now = current_fs_time(inode->i_sb); + if (!timespec_equal(&inode->i_mtime, &now)) + sync_it = S_MTIME; + + if (!timespec_equal(&inode->i_ctime, &now)) + sync_it |= S_CTIME; + + if (IS_I_VERSION(inode)) + sync_it |= S_VERSION; + + if (!sync_it) + return 0; + + /* Finally allowed to write? Takes lock. */ + if (mnt_want_write_file(file)) + return 0; + + /* Only change inode inside the lock region */ + if (sync_it & S_VERSION) + inode_inc_iversion(inode); + if (sync_it & S_CTIME) + inode->i_ctime = now; + if (sync_it & S_MTIME) + inode->i_mtime = now; + ret = btrfs_dirty_inode(inode); + if (!ret) + mark_inode_dirty_sync(inode); + mnt_drop_write(file->f_path.mnt); + return ret; } /* @@ -6304,6 +6343,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) u64 page_end; ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); + if (!ret) + ret = btrfs_update_time(vma->vm_file); if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; @@ -7353,6 +7394,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { .follow_link = page_follow_link_light, .put_link = page_put_link, .getattr = btrfs_getattr, + .setattr = btrfs_setattr, .permission = btrfs_permission, .setxattr = btrfs_setxattr, .getxattr = btrfs_getxattr, diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1a3ce9e0b495..05b40457e26c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "compat.h" #include "delayed-inode.h" #include "ctree.h" @@ -1290,6 +1291,16 @@ static int btrfs_unfreeze(struct super_block *sb) return 0; } +static void btrfs_fs_dirty_inode(struct inode *inode, int flags) +{ + int ret; + + ret = btrfs_dirty_inode(inode); + if (ret) + printk_ratelimited(KERN_ERR "btrfs: fail to dirty inode %Lu " + "error %d\n", btrfs_ino(inode), ret); +} + static const struct super_operations btrfs_super_ops = { .drop_inode = btrfs_drop_inode, .evict_inode = btrfs_evict_inode, @@ -1297,7 +1308,7 @@ static const struct super_operations btrfs_super_ops = { .sync_fs = btrfs_sync_fs, .show_options = btrfs_show_options, .write_inode = btrfs_write_inode, - .dirty_inode = btrfs_dirty_inode, + .dirty_inode = btrfs_fs_dirty_inode, .alloc_inode = btrfs_alloc_inode, .destroy_inode = btrfs_destroy_inode, .statfs = btrfs_statfs, -- cgit From 660d3f6cde552323578b85fc5a09a6742f1fe804 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 9 Dec 2011 11:18:51 -0500 Subject: Btrfs: fix how we do delalloc reservations and how we free reservations on error Running xfstests 269 with some tracing my scripts kept spitting out errors about releasing bytes that we didn't actually have reserved. This took me down a huge rabbit hole and it turns out the way we deal with reserved_extents is wrong, we need to only be setting it if the reservation succeeds, otherwise the free() method will come in and unreserve space that isn't actually reserved yet, which can lead to other warnings and such. The math was all working out right in the end, but it caused all sorts of other issues in addition to making my scripts yell and scream and generally make it impossible for me to track down the original issue I was looking for. The other problem is with our error handling in the reservation code. There are two cases that we need to deal with 1) We raced with free. In this case free won't free anything because csum_bytes is modified before we dro the lock in our reservation path, so free rightly doesn't release any space because the reservation code may be depending on that reservation. However if we fail, we need the reservation side to do the free at that point since that space is no longer in use. So as it stands the code was doing this fine and it worked out, except in case #2 2) We don't race with free. Nobody comes in and changes anything, and our reservation fails. In this case we didn't reserve anything anyway and we just need to clean up csum_bytes but not free anything. So we keep track of csum_bytes before we drop the lock and if it hasn't changed we know we can just decrement csum_bytes and carry on. Because of the case where we can race with free()'s since we have to drop our spin_lock to do the reservation, I'm going to serialize all reservations with the i_mutex. We already get this for free in the heavy use paths, truncate and file write all hold the i_mutex, just needed to add it to page_mkwrite and various ioctl/balance things. With this patch my space leak scripts no longer scream bloody murder. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 43 ++++++++++++++++++++++++++++++------------- fs/btrfs/inode.c | 10 ++++++++++ fs/btrfs/ioctl.c | 2 ++ fs/btrfs/relocation.c | 2 ++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 05e1386b8bec..4eb4d2748bec 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4203,12 +4203,17 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; u64 to_reserve = 0; + u64 csum_bytes; unsigned nr_extents = 0; + int extra_reserve = 0; int flush = 1; int ret; + /* Need to be holding the i_mutex here if we aren't free space cache */ if (btrfs_is_free_space_inode(root, inode)) flush = 0; + else + WARN_ON(!mutex_is_locked(&inode->i_mutex)); if (flush && btrfs_transaction_in_commit(root->fs_info)) schedule_timeout(1); @@ -4219,11 +4224,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) BTRFS_I(inode)->outstanding_extents++; if (BTRFS_I(inode)->outstanding_extents > - BTRFS_I(inode)->reserved_extents) { + BTRFS_I(inode)->reserved_extents) nr_extents = BTRFS_I(inode)->outstanding_extents - BTRFS_I(inode)->reserved_extents; - BTRFS_I(inode)->reserved_extents += nr_extents; - } /* * Add an item to reserve for updating the inode when we complete the @@ -4231,11 +4234,12 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) */ if (!BTRFS_I(inode)->delalloc_meta_reserved) { nr_extents++; - BTRFS_I(inode)->delalloc_meta_reserved = 1; + extra_reserve = 1; } to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); + csum_bytes = BTRFS_I(inode)->csum_bytes; spin_unlock(&BTRFS_I(inode)->lock); ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); @@ -4245,22 +4249,35 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) spin_lock(&BTRFS_I(inode)->lock); dropped = drop_outstanding_extent(inode); - to_free = calc_csum_metadata_size(inode, num_bytes, 0); - spin_unlock(&BTRFS_I(inode)->lock); - to_free += btrfs_calc_trans_metadata_size(root, dropped); - /* - * Somebody could have come in and twiddled with the - * reservation, so if we have to free more than we would have - * reserved from this reservation go ahead and release those - * bytes. + * If the inodes csum_bytes is the same as the original + * csum_bytes then we know we haven't raced with any free()ers + * so we can just reduce our inodes csum bytes and carry on. + * Otherwise we have to do the normal free thing to account for + * the case that the free side didn't free up its reserve + * because of this outstanding reservation. */ - to_free -= to_reserve; + if (BTRFS_I(inode)->csum_bytes == csum_bytes) + calc_csum_metadata_size(inode, num_bytes, 0); + else + to_free = calc_csum_metadata_size(inode, num_bytes, 0); + spin_unlock(&BTRFS_I(inode)->lock); + if (dropped) + to_free += btrfs_calc_trans_metadata_size(root, dropped); + if (to_free) btrfs_block_rsv_release(root, block_rsv, to_free); return ret; } + spin_lock(&BTRFS_I(inode)->lock); + if (extra_reserve) { + BTRFS_I(inode)->delalloc_meta_reserved = 1; + nr_extents--; + } + BTRFS_I(inode)->reserved_extents += nr_extents; + spin_unlock(&BTRFS_I(inode)->lock); + block_rsv_add_bytes(block_rsv, to_reserve, 1); return 0; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index eec33b9c953d..8938174e6bc1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2192,7 +2192,14 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) continue; } nr_truncate++; + /* + * Need to hold the imutex for reservation purposes, not + * a huge deal here but I have a WARN_ON in + * btrfs_delalloc_reserve_space to catch offenders. + */ + mutex_lock(&inode->i_mutex); ret = btrfs_truncate(inode); + mutex_unlock(&inode->i_mutex); } else { nr_unlink++; } @@ -6342,7 +6349,10 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) u64 page_start; u64 page_end; + /* Need this to keep space reservations serialized */ + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); + mutex_unlock(&inode->i_mutex); if (!ret) ret = btrfs_update_time(vma->vm_file); if (ret) { diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 72d461656f60..dd8891662355 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -858,8 +858,10 @@ static int cluster_pages_for_defrag(struct inode *inode, return 0; file_end = (isize - 1) >> PAGE_CACHE_SHIFT; + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_space(inode, num_pages << PAGE_CACHE_SHIFT); + mutex_unlock(&inode->i_mutex); if (ret) return ret; again: diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index dff29d5e151a..cfb55434a469 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2947,7 +2947,9 @@ static int relocate_file_extent_cluster(struct inode *inode, index = (cluster->start - offset) >> PAGE_CACHE_SHIFT; last_index = (cluster->end - offset) >> PAGE_CACHE_SHIFT; while (index <= last_index) { + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_metadata(inode, PAGE_CACHE_SIZE); + mutex_unlock(&inode->i_mutex); if (ret) goto out; -- cgit From 7041ee97281c30a78658904140c7bd9373a36142 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 9 Dec 2011 13:26:22 -0500 Subject: Btrfs: fix leaked space in truncate We were occasionaly leaking space when running xfstest 269. This is because if we failed to start the transaction in the truncate loop we'd just goto out, but we need to break so that the inode is removed from the orphan list and the space is properly freed. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8938174e6bc1..6349c63a4b37 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6566,8 +6566,9 @@ static int btrfs_truncate(struct inode *inode) /* Just need the 1 for updating the inode */ trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { - err = PTR_ERR(trans); - goto out; + ret = err = PTR_ERR(trans); + trans = NULL; + break; } } -- cgit From ee4d89f0c4967c624c92516fcc37b41069bfdc23 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 13 Dec 2011 12:55:58 -0500 Subject: Btrfs: don't panic if orphan item already exists I've been hitting this BUG_ON() in btrfs_orphan_add when running xfstest 269 in a loop. This is because we will add an orphan item, do the truncate, the truncate will fail for whatever reason (*cough*ENOSPC*cough*) and then we're left with an orphan item still in the fs. Then we come back later to do another truncate and it blows up because we already have an orphan item. This is ok so just fix the BUG_ON() to only BUG() if ret is not EEXIST. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6349c63a4b37..b212f391ceab 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2032,7 +2032,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) /* insert an orphan item to track this unlinked/truncated file */ if (insert >= 1) { ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); - BUG_ON(ret); + BUG_ON(ret && ret != -EEXIST); } /* insert an orphan item to track subvolume contains orphan files */ -- cgit From e65cbb94e036058128a5dec6398be2fd64cf88ba Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 13 Dec 2011 16:04:54 -0500 Subject: Btrfs: only set cache_generation if we setup the block group A user reported a problem booting into a new kernel with the old format inodes. He was panicing in cow_file_range while writing out the inode cache. This is because if the block group is not cached we'll just skip writing out the cache, however if it gets dirtied again in the same transaction and it finished caching we'd go ahead and write it out, but since we set cache_generation to the transid we think we've already truncated it and will just carry on, running into cow_file_range and blowing up. We need to make sure we only set cache_generation if we've done the truncate. The user tested this patch and verified that the panic no longer occured. Thanks, Reported-and-Tested-by: Klaus Bitto Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4eb4d2748bec..8603ee4e3dfd 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2822,7 +2822,7 @@ out_free: btrfs_release_path(path); out: spin_lock(&block_group->lock); - if (!ret) + if (!ret && dcs == BTRFS_DC_SETUP) block_group->cache_generation = trans->transid; block_group->disk_cache_state = dcs; spin_unlock(&block_group->lock); -- cgit From d3db728125c4470a2d061ac10fa7395e18237263 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 14 Dec 2011 12:16:08 +0000 Subject: xen: only limit memory map to maximum reservation for domain 0. d312ae878b6a "xen: use maximum reservation to limit amount of usable RAM" clamped the total amount of RAM to the current maximum reservation. This is correct for dom0 but is not correct for guest domains. In order to boot a guest "pre-ballooned" (e.g. with memory=1G but maxmem=2G) in order to allow for future memory expansion the guest must derive max_pfn from the e820 provided by the toolstack and not the current maximum reservation (which can reflect only the current maximum, not the guest lifetime max). The existing algorithm already behaves this correctly if we do not artificially limit the maximum number of pages for the guest case. For a guest booted with maxmem=512, memory=128 this results in: [ 0.000000] BIOS-provided physical RAM map: [ 0.000000] Xen: 0000000000000000 - 00000000000a0000 (usable) [ 0.000000] Xen: 00000000000a0000 - 0000000000100000 (reserved) -[ 0.000000] Xen: 0000000000100000 - 0000000008100000 (usable) -[ 0.000000] Xen: 0000000008100000 - 0000000020800000 (unusable) +[ 0.000000] Xen: 0000000000100000 - 0000000020800000 (usable) ... [ 0.000000] NX (Execute Disable) protection: active [ 0.000000] DMI not present or invalid. [ 0.000000] e820 update range: 0000000000000000 - 0000000000010000 (usable) ==> (reserved) [ 0.000000] e820 remove range: 00000000000a0000 - 0000000000100000 (usable) -[ 0.000000] last_pfn = 0x8100 max_arch_pfn = 0x1000000 +[ 0.000000] last_pfn = 0x20800 max_arch_pfn = 0x1000000 [ 0.000000] initial memory mapped : 0 - 027ff000 [ 0.000000] Base memory trampoline at [c009f000] 9f000 size 4096 -[ 0.000000] init_memory_mapping: 0000000000000000-0000000008100000 -[ 0.000000] 0000000000 - 0008100000 page 4k -[ 0.000000] kernel direct mapping tables up to 8100000 @ 27bb000-27ff000 +[ 0.000000] init_memory_mapping: 0000000000000000-0000000020800000 +[ 0.000000] 0000000000 - 0020800000 page 4k +[ 0.000000] kernel direct mapping tables up to 20800000 @ 26f8000-27ff000 [ 0.000000] xen: setting RW the range 27e8000 - 27ff000 [ 0.000000] 0MB HIGHMEM available. -[ 0.000000] 129MB LOWMEM available. -[ 0.000000] mapped low ram: 0 - 08100000 -[ 0.000000] low ram: 0 - 08100000 +[ 0.000000] 520MB LOWMEM available. +[ 0.000000] mapped low ram: 0 - 20800000 +[ 0.000000] low ram: 0 - 20800000 With this change "xl mem-set 512M" will successfully increase the guest RAM (by reducing the balloon). There is no change for dom0. Reported-and-Tested-by: George Shuklin Signed-off-by: Ian Campbell Cc: stable@kernel.org Reviewed-by: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/setup.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 38d0af4fefec..a54ff1aab6eb 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -173,9 +173,21 @@ static unsigned long __init xen_get_max_pages(void) domid_t domid = DOMID_SELF; int ret; - ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); - if (ret > 0) - max_pages = ret; + /* + * For the initial domain we use the maximum reservation as + * the maximum page. + * + * For guest domains the current maximum reservation reflects + * the current maximum rather than the static maximum. In this + * case the e820 map provided to us will cover the static + * maximum region. + */ + if (xen_initial_domain()) { + ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); + if (ret > 0) + max_pages = ret; + } + return min(max_pages, MAX_DOMAIN_PAGES); } -- cgit From 63a741757d15320a25ebf5778f8651cce2ed0611 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 15 Dec 2011 11:28:46 -0500 Subject: xen/swiotlb: Use page alignment for early buffer allocation. This fixes an odd bug found on a Dell PowerEdge 1850/0RC130 (BIOS A05 01/09/2006) where all of the modules doing pci_set_dma_mask would fail with: ata_piix 0000:00:1f.1: enabling device (0005 -> 0007) ata_piix 0000:00:1f.1: can't derive routing for PCI INT A ata_piix 0000:00:1f.1: BMDMA: failed to set dma mask, falling back to PIO The issue was the Xen-SWIOTLB was allocated such as that the end of buffer was stradling a page (and also above 4GB). The fix was spotted by Kalev Leonid which was to piggyback on git commit e79f86b2ef9c0a8c47225217c1018b7d3d90101c "swiotlb: Use page alignment for early buffer allocation" which: We could call free_bootmem_late() if swiotlb is not used, and it will shrink to page alignment. So alloc them with page alignment at first, to avoid lose two pages And doing that fixes the outstanding issue. CC: stable@kernel.org Suggested-by: "Kalev, Leonid" Reported-and-Tested-by: "Taylor, Neal E" Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 8e964b91c447..284798aaf8b1 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -166,7 +166,7 @@ retry: /* * Get IO TLB memory from any location. */ - xen_io_tlb_start = alloc_bootmem(bytes); + xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); if (!xen_io_tlb_start) { m = "Cannot allocate Xen-SWIOTLB buffer!\n"; goto error; @@ -179,7 +179,7 @@ retry: bytes, xen_io_tlb_nslabs); if (rc) { - free_bootmem(__pa(xen_io_tlb_start), bytes); + free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); m = "Failed to get contiguous memory for DMA from Xen!\n"\ "You either: don't have the permissions, do not have"\ " enough free memory under 4GB, or the hypervisor memory"\ -- cgit From 87b9b0e0d50db3282fb1eb702307ccfca8775744 Mon Sep 17 00:00:00 2001 From: Ashish Jangam Date: Thu, 15 Dec 2011 14:55:46 +0530 Subject: gpio: Fix DA9052 GPIO build errors. This patch is functionally tested on Samsung SMDKV6410. Reported-by: Stephen Rothwell Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam [grant.likely: don't create an unnecessary header file] Signed-off-by: Grant Likely --- drivers/gpio/gpio-da9052.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 038f5eb8b13d..f8ce29ef9f88 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -22,7 +22,6 @@ #include #include #include -#include #define DA9052_INPUT 1 #define DA9052_OUTPUT_OPENDRAIN 2 @@ -43,6 +42,9 @@ #define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0 #define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F #define DA9052_GPIO_NIBBLE_SHIFT 4 +#define DA9052_IRQ_GPI0 16 +#define DA9052_GPIO_ODD_SHIFT 7 +#define DA9052_GPIO_EVEN_SHIFT 3 struct da9052_gpio { struct da9052 *da9052; @@ -104,33 +106,26 @@ static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset) static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value) { struct da9052_gpio *gpio = to_da9052_gpio(gc); - unsigned char register_value = 0; int ret; if (da9052_gpio_port_odd(offset)) { - if (value) { - register_value = DA9052_GPIO_ODD_PORT_MODE; ret = da9052_reg_update(gpio->da9052, (offset >> 1) + DA9052_GPIO_0_1_REG, DA9052_GPIO_ODD_PORT_MODE, - register_value); + value << DA9052_GPIO_ODD_SHIFT); if (ret != 0) dev_err(gpio->da9052->dev, "Failed to updated gpio odd reg,%d", ret); - } } else { - if (value) { - register_value = DA9052_GPIO_EVEN_PORT_MODE; ret = da9052_reg_update(gpio->da9052, (offset >> 1) + DA9052_GPIO_0_1_REG, DA9052_GPIO_EVEN_PORT_MODE, - register_value); + value << DA9052_GPIO_EVEN_SHIFT); if (ret != 0) dev_err(gpio->da9052->dev, "Failed to updated gpio even reg,%d", ret); - } } } @@ -201,9 +196,9 @@ static struct gpio_chip reference_gp __devinitdata = { .direction_input = da9052_gpio_direction_input, .direction_output = da9052_gpio_direction_output, .to_irq = da9052_gpio_to_irq, - .can_sleep = 1; - .ngpio = 16; - .base = -1; + .can_sleep = 1, + .ngpio = 16, + .base = -1, }; static int __devinit da9052_gpio_probe(struct platform_device *pdev) -- cgit From e755d9ab387c4c2401dce5b6f435432a829f41cb Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Thu, 15 Dec 2011 13:36:29 -0500 Subject: Btrfs: deal with NULL srv_rsv in the delalloc inode reservation code btrfs_update_inode is sometimes called with a null reservation. Signed-off-by: Chris Mason --- fs/btrfs/delayed-inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6a1a6800776c..c7ddf8a01c54 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -640,8 +640,8 @@ static int btrfs_delayed_inode_reserve_metadata( * Now if src_rsv == delalloc_block_rsv we'll let it just steal since * we're accounted for. */ - if (!trans->bytes_reserved && - src_rsv != &root->fs_info->delalloc_block_rsv) { + if (!src_rsv || (!trans->bytes_reserved && + src_rsv != &root->fs_info->delalloc_block_rsv)) { ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes); /* * Since we're under a transaction reserve_metadata_bytes could -- cgit From 4eabc941259f9d8c8fb71746d3f30c87e1d9e49b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 15 Dec 2011 20:03:04 +0100 Subject: block: don't kick empty queue in blk_drain_queue() While probing, fd sets up queue, probes hardware and tears down the queue if probing fails. In the process, blk_drain_queue() kicks the queue which failed to finish initialization and fd is unhappy about that. floppy0: no floppy controllers found ------------[ cut here ]------------ WARNING: at drivers/block/floppy.c:2929 do_fd_request+0xbf/0xd0() Hardware name: To Be Filled By O.E.M. VFS: do_fd_request called on non-open device Modules linked in: Pid: 1, comm: swapper Not tainted 3.2.0-rc4-00077-g5983fe2 #2 Call Trace: [] warn_slowpath_common+0x7a/0xb0 [] warn_slowpath_fmt+0x41/0x50 [] do_fd_request+0xbf/0xd0 [] blk_drain_queue+0x65/0x80 [] blk_cleanup_queue+0xe3/0x1a0 [] floppy_init+0xdeb/0xe28 [] ? daring+0x6b/0x6b [] do_one_initcall+0x3f/0x170 [] kernel_init+0x9d/0x11e [] ? schedule_tail+0x22/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? start_kernel+0x2be/0x2be [] ? gs_change+0xb/0xb Avoid it by making blk_drain_queue() kick queue iff dispatch queue has something on it. Signed-off-by: Tejun Heo Reported-by: Ralf Hildebrandt Reported-by: Wu Fengguang Tested-by: Sergei Trofimovich Signed-off-by: Jens Axboe --- block/blk-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/block/blk-core.c b/block/blk-core.c index 20d69f6beb6b..15de223c7f93 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -366,7 +366,14 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) if (drain_all) blk_throtl_drain(q); - __blk_run_queue(q); + /* + * This function might be called on a queue which failed + * driver init after queue creation. Some drivers + * (e.g. fd) get unhappy in such cases. Kick queue iff + * dispatch queue has something on it. + */ + if (!list_empty(&q->queue_head)) + __blk_run_queue(q); if (drain_all) nr_rqs = q->rq.count[0] + q->rq.count[1]; -- cgit From 9f57bd4d6dc69a4e3bf43044fa00fcd24dd363e3 Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Thu, 15 Dec 2011 11:25:59 -0800 Subject: percpu: fix per_cpu_ptr_to_phys() handling of non-page-aligned addresses per_cpu_ptr_to_phys() incorrectly rounds up its result for non-kmalloc case to the page boundary, which is bogus for any non-page-aligned address. This affects the only in-tree user of this function - sysfs handler for per-cpu 'crash_notes' physical address. The trouble is that the crash_notes per-cpu variable is not page-aligned: crash_notes = 0xc08e8ed4 PER-CPU OFFSET VALUES: CPU 0: 3711f000 CPU 1: 37129000 CPU 2: 37133000 CPU 3: 3713d000 So, the per-cpu addresses are: crash_notes on CPU 0: f7a07ed4 => phys 36b57ed4 crash_notes on CPU 1: f7a11ed4 => phys 36b4ded4 crash_notes on CPU 2: f7a1bed4 => phys 36b43ed4 crash_notes on CPU 3: f7a25ed4 => phys 36b39ed4 However, /sys/devices/system/cpu/cpu*/crash_notes says: /sys/devices/system/cpu/cpu0/crash_notes: 36b57000 /sys/devices/system/cpu/cpu1/crash_notes: 36b4d000 /sys/devices/system/cpu/cpu2/crash_notes: 36b43000 /sys/devices/system/cpu/cpu3/crash_notes: 36b39000 As you can see, all values are rounded down to a page boundary. Consequently, this is where kexec sets up the NOTE segments, and thus where the secondary kernel is looking for them. However, when the first kernel crashes, it saves the notes to the unaligned addresses, where they are not found. Fix it by adding offset_in_page() to the translated page address. -tj: Combined Eugene's and Petr's commit messages. Signed-off-by: Eugene Surovegin Signed-off-by: Tejun Heo Reported-by: Petr Tesarik Cc: stable@kernel.org --- mm/percpu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/percpu.c b/mm/percpu.c index 3bb810a72006..716eb4acf2fc 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1023,9 +1023,11 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr) if (!is_vmalloc_addr(addr)) return __pa(addr); else - return page_to_phys(vmalloc_to_page(addr)); + return page_to_phys(vmalloc_to_page(addr)) + + offset_in_page(addr); } else - return page_to_phys(pcpu_addr_to_page(addr)); + return page_to_phys(pcpu_addr_to_page(addr)) + + offset_in_page(addr); } /** -- cgit From d85c8a6f1bc083279215ff6e79b7c292bf3ec905 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Thu, 15 Dec 2011 15:38:41 -0500 Subject: Btrfs: unplug every once and a while The btrfs io submission threads can build up massive plug lists. This keeps things more reasonable so we don't hand over huge dumps of IO at once. Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 91ea57a1474a..f4b839fd3c9d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -295,6 +295,12 @@ loop_lock: btrfs_requeue_work(&device->work); goto done; } + /* unplug every 64 requests just for good measure */ + if (batch_run % 64 == 0) { + blk_finish_plug(&plug); + blk_start_plug(&plug); + sync_pending = 0; + } } cond_resched(); -- cgit From ddf5a25c5fdd4cc276edf451871c38002eec0f95 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 15 Dec 2011 21:47:56 +0100 Subject: ARM: unwinder: fix bisection to find origin in .idx section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bisection implemented in unwind_find_origin() stopped to early. If there is only a single entry left to check the original code just took the end point as origin which might be wrong. This was introduced in commit de66a979012d ("ARM: 7187/1: fix unwinding for XIP kernels"). Reported-and-tested-by: Nick Bowler Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Torvalds --- arch/arm/kernel/unwind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 3f03fe0c3269..00df012c4678 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -160,12 +160,12 @@ static const struct unwind_idx *unwind_find_origin( const struct unwind_idx *start, const struct unwind_idx *stop) { pr_debug("%s(%p, %p)\n", __func__, start, stop); - while (start < stop - 1) { + while (start < stop) { const struct unwind_idx *mid = start + ((stop - start) >> 1); if (mid->addr_offset >= 0x40000000) /* negative offset */ - start = mid; + start = mid + 1; else /* positive offset */ stop = mid; -- cgit From 6c52961743f38747401b47127b82159ab6d8a7a4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 15 Dec 2011 18:38:10 -0500 Subject: NFS: Fix a regression in nfs_file_llseek() After commit 06222e491e663dac939f04b125c9dc52126a75c4 (fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek) the behaviour of llseek() was changed so that it always revalidates the file size. The bug appears to be due to a logic error in the afore-mentioned commit, which always evaluates to 'true'. Reported-by: Roel Kluin Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org [>=3.1] --- fs/nfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eca56d4b39c0..606ef0f20aed 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -147,7 +147,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate * the cached file length */ - if (origin != SEEK_SET || origin != SEEK_CUR) { + if (origin != SEEK_SET && origin != SEEK_CUR) { struct inode *inode = filp->f_mapping->host; int retval = nfs_revalidate_file_size(inode, filp); -- cgit From ab2789213d224202237292d78aaa0c386c7b28b2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 15 Dec 2011 11:47:00 -0800 Subject: sched: Fix select_idle_sibling() regression in selecting an idle SMT sibling Mike Galbraith reported that this recent commit: commit 4dcfe1025b513c2c1da5bf5586adb0e80148f612 Author: Peter Zijlstra Date: Thu Nov 10 13:01:10 2011 +0100 sched: Avoid SMT siblings in select_idle_sibling() if possible stopped selecting an idle SMT sibling when there are no idle cores in a single socket system. Intent of the select_idle_sibling() was to fallback to an idle SMT sibling, if it fails to identify an idle core. But this fallback was not happening on systems where all the scheduler domains had `SD_SHARE_PKG_RESOURCES' flag set. Fix it. Slightly bigger patch of cleaning all these goto's etc is queued up for the next release. Reported-by: Mike Galbraith Reported-by: Alex Shi Signed-off-by: Peter Zijlstra Signed-off-by: Suresh Siddha Link: http://lkml.kernel.org/r/1323978421.1984.244.camel@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- kernel/sched_fair.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index a78ed2736ba7..8a39fa3e3c6c 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2352,13 +2352,11 @@ again: if (!smt && (sd->flags & SD_SHARE_CPUPOWER)) continue; - if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) { - if (!smt) { - smt = 1; - goto again; - } + if (smt && !(sd->flags & SD_SHARE_CPUPOWER)) + break; + + if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) break; - } sg = sd->groups; do { @@ -2378,6 +2376,10 @@ next: sg = sg->next; } while (sg != sd->groups); } + if (!smt) { + smt = 1; + goto again; + } done: rcu_read_unlock(); -- cgit From 0999bbe08196cd9459683204974fda4d62a7d1b3 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 28 Nov 2011 12:22:56 -0500 Subject: drm/i915: no-lvds quirk for ASUS AT5NM10T-I https://bugzilla.redhat.com/show_bug.cgi?id=750006 Signed-off-by: Adam Jackson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 42f165a520de..e44191132ac4 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -715,6 +715,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Asus AT5NM10T-I", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"), + }, + }, { } /* terminating entry */ }; -- cgit From 3573c4103f7a486838bb6b5b8353788103f91802 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 14 Oct 2011 18:16:22 -0300 Subject: drm/i915: set the right SDVO transcoder for CPT v2: add a CPT-specific macro, make code cleaner v3: fix commit message Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41272 Cc: stable@kernel.org Signed-off-by: Paulo Zanoni Reviewed-by: Chris Wilson Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6ef68c74189d..a26d5b0a3690 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3303,10 +3303,10 @@ /* or SDVOB */ #define HDMIB 0xe1140 #define PORT_ENABLE (1 << 31) -#define TRANSCODER_A (0) -#define TRANSCODER_B (1 << 30) -#define TRANSCODER(pipe) ((pipe) << 30) -#define TRANSCODER_MASK (1 << 30) +#define TRANSCODER(pipe) ((pipe) << 30) +#define TRANSCODER_CPT(pipe) ((pipe) << 29) +#define TRANSCODER_MASK (1 << 30) +#define TRANSCODER_MASK_CPT (3 << 29) #define COLOR_FORMAT_8bpc (0) #define COLOR_FORMAT_12bpc (3 << 26) #define SDVOB_HOTPLUG_ENABLE (1 << 23) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3003fb25aefd..e308d674c669 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1086,8 +1086,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, } sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; } - if (intel_crtc->pipe == 1) - sdvox |= SDVO_PIPE_B_SELECT; + + if (INTEL_PCH_TYPE(dev) >= PCH_CPT) + sdvox |= TRANSCODER_CPT(intel_crtc->pipe); + else + sdvox |= TRANSCODER(intel_crtc->pipe); + if (intel_sdvo->has_hdmi_audio) sdvox |= SDVO_AUDIO_ENABLE; -- cgit From 03d00ac53f9bcde06ff7e33d6676083c18d569a4 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 14 Oct 2011 18:17:41 -0300 Subject: drm/i915: add PCH info to i915_capabilities Signed-off-by: Chris Wilson Signed-off-by: Paulo Zanoni Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d09a6e02dc95..004b048c5192 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -62,6 +62,7 @@ static int i915_capabilities(struct seq_file *m, void *data) const struct intel_device_info *info = INTEL_INFO(dev); seq_printf(m, "gen: %d\n", info->gen); + seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev)); #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x)) B(is_mobile); B(is_i85x); -- cgit From 4ed0b577457eb6aeb7cdc7e7316576e63d15abb2 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Thu, 10 Nov 2011 13:55:15 -0200 Subject: drm/i915: prevent division by zero when asking for chipset power This prevents an in-kernel division by zero which happens when we are asking for i915_chipset_val too quickly, or within a race condition between the power monitoring thread and userspace accesses via debugfs. The issue can be reproduced easily via the following command: while ``; do cat /sys/kernel/debug/dri/0/i915_emon_status; done This is particularly dangerous because it can be triggered by a non-privileged user by just reading the debugfs entry. This issue was also found independently by Konstantin Belousov , who proposed a similar patch. Reported-by: Konstantin Belousov Acked-by: Jesse Barnes Acked-by: Keith Packard Reviewed-by: Chris Wilson Cc: Signed-off-by: Eugeni Dodonov Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_dma.c | 10 ++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a9533c54c93c..a9ae374861e7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1454,6 +1454,14 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) diff1 = now - dev_priv->last_time1; + /* Prevent division-by-zero if we are asking too fast. + * Also, we don't get interesting results if we are polling + * faster than once in 10ms, so just return the saved value + * in such cases. + */ + if (diff1 <= 10) + return dev_priv->chipset_power; + count1 = I915_READ(DMIEC); count2 = I915_READ(DDREC); count3 = I915_READ(CSIEC); @@ -1484,6 +1492,8 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) dev_priv->last_count1 = total_count; dev_priv->last_time1 = now; + dev_priv->chipset_power = ret; + return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8ba88cfc36de..39a72f642b33 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -713,6 +713,7 @@ typedef struct drm_i915_private { u64 last_count1; unsigned long last_time1; + unsigned long chipset_power; u64 last_count2; struct timespec last_time2; unsigned long gfx_power; -- cgit From 522200858093a6f31af9830672109f6d9807dd1e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Jun 2011 14:45:50 +0100 Subject: drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check We were checking whether the supplied edid matched the connector it was read from. We do this in case a DDC read returns an EDID for another device on a multifunction or otherwise interesting card. However, we failed to include LVDS as a digital device and so rejecting an otherwise valid EDID. Fixes the detection of the secondary SDVO LVDS panel on the Libretto W105. Signed-off-by: Chris Wilson Reviewed-by: Adam Jackson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=39216 Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_sdvo.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e308d674c669..f7b9268df266 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -50,6 +50,7 @@ #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) +#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) static const char *tv_format_names[] = { @@ -1318,6 +1319,18 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) return status; } +static bool +intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, + struct edid *edid) +{ + bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); + bool connector_is_digital = !!IS_DIGITAL(sdvo); + + DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", + connector_is_digital, monitor_is_digital); + return connector_is_digital == monitor_is_digital; +} + static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector, bool force) { @@ -1362,10 +1375,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) if (edid == NULL) edid = intel_sdvo_get_analog_edid(connector); if (edid != NULL) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) - ret = connector_status_disconnected; - else + if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, + edid)) ret = connector_status_connected; + else + ret = connector_status_disconnected; + connector->display_info.raw_edid = NULL; kfree(edid); } else @@ -1406,11 +1421,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) edid = intel_sdvo_get_analog_edid(connector); if (edid != NULL) { - struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); - bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); - - if (connector_is_digital == monitor_is_digital) { + if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), + edid)) { drm_mode_connector_update_edid_property(connector, edid); drm_add_edid_modes(connector, edid); } -- cgit From 8bc1f85c02a20a59956b00b3acea12c04dce9ae8 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Wed, 23 Nov 2011 16:42:14 -0200 Subject: iommu: Export intel_iommu_enabled to signal when iommu is in use In i915 driver, we do not enable either rc6 or semaphores on SNB when dmar is enabled. The new 'intel_iommu_enabled' variable signals when the iommu code is in operation. Cc: Ted Phelps Cc: Peter Cc: Lukas Hejtmanek Cc: Andrew Lutomirski CC: Daniel Vetter Cc: Eugeni Dodonov Signed-off-by: Keith Packard --- drivers/iommu/intel-iommu.c | 5 +++++ include/linux/dma_remapping.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c0c7820d4c46..8dc19b8f5d45 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -405,6 +405,9 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/ +int intel_iommu_enabled = 0; +EXPORT_SYMBOL_GPL(intel_iommu_enabled); + static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -3647,6 +3650,8 @@ int __init intel_iommu_init(void) bus_register_notifier(&pci_bus_type, &device_nb); + intel_iommu_enabled = 1; + return 0; } diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index ef90cbd8e173..57c9a8ae4f2d 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -31,6 +31,7 @@ extern void free_dmar_iommu(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); extern int dmar_disabled; +extern int intel_iommu_enabled; #else static inline int iommu_calculate_agaw(struct intel_iommu *iommu) { @@ -44,6 +45,7 @@ static inline void free_dmar_iommu(struct intel_iommu *iommu) { } #define dmar_disabled (1) +#define intel_iommu_enabled (0) #endif -- cgit From c0f372b3746d4ede07b2ace2beabd38d9c045b25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Nov 2011 22:24:52 -0800 Subject: drm/i915: By default, enable RC6 on IVB and SNB when reasonable RC6 should always work on IVB, and should work on SNB whenever IO remapping is disabled. RC6 never works on Ironlake. Make the default value for the parameter follow these guidelines. Setting the value to either 0 or 1 will force the specified behavior. Signed-off-by: Keith Packard Reviewed-by: Kenneth Graunke Reviewed-by: Eugeni Dodonov Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38567 Cc: Ted Phelps Cc: Peter Cc: Lukas Hejtmanek Cc: Andrew Lutomirski --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_display.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 28836fe72211..47a42eb6cc43 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -63,10 +63,10 @@ module_param_named(semaphores, i915_semaphores, int, 0600); MODULE_PARM_DESC(semaphores, "Use semaphores for inter-ring sync (default: false)"); -unsigned int i915_enable_rc6 __read_mostly = 0; +int i915_enable_rc6 __read_mostly = -1; module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); MODULE_PARM_DESC(i915_enable_rc6, - "Enable power-saving render C-state 6 (default: true)"); + "Enable power-saving render C-state 6 (default: -1 (use per-chip default)"); int i915_enable_fbc __read_mostly = -1; module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 39a72f642b33..6bcafb5bf7fe 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1006,7 +1006,7 @@ extern unsigned int i915_semaphores __read_mostly; extern unsigned int i915_lvds_downclock __read_mostly; extern int i915_panel_use_ssc __read_mostly; extern int i915_vbt_sdvo_panel_type __read_mostly; -extern unsigned int i915_enable_rc6 __read_mostly; +extern int i915_enable_rc6 __read_mostly; extern int i915_enable_fbc __read_mostly; extern bool i915_enable_hangcheck __read_mostly; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 633c69365388..d544de9e6634 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -38,8 +38,8 @@ #include "i915_drv.h" #include "i915_trace.h" #include "drm_dp_helper.h" - #include "drm_crtc_helper.h" +#include #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) @@ -7887,6 +7887,33 @@ void intel_init_emon(struct drm_device *dev) dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); } +static bool intel_enable_rc6(struct drm_device *dev) +{ + /* + * Respect the kernel parameter if it is set + */ + if (i915_enable_rc6 >= 0) + return i915_enable_rc6; + + /* + * Disable RC6 on Ironlake + */ + if (INTEL_INFO(dev)->gen == 5) + return 0; + + /* + * Enable rc6 on Sandybridge if DMA remapping is disabled + */ + if (INTEL_INFO(dev)->gen == 6) { + DRM_DEBUG_DRIVER("Sandybridge: intel_iommu_enabled %s -- RC6 %sabled\n", + intel_iommu_enabled ? "true" : "false", + !intel_iommu_enabled ? "en" : "dis"); + return !intel_iommu_enabled; + } + DRM_DEBUG_DRIVER("RC6 enabled\n"); + return 1; +} + void gen6_enable_rps(struct drm_i915_private *dev_priv) { u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); @@ -7923,7 +7950,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ - if (i915_enable_rc6) + if (intel_enable_rc6(dev_priv->dev)) rc6_mask = GEN6_RC_CTL_RC6p_ENABLE | GEN6_RC_CTL_RC6_ENABLE; @@ -8372,7 +8399,7 @@ void ironlake_enable_rc6(struct drm_device *dev) /* rc6 disabled by default due to repeated reports of hanging during * boot and resume. */ - if (!i915_enable_rc6) + if (!intel_enable_rc6(dev)) return; mutex_lock(&dev->struct_mutex); -- cgit From 7317c75e66fce0c9f82fbe6f72f7e5256b315422 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 29 Aug 2011 09:45:28 -0700 Subject: drm/i915: don't set unpin_work if vblank_get fails This fixes a race where we may try to finish a page flip and decrement the refcount even if our vblank_get failed and we ended up with a spurious flip pending interrupt. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=34211. Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d544de9e6634..91b5f8707a62 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7189,11 +7189,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->old_fb_obj = intel_fb->obj; INIT_WORK(&work->work, intel_unpin_work_fn); + ret = drm_vblank_get(dev, intel_crtc->pipe); + if (ret) + goto free_work; + /* We borrow the event spin lock for protecting unpin_work */ spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { spin_unlock_irqrestore(&dev->event_lock, flags); kfree(work); + drm_vblank_put(dev, intel_crtc->pipe); DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); return -EBUSY; @@ -7212,10 +7217,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, crtc->fb = fb; - ret = drm_vblank_get(dev, intel_crtc->pipe); - if (ret) - goto cleanup_objs; - work->pending_flip_obj = obj; work->enable_stall_check = true; @@ -7238,7 +7239,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, cleanup_pending: atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); -cleanup_objs: drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); @@ -7247,6 +7247,8 @@ cleanup_objs: intel_crtc->unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); + drm_vblank_put(dev, intel_crtc->pipe); +free_work: kfree(work); return ret; -- cgit From f45b55575cedb7efa782e43f1ea74338456d0381 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Fri, 9 Dec 2011 17:16:37 -0800 Subject: drm/i915: enable semaphores on per-device defaults This adds a default setting for semaphores parameter, and enables semaphores by default on IVB. For now, as semaphores interaction with VTd causes random issues on SNB, we do not enable them by default. But they can still be enabled via the semaphores=1 kernel parameter. v2: enables semaphores on SNB when IO remapping is disabled, with base on Keith Packard patch. CC: Daniel Vetter CC: Ben Widawsky CC: Keith Packard CC: Jesse Barnes CC: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=42696 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=40564 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41353 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38862 Reviewed-by: Chris Wilson Reviewed-by: Daniel Vetter Signed-off-by: Eugeni Dodonov Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 47a42eb6cc43..a1103fc6597d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -58,10 +58,10 @@ module_param_named(powersave, i915_powersave, int, 0600); MODULE_PARM_DESC(powersave, "Enable powersavings, fbc, downclocking, etc. (default: true)"); -unsigned int i915_semaphores __read_mostly = 0; +int i915_semaphores __read_mostly = -1; module_param_named(semaphores, i915_semaphores, int, 0600); MODULE_PARM_DESC(semaphores, - "Use semaphores for inter-ring sync (default: false)"); + "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))"); int i915_enable_rc6 __read_mostly = -1; module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6bcafb5bf7fe..554bef7a3b9c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1002,7 +1002,7 @@ extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; extern int i915_panel_ignore_lid __read_mostly; extern unsigned int i915_powersave __read_mostly; -extern unsigned int i915_semaphores __read_mostly; +extern int i915_semaphores __read_mostly; extern unsigned int i915_lvds_downclock __read_mostly; extern int i915_panel_use_ssc __read_mostly; extern int i915_vbt_sdvo_panel_type __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 3693e83a97f3..c681dc149d2a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -32,6 +32,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include struct change_domains { uint32_t invalidate_domains; @@ -746,6 +747,22 @@ i915_gem_execbuffer_flush(struct drm_device *dev, return 0; } +static bool +intel_enable_semaphores(struct drm_device *dev) +{ + if (INTEL_INFO(dev)->gen < 6) + return 0; + + if (i915_semaphores >= 0) + return i915_semaphores; + + /* Enable semaphores on SNB when IO remapping is off */ + if (INTEL_INFO(dev)->gen == 6) + return !intel_iommu_enabled; + + return 1; +} + static int i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, struct intel_ring_buffer *to) @@ -758,7 +775,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, return 0; /* XXX gpu semaphores are implicated in various hard hangs on SNB */ - if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores) + if (!intel_enable_semaphores(obj->base.dev)) return i915_gem_object_wait_rendering(obj); idx = intel_ring_sync_index(from, to); -- cgit From 3b5c78a35cf7511c15e09a9b0ffab290a42d9bcf Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 13 Dec 2011 15:41:00 -0800 Subject: drm/i915/dp: Dither down to 6bpc if it makes the mode fit Some active adaptors (VGA usually) only have two lanes at 2.7GHz. That's a maximum pixel clock of 144MHz at 8bpc, but 192MHz at 6bpc. Fixes Asus UX31 panel being black at startup due to no valid modes since dc22ee6fc18ce0f15424e753e8473c306ece95c1. v2: Rebased to current code, resulting in the fix applying to EDP panels as well. Also changed from spatio-temporal to just spatial dithering on pre-ironlake, to be conssitent (and less visual flicker) Signed-off-by: Adam Jackson Signed-off-by: Eric Anholt Tested-by: Eric Anholt Tested-by: Dirk Hohndel Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++-- drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++++++++------ drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91b5f8707a62..d809b038ca88 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4670,6 +4670,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) /** * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send * @crtc: CRTC structure + * @mode: requested mode * * A pipe may be connected to one or more outputs. Based on the depth of the * attached framebuffer, choose a good color depth to use on the pipe. @@ -4681,13 +4682,15 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc * Displays may support a restricted set as well, check EDID and clamp as * appropriate. + * DP may want to dither down to 6bpc to fit larger modes * * RETURNS: * Dithering requirement (i.e. false if display bpc and pipe bpc match, * true if they don't match). */ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, - unsigned int *pipe_bpp) + unsigned int *pipe_bpp, + struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -4758,6 +4761,11 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + DRM_DEBUG_KMS("Dithering DP to 6bpc\n"); + display_bpc = 6; + } + /* * We could just drive the pipe at the highest bpc all the time and * enable dithering as needed, but that costs bandwidth. So choose @@ -5019,6 +5027,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPECONF_DOUBLE_WIDE; } + /* default to 8bpc */ + pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); + if (is_dp) { + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + pipeconf |= PIPECONF_BPP_6 | + PIPECONF_DITHER_EN | + PIPECONF_DITHER_TYPE_SP; + } + } + dpll |= DPLL_VCO_ENABLE; DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); @@ -5480,7 +5498,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp); + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); switch (pipe_bpp) { case 18: temp |= PIPE_6BPC; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 294f55788f0b..92b041b66e49 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -208,13 +208,15 @@ intel_dp_link_clock(uint8_t link_bw) */ static int -intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock) +intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp) { struct drm_crtc *crtc = intel_dp->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int bpp = 24; - if (intel_crtc) + if (check_bpp) + bpp = check_bpp; + else if (intel_crtc) bpp = intel_crtc->bpp; return (pixel_clock * bpp + 9) / 10; @@ -233,6 +235,7 @@ intel_dp_mode_valid(struct drm_connector *connector, struct intel_dp *intel_dp = intel_attached_dp(connector); int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_lanes = intel_dp_max_lane_count(intel_dp); + int max_rate, mode_rate; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) @@ -242,9 +245,17 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - if (intel_dp_link_required(intel_dp, mode->clock) - > intel_dp_max_data_rate(max_link_clock, max_lanes)) - return MODE_CLOCK_HIGH; + mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0); + max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); + + if (mode_rate > max_rate) { + mode_rate = intel_dp_link_required(intel_dp, + mode->clock, 18); + if (mode_rate > max_rate) + return MODE_CLOCK_HIGH; + else + mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; + } if (mode->clock < 10000) return MODE_CLOCK_LOW; @@ -672,6 +683,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, int lane_count, clock; int max_lane_count = intel_dp_max_lane_count(intel_dp); int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; + int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { @@ -689,7 +701,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); - if (intel_dp_link_required(intel_dp, mode->clock) + if (intel_dp_link_required(intel_dp, mode->clock, bpp) <= link_avail) { intel_dp->link_bw = bws[clock]; intel_dp->lane_count = lane_count; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bd9a604b73da..a1b4343814e8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -110,6 +110,7 @@ /* drm_display_mode->private_flags */ #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) +#define INTEL_MODE_DP_FORCE_6BPC (0x10) static inline void intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, -- cgit From 142349f541d0bb6bc3e0d4563268105aada42b0b Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 16 Dec 2011 12:32:57 -0500 Subject: btrfs: lower the dirty balance poll interval Tests show that the original large intervals can easily make the dirty limit exceeded on 100 concurrent dd's. So adapt to as large as the next check point selected by the dirty throttling algorithm. Signed-off-by: Wu Fengguang Signed-off-by: Chris Mason --- fs/btrfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index dafdfa059bf6..52305a885c3f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1167,6 +1167,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); + nrptrs = min(nrptrs, current->nr_dirtied_pause - current->nr_dirtied); + nrptrs = max(nrptrs, 8); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); if (!pages) return -ENOMEM; -- cgit From ed4a51842a9d9e618d4f4c31349b15b974dba5df Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 16 Dec 2011 12:58:39 -0800 Subject: Revert "drm/i915: fix infinite recursion on unbind due to ilk vt-d w/a" This reverts commit eb1711bb94991e93669c5a1b5f84f11be2d51ea1. It blows up the i915 seqno tracking, resulting in the BUG_ON(seqno == 0); in i915_wait_request() triggering, which will cause lock-ups. See for example https://bugs.launchpad.net/ubuntu/+source/linux/+bug/903010 https://lkml.org/lkml/2011/12/14/395 Reported-requested-and-tested-by: Dirk Hohndel Reported-by: Richard Eames Reported-by: Rocko Requin Acked-by: Daniel Vetter Cc: Dave Airlie Cc: Chris Wilson Cc: Keith Packard Cc: Eric Anholt Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_gem.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 60ff1b63b568..8359dc777041 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2026,13 +2026,8 @@ i915_wait_request(struct intel_ring_buffer *ring, * to handle this, the waiter on a request often wants an associated * buffer to have made it to the inactive list, and we would need * a separate wait queue to handle that. - * - * To avoid a recursion with the ilk VT-d workaround (that calls - * gpu_idle when unbinding objects with interruptible==false) don't - * retire requests in that case (because it might call unbind if the - * active list holds the last reference to the object). */ - if (ret == 0 && dev_priv->mm.interruptible) + if (ret == 0) i915_gem_retire_requests_ring(ring); return ret; -- cgit From 384703b8e6cd4c8ef08512e596024e028c91c339 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 16 Dec 2011 18:36:26 -0800 Subject: Linux 3.2-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d1ea73f74c2f..a43733df3978 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit From b3bba872ddb0320a7ecb54decae53c13ceb2ed4c Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Thu, 8 Dec 2011 16:53:54 -0600 Subject: writeback: show writeback reason with __print_symbolic This makes the binary trace understandable by trace-cmd. CC: Dave Chinner CC: Curt Wohlgemuth CC: Steven Rostedt Signed-off-by: Wu Fengguang --- fs/fs-writeback.c | 11 ----------- include/trace/events/writeback.h | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ac86f8b3e3cb..517f211a3bd4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -47,17 +47,6 @@ struct wb_writeback_work { struct completion *done; /* set if the caller waits */ }; -const char *wb_reason_name[] = { - [WB_REASON_BACKGROUND] = "background", - [WB_REASON_TRY_TO_FREE_PAGES] = "try_to_free_pages", - [WB_REASON_SYNC] = "sync", - [WB_REASON_PERIODIC] = "periodic", - [WB_REASON_LAPTOP_TIMER] = "laptop_timer", - [WB_REASON_FREE_MORE_MEM] = "free_more_memory", - [WB_REASON_FS_FREE_SPACE] = "fs_free_space", - [WB_REASON_FORKER_THREAD] = "forker_thread" -}; - /* * Include the creation of the trace points after defining the * wb_writeback_work structure so that the definition remains local to this diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index b99caa8b780c..99d1d0decf88 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -21,6 +21,16 @@ {I_REFERENCED, "I_REFERENCED"} \ ) +#define WB_WORK_REASON \ + {WB_REASON_BACKGROUND, "background"}, \ + {WB_REASON_TRY_TO_FREE_PAGES, "try_to_free_pages"}, \ + {WB_REASON_SYNC, "sync"}, \ + {WB_REASON_PERIODIC, "periodic"}, \ + {WB_REASON_LAPTOP_TIMER, "laptop_timer"}, \ + {WB_REASON_FREE_MORE_MEM, "free_more_memory"}, \ + {WB_REASON_FS_FREE_SPACE, "fs_free_space"}, \ + {WB_REASON_FORKER_THREAD, "forker_thread"} + struct wb_writeback_work; DECLARE_EVENT_CLASS(writeback_work_class, @@ -55,7 +65,7 @@ DECLARE_EVENT_CLASS(writeback_work_class, __entry->for_kupdate, __entry->range_cyclic, __entry->for_background, - wb_reason_name[__entry->reason] + __print_symbolic(__entry->reason, WB_WORK_REASON) ) ); #define DEFINE_WRITEBACK_WORK_EVENT(name) \ @@ -184,7 +194,8 @@ TRACE_EVENT(writeback_queue_io, __entry->older, /* older_than_this in jiffies */ __entry->age, /* older_than_this in relative milliseconds */ __entry->moved, - wb_reason_name[__entry->reason]) + __print_symbolic(__entry->reason, WB_WORK_REASON) + ) ); TRACE_EVENT(global_dirty_state, -- cgit From 37de03ea1246c8280f6c8c6f61ea98973e9b9448 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Dec 2011 20:55:03 +0800 Subject: i2c: i2c-s3c2410: Add a cpu_relax() to busy wait for bus idle Be a bit more friendly. Signed-off-by: Mark Brown Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 2754cef86a06..37b2de106808 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -534,6 +534,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, /* first, try busy waiting briefly */ do { + cpu_relax(); iicstat = readl(i2c->regs + S3C2410_IICSTAT); } while ((iicstat & S3C2410_IICSTAT_START) && --spins); -- cgit From 8ebe661dd2ab16e2e9c272ed5c86019c7407b9a1 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Fri, 9 Dec 2011 15:33:55 +0530 Subject: i2c-s3c2410: Fix return code of s3c24xx_i2c_parse_dt_gpio s3c24xx_i2c_parse_dt_gpio is called when cfg_gpio is not defined in the platform data of the i2c device. When DT is not enabled, the above function always returns -EINVAL. Since there can be some i2c devices which don't need to configure any gpio lines, the probe of such devices would fail here. Changing the default return value to success would fix this issue. Signed-off-by: Tushar Behera Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 37b2de106808..4c1718081685 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -787,7 +787,7 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) #else static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) { - return -EINVAL; + return 0; } static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) -- cgit From 1d5a34fe990c9e2e2f672b238ad881d0d4ed376b Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 6 Dec 2011 10:25:58 -0800 Subject: I2C: OMAP: fix FIFO usage for OMAP4 Currently the fifo depth is set to zero for OMAP4 which disables the FIFO usage. This patch enables the FIFO usage for I2C transactions on OMAP4 also. Tested on omap4430 and 3430. Tested-and-Reported-by: Nishanth Menon Signed-off-by: Shubhrajyoti D Signed-off-by: Kevin Hilman Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a43d0023446a..fa23faa20f0e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1047,13 +1047,14 @@ omap_i2c_probe(struct platform_device *pdev) * size. This is to ensure that we can handle the status on int * call back latencies. */ - if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) { - dev->fifo_size = 0; + + dev->fifo_size = (dev->fifo_size / 2); + + if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) dev->b_hw = 0; /* Disable hardware fixes */ - } else { - dev->fifo_size = (dev->fifo_size / 2); + else dev->b_hw = 1; /* Enable hardware fixes */ - } + /* calculate wakeup latency constraint for MPU */ if (dev->set_mpu_wkup_lat != NULL) dev->latency = (1000000 * dev->fifo_size) / -- cgit From 0d5fb5ea7d0e6bc84a523c39a666d7eb1a7e43de Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 29 Nov 2011 15:19:10 +0800 Subject: i2c-eg20t: correct the driver init order of pch_i2c_probe() Before registering an adapter to i2c subsystem, we need make sure driver is ready for incoming i2c xfer, becasue the i2c_add_adapter() may trigger a i2c device driver's proble function which may start some real i2c xfer. I met this issue when integrating a TSC2007 i2c touch screen device with the i2c-eg20t driver. This patch will call request_irq() and hw init before calling i2c_add_adapter(). Signed-off-by: Feng Tang Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-eg20t.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 8cebef49aeac..18936ac9d51c 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -893,6 +893,13 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev, /* Set the number of I2C channel instance */ adap_info->ch_num = id->driver_data; + ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, + KBUILD_MODNAME, adap_info); + if (ret) { + pch_pci_err(pdev, "request_irq FAILED\n"); + goto err_request_irq; + } + for (i = 0; i < adap_info->ch_num; i++) { pch_adap = &adap_info->pch_data[i].pch_adapter; adap_info->pch_i2c_suspended = false; @@ -910,28 +917,23 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev, pch_adap->dev.parent = &pdev->dev; + pch_i2c_init(&adap_info->pch_data[i]); ret = i2c_add_adapter(pch_adap); if (ret) { pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i); - goto err_i2c_add_adapter; + goto err_add_adapter; } - - pch_i2c_init(&adap_info->pch_data[i]); - } - ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, - KBUILD_MODNAME, adap_info); - if (ret) { - pch_pci_err(pdev, "request_irq FAILED\n"); - goto err_i2c_add_adapter; } pci_set_drvdata(pdev, adap_info); pch_pci_dbg(pdev, "returns %d.\n", ret); return 0; -err_i2c_add_adapter: +err_add_adapter: for (j = 0; j < i; j++) i2c_del_adapter(&adap_info->pch_data[j].pch_adapter); + free_irq(pdev->irq, adap_info); +err_request_irq: pci_iounmap(pdev, base_addr); err_pci_iomap: pci_release_regions(pdev); -- cgit From fa0ad6575f6d459e215dded90b10cc455a889145 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 5 Nov 2011 12:21:30 +0100 Subject: kconfig: adapt update-po-config to new UML layout Commit 5c48b108 ("um: take arch/um/sys-x86 to arch/x86/um") broke the make target update-po-config, as its symlink trick (again) fails. (Previous breakage was fixed with commit bdc69ca4 ("kconfig: change update-po-config to reflect new layout of arch/um").) The new UML layout allows to drop the symlick trick entirely. And if, one day, another architecture supports UML too, that should now work without again breaking this make target. Signed-off-by: Paul Bolle Signed-off-by: Michal Marek --- scripts/kconfig/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index ba573fe7c74d..914833d99b06 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -60,8 +60,8 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h --directory=$(srctree) --directory=$(objtree) \ --output $(obj)/config.pot $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot - $(Q)ln -fs Kconfig.x86 arch/um/Kconfig - $(Q)(for i in `ls $(srctree)/arch/*/Kconfig`; \ + $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \ + $(srctree)/arch/*/um/Kconfig`; \ do \ echo " GEN $$i"; \ $(obj)/kxgettext $$i \ @@ -69,7 +69,6 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h done ) $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ --output $(obj)/linux.pot - $(Q)rm -f $(srctree)/arch/um/Kconfig $(Q)rm -f $(obj)/config.pot PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig -- cgit From 497f16f21a04060098c0da6ed522fbcafb90c0db Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 17 Dec 2011 18:33:37 -0800 Subject: pci: Fix hotplug of Express Module with pci bridges I noticed that hotplug of one setup does not work with recent change in pci tree. After checking the bridge conf setup, I noticed that the bridges get assigned but do not get enabled. The reason is the following commit, while simply ignores bridge resources when enabling a pci device: | commit bbef98ab0f019f1b0c25c1acdf1683c68933d41b | Author: Ram Pai | Date: Sun Nov 6 10:33:10 2011 +0800 | | PCI: defer enablement of SRIOV BARS |... | NOTE: Note, there is subtle change in the pci_enable_device() API. Any | driver that depends on SRIOV BARS to be enabled in pci_enable_device() | can fail. Put back bridge resource and ROM resource checking to fix the problem. That should fix regression like BIOS does not assign correct resource to bridge. Discussion can be found at: http://www.spinics.net/lists/linux-pci/msg12874.html Signed-off-by: Yinghai Lu Acked-by: Jesse Barnes Signed-off-by: Linus Torvalds --- drivers/pci/pci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index faccb8937706..6d4a5319148d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1129,7 +1129,11 @@ static int __pci_enable_device_flags(struct pci_dev *dev, if (atomic_add_return(1, &dev->enable_cnt) > 1) return 0; /* already enabled */ - for (i = 0; i < PCI_ROM_RESOURCE; i++) + /* only skip sriov related */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) + if (dev->resource[i].flags & flags) + bars |= (1 << i); + for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++) if (dev->resource[i].flags & flags) bars |= (1 << i); -- cgit From 36e999a83a4a4badd389901eb6d23a30e199b8db Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Thu, 8 Dec 2011 17:23:21 -0800 Subject: Bluetooth: Prevent uninitialized data access in L2CAP configuration When configuring an ERTM or streaming mode connection, remote devices are expected to send an RFC option in a successful config response. A misbehaving remote device might not send an RFC option, and the L2CAP code should not access uninitialized data in this case. Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap_core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 5ea94a1eecf2..17b5b1cd9657 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2152,7 +2152,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi void *ptr = req->data; int type, olen; unsigned long val; - struct l2cap_conf_rfc rfc; + struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); @@ -2271,6 +2271,16 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) } } + /* Use sane default values in case a misbehaving remote device + * did not send an RFC option. + */ + rfc.mode = chan->mode; + rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); + rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); + rfc.max_pdu_size = cpu_to_le16(chan->imtu); + + BT_ERR("Expected RFC option was not found, using defaults"); + done: switch (rfc.mode) { case L2CAP_MODE_ERTM: -- cgit From 79e654787c67f6b05f73366ff8ccac72ba7249e6 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Tue, 6 Dec 2011 16:23:26 -0800 Subject: Bluetooth: Clear RFCOMM session timer when disconnecting last channel When the last RFCOMM data channel is closed, a timer is normally set up to disconnect the control channel at a later time. If the control channel disconnect command is sent with the timer pending, the timer needs to be cancelled. If the timer is not cancelled in this situation, the reference counting logic for the RFCOMM session does not work correctly when the remote device closes the L2CAP connection. The session is freed at the wrong time, leading to a kernel panic. Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/rfcomm/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4e32e18211f9..2d28dfe98389 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1146,6 +1146,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) if (list_empty(&s->dlcs)) { s->state = BT_DISCONN; rfcomm_send_disc(s, 0); + rfcomm_session_clear_timer(s); } break; -- cgit From d7660918fce210f421cc58c060ca3de71e4ffd37 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sun, 18 Dec 2011 22:33:30 -0200 Subject: Revert "Bluetooth: Revert: Fix L2CAP connection establishment" This reverts commit 4dff523a913197e3314c7b0d08734ab037709093. It was reported that this patch cause issues when trying to connect to legacy devices so reverting it. Reported-by: David Fries Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e0af7237cd92..c1c597e3e198 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -673,7 +673,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: - if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) + if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) -- cgit From 8015e3defe491d305b20c2e64b154b999e6da065 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 19 Dec 2011 17:57:52 +0800 Subject: ALSA: atmel/ac97c: using software reset instead hardware reset if not available Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Takashi Iwai --- sound/atmel/ac97c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 6e5addeb236b..73516f69ac7c 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -899,6 +899,10 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip) /* AC97 v2.2 specifications says minimum 1 us. */ udelay(2); gpio_set_value(chip->reset_pin, 1); + } else { + ac97c_writel(chip, MR, AC97C_MR_WRST | AC97C_MR_ENA); + udelay(2); + ac97c_writel(chip, MR, AC97C_MR_ENA); } } -- cgit From b1b73d095084e754562961c443aa8f6587a55f8e Mon Sep 17 00:00:00 2001 From: Kusanagi Kouichi Date: Mon, 19 Dec 2011 18:13:19 +0900 Subject: time/clocksource: Fix kernel-doc warnings Fix various KernelDoc build warnings. Signed-off-by: Kusanagi Kouichi Cc: John Stultz Link: http://lkml.kernel.org/r/20111219091320.0D5AF6FC03D@msa105.auone-net.jp Signed-off-by: Ingo Molnar --- include/linux/clocksource.h | 11 ++++++++--- kernel/time/clocksource.c | 12 +++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index c86c940d1de3..081147da0564 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -71,7 +71,7 @@ struct timecounter { /** * cyclecounter_cyc2ns - converts cycle counter cycles to nanoseconds - * @tc: Pointer to cycle counter. + * @cc: Pointer to cycle counter. * @cycles: Cycles * * XXX - This could use some mult_lxl_ll() asm optimization. Same code @@ -114,7 +114,7 @@ extern u64 timecounter_read(struct timecounter *tc); * time base as values returned by * timecounter_read() * @tc: Pointer to time counter. - * @cycle: a value returned by tc->cc->read() + * @cycle_tstamp: a value returned by tc->cc->read() * * Cycle counts that are converted correctly as long as they * fall into the interval [-1/2 max cycle count, +1/2 max cycle count], @@ -156,11 +156,12 @@ extern u64 timecounter_cyc2time(struct timecounter *tc, * @mult: cycle to nanosecond multiplier * @shift: cycle to nanosecond divisor (power of two) * @max_idle_ns: max idle time permitted by the clocksource (nsecs) - * @maxadj maximum adjustment value to mult (~11%) + * @maxadj: maximum adjustment value to mult (~11%) * @flags: flags describing special properties * @archdata: arch-specific data * @suspend: suspend function for the clocksource, if necessary * @resume: resume function for the clocksource, if necessary + * @cycle_last: most recent cycle counter value seen by ::read() */ struct clocksource { /* @@ -187,6 +188,7 @@ struct clocksource { void (*suspend)(struct clocksource *cs); void (*resume)(struct clocksource *cs); + /* private: */ #ifdef CONFIG_CLOCKSOURCE_WATCHDOG /* Watchdog related data, used by the framework */ struct list_head wd_list; @@ -261,6 +263,9 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant) /** * clocksource_cyc2ns - converts clocksource cycles to nanoseconds + * @cycles: cycles + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) * * Converts cycles to nanoseconds, using the given mult and shift. * diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index da2f760e780c..d3ad022136e5 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -647,7 +647,7 @@ static void clocksource_enqueue(struct clocksource *cs) /** * __clocksource_updatefreq_scale - Used update clocksource with new freq - * @t: clocksource to be registered + * @cs: clocksource to be registered * @scale: Scale factor multiplied against freq to get clocksource hz * @freq: clocksource frequency (cycles per second) divided by scale * @@ -699,7 +699,7 @@ EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); /** * __clocksource_register_scale - Used to install new clocksources - * @t: clocksource to be registered + * @cs: clocksource to be registered * @scale: Scale factor multiplied against freq to get clocksource hz * @freq: clocksource frequency (cycles per second) divided by scale * @@ -727,7 +727,7 @@ EXPORT_SYMBOL_GPL(__clocksource_register_scale); /** * clocksource_register - Used to install new clocksources - * @t: clocksource to be registered + * @cs: clocksource to be registered * * Returns -EBUSY if registration fails, zero otherwise. */ @@ -761,6 +761,8 @@ static void __clocksource_change_rating(struct clocksource *cs, int rating) /** * clocksource_change_rating - Change the rating of a registered clocksource + * @cs: clocksource to be changed + * @rating: new rating */ void clocksource_change_rating(struct clocksource *cs, int rating) { @@ -772,6 +774,7 @@ EXPORT_SYMBOL(clocksource_change_rating); /** * clocksource_unregister - remove a registered clocksource + * @cs: clocksource to be unregistered */ void clocksource_unregister(struct clocksource *cs) { @@ -787,6 +790,7 @@ EXPORT_SYMBOL(clocksource_unregister); /** * sysfs_show_current_clocksources - sysfs interface for current clocksource * @dev: unused + * @attr: unused * @buf: char buffer to be filled with clocksource list * * Provides sysfs interface for listing current clocksource. @@ -807,6 +811,7 @@ sysfs_show_current_clocksources(struct sys_device *dev, /** * sysfs_override_clocksource - interface for manually overriding clocksource * @dev: unused + * @attr: unused * @buf: name of override clocksource * @count: length of buffer * @@ -842,6 +847,7 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev, /** * sysfs_show_available_clocksources - sysfs interface for listing clocksource * @dev: unused + * @attr: unused * @buf: char buffer to be filled with clocksource list * * Provides sysfs interface for listing registered clocksources -- cgit From c32987918efaa6949c5b2f3e43b654a742b18f7d Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Tue, 13 Dec 2011 00:37:56 +0100 Subject: mtd: plat_ram: call mtd_device_register only if partition data exists mtd_device_parse_register() registers the device as a whole if no partition data is passed so there is no reason to call mtd_device_register() after that. Signed-off-by: Ilya Yanok Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/maps/plat-ram.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 94f553489725..45876d0e5b8e 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -227,10 +227,14 @@ static int platram_probe(struct platform_device *pdev) if (!err) dev_info(&pdev->dev, "registered mtd device\n"); - /* add the whole device. */ - err = mtd_device_register(info->mtd, NULL, 0); - if (err) - dev_err(&pdev->dev, "failed to register the entire device\n"); + if (pdata->nr_partitions) { + /* add the whole device. */ + err = mtd_device_register(info->mtd, NULL, 0); + if (err) { + dev_err(&pdev->dev, + "failed to register the entire device\n"); + } + } return err; -- cgit From 7422ba5343b8c1dbe1a517d0fcc15e7d671ca960 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 13:45:01 +0200 Subject: usb: gadget: epautoconf: do not change number of streams We should not change gadget driver's descriptors just because we think it's right to do so. There are several of reasons which would support this statement but it suffices to say that this was probably never tested because it updates bmAttributes without asking the driver if it's ok to do so. This means that e.g. on UASP gadget it would enable stream support even for the command endpoint which must not have stream support enabled. In fact, this change is fixing the bug introduced by commit a59d6b9 (usb: gadget: add streams support to the gadget framework) which was caught when testing UASP gadget with dwc3 driver. Cc: Tatyana Brokhman Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 596a0b464e61..4dff83d2f265 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -130,9 +130,6 @@ ep_matches ( num_req_streams = ep_comp->bmAttributes & 0x1f; if (num_req_streams > ep->max_streams) return 0; - /* Update the ep_comp descriptor if needed */ - if (num_req_streams != ep->max_streams) - ep_comp->bmAttributes = ep->max_streams; } } -- cgit From ebd4c6f6261c96d1cf9f004965384d57c4202fd6 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 28 Nov 2011 13:19:08 +0100 Subject: vmwgfx: Use the revised fifo hw version register when present The driver implements the needed resource management required to use that register. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 8 +++++++- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 10 ++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 03bbc2a6f9a7..a0c2f12b1e1b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -33,6 +33,7 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) { __le32 __iomem *fifo_mem = dev_priv->mmio_virt; uint32_t fifo_min, hwversion; + const struct vmw_fifo_state *fifo = &dev_priv->fifo; if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)) return false; @@ -41,7 +42,12 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int)) return false; - hwversion = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION); + hwversion = ioread32(fifo_mem + + ((fifo->capabilities & + SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? + SVGA_FIFO_3D_HWVERSION_REVISED : + SVGA_FIFO_3D_HWVERSION)); + if (hwversion == 0) return false; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 5ff561d4e0b4..1edb63ec3f34 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -58,8 +58,14 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, case DRM_VMW_PARAM_FIFO_HW_VERSION: { __le32 __iomem *fifo_mem = dev_priv->mmio_virt; - - param->value = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION); + const struct vmw_fifo_state *fifo = &dev_priv->fifo; + + param->value = + ioread32(fifo_mem + + ((fifo->capabilities & + SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? + SVGA_FIFO_3D_HWVERSION_REVISED : + SVGA_FIFO_3D_HWVERSION)); break; } default: -- cgit From ef5ab24bd3373941bd27e371512c0009eb11581c Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:09 +0100 Subject: vmwgfx: Remove dmabuf check in present ioctl Doesn't protect any error code and only gets in the way of debugging. Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 1edb63ec3f34..66917c6c3813 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -172,13 +172,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, ret = -EINVAL; goto out_no_fb; } - vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj)); - if (!vfb->dmabuf) { - DRM_ERROR("Framebuffer not dmabuf backed.\n"); - ret = -EINVAL; - goto out_no_fb; - } ret = ttm_read_lock(&vmaster->lock, true); if (unlikely(ret != 0)) -- cgit From 6a91d97e02d7efde955c25a5b0fbf950cd2a6efa Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:10 +0100 Subject: vmwgfx: Refactor cursor update Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 66 ++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 37d40545ed77..bee671624a98 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -82,6 +82,43 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv, return 0; } +int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, + struct vmw_dma_buffer *dmabuf, + u32 width, u32 height, + u32 hotspotX, u32 hotspotY) +{ + struct ttm_bo_kmap_obj map; + unsigned long kmap_offset; + unsigned long kmap_num; + void *virtual; + bool dummy; + int ret; + + kmap_offset = 0; + kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT; + + ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0); + if (unlikely(ret != 0)) { + DRM_ERROR("reserve failed\n"); + return -EINVAL; + } + + ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map); + if (unlikely(ret != 0)) + goto err_unreserve; + + virtual = ttm_kmap_obj_virtual(&map, &dummy); + ret = vmw_cursor_update_image(dev_priv, virtual, width, height, + hotspotX, hotspotY); + + ttm_bo_kunmap(&map); +err_unreserve: + ttm_bo_unreserve(&dmabuf->base); + + return ret; +} + + void vmw_cursor_update_position(struct vmw_private *dev_priv, bool show, int x, int y) { @@ -146,36 +183,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, vmw_cursor_update_image(dev_priv, surface->snooper.image, 64, 64, du->hotspot_x, du->hotspot_y); } else if (dmabuf) { - struct ttm_bo_kmap_obj map; - unsigned long kmap_offset; - unsigned long kmap_num; - void *virtual; - bool dummy; - /* vmw_user_surface_lookup takes one reference */ du->cursor_dmabuf = dmabuf; - kmap_offset = 0; - kmap_num = (64*64*4) >> PAGE_SHIFT; - - ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0); - if (unlikely(ret != 0)) { - DRM_ERROR("reserve failed\n"); - return -EINVAL; - } - - ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map); - if (unlikely(ret != 0)) - goto err_unreserve; - - virtual = ttm_kmap_obj_virtual(&map, &dummy); - vmw_cursor_update_image(dev_priv, virtual, 64, 64, - du->hotspot_x, du->hotspot_y); - - ttm_bo_kunmap(&map); -err_unreserve: - ttm_bo_unreserve(&dmabuf->base); - + ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height, + du->hotspot_x, du->hotspot_y); } else { vmw_cursor_update_position(dev_priv, false, 0, 0); return 0; -- cgit From 551a6697d08f92a311d6adbf8d03af2bc7f9e2ee Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:11 +0100 Subject: vmwgfx: Add helper function to get surface or dmabuf Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 8cca91a93bde..dc279706ca70 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -390,6 +390,11 @@ extern int vmw_context_check(struct vmw_private *dev_priv, struct ttm_object_file *tfile, int id, struct vmw_resource **p_res); +extern int vmw_user_lookup_handle(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t handle, + struct vmw_surface **out_surf, + struct vmw_dma_buffer **out_buf); extern void vmw_surface_res_free(struct vmw_resource *res); extern int vmw_surface_init(struct vmw_private *dev_priv, struct vmw_surface *srf, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 86c5e4cceb31..1c7f09e26819 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1190,6 +1190,29 @@ void vmw_resource_unreserve(struct list_head *list) write_unlock(lock); } +/** + * Helper function that looks either a surface or dmabuf. + * + * The pointer this pointed at by out_surf and out_buf needs to be null. + */ +int vmw_user_lookup_handle(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t handle, + struct vmw_surface **out_surf, + struct vmw_dma_buffer **out_buf) +{ + int ret; + + BUG_ON(*out_surf || *out_buf); + + ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf); + if (!ret) + return 0; + + ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf); + return ret; +} + int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, struct ttm_object_file *tfile, -- cgit From e7ac9211f29f2fc2e7d11586a33267d2a26d3f2f Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:12 +0100 Subject: vmwgfx: Refactor kms code to use vmw_user_lookup_handle helper Signed-off-by: Jakob Bornecrantz Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 98 ++++++++++++++----------------------- 1 file changed, 37 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index bee671624a98..ac24cfd431b5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -147,24 +147,21 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, return -EINVAL; if (handle) { - ret = vmw_user_surface_lookup_handle(dev_priv, tfile, - handle, &surface); - if (!ret) { - if (!surface->snooper.image) { - DRM_ERROR("surface not suitable for cursor\n"); - vmw_surface_unreference(&surface); - return -EINVAL; - } - } else { - ret = vmw_user_dmabuf_lookup(tfile, - handle, &dmabuf); - if (ret) { - DRM_ERROR("failed to find surface or dmabuf: %i\n", ret); - return -EINVAL; - } + ret = vmw_user_lookup_handle(dev_priv, tfile, + handle, &surface, &dmabuf); + if (ret) { + DRM_ERROR("failed to find surface or dmabuf: %i\n", ret); + return -EINVAL; } } + /* need to do this before taking down old image */ + if (surface && !surface->snooper.image) { + DRM_ERROR("surface not suitable for cursor\n"); + vmw_surface_unreference(&surface); + return -EINVAL; + } + /* takedown old cursor */ if (du->cursor_surface) { du->cursor_surface->snooper.crtc = NULL; @@ -568,6 +565,10 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, * Sanity checks. */ + /* Surface must be marked as a scanout. */ + if (unlikely(!surface->scanout)) + return -EINVAL; + if (unlikely(surface->mip_levels[0] != 1 || surface->num_sizes != 1 || surface->sizes[0].width < mode_cmd->width || @@ -1045,46 +1046,29 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, return ERR_PTR(-ENOENT); } - /** - * End conditioned code. - */ - - ret = vmw_user_surface_lookup_handle(dev_priv, tfile, - mode_cmd->handle, &surface); + /* returns either a dmabuf or surface */ + ret = vmw_user_lookup_handle(dev_priv, tfile, + mode_cmd->handle, + &surface, &bo); if (ret) - goto try_dmabuf; - - if (!surface->scanout) - goto err_not_scanout; - - ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface, - &vfb, mode_cmd); - - /* vmw_user_surface_lookup takes one ref so does new_fb */ - vmw_surface_unreference(&surface); - - if (ret) { - DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); - ttm_base_object_unref(&user_obj); - return ERR_PTR(ret); - } else - vfb->user_obj = user_obj; - return &vfb->base; - -try_dmabuf: - DRM_INFO("%s: trying buffer\n", __func__); - - ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); - if (ret) { - DRM_ERROR("failed to find buffer: %i\n", ret); - return ERR_PTR(-ENOENT); - } - - ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, - mode_cmd); + goto err_out; + + /* Create the new framebuffer depending one what we got back */ + if (bo) + ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, + mode_cmd); + else if (surface) + ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, + surface, &vfb, mode_cmd); + else + BUG(); - /* vmw_user_dmabuf_lookup takes one ref so does new_fb */ - vmw_dmabuf_unreference(&bo); +err_out: + /* vmw_user_lookup_handle takes one ref so does new_fb */ + if (bo) + vmw_dmabuf_unreference(&bo); + if (surface) + vmw_surface_unreference(&surface); if (ret) { DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); @@ -1094,14 +1078,6 @@ try_dmabuf: vfb->user_obj = user_obj; return &vfb->base; - -err_not_scanout: - DRM_ERROR("surface not marked as scanout\n"); - /* vmw_user_surface_lookup takes one ref */ - vmw_surface_unreference(&surface); - ttm_base_object_unref(&user_obj); - - return ERR_PTR(-EINVAL); } static struct drm_mode_config_funcs vmw_kms_funcs = { -- cgit From 203dc2201326fa64411158c84ab0745546300310 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:13 +0100 Subject: vmwgfx: Do better culling of presents Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ac24cfd431b5..d31ae338cfc1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1098,6 +1098,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, size_t fifo_size; int i, k, num_units; int ret = 0; /* silence warning */ + int left, right, top, bottom; struct { SVGA3dCmdHeader header; @@ -1122,30 +1123,42 @@ int vmw_kms_present(struct vmw_private *dev_priv, return -ENOMEM; } + left = clips->x; + right = clips->x + clips->w; + top = clips->y; + bottom = clips->y + clips->h; + + for (i = 1; i < num_clips; i++) { + left = min_t(int, left, (int)clips[i].x); + right = max_t(int, right, (int)clips[i].x + clips[i].w); + top = min_t(int, top, (int)clips[i].y); + bottom = max_t(int, bottom, (int)clips[i].y + clips[i].h); + } + /* only need to do this once */ memset(cmd, 0, fifo_size); cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); - cmd->body.srcRect.left = 0; - cmd->body.srcRect.right = surface->sizes[0].width; - cmd->body.srcRect.top = 0; - cmd->body.srcRect.bottom = surface->sizes[0].height; + cmd->body.srcRect.left = left; + cmd->body.srcRect.right = right; + cmd->body.srcRect.top = top; + cmd->body.srcRect.bottom = bottom; blits = (SVGASignedRect *)&cmd[1]; for (i = 0; i < num_clips; i++) { - blits[i].left = clips[i].x; - blits[i].right = clips[i].x + clips[i].w; - blits[i].top = clips[i].y; - blits[i].bottom = clips[i].y + clips[i].h; + blits[i].left = clips[i].x - left; + blits[i].right = clips[i].x + clips[i].w - left; + blits[i].top = clips[i].y - top; + blits[i].bottom = clips[i].y + clips[i].h - top; } for (k = 0; k < num_units; k++) { struct vmw_display_unit *unit = units[k]; - int clip_x1 = destX - unit->crtc.x; - int clip_y1 = destY - unit->crtc.y; - int clip_x2 = clip_x1 + surface->sizes[0].width; - int clip_y2 = clip_y1 + surface->sizes[0].height; + int clip_x1 = left + destX - unit->crtc.x; + int clip_y1 = top + destY - unit->crtc.y; + int clip_x2 = right + destX - unit->crtc.x; + int clip_y2 = bottom + destY - unit->crtc.y; /* skip any crtcs that misses the clip region */ if (clip_x1 >= unit->crtc.mode.hdisplay || -- cgit From bfc2638dc05f2b27538e40821fdbc8399730b1ea Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:14 +0100 Subject: vmwgfx: Resend the cursor after legacy modeset Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 5 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index af8e6e5bd964..e1cb8556355f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -62,9 +62,14 @@ struct vmw_framebuffer { int vmw_cursor_update_image(struct vmw_private *dev_priv, u32 *image, u32 width, u32 height, u32 hotspotX, u32 hotspotY); +int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, + struct vmw_dma_buffer *dmabuf, + u32 width, u32 height, + u32 hotspotX, u32 hotspotY); void vmw_cursor_update_position(struct vmw_private *dev_priv, bool show, int x, int y); + /** * Base class display unit. * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 90c5e3928491..8f8dbd43c33d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -74,9 +74,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) { struct vmw_legacy_display *lds = dev_priv->ldu_priv; struct vmw_legacy_display_unit *entry; + struct vmw_display_unit *du = NULL; struct drm_framebuffer *fb = NULL; struct drm_crtc *crtc = NULL; - int i = 0; + int i = 0, ret; /* If there is no display topology the host just assumes * that the guest will set the same layout as the host. @@ -129,6 +130,25 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) lds->last_num_active = lds->num_active; + + /* Find the first du with a cursor. */ + list_for_each_entry(entry, &lds->active, active) { + du = &entry->base; + + if (!du->cursor_dmabuf) + continue; + + ret = vmw_cursor_update_dmabuf(dev_priv, + du->cursor_dmabuf, + 64, 64, + du->hotspot_x, + du->hotspot_y); + if (ret == 0) + break; + + DRM_ERROR("Could not update cursor image\n"); + } + return 0; } -- cgit From 6abff3c78051e40130a1c653f874fb12b9d40254 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 28 Nov 2011 13:19:15 +0100 Subject: vmwgfx: Clip cliprects against screen boundaries in present and dirty Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 209 +++++++++++++++++++++++++++--------- 1 file changed, 156 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index d31ae338cfc1..8aa1dbb45c67 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -31,6 +31,44 @@ /* Might need a hrtimer here? */ #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) + +struct vmw_clip_rect { + int x1, x2, y1, y2; +}; + +/** + * Clip @num_rects number of @rects against @clip storing the + * results in @out_rects and the number of passed rects in @out_num. + */ +void vmw_clip_cliprects(struct drm_clip_rect *rects, + int num_rects, + struct vmw_clip_rect clip, + SVGASignedRect *out_rects, + int *out_num) +{ + int i, k; + + for (i = 0, k = 0; i < num_rects; i++) { + int x1 = max_t(int, clip.x1, rects[i].x1); + int y1 = max_t(int, clip.y1, rects[i].y1); + int x2 = min_t(int, clip.x2, rects[i].x2); + int y2 = min_t(int, clip.y2, rects[i].y2); + + if (x1 >= x2) + continue; + if (y1 >= y2) + continue; + + out_rects[k].left = x1; + out_rects[k].top = y1; + out_rects[k].right = x2; + out_rects[k].bottom = y2; + k++; + } + + *out_num = k; +} + void vmw_display_unit_cleanup(struct vmw_display_unit *du) { if (du->cursor_surface) @@ -386,8 +424,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, struct drm_clip_rect *clips, unsigned num_clips, int inc) { - struct drm_clip_rect *clips_ptr; struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; + struct drm_clip_rect *clips_ptr; + struct drm_clip_rect *tmp; struct drm_crtc *crtc; size_t fifo_size; int i, num_units; @@ -400,7 +439,6 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, } *cmd; SVGASignedRect *blits; - num_units = 0; list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { @@ -411,13 +449,24 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, BUG_ON(!clips || !num_clips); + tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL); + if (unlikely(tmp == NULL)) { + DRM_ERROR("Temporary cliprect memory alloc failed.\n"); + return -ENOMEM; + } + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips; cmd = kzalloc(fifo_size, GFP_KERNEL); if (unlikely(cmd == NULL)) { DRM_ERROR("Temporary fifo memory alloc failed.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto out_free_tmp; } + /* setup blits pointer */ + blits = (SVGASignedRect *)&cmd[1]; + + /* initial clip region */ left = clips->x1; right = clips->x2; top = clips->y1; @@ -443,45 +492,60 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, cmd->body.srcRect.bottom = bottom; clips_ptr = clips; - blits = (SVGASignedRect *)&cmd[1]; for (i = 0; i < num_clips; i++, clips_ptr += inc) { - blits[i].left = clips_ptr->x1 - left; - blits[i].right = clips_ptr->x2 - left; - blits[i].top = clips_ptr->y1 - top; - blits[i].bottom = clips_ptr->y2 - top; + tmp[i].x1 = clips_ptr->x1 - left; + tmp[i].x2 = clips_ptr->x2 - left; + tmp[i].y1 = clips_ptr->y1 - top; + tmp[i].y2 = clips_ptr->y2 - top; } /* do per unit writing, reuse fifo for each */ for (i = 0; i < num_units; i++) { struct vmw_display_unit *unit = units[i]; - int clip_x1 = left - unit->crtc.x; - int clip_y1 = top - unit->crtc.y; - int clip_x2 = right - unit->crtc.x; - int clip_y2 = bottom - unit->crtc.y; + struct vmw_clip_rect clip; + int num; + + clip.x1 = left - unit->crtc.x; + clip.y1 = top - unit->crtc.y; + clip.x2 = right - unit->crtc.x; + clip.y2 = bottom - unit->crtc.y; /* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) + if (clip.x1 >= unit->crtc.mode.hdisplay || + clip.y1 >= unit->crtc.mode.vdisplay || + clip.x2 <= 0 || clip.y2 <= 0) continue; + /* + * In order for the clip rects to be correctly scaled + * the src and dest rects needs to be the same size. + */ + cmd->body.destRect.left = clip.x1; + cmd->body.destRect.right = clip.x2; + cmd->body.destRect.top = clip.y1; + cmd->body.destRect.bottom = clip.y2; + + /* create a clip rect of the crtc in dest coords */ + clip.x2 = unit->crtc.mode.hdisplay - clip.x1; + clip.y2 = unit->crtc.mode.vdisplay - clip.y1; + clip.x1 = 0 - clip.x1; + clip.y1 = 0 - clip.y1; + /* need to reset sid as it is changed by execbuf */ cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle); - cmd->body.destScreenId = unit->unit; - /* - * The blit command is a lot more resilient then the - * readback command when it comes to clip rects. So its - * okay to go out of bounds. - */ + /* clip and write blits to cmd stream */ + vmw_clip_cliprects(tmp, num_clips, clip, blits, &num); - cmd->body.destRect.left = clip_x1; - cmd->body.destRect.right = clip_x2; - cmd->body.destRect.top = clip_y1; - cmd->body.destRect.bottom = clip_y2; + /* if no cliprects hit skip this */ + if (num == 0) + continue; + /* recalculate package length */ + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; + cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, 0, NULL); @@ -489,7 +553,10 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, break; } + kfree(cmd); +out_free_tmp: + kfree(tmp); return ret; } @@ -795,6 +862,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, int clip_y1 = clips_ptr->y1 - unit->crtc.y; int clip_x2 = clips_ptr->x2 - unit->crtc.x; int clip_y2 = clips_ptr->y2 - unit->crtc.y; + int move_x, move_y; /* skip any crtcs that misses the clip region */ if (clip_x1 >= unit->crtc.mode.hdisplay || @@ -802,12 +870,21 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, clip_x2 <= 0 || clip_y2 <= 0) continue; + /* clip size to crtc size */ + clip_x2 = min_t(int, clip_x2, unit->crtc.mode.hdisplay); + clip_y2 = min_t(int, clip_y2, unit->crtc.mode.vdisplay); + + /* translate both src and dest to bring clip into screen */ + move_x = min_t(int, clip_x1, 0); + move_y = min_t(int, clip_y1, 0); + + /* actual translate done here */ blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN; blits[hit_num].body.destScreenId = unit->unit; - blits[hit_num].body.srcOrigin.x = clips_ptr->x1; - blits[hit_num].body.srcOrigin.y = clips_ptr->y1; - blits[hit_num].body.destRect.left = clip_x1; - blits[hit_num].body.destRect.top = clip_y1; + blits[hit_num].body.srcOrigin.x = clips_ptr->x1 - move_x; + blits[hit_num].body.srcOrigin.y = clips_ptr->y1 - move_y; + blits[hit_num].body.destRect.left = clip_x1 - move_x; + blits[hit_num].body.destRect.top = clip_y1 - move_y; blits[hit_num].body.destRect.right = clip_x2; blits[hit_num].body.destRect.bottom = clip_y2; hit_num++; @@ -1094,6 +1171,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, uint32_t num_clips) { struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; + struct drm_clip_rect *tmp; struct drm_crtc *crtc; size_t fifo_size; int i, k, num_units; @@ -1116,11 +1194,18 @@ int vmw_kms_present(struct vmw_private *dev_priv, BUG_ON(surface == NULL); BUG_ON(!clips || !num_clips); + tmp = kzalloc(sizeof(*tmp) * num_clips, GFP_KERNEL); + if (unlikely(tmp == NULL)) { + DRM_ERROR("Temporary cliprect memory alloc failed.\n"); + return -ENOMEM; + } + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips; cmd = kmalloc(fifo_size, GFP_KERNEL); if (unlikely(cmd == NULL)) { DRM_ERROR("Failed to allocate temporary fifo memory.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto out_free_tmp; } left = clips->x; @@ -1138,50 +1223,66 @@ int vmw_kms_present(struct vmw_private *dev_priv, /* only need to do this once */ memset(cmd, 0, fifo_size); cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); - cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); + + blits = (SVGASignedRect *)&cmd[1]; cmd->body.srcRect.left = left; cmd->body.srcRect.right = right; cmd->body.srcRect.top = top; cmd->body.srcRect.bottom = bottom; - blits = (SVGASignedRect *)&cmd[1]; for (i = 0; i < num_clips; i++) { - blits[i].left = clips[i].x - left; - blits[i].right = clips[i].x + clips[i].w - left; - blits[i].top = clips[i].y - top; - blits[i].bottom = clips[i].y + clips[i].h - top; + tmp[i].x1 = clips[i].x - left; + tmp[i].x2 = clips[i].x + clips[i].w - left; + tmp[i].y1 = clips[i].y - top; + tmp[i].y2 = clips[i].y + clips[i].h - top; } for (k = 0; k < num_units; k++) { struct vmw_display_unit *unit = units[k]; - int clip_x1 = left + destX - unit->crtc.x; - int clip_y1 = top + destY - unit->crtc.y; - int clip_x2 = right + destX - unit->crtc.x; - int clip_y2 = bottom + destY - unit->crtc.y; + struct vmw_clip_rect clip; + int num; + + clip.x1 = left + destX - unit->crtc.x; + clip.y1 = top + destY - unit->crtc.y; + clip.x2 = right + destX - unit->crtc.x; + clip.y2 = bottom + destY - unit->crtc.y; /* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) + if (clip.x1 >= unit->crtc.mode.hdisplay || + clip.y1 >= unit->crtc.mode.vdisplay || + clip.x2 <= 0 || clip.y2 <= 0) continue; + /* + * In order for the clip rects to be correctly scaled + * the src and dest rects needs to be the same size. + */ + cmd->body.destRect.left = clip.x1; + cmd->body.destRect.right = clip.x2; + cmd->body.destRect.top = clip.y1; + cmd->body.destRect.bottom = clip.y2; + + /* create a clip rect of the crtc in dest coords */ + clip.x2 = unit->crtc.mode.hdisplay - clip.x1; + clip.y2 = unit->crtc.mode.vdisplay - clip.y1; + clip.x1 = 0 - clip.x1; + clip.y1 = 0 - clip.y1; + /* need to reset sid as it is changed by execbuf */ cmd->body.srcImage.sid = sid; - cmd->body.destScreenId = unit->unit; - /* - * The blit command is a lot more resilient then the - * readback command when it comes to clip rects. So its - * okay to go out of bounds. - */ + /* clip and write blits to cmd stream */ + vmw_clip_cliprects(tmp, num_clips, clip, blits, &num); - cmd->body.destRect.left = clip_x1; - cmd->body.destRect.right = clip_x2; - cmd->body.destRect.top = clip_y1; - cmd->body.destRect.bottom = clip_y2; + /* if no cliprects hit skip this */ + if (num == 0) + continue; + /* recalculate package length */ + fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; + cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, 0, NULL); @@ -1190,6 +1291,8 @@ int vmw_kms_present(struct vmw_private *dev_priv, } kfree(cmd); +out_free_tmp: + kfree(tmp); return ret; } -- cgit From 12275dd4b747f5d87fa36229774d76bca8e63068 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 19 Dec 2011 09:30:35 -0500 Subject: Revert "xen/pv-on-hvm kexec: add xs_reset_watches to shutdown watches from old kernel" This reverts commit ddacf5ef684a655abe2bb50c4b2a5b72ae0d5e05. As when booting the kernel under Amazon EC2 as an HVM guest it ends up hanging during startup. Reverting this we loose the fix for kexec booting to the crash kernels. Fixes Canonical BZ #901305 (http://bugs.launchpad.net/bugs/901305) Tested-by: Alessandro Salvatori Reported-by: Stefan Bader Acked-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xenbus/xenbus_xs.c | 13 ------------- include/xen/interface/io/xs_wire.h | 3 +-- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index b3b8f2f3ad10..ede860f921df 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -621,15 +621,6 @@ static struct xenbus_watch *find_watch(const char *token) return NULL; } -static void xs_reset_watches(void) -{ - int err; - - err = xs_error(xs_single(XBT_NIL, XS_RESET_WATCHES, "", NULL)); - if (err && err != -EEXIST) - printk(KERN_WARNING "xs_reset_watches failed: %d\n", err); -} - /* Register callback to watch this node. */ int register_xenbus_watch(struct xenbus_watch *watch) { @@ -906,9 +897,5 @@ int xs_init(void) if (IS_ERR(task)) return PTR_ERR(task); - /* shutdown watches for kexec boot */ - if (xen_hvm_domain()) - xs_reset_watches(); - return 0; } diff --git a/include/xen/interface/io/xs_wire.h b/include/xen/interface/io/xs_wire.h index f0b6890370be..f6f07aa35af5 100644 --- a/include/xen/interface/io/xs_wire.h +++ b/include/xen/interface/io/xs_wire.h @@ -29,8 +29,7 @@ enum xsd_sockmsg_type XS_IS_DOMAIN_INTRODUCED, XS_RESUME, XS_SET_TARGET, - XS_RESTRICT, - XS_RESET_WATCHES + XS_RESTRICT }; #define XS_WRITE_NONE "NONE" -- cgit From 913050b91eb94f194392dd797b1ff3779f606ac0 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 19 Dec 2011 16:38:30 +0100 Subject: oprofile: Fix uninitialized memory access when writing to writing to oprofilefs If oprofilefs_ulong_from_user() is called with count equals zero, *val remains unchanged. Depending on the implementation it might be uninitialized. Change oprofilefs_ulong_from_user()'s interface to return count on success. Thus, we are able to return early if count equals zero which avoids using *val uninitialized. Fixing all users of oprofilefs_ulong_ from_user(). This follows write syscall implementation when count is zero: "If count is zero ... [and if] no errors are detected, 0 will be returned without causing any other effect." (man 2 write) Reported-By: Mike Waychison Signed-off-by: Robert Richter Cc: Andrew Morton Cc: Cc: oprofile-list Link: http://lkml.kernel.org/r/20111219153830.GH16765@erda.amd.com Signed-off-by: Ingo Molnar --- arch/s390/oprofile/init.c | 2 +- drivers/oprofile/oprofile_files.c | 7 ++++--- drivers/oprofile/oprofilefs.c | 11 +++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 6efc18b5e60a..bd58b72454cf 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -88,7 +88,7 @@ static ssize_t hwsampler_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (oprofile_started) diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index 89f63456646f..84a208dbed93 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -45,7 +45,7 @@ static ssize_t timeout_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; retval = oprofile_set_timeout(val); @@ -84,7 +84,7 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; retval = oprofile_set_ulong(&oprofile_backtrace_depth, val); @@ -141,9 +141,10 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; + retval = 0; if (val) retval = oprofile_start(); else diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index d0de6cc2d7a5..2f0aa0f700e6 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -60,6 +60,13 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user *buf, size_t cou } +/* + * Note: If oprofilefs_ulong_from_user() returns 0, then *val remains + * unchanged and might be uninitialized. This follows write syscall + * implementation when count is zero: "If count is zero ... [and if] + * no errors are detected, 0 will be returned without causing any + * other effect." (man 2 write) + */ int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_t count) { char tmpbuf[TMPBUFSIZE]; @@ -79,7 +86,7 @@ int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_ raw_spin_lock_irqsave(&oprofilefs_lock, flags); *val = simple_strtoul(tmpbuf, NULL, 0); raw_spin_unlock_irqrestore(&oprofilefs_lock, flags); - return 0; + return count; } @@ -99,7 +106,7 @@ static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_ return -EINVAL; retval = oprofilefs_ulong_from_user(&value, buf, count); - if (retval) + if (retval <= 0) return retval; retval = oprofile_set_ulong(file->private_data, value); -- cgit From e0197aae59e55c06db172bfbe1a1cdb8c0e1cab3 Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Thu, 15 Dec 2011 11:36:43 -0800 Subject: cgroups: fix a css_set not found bug in cgroup_attach_proc There is a BUG when migrating a PF_EXITING proc. Since css_set_prefetch() is not called for the PF_EXITING case, find_existing_css_set() will return NULL inside cgroup_task_migrate() causing a BUG. This bug is easy to reproduce. Create a zombie and echo its pid to cgroup.procs. $ cat zombie.c \#include int main() { if (fork()) pause(); return 0; } $ We are hitting this bug pretty regularly on ChromeOS. This bug is already fixed by Tejun Heo's cgroup patchset which is targetted for the next merge window: https://lkml.org/lkml/2011/11/1/356 I've create a smaller patch here which just fixes this bug so that a fix can be merged into the current release and stable. Signed-off-by: Mandeep Singh Baines Downstream-Bug-Report: http://crosbug.com/23953 Reviewed-by: Li Zefan Signed-off-by: Tejun Heo Cc: containers@lists.linux-foundation.org Cc: cgroups@vger.kernel.org Cc: stable@kernel.org Cc: KAMEZAWA Hiroyuki Cc: Frederic Weisbecker Cc: Oleg Nesterov Cc: Andrew Morton Cc: Paul Menage Cc: Olof Johansson --- kernel/cgroup.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index d9d5648f3cdc..a184470cf9b5 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2098,11 +2098,6 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader) continue; /* get old css_set pointer */ task_lock(tsk); - if (tsk->flags & PF_EXITING) { - /* ignore this task if it's going away */ - task_unlock(tsk); - continue; - } oldcg = tsk->cgroups; get_css_set(oldcg); task_unlock(tsk); -- cgit From 04ded1672402577cd3f390c764f3046cc704a42a Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 6 Dec 2011 21:17:11 +0000 Subject: RDMA/cma: Verify private data length private_data_len is defined as a u8. If the user specifies a large private_data size (> 220 bytes), we will calculate a total length that exceeds 255, resulting in private_data_len wrapping back to 0. This can lead to overwriting random kernel memory. Avoid this by verifying that the resulting size fits into a u8. Reported-by: B. Thery Addresses: Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 75ff821c0af0..d0d4aa9f4802 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2513,6 +2513,9 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, req.private_data_len = sizeof(struct cma_hdr) + conn_param->private_data_len; + if (req.private_data_len < conn_param->private_data_len) + return -EINVAL; + req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC); if (!req.private_data) return -ENOMEM; @@ -2562,6 +2565,9 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, memset(&req, 0, sizeof req); offset = cma_user_data_offset(id_priv->id.ps); req.private_data_len = offset + conn_param->private_data_len; + if (req.private_data_len < conn_param->private_data_len) + return -EINVAL; + private_data = kzalloc(req.private_data_len, GFP_ATOMIC); if (!private_data) return -ENOMEM; -- cgit From 29d1b16145e78e0f4af54751965c4a09e83bd872 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 2 Dec 2011 12:41:30 -0500 Subject: IB/qib: Correct sense on freectxts increment and decrement Commit 53ab1c64983 ("IB/qib: Correct nfreectxts for multiple HCAs") reversed the increments and decrements of dd->nfreectxts. Fix it. Reviewed-by: Ram Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_file_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 574600ef5b42..a7403248d83d 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1285,7 +1285,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt, strlcpy(rcd->comm, current->comm, sizeof(rcd->comm)); ctxt_fp(fp) = rcd; qib_stats.sps_ctxts++; - dd->freectxts++; + dd->freectxts--; ret = 0; goto bail; @@ -1794,7 +1794,7 @@ static int qib_close(struct inode *in, struct file *fp) if (dd->pageshadow) unlock_expected_tids(rcd); qib_stats.sps_ctxts--; - dd->freectxts--; + dd->freectxts++; } mutex_unlock(&qib_mutex); -- cgit From 96f1f05af76b601ab21a7dc603ae0a1cea4efc3d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 16 Dec 2011 07:53:18 -0800 Subject: iwlwifi: update SCD BC table for all SCD queues Since we configure all the queues as CHAINABLE, we need to update the byte count for all the queues, not only the AGGREGATABLE ones. Not doing so can confuse the SCD and make the fw assert. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ce918980e977..5f17ab8e76ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1197,9 +1197,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); /* Set up entry for this TFD in Tx byte-count array */ - if (is_agg) - iwl_trans_txq_update_byte_cnt_tbl(trans, txq, - le16_to_cpu(tx_cmd->len)); + iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); -- cgit From c070e38e4ee005f55895df177a9e14d90d6204b3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 16 Nov 2011 10:54:02 -0300 Subject: [media] omap3isp: Fix crash caused by subdevs now having a pointer to devnodes Commit 3e0ec41c5c5ee14e27f65e28d4a616de34f59a97 ("V4L: dynamically allocate video_device nodes in subdevices") makes the embedding video_device directly. Fix accesses to the devnode accordingly. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap3isp/ispccdc.c | 2 +- drivers/media/video/omap3isp/ispstat.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index b0b0fa5a3572..54a4a3f22e2e 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -1408,7 +1408,7 @@ static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc) { struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->video_out.video.entity); - struct video_device *vdev = &ccdc->subdev.devnode; + struct video_device *vdev = ccdc->subdev.devnode; struct v4l2_event event; memset(&event, 0, sizeof(event)); diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c index 68d539456c55..bc0b2c7349b9 100644 --- a/drivers/media/video/omap3isp/ispstat.c +++ b/drivers/media/video/omap3isp/ispstat.c @@ -496,7 +496,7 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size) static void isp_stat_queue_event(struct ispstat *stat, int err) { - struct video_device *vdev = &stat->subdev.devnode; + struct video_device *vdev = stat->subdev.devnode; struct v4l2_event event; struct omap3isp_stat_event_status *status = (void *)event.u.data; -- cgit From a03ffcf873fe0f2565386ca8ef832144c42e67fa Mon Sep 17 00:00:00 2001 From: Markus Kötter Date: Sat, 17 Dec 2011 11:39:08 +0000 Subject: net: bpf_jit: fix an off-one bug in x86_64 cond jump target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit x86 jump instruction size is 2 or 5 bytes (near/long jump), not 2 or 6 bytes. In case a conditional jump is followed by a long jump, conditional jump target is one byte past the start of target instruction. Signed-off-by: Markus Kötter Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- arch/x86/net/bpf_jit_comp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index bfab3fa10edc..7b65f752c5f8 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -568,8 +568,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (filter[i].jt != 0) { - if (filter[i].jf) - t_offset += is_near(f_offset) ? 2 : 6; + if (filter[i].jf && f_offset) + t_offset += is_near(f_offset) ? 2 : 5; EMIT_COND_JMP(t_op, t_offset); if (filter[i].jf) EMIT_JMP(f_offset); -- cgit From 9cef310fcdee12b49b8b4c96fd8f611c8873d284 Mon Sep 17 00:00:00 2001 From: Alex Juncu Date: Thu, 15 Dec 2011 23:01:25 +0000 Subject: llc: llc_cmsg_rcv was getting called after sk_eat_skb. Received non stream protocol packets were calling llc_cmsg_rcv that used a skb after that skb was released by sk_eat_skb. This caused received STP packets to generate kernel panics. Signed-off-by: Alexandru Juncu Signed-off-by: Kunjan Naik Signed-off-by: David S. Miller --- net/llc/af_llc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index dfd3a648a551..a18e6c3d36e3 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -833,15 +833,15 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, copied += used; len -= used; + /* For non stream protcols we get one packet per recvmsg call */ + if (sk->sk_type != SOCK_STREAM) + goto copy_uaddr; + if (!(flags & MSG_PEEK)) { sk_eat_skb(sk, skb, 0); *seq = 0; } - /* For non stream protcols we get one packet per recvmsg call */ - if (sk->sk_type != SOCK_STREAM) - goto copy_uaddr; - /* Partial read */ if (used + offset < skb->len) continue; @@ -857,6 +857,12 @@ copy_uaddr: } if (llc_sk(sk)->cmsg_flags) llc_cmsg_rcv(msg, skb); + + if (!(flags & MSG_PEEK)) { + sk_eat_skb(sk, skb, 0); + *seq = 0; + } + goto out; } -- cgit From 2ca6cf06d988fea21e812a86be79353352677c9c Mon Sep 17 00:00:00 2001 From: françois romieu Date: Thu, 15 Dec 2011 08:37:43 +0000 Subject: r8169: fix Config2 MSIEnable bit setting. The MSIEnable bit is only available for the 8169. Avoid Config2 writes for the post-8169 8168 and 810x. Reported-by: Su Kang Yin Signed-off-by: Francois Romieu Cc: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 67bf07819992..c8f47f17186f 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -477,7 +477,6 @@ enum rtl_register_content { /* Config1 register p.24 */ LEDS1 = (1 << 7), LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ Speed_down = (1 << 4), MEMMAP = (1 << 3), IOMAP = (1 << 2), @@ -485,6 +484,7 @@ enum rtl_register_content { PMEnable = (1 << 0), /* Power Management Enable */ /* Config2 register p. 25 */ + MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ PCI_Clock_66MHz = 0x01, PCI_Clock_33MHz = 0x00, @@ -3426,22 +3426,24 @@ static const struct rtl_cfg_info { }; /* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, +static unsigned rtl_try_msi(struct rtl8169_private *tp, const struct rtl_cfg_info *cfg) { + void __iomem *ioaddr = tp->mmio_addr; unsigned msi = 0; u8 cfg2; cfg2 = RTL_R8(Config2) & ~MSIEnable; if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); + if (pci_enable_msi(tp->pci_dev)) { + netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n"); } else { cfg2 |= MSIEnable; msi = RTL_FEATURE_MSI; } } - RTL_W8(Config2, cfg2); + if (tp->mac_version <= RTL_GIGA_MAC_VER_06) + RTL_W8(Config2, cfg2); return msi; } @@ -4077,7 +4079,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->features |= RTL_FEATURE_WOL; if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); + tp->features |= rtl_try_msi(tp, cfg); RTL_W8(Cfg9346, Cfg9346_Lock); if (rtl_tbi_enabled(tp)) { -- cgit From 13f541c10b30fc6529200d7f9a0073217709622f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 19 Dec 2011 22:07:58 +0100 Subject: x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT When printing the code bytes in show_registers(), the markers around the byte at the fault address could make the printk() format string look like a valid log level and facility code. This would prevent this byte from being printed and result in a spurious newline: [ 7555.765589] Code: 8b 32 e9 94 00 00 00 81 7d 00 ff 00 00 00 0f 87 96 00 00 00 48 8b 83 c0 00 00 00 44 89 e2 44 89 e6 48 89 df 48 8b 80 d8 02 00 00 [ 7555.765683] 8b 48 28 48 89 d0 81 e2 ff 0f 00 00 48 c1 e8 0c 48 c1 e0 04 Add KERN_CONT where needed, and elsewhere in show_registers() for consistency. Signed-off-by: Clemens Ladisch Link: http://lkml.kernel.org/r/4EEFA7AE.9020407@ladisch.de Signed-off-by: H. Peter Anvin --- arch/x86/kernel/dumpstack_32.c | 8 ++++---- arch/x86/kernel/dumpstack_64.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 3b97a80ce329..c99f9ed013d5 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) for (i = 0; i < code_len; i++, ip++) { if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { - printk(" Bad EIP value."); + printk(KERN_CONT " Bad EIP value."); break; } if (ip == (u8 *)regs->ip) - printk("<%02x> ", c); + printk(KERN_CONT "<%02x> ", c); else - printk("%02x ", c); + printk(KERN_CONT "%02x ", c); } } - printk("\n"); + printk(KERN_CONT "\n"); } int is_valid_bugaddr(unsigned long ip) diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 19853ad8afc5..6d728d9284bd 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) for (i = 0; i < code_len; i++, ip++) { if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { - printk(" Bad RIP value."); + printk(KERN_CONT " Bad RIP value."); break; } if (ip == (u8 *)regs->ip) - printk("<%02x> ", c); + printk(KERN_CONT "<%02x> ", c); else - printk("%02x ", c); + printk(KERN_CONT "%02x ", c); } } - printk("\n"); + printk(KERN_CONT "\n"); } int is_valid_bugaddr(unsigned long ip) -- cgit From 2692ba61a82203404abd7dd2a027bda962861f74 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Fri, 16 Dec 2011 12:44:15 +0000 Subject: sctp: fix incorrect overflow check on autoclose Commit 8ffd3208 voids the previous patches f6778aab and 810c0719 for limiting the autoclose value. If userspace passes in -1 on 32-bit platform, the overflow check didn't work and autoclose would be set to 0xffffffff. This patch defines a max_autoclose (in seconds) for limiting the value and exposes it through sysctl, with the following intentions. 1) Avoid overflowing autoclose * HZ. 2) Keep the default autoclose bound consistent across 32- and 64-bit platforms (INT_MAX / HZ in this patch). 3) Keep the autoclose value consistent between setsockopt() and getsockopt() calls. Suggested-by: Vlad Yasevich Signed-off-by: Xi Wang Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 4 ++++ net/sctp/associola.c | 2 +- net/sctp/protocol.c | 3 +++ net/sctp/socket.c | 2 -- net/sctp/sysctl.c | 13 +++++++++++++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index e90e7a9935dd..a15432da27c3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -241,6 +241,9 @@ extern struct sctp_globals { * bits is an indicator of when to send and window update SACK. */ int rwnd_update_shift; + + /* Threshold for autoclose timeout, in seconds. */ + unsigned long max_autoclose; } sctp_globals; #define sctp_rto_initial (sctp_globals.rto_initial) @@ -281,6 +284,7 @@ extern struct sctp_globals { #define sctp_auth_enable (sctp_globals.auth_enable) #define sctp_checksum_disable (sctp_globals.checksum_disable) #define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift) +#define sctp_max_autoclose (sctp_globals.max_autoclose) /* SCTP Socket type: UDP or TCP style. */ typedef enum { diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 152b5b3c3fff..acd2edbc073e 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -173,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = - (unsigned long)sp->autoclose * HZ; + min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ; /* Initializes the timers */ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 61b9fca5a173..6f6ad8686833 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1285,6 +1285,9 @@ SCTP_STATIC __init int sctp_init(void) sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; + /* Initialize maximum autoclose timeout. */ + sctp_max_autoclose = INT_MAX / HZ; + /* Initialize handle used for association ids. */ idr_init(&sctp_assocs_id); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 13bf5fcdbff1..54a7cd2fdd7a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2200,8 +2200,6 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, return -EINVAL; if (copy_from_user(&sp->autoclose, optval, optlen)) return -EFAULT; - /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */ - sp->autoclose = min_t(long, sp->autoclose, MAX_SCHEDULE_TIMEOUT / HZ); return 0; } diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 6b3952961b85..60ffbd067ff7 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -53,6 +53,10 @@ static int sack_timer_min = 1; static int sack_timer_max = 500; static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ static int rwnd_scale_max = 16; +static unsigned long max_autoclose_min = 0; +static unsigned long max_autoclose_max = + (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) + ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; extern long sysctl_sctp_mem[3]; extern int sysctl_sctp_rmem[3]; @@ -258,6 +262,15 @@ static ctl_table sctp_table[] = { .extra1 = &one, .extra2 = &rwnd_scale_max, }, + { + .procname = "max_autoclose", + .data = &sctp_max_autoclose, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax, + .extra1 = &max_autoclose_min, + .extra2 = &max_autoclose_max, + }, { /* sentinel */ } }; -- cgit From 7746ab0abb512826540a9a0c917519d11a7bf392 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Sun, 18 Dec 2011 10:02:04 +0000 Subject: davinci-cpdma: fix locking issue in cpdma_chan_stop Free the channel lock before calling __cpdma_chan_process to prevent dead lock. Signed-off-by: Ilya Yanok Tested-by: Ameya Palande <2ameya@gmail.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index dca9d3369cdd..c97d2f590855 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -836,11 +836,13 @@ int cpdma_chan_stop(struct cpdma_chan *chan) chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); /* handle completed packets */ + spin_unlock_irqrestore(&chan->lock, flags); do { ret = __cpdma_chan_process(chan); if (ret < 0) break; } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + spin_lock_irqsave(&chan->lock, flags); /* remaining packets haven't been tx/rx'ed, clean them up */ while (chan->head) { -- cgit From e8303a3b2196272c3eb994d0fd1a189a958a2bdd Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Fri, 16 Dec 2011 10:49:22 +0000 Subject: asix: new device id Adds the device id needed for the USB Ethernet Adapter delivered by ASUS with their Zenbook. Signed-off-by: Aurelien Jacobs Acked-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e6fed4d4cb77..e95f0e60a9bc 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1655,6 +1655,10 @@ static const struct usb_device_id products [] = { // ASIX 88772a USB_DEVICE(0x0db0, 0xa877), .driver_info = (unsigned long) &ax88772_info, +}, { + // Asus USB Ethernet Adapter + USB_DEVICE (0x0b95, 0x7e2b), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; -- cgit From 29495aa04a30c21565243c5b9c028510446d242c Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 3 Nov 2011 11:09:45 +0100 Subject: mmc: sdhci: remove "state" argument from sdhci_suspend_host Drop the "state" argument from sdhci_suspend_host. Its only user is the PCI glue; this allows to move all SDHCI glues to use dev_pm_ops instead. Signed-off-by: Manuel Lauss Acked-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-cns3xxx.c | 5 +---- drivers/mmc/host/sdhci-dove.c | 5 +---- drivers/mmc/host/sdhci-esdhc-imx.c | 5 +---- drivers/mmc/host/sdhci-of-esdhc.c | 5 +---- drivers/mmc/host/sdhci-of-hlwd.c | 5 +---- drivers/mmc/host/sdhci-pci.c | 26 +++++++++++++------------- drivers/mmc/host/sdhci-pltfm.c | 18 +++++++++++------- drivers/mmc/host/sdhci-pltfm.h | 6 ++++-- drivers/mmc/host/sdhci-pxav2.c | 5 +---- drivers/mmc/host/sdhci-pxav3.c | 5 +---- drivers/mmc/host/sdhci-s3c.c | 21 ++++++++++++++------- drivers/mmc/host/sdhci-tegra.c | 5 +---- drivers/mmc/host/sdhci.c | 2 +- drivers/mmc/host/sdhci.h | 2 +- 14 files changed, 52 insertions(+), 63 deletions(-) diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 87b6f079b6e0..b4257e700617 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -109,13 +109,10 @@ static struct platform_driver sdhci_cns3xxx_driver = { .driver = { .name = "sdhci-cns3xxx", .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_cns3xxx_probe, .remove = __devexit_p(sdhci_cns3xxx_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_cns3xxx_init(void) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index f2d29dca4420..a81312c91f70 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -82,13 +82,10 @@ static struct platform_driver sdhci_dove_driver = { .driver = { .name = "sdhci-dove", .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_dove_probe, .remove = __devexit_p(sdhci_dove_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_dove_init(void) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 4b976f00ea85..38ebc4ea259f 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -599,14 +599,11 @@ static struct platform_driver sdhci_esdhc_imx_driver = { .name = "sdhci-esdhc-imx", .owner = THIS_MODULE, .of_match_table = imx_esdhc_dt_ids, + .pm = SDHCI_PLTFM_PMOPS, }, .id_table = imx_esdhc_devtype, .probe = sdhci_esdhc_imx_probe, .remove = __devexit_p(sdhci_esdhc_imx_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_esdhc_imx_init(void) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 59e9d003e589..01e5f627e0f0 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -125,13 +125,10 @@ static struct platform_driver sdhci_esdhc_driver = { .name = "sdhci-esdhc", .owner = THIS_MODULE, .of_match_table = sdhci_esdhc_of_match, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_esdhc_probe, .remove = __devexit_p(sdhci_esdhc_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_esdhc_init(void) diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 9b0d794a4f69..3619adc7d9fc 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c @@ -87,13 +87,10 @@ static struct platform_driver sdhci_hlwd_driver = { .name = "sdhci-hlwd", .owner = THIS_MODULE, .of_match_table = sdhci_hlwd_of_match, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_hlwd_probe, .remove = __devexit_p(sdhci_hlwd_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_hlwd_init(void) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index d833d9c2f7e3..6878a94626bc 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -54,8 +54,7 @@ struct sdhci_pci_fixes { int (*probe_slot) (struct sdhci_pci_slot *); void (*remove_slot) (struct sdhci_pci_slot *, int); - int (*suspend) (struct sdhci_pci_chip *, - pm_message_t); + int (*suspend) (struct sdhci_pci_chip *); int (*resume) (struct sdhci_pci_chip *); }; @@ -549,7 +548,7 @@ static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead) jmicron_enable_mmc(slot->host, 0); } -static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state) +static int jmicron_suspend(struct sdhci_pci_chip *chip) { int i; @@ -993,8 +992,9 @@ static struct sdhci_ops sdhci_pci_ops = { #ifdef CONFIG_PM -static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int sdhci_pci_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct sdhci_pci_chip *chip; struct sdhci_pci_slot *slot; mmc_pm_flag_t slot_pm_flags; @@ -1010,7 +1010,7 @@ static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (!slot) continue; - ret = sdhci_suspend_host(slot->host, state); + ret = sdhci_suspend_host(slot->host); if (ret) { for (i--; i >= 0; i--) @@ -1026,7 +1026,7 @@ static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state) } if (chip->fixes && chip->fixes->suspend) { - ret = chip->fixes->suspend(chip, state); + ret = chip->fixes->suspend(chip); if (ret) { for (i = chip->num_slots - 1; i >= 0; i--) sdhci_resume_host(chip->slots[i]->host); @@ -1042,16 +1042,17 @@ static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state) } pci_set_power_state(pdev, PCI_D3hot); } else { - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + pci_enable_wake(pdev, PCI_D3hot, 0); pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pci_set_power_state(pdev, PCI_D3hot); } return 0; } -static int sdhci_pci_resume(struct pci_dev *pdev) +static int sdhci_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct sdhci_pci_chip *chip; struct sdhci_pci_slot *slot; int i, ret; @@ -1099,7 +1100,6 @@ static int sdhci_pci_runtime_suspend(struct device *dev) struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); struct sdhci_pci_chip *chip; struct sdhci_pci_slot *slot; - pm_message_t state = { .event = PM_EVENT_SUSPEND }; int i, ret; chip = pci_get_drvdata(pdev); @@ -1121,7 +1121,7 @@ static int sdhci_pci_runtime_suspend(struct device *dev) } if (chip->fixes && chip->fixes->suspend) { - ret = chip->fixes->suspend(chip, state); + ret = chip->fixes->suspend(chip); if (ret) { for (i = chip->num_slots - 1; i >= 0; i--) sdhci_runtime_resume_host(chip->slots[i]->host); @@ -1176,6 +1176,8 @@ static int sdhci_pci_runtime_idle(struct device *dev) #endif static const struct dev_pm_ops sdhci_pci_pm_ops = { + .suspend = sdhci_pci_suspend, + .resume = sdhci_pci_resume, .runtime_suspend = sdhci_pci_runtime_suspend, .runtime_resume = sdhci_pci_runtime_resume, .runtime_idle = sdhci_pci_runtime_idle, @@ -1428,8 +1430,6 @@ static struct pci_driver sdhci_driver = { .id_table = pci_ids, .probe = sdhci_pci_probe, .remove = __devexit_p(sdhci_pci_remove), - .suspend = sdhci_pci_suspend, - .resume = sdhci_pci_resume, .driver = { .pm = &sdhci_pci_pm_ops }, diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index a9e12ea05583..03970bcb3495 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -194,21 +194,25 @@ int sdhci_pltfm_unregister(struct platform_device *pdev) EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); #ifdef CONFIG_PM -int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state) +static int sdhci_pltfm_suspend(struct device *dev) { - struct sdhci_host *host = platform_get_drvdata(dev); + struct sdhci_host *host = dev_get_drvdata(dev); - return sdhci_suspend_host(host, state); + return sdhci_suspend_host(host); } -EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend); -int sdhci_pltfm_resume(struct platform_device *dev) +static int sdhci_pltfm_resume(struct device *dev) { - struct sdhci_host *host = platform_get_drvdata(dev); + struct sdhci_host *host = dev_get_drvdata(dev); return sdhci_resume_host(host); } -EXPORT_SYMBOL_GPL(sdhci_pltfm_resume); + +const struct dev_pm_ops sdhci_pltfm_pmops = { + .suspend = sdhci_pltfm_suspend, + .resume = sdhci_pltfm_resume, +}; +EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops); #endif /* CONFIG_PM */ static int __init sdhci_pltfm_drv_init(void) diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 3a9fc3f40840..37e0e184a0bb 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -99,8 +99,10 @@ extern int sdhci_pltfm_register(struct platform_device *pdev, extern int sdhci_pltfm_unregister(struct platform_device *pdev); #ifdef CONFIG_PM -extern int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state); -extern int sdhci_pltfm_resume(struct platform_device *dev); +extern const struct dev_pm_ops sdhci_pltfm_pmops; +#define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) +#else +#define SDHCI_PLTFM_PMOPS NULL #endif #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index d4bf6d30c7ba..7a039c3cb1f1 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -218,13 +218,10 @@ static struct platform_driver sdhci_pxav2_driver = { .driver = { .name = "sdhci-pxav2", .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_pxav2_probe, .remove = __devexit_p(sdhci_pxav2_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_pxav2_init(void) { diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index cff4ad3e7a59..15673a7ee6a5 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -264,13 +264,10 @@ static struct platform_driver sdhci_pxav3_driver = { .driver = { .name = "sdhci-pxav3", .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_pxav3_probe, .remove = __devexit_p(sdhci_pxav3_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_pxav3_init(void) { diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index cb60c4197e0a..0d33ff0d67fb 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -622,23 +622,29 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) #ifdef CONFIG_PM -static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm) +static int sdhci_s3c_suspend(struct device *dev) { - struct sdhci_host *host = platform_get_drvdata(dev); + struct sdhci_host *host = dev_get_drvdata(dev); - return sdhci_suspend_host(host, pm); + return sdhci_suspend_host(host); } -static int sdhci_s3c_resume(struct platform_device *dev) +static int sdhci_s3c_resume(struct device *dev) { - struct sdhci_host *host = platform_get_drvdata(dev); + struct sdhci_host *host = dev_get_drvdata(dev); return sdhci_resume_host(host); } +static const struct dev_pm_ops sdhci_s3c_pmops = { + .suspend = sdhci_s3c_suspend, + .resume = sdhci_s3c_resume, +}; + +#define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops) + #else -#define sdhci_s3c_suspend NULL -#define sdhci_s3c_resume NULL +#define SDHCI_S3C_PMOPS NULL #endif static struct platform_driver sdhci_s3c_driver = { @@ -647,6 +653,7 @@ static struct platform_driver sdhci_s3c_driver = { .driver = { .owner = THIS_MODULE, .name = "s3c-sdhci", + .pm = SDHCI_S3C_PMOPS, }, }; diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 89699e861fc1..e2e18d3f949c 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -318,13 +318,10 @@ static struct platform_driver sdhci_tegra_driver = { .name = "sdhci-tegra", .owner = THIS_MODULE, .of_match_table = sdhci_tegra_dt_match, + .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_tegra_probe, .remove = __devexit_p(sdhci_tegra_remove), -#ifdef CONFIG_PM - .suspend = sdhci_pltfm_suspend, - .resume = sdhci_pltfm_resume, -#endif }; static int __init sdhci_tegra_init(void) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6d8eea323541..19ed580f2cab 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2327,7 +2327,7 @@ out: #ifdef CONFIG_PM -int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) +int sdhci_suspend_host(struct sdhci_host *host) { int ret; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0a5b65460d8a..a04d4d0c6fd2 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -374,7 +374,7 @@ extern int sdhci_add_host(struct sdhci_host *host); extern void sdhci_remove_host(struct sdhci_host *host, int dead); #ifdef CONFIG_PM -extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); +extern int sdhci_suspend_host(struct sdhci_host *host); extern int sdhci_resume_host(struct sdhci_host *host); extern void sdhci_enable_irq_wakeups(struct sdhci_host *host); #endif -- cgit From 5c7f0e083d2d98ba14ddd10e88f001a0ead4cae4 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Mon, 19 Dec 2011 15:51:38 -0800 Subject: Revert "mmc: enable runtime PM by default" When SDIO runtime PM was originally introduced, we immediately faced two regressions with two different chipsets, and in response decided not to enable it by default. With the recent work on the 8686 we hoped we found all the gotchas, so 08da834 did make sense (at least experimentally). Unfortunately we now see that some setups out there still refuse to work when SDIO runtime PM is enabled by default (see http://www.spinics.net/lists/linux-mmc/msg11161.html), and obviously we can't live with these kind of regressions. This reverts commit 08da834a24312157f512224691ad1fddd11c1073. Signed-off-by: Ohad Ben-Cohen Cc: Daniel Drake Signed-off-by: Chris Ball --- drivers/mmc/core/host.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index e8a5eb38748b..d31c78b72b0f 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -302,17 +302,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) host->max_blk_size = 512; host->max_blk_count = PAGE_CACHE_SIZE / 512; - /* - * Enable runtime power management by default. This flag was added due - * to runtime power management causing disruption for some users, but - * the power on/off code has been improved since then. - * - * We'll enable this flag by default as an experiment, and if no - * problems are reported, we will follow up later and remove the flag - * altogether. - */ - host->caps = MMC_CAP_POWER_OFF_CARD; - return host; free: -- cgit From 61074287c2965edf0fc75b54ae8f4ce99f182669 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 15 Dec 2011 13:34:50 +1030 Subject: mmc: vub300: fix type of firmware_rom_wait_states module parameter You didn't mean this to be a bool. Signed-off-by: Rusty Russell Acked-by: Tony Olech Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/vub300.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index e8f6e65183d7..2ec978bc32ba 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -259,7 +259,7 @@ static int firmware_rom_wait_states = 0x04; static int firmware_rom_wait_states = 0x1C; #endif -module_param(firmware_rom_wait_states, bool, 0644); +module_param(firmware_rom_wait_states, int, 0644); MODULE_PARM_DESC(firmware_rom_wait_states, "ROM wait states byte=RRRIIEEE (Reserved Internal External)"); -- cgit From d21b59451886cb82448302f8d6f9ac87c3bd56cf Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Mon, 5 Dec 2011 13:17:41 +0200 Subject: evm: key must be set once during initialization On multi-core systems, setting of the key before every caclculation, causes invalid HMAC calculation for other tfm users, because internal state (ipad, opad) can be invalid before set key call returns. It needs to be set only once during initialization. Signed-off-by: Dmitry Kasatkin Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/evm/evm_crypto.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 5dd5b140242c..4ad657d88097 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -41,6 +41,12 @@ static struct shash_desc *init_desc(void) hmac_tfm = NULL; return ERR_PTR(rc); } + rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); + if (rc) { + crypto_free_shash(hmac_tfm); + hmac_tfm = NULL; + return ERR_PTR(rc); + } } desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm), @@ -51,11 +57,7 @@ static struct shash_desc *init_desc(void) desc->tfm = hmac_tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); - if (rc) - goto out; rc = crypto_shash_init(desc); -out: if (rc) { kfree(desc); return ERR_PTR(rc); -- cgit From 97426f985729573cea06e82e271cc3929f1f5f8e Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Mon, 5 Dec 2011 13:17:42 +0200 Subject: evm: prevent racing during tfm allocation There is a small chance of racing during tfm allocation. This patch fixes it. Signed-off-by: Dmitry Kasatkin Acked-by: Mimi Zohar Signed-off-by: James Morris --- security/integrity/evm/evm_crypto.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 4ad657d88097..8738deff26fa 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -27,26 +27,35 @@ static int evmkey_len = MAX_KEY_SIZE; struct crypto_shash *hmac_tfm; +static DEFINE_MUTEX(mutex); + static struct shash_desc *init_desc(void) { int rc; struct shash_desc *desc; if (hmac_tfm == NULL) { + mutex_lock(&mutex); + if (hmac_tfm) + goto out; hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hmac_tfm)) { pr_err("Can not allocate %s (reason: %ld)\n", evm_hmac, PTR_ERR(hmac_tfm)); rc = PTR_ERR(hmac_tfm); hmac_tfm = NULL; + mutex_unlock(&mutex); return ERR_PTR(rc); } rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); if (rc) { crypto_free_shash(hmac_tfm); hmac_tfm = NULL; + mutex_unlock(&mutex); return ERR_PTR(rc); } +out: + mutex_unlock(&mutex); } desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm), -- cgit From 9ad33ba51a1ac29ba3cf90d95e4b7f7eba278f6c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 31 Oct 2011 10:34:01 +0800 Subject: mfd: Add missed free_irq in da903x_remove Signed-off-by: Axel Lin Acked-by: Eric Miao Signed-off-by: Samuel Ortiz --- drivers/mfd/da903x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 1b79c37fd599..62ce685a79cb 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -549,6 +549,7 @@ static int __devexit da903x_remove(struct i2c_client *client) struct da903x_chip *chip = i2c_get_clientdata(client); da903x_remove_subdevs(chip); + free_irq(client->irq, chip); kfree(chip); return 0; } -- cgit From 890c98e3746fa8705cc9c70979e64360cf2d8a31 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 31 Oct 2011 11:00:06 +0800 Subject: mfd: Set adp5520 bits if new value is different from the old one Current code checks if all the bit_mask bits are all zero is wrong. We need to write new value if the bit mask fields of new value is not equal to old value. Signed-off-by: Axel Lin Acked-by: Michael Hennerich Signed-off-by: Samuel Ortiz --- drivers/mfd/adp5520.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index f1d88483112c..8d816cce8322 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -109,7 +109,7 @@ int adp5520_set_bits(struct device *dev, int reg, uint8_t bit_mask) ret = __adp5520_read(chip->client, reg, ®_val); - if (!ret && ((reg_val & bit_mask) == 0)) { + if (!ret && ((reg_val & bit_mask) != bit_mask)) { reg_val |= bit_mask; ret = __adp5520_write(chip->client, reg, reg_val); } -- cgit From af65e6cef488be0bd15932c8ce9801a47a183051 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 31 Oct 2011 14:23:03 +0800 Subject: mfd: Set da903x bits if new value is different from the old one It does not make sense to write new value only when all the bit_mask bits are zero. We need to write new value if the bit mask fields of new value is not equal to old value. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/da903x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 62ce685a79cb..1924b857a0fb 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -182,7 +182,7 @@ int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask) if (ret) goto out; - if ((reg_val & bit_mask) == 0) { + if ((reg_val & bit_mask) != bit_mask) { reg_val |= bit_mask; ret = __da903x_write(chip->client, reg, reg_val); } -- cgit From 26bc4e0cc5426e86398d6780d160f02c0a347087 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 31 Oct 2011 14:24:30 +0800 Subject: mfd: Set tps6586x bits if new value is different from the old one It does not make sense to write new value only when all the bit_mask bits are zero. We need to write new value if the bit mask fields of new value is not equal to old value. Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/tps6586x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index bba26d96c240..a5ddf31b60ca 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -197,7 +197,7 @@ int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) if (ret) goto out; - if ((reg_val & bit_mask) == 0) { + if ((reg_val & bit_mask) != bit_mask) { reg_val |= bit_mask; ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); } -- cgit From b5488b6e868454fb10d23278de5038cda98b13ab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Nov 2011 23:14:46 +0000 Subject: mfd: Update wm8994 active device checks for WM1811 This didn't go in as part of the original MFD patch for WM1811 due to cross tree issues. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 5d6ba132837e..61894fced8ea 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -239,6 +239,7 @@ static int wm8994_suspend(struct device *dev) switch (wm8994->type) { case WM8958: + case WM1811: ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1); if (ret < 0) { dev_err(dev, "Failed to read power status: %d\n", ret); -- cgit From 858a6303f2b14945447a964563f54c918ef3927e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 7 Nov 2011 11:20:09 +0800 Subject: mfd: include linux/module.h for ab5500-debugfs Include linux/module.h to fix below build error: CC drivers/mfd/ab5500-debugfs.o drivers/mfd/ab5500-debugfs.c:571: error: 'THIS_MODULE' undeclared here (not in a function) make[2]: *** [drivers/mfd/ab5500-debugfs.o] Error 1 Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Samuel Ortiz --- drivers/mfd/ab5500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c index 43c0ebb81956..b7b2d3483fd4 100644 --- a/drivers/mfd/ab5500-debugfs.c +++ b/drivers/mfd/ab5500-debugfs.c @@ -4,7 +4,7 @@ * Debugfs support for the AB5500 MFD driver */ -#include +#include #include #include #include -- cgit From 8653be1afd60d6e8c36139b487e375b70357d9ef Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Mon, 1 Aug 2011 23:00:28 +0200 Subject: mfd: Fix twl-core oops while calling twl_i2c_* for unbound driver Check inuse variable before trying to access twl_map to prevent dereferencing of uninitialized variable. Signed-off-by: Ilya Yanok Cc: stable@kernel.org Signed-off-by: Samuel Ortiz --- drivers/mfd/twl-core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index bfbd66021afd..61e70cfaa774 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -363,13 +363,13 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); return -EPERM; } - sid = twl_map[mod_no].sid; - twl = &twl_modules[sid]; - if (unlikely(!inuse)) { - pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); + pr_err("%s: not initialized\n", DRIVER_NAME); return -EPERM; } + sid = twl_map[mod_no].sid; + twl = &twl_modules[sid]; + mutex_lock(&twl->xfer_lock); /* * [MSG1]: fill the register address data @@ -420,13 +420,13 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); return -EPERM; } - sid = twl_map[mod_no].sid; - twl = &twl_modules[sid]; - if (unlikely(!inuse)) { - pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); + pr_err("%s: not initialized\n", DRIVER_NAME); return -EPERM; } + sid = twl_map[mod_no].sid; + twl = &twl_modules[sid]; + mutex_lock(&twl->xfer_lock); /* [MSG1] fill the register address data */ msg = &twl->xfer_msg[0]; -- cgit From df7206477e36bb73e81b99c2cbbc1b91e4b1c8ac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 10 Nov 2011 09:56:18 +0800 Subject: mfd: add #ifdef CONFIG_DEBUG_FS guard for ab8500_debug_resources Fix below build warning if CONFIG_DEBUG_FS is disabled. CC drivers/mfd/ab8500-core.o drivers/mfd/ab8500-core.c:623: warning: 'ab8500_debug_resources' defined but not used Signed-off-by: Axel Lin Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 1e9173804ede..d3d572b2317b 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -620,6 +620,7 @@ static struct resource __devinitdata ab8500_fg_resources[] = { static struct resource __devinitdata ab8500_chargalg_resources[] = {}; +#ifdef CONFIG_DEBUG_FS static struct resource __devinitdata ab8500_debug_resources[] = { { .name = "IRQ_FIRST", @@ -634,6 +635,7 @@ static struct resource __devinitdata ab8500_debug_resources[] = { .flags = IORESOURCE_IRQ, }, }; +#endif static struct resource __devinitdata ab8500_usb_resources[] = { { -- cgit From 8f6a459a9daa6ce76d7c192f2cb3047fffb45ec8 Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Tue, 22 Nov 2011 14:39:51 +0100 Subject: mfd: Handle tps65910 clear-mask correctly The function is not actually cleaing the bitmask. Signed-off-by: Marcus Folkesson Signed-off-by: Samuel Ortiz --- drivers/mfd/tps65910.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 6f5b8cf2f652..c1da84bc1573 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -120,7 +120,7 @@ int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) goto out; } - data &= mask; + data &= ~mask; err = tps65910_i2c_write(tps65910, reg, 1, &data); if (err) dev_err(tps65910->dev, "write to reg %x failed\n", reg); -- cgit From 286f8f3cd615177d5d0f8af8059a3fa39f51fa97 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 27 Nov 2011 07:17:41 +1100 Subject: mfd: Base interrupt for twl4030-irq must be one-shot As the interrupt source is only cleared by the threaded interrupt service routine, we need to make the base interrupt IRQF_ONESHOT. Without this, the first interrupt from the TWL4030 cause the CPU to enter an infinite loop trying to handle to interrupt but never clearing it. Signed-off-by: NeilBrown Tested-by: Felipe Contreras Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-irq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index f062c8cc6c38..3d3d6ed48f8d 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -733,8 +733,9 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) } /* install an irq handler to demultiplex the TWL4030 interrupt */ - status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, 0, - "TWL4030-PIH", NULL); + status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, + IRQF_ONESHOT, + "TWL4030-PIH", NULL); if (status < 0) { pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); goto fail_rqirq; -- cgit From c1e61bcf8269d3bc4390a363ad2e1bc1dc226bda Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 27 Nov 2011 07:17:41 +1100 Subject: mfd: Use request_threaded_irq for twl4030-irq instead of irq_set_chained_handler irq_set_chained_handler sets 'desc->handle_irq'. However this irq is called by handle_nested_irq from handle_twl4030_pih, and that uses action->thread_fn. So the handled set with irq_set_chained_handler is never called. So change to use request_threaded_irq instead - that sets the correct field. Tested on GTA04 Phoenux. Signed-off-by: NeilBrown Tested-by: Felipe Contreras Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-irq.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 3d3d6ed48f8d..29f11e0765fe 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -432,6 +432,7 @@ struct sih_agent { u32 edge_change; struct mutex irq_lock; + char *irq_name; }; /*----------------------------------------------------------------------*/ @@ -589,7 +590,7 @@ static inline int sih_read_isr(const struct sih *sih) * Generic handler for SIH interrupts ... we "know" this is called * in task context, with IRQs enabled. */ -static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) +static irqreturn_t handle_twl4030_sih(int irq, void *data) { struct sih_agent *agent = irq_get_handler_data(irq); const struct sih *sih = agent->sih; @@ -602,7 +603,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) pr_err("twl4030: %s SIH, read ISR error %d\n", sih->name, isr); /* REVISIT: recover; eventually mask it all, etc */ - return; + return IRQ_HANDLED; } while (isr) { @@ -616,6 +617,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) pr_err("twl4030: %s SIH, invalid ISR bit %d\n", sih->name, irq); } + return IRQ_HANDLED; } static unsigned twl4030_irq_next; @@ -668,18 +670,19 @@ int twl4030_sih_setup(int module) activate_irq(irq); } - status = irq_base; twl4030_irq_next += i; /* replace generic PIH handler (handle_simple_irq) */ irq = sih_mod + twl4030_irq_base; irq_set_handler_data(irq, agent); - irq_set_chained_handler(irq, handle_twl4030_sih); + agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name); + status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, + agent->irq_name ?: sih->name, NULL); pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, irq, irq_base, twl4030_irq_next - 1); - return status; + return status < 0 ? status : irq_base; } /* FIXME need a call to reverse twl4030_sih_setup() ... */ -- cgit From fa860403e61cf5201e2f03b726aa53c30ae9a659 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 9 Dec 2011 11:27:55 +0800 Subject: mfd: Include linux/io.h to jz4740-adc Include linux/io.h to fix below build error: CC drivers/mfd/jz4740-adc.o drivers/mfd/jz4740-adc.c: In function 'jz4740_adc_irq_demux': drivers/mfd/jz4740-adc.c:73: error: implicit declaration of function 'readb' drivers/mfd/jz4740-adc.c: In function 'jz4740_adc_set_enabled': drivers/mfd/jz4740-adc.c:110: error: implicit declaration of function 'writeb' drivers/mfd/jz4740-adc.c: In function 'jz4740_adc_set_config': drivers/mfd/jz4740-adc.c:146: error: implicit declaration of function 'readl' drivers/mfd/jz4740-adc.c:151: error: implicit declaration of function 'writel' drivers/mfd/jz4740-adc.c: In function 'jz4740_adc_probe': drivers/mfd/jz4740-adc.c:249: error: implicit declaration of function 'ioremap_nocache' drivers/mfd/jz4740-adc.c:249: warning: assignment makes pointer from integer without a cast drivers/mfd/jz4740-adc.c:289: warning: passing argument 3 of 'mfd_add_devices' discards qualifiers from pointer target type include/linux/mfd/core.h:93: note: expected 'struct mfd_cell *' but argument is of type 'const struct mfd_cell *' drivers/mfd/jz4740-adc.c:299: error: implicit declaration of function 'iounmap' make[2]: *** [drivers/mfd/jz4740-adc.o] Error 1 make[1]: *** [drivers/mfd] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Samuel Ortiz --- drivers/mfd/jz4740-adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 1e9ee533eacb..ef39528088f2 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include -- cgit From b246272ecc5ac68c743b15c9e41a2275f7ce70e2 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 19 Dec 2011 17:11:52 -0800 Subject: cpusets: stall when updating mems_allowed for mempolicy or disjoint nodemask Kernels where MAX_NUMNODES > BITS_PER_LONG may temporarily see an empty nodemask in a tsk's mempolicy if its previous nodemask is remapped onto a new set of allowed cpuset nodes where the two nodemasks, as a result of the remap, are now disjoint. c0ff7453bb5c ("cpuset,mm: fix no node to alloc memory when changing cpuset's mems") adds get_mems_allowed() to prevent the set of allowed nodes from changing for a thread. This causes any update to a set of allowed nodes to stall until put_mems_allowed() is called. This stall is unncessary, however, if at least one node remains unchanged in the update to the set of allowed nodes. This was addressed by 89e8a244b97e ("cpusets: avoid looping when storing to mems_allowed if one node remains set"), but it's still possible that an empty nodemask may be read from a mempolicy because the old nodemask may be remapped to the new nodemask during rebind. To prevent this, only avoid the stall if there is no mempolicy for the thread being changed. This is a temporary solution until all reads from mempolicy nodemasks can be guaranteed to not be empty without the get_mems_allowed() synchronization. Also moves the check for nodemask intersection inside task_lock() so that tsk->mems_allowed cannot change. This ensures that nothing can set this tsk's mems_allowed out from under us and also protects tsk->mempolicy. Reported-by: Miao Xie Signed-off-by: David Rientjes Cc: KOSAKI Motohiro Cc: Paul Menage Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 9fe58c46a426..0b1712dba587 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -123,6 +123,19 @@ static inline struct cpuset *task_cs(struct task_struct *task) struct cpuset, css); } +#ifdef CONFIG_NUMA +static inline bool task_has_mempolicy(struct task_struct *task) +{ + return task->mempolicy; +} +#else +static inline bool task_has_mempolicy(struct task_struct *task) +{ + return false; +} +#endif + + /* bits in struct cpuset flags field */ typedef enum { CS_CPU_EXCLUSIVE, @@ -949,7 +962,7 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from, static void cpuset_change_task_nodemask(struct task_struct *tsk, nodemask_t *newmems) { - bool masks_disjoint = !nodes_intersects(*newmems, tsk->mems_allowed); + bool need_loop; repeat: /* @@ -962,6 +975,14 @@ repeat: return; task_lock(tsk); + /* + * Determine if a loop is necessary if another thread is doing + * get_mems_allowed(). If at least one node remains unchanged and + * tsk does not have a mempolicy, then an empty nodemask will not be + * possible when mems_allowed is larger than a word. + */ + need_loop = task_has_mempolicy(tsk) || + !nodes_intersects(*newmems, tsk->mems_allowed); nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); @@ -981,11 +1002,9 @@ repeat: /* * Allocation of memory is very fast, we needn't sleep when waiting - * for the read-side. No wait is necessary, however, if at least one - * node remains unchanged. + * for the read-side. */ - while (masks_disjoint && - ACCESS_ONCE(tsk->mems_allowed_change_disable)) { + while (need_loop && ACCESS_ONCE(tsk->mems_allowed_change_disable)) { task_unlock(tsk); if (!task_curr(tsk)) yield(); -- cgit From 695c60f21c69e525a89279a5f35bae4ff237afbc Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Mon, 19 Dec 2011 17:11:55 -0800 Subject: nilfs2: unbreak compat ioctl commit 828b1c50ae ("nilfs2: add compat ioctl") incidentally broke all other NILFS compat ioctls. Make them work again. Signed-off-by: Thomas Meyer Signed-off-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Cc: [3.0+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/ioctl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 41d6743d303c..3e654273cfc2 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -842,6 +842,19 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case FS_IOC32_GETVERSION: cmd = FS_IOC_GETVERSION; break; + case NILFS_IOCTL_CHANGE_CPMODE: + case NILFS_IOCTL_DELETE_CHECKPOINT: + case NILFS_IOCTL_GET_CPINFO: + case NILFS_IOCTL_GET_CPSTAT: + case NILFS_IOCTL_GET_SUINFO: + case NILFS_IOCTL_GET_SUSTAT: + case NILFS_IOCTL_GET_VINFO: + case NILFS_IOCTL_GET_BDESCS: + case NILFS_IOCTL_CLEAN_SEGMENTS: + case NILFS_IOCTL_SYNC: + case NILFS_IOCTL_RESIZE: + case NILFS_IOCTL_SET_ALLOC_RANGE: + break; default: return -ENOIOCTLCMD; } -- cgit From 481fe17e973fb97aa3edf17c69557afe88d8334f Mon Sep 17 00:00:00 2001 From: Haogang Chen Date: Mon, 19 Dec 2011 17:11:56 -0800 Subject: nilfs2: potential integer overflow in nilfs_ioctl_clean_segments() There is a potential integer overflow in nilfs_ioctl_clean_segments(). When a large argv[n].v_nmembs is passed from the userspace, the subsequent call to vmalloc() will allocate a buffer smaller than expected, which leads to out-of-bound access in nilfs_ioctl_move_blocks() and lfs_clean_segments(). The following check does not prevent the overflow because nsegs is also controlled by the userspace and could be very large. if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment) goto out_free; This patch clamps argv[n].v_nmembs to UINT_MAX / argv[n].v_size, and returns -EINVAL when overflow. Signed-off-by: Haogang Chen Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/ioctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 3e654273cfc2..ac258beeda3c 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -625,6 +625,9 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment) goto out_free; + if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size) + goto out_free; + len = argv[n].v_size * argv[n].v_nmembs; base = (void __user *)(unsigned long)argv[n].v_base; if (len == 0) { -- cgit From a41c58a6665cc995e237303b05db42100b71b65e Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Mon, 19 Dec 2011 17:11:57 -0800 Subject: memcg: keep root group unchanged if creation fails If the request is to create non-root group and we fail to meet it, we should leave the root unchanged. Signed-off-by: Hillf Danton Acked-by: Hugh Dickins Acked-by: KAMEZAWA Hiroyuki Acked-by: Michal Hocko Cc: Balbir Singh Cc: David Rientjes Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6aff93c98aca..b63f5f7dfa07 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4907,9 +4907,9 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) int cpu; enable_swap_cgroup(); parent = NULL; - root_mem_cgroup = memcg; if (mem_cgroup_soft_limit_tree_init()) goto free_out; + root_mem_cgroup = memcg; for_each_possible_cpu(cpu) { struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); @@ -4948,7 +4948,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) return &memcg->css; free_out: __mem_cgroup_free(memcg); - root_mem_cgroup = NULL; return ERR_PTR(error); } -- cgit From ff05b6f7ae762b6eb464183eec994b28ea09f6dd Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Mon, 19 Dec 2011 17:11:59 -0800 Subject: oom: fix integer overflow of points in oom_badness An integer overflow will happen on 64bit archs if task's sum of rss, swapents and nr_ptes exceeds (2^31)/1000 value. This was introduced by commit f755a04 oom: use pte pages in OOM score where the oom score computation was divided into several steps and it's no longer computed as one expression in unsigned long(rss, swapents, nr_pte are unsigned long), where the result value assigned to points(int) is in range(1..1000). So there could be an int overflow while computing 176 points *= 1000; and points may have negative value. Meaning the oom score for a mem hog task will be one. 196 if (points <= 0) 197 return 1; For example: [ 3366] 0 3366 35390480 24303939 5 0 0 oom01 Out of memory: Kill process 3366 (oom01) score 1 or sacrifice child Here the oom1 process consumes more than 24303939(rss)*4096~=92GB physical memory, but it's oom score is one. In this situation the mem hog task is skipped and oom killer kills another and most probably innocent task with oom score greater than one. The points variable should be of type long instead of int to prevent the int overflow. Signed-off-by: Frantisek Hrbata Acked-by: KOSAKI Motohiro Acked-by: Oleg Nesterov Acked-by: David Rientjes Cc: [2.6.36+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/oom_kill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 76f2c5ae908e..069b64e521fc 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -176,7 +176,7 @@ static bool oom_unkillable_task(struct task_struct *p, unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, const nodemask_t *nodemask, unsigned long totalpages) { - int points; + long points; if (oom_unkillable_task(p, mem, nodemask)) return 0; -- cgit From b75d91f7ca513f0a4d0d1ad0942fb90cf5a2bc88 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 19 Dec 2011 17:12:02 -0800 Subject: ipmi_watchdog: restore settings when BMC reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the BMC gets reset, it will return 0x80 response errors. In less than a week # grep "Error 80 on cmd 22" /var/log/kernel |wc -l 378681 In this case, it is probably a good idea to restore the IPMI settings. Signed-off-by: Corey Minyard Tested-by: Arkadiusz Miśkiewicz Reported-by: Arkadiusz Miśkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_watchdog.c | 41 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index c2917ffad2c2..34767a6d7f42 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -139,6 +139,8 @@ #define IPMI_WDOG_SET_TIMER 0x24 #define IPMI_WDOG_GET_TIMER 0x25 +#define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80 + /* These are here until the real ones get into the watchdog.h interface. */ #ifndef WDIOC_GETTIMEOUT #define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int) @@ -596,6 +598,7 @@ static int ipmi_heartbeat(void) struct kernel_ipmi_msg msg; int rv; struct ipmi_system_interface_addr addr; + int timeout_retries = 0; if (ipmi_ignore_heartbeat) return 0; @@ -616,6 +619,7 @@ static int ipmi_heartbeat(void) mutex_lock(&heartbeat_lock); +restart: atomic_set(&heartbeat_tofree, 2); /* @@ -653,7 +657,33 @@ static int ipmi_heartbeat(void) /* Wait for the heartbeat to be sent. */ wait_for_completion(&heartbeat_wait); - if (heartbeat_recv_msg.msg.data[0] != 0) { + if (heartbeat_recv_msg.msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP) { + timeout_retries++; + if (timeout_retries > 3) { + printk(KERN_ERR PFX ": Unable to restore the IPMI" + " watchdog's settings, giving up.\n"); + rv = -EIO; + goto out_unlock; + } + + /* + * The timer was not initialized, that means the BMC was + * probably reset and lost the watchdog information. Attempt + * to restore the timer's info. Note that we still hold + * the heartbeat lock, to keep a heartbeat from happening + * in this process, so must say no heartbeat to avoid a + * deadlock on this mutex. + */ + rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + if (rv) { + printk(KERN_ERR PFX ": Unable to send the command to" + " set the watchdog's settings, giving up.\n"); + goto out_unlock; + } + + /* We might need a new heartbeat, so do it now */ + goto restart; + } else if (heartbeat_recv_msg.msg.data[0] != 0) { /* * Got an error in the heartbeat response. It was already * reported in ipmi_wdog_msg_handler, but we should return @@ -662,6 +692,7 @@ static int ipmi_heartbeat(void) rv = -EINVAL; } +out_unlock: mutex_unlock(&heartbeat_lock); return rv; @@ -922,11 +953,15 @@ static struct miscdevice ipmi_wdog_miscdev = { static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, void *handler_data) { - if (msg->msg.data[0] != 0) { + if (msg->msg.cmd == IPMI_WDOG_RESET_TIMER && + msg->msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP) + printk(KERN_INFO PFX "response: The IPMI controller appears" + " to have been reset, will attempt to reinitialize" + " the watchdog timer\n"); + else if (msg->msg.data[0] != 0) printk(KERN_ERR PFX "response: Error %x on cmd %x\n", msg->msg.data[0], msg->msg.cmd); - } ipmi_free_recv_msg(msg); } -- cgit From 0006526d78e93c3684c806bf7cf3f67dfa49c3c8 Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Mon, 19 Dec 2011 17:12:04 -0800 Subject: mm/vmalloc.c: remove static declaration of va from __get_vm_area_node Static storage is not required for the struct vmap_area in __get_vm_area_node. Removing "static" to store this variable on the stack instead. Signed-off-by: Kautuk Consul Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 1d8b32f07139..27be2f0d4cb7 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1290,7 +1290,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long align, unsigned long flags, unsigned long start, unsigned long end, int node, gfp_t gfp_mask, void *caller) { - static struct vmap_area *va; + struct vmap_area *va; struct vm_struct *area; BUG_ON(in_interrupt()); -- cgit From 3d3c8f93a237b64580c5c5e138edeb1377e98230 Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Mon, 19 Dec 2011 17:12:06 -0800 Subject: binary_sysctl(): fix memory leak binary_sysctl() calls sysctl_getname() which allocates from names_cache slab usin __getname() The matching function to free the name is __putname(), and not putname() which should be used only to match getname() allocations. This is because when auditing is enabled, putname() calls audit_putname *instead* (not in addition) to __putname(). Then, if a syscall is in progress, audit_putname does not release the name - instead, it expects the name to get released when the syscall completes, but that will happen only if audit_getname() was called previously, i.e. if the name was allocated with getname() rather than the naked __getname(). So, __getname() followed by putname() ends up leaking memory. Signed-off-by: Michel Lespinasse Acked-by: Al Viro Cc: Christoph Hellwig Cc: Eric Paris Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sysctl_binary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index 6318b511afa1..a650694883a1 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c @@ -1354,7 +1354,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, fput(file); out_putname: - putname(pathname); + __putname(pathname); out: return result; } -- cgit From a76c0adf60f6ca5ff3481992e4ea0383776b24d2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 19 Dec 2011 04:11:40 +0000 Subject: sctp: Do not account for sizeof(struct sk_buff) in estimated rwnd When checking whether a DATA chunk fits into the estimated rwnd a full sizeof(struct sk_buff) is added to the needed chunk size. This quickly exhausts the available rwnd space and leads to packets being sent which are much below the PMTU limit. This can lead to much worse performance. The reason for this behaviour was to avoid putting too much memory pressure on the receiver. The concept is not completely irational because a Linux receiver does in fact clone an skb for each DATA chunk delivered. However, Linux also reserves half the available socket buffer space for data structures therefore usage of it is already accounted for. When proposing to change this the last time it was noted that this behaviour was introduced to solve a performance issue caused by rwnd overusage in combination with small DATA chunks. Trying to reproduce this I found that with the sk_buff overhead removed, the performance would improve significantly unless socket buffer limits are increased. The following numbers have been gathered using a patched iperf supporting SCTP over a live 1 Gbit ethernet network. The -l option was used to limit DATA chunk sizes. The numbers listed are based on the average of 3 test runs each. Default values have been used for sk_(r|w)mem. Chunk Size Unpatched No Overhead ------------------------------------- 4 15.2 Kbit [!] 12.2 Mbit [!] 8 35.8 Kbit [!] 26.0 Mbit [!] 16 95.5 Kbit [!] 54.4 Mbit [!] 32 106.7 Mbit 102.3 Mbit 64 189.2 Mbit 188.3 Mbit 128 331.2 Mbit 334.8 Mbit 256 537.7 Mbit 536.0 Mbit 512 766.9 Mbit 766.6 Mbit 1024 810.1 Mbit 808.6 Mbit Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sctp/output.c | 8 +------- net/sctp/outqueue.c | 6 ++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 08b3cead6503..817174eb5f41 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -697,13 +697,7 @@ static void sctp_packet_append_data(struct sctp_packet *packet, /* Keep track of how many bytes are in flight to the receiver. */ asoc->outqueue.outstanding_bytes += datasize; - /* Update our view of the receiver's rwnd. Include sk_buff overhead - * while updating peer.rwnd so that it reduces the chances of a - * receiver running out of receive buffer space even when receive - * window is still open. This can happen when a sender is sending - * sending small messages. - */ - datasize += sizeof(struct sk_buff); + /* Update our view of the receiver's rwnd. */ if (datasize < rwnd) rwnd -= datasize; else diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 14c2b06028ff..cfeb1d4a1ee6 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -411,8 +411,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, chunk->transport->flight_size -= sctp_data_size(chunk); q->outstanding_bytes -= sctp_data_size(chunk); - q->asoc->peer.rwnd += (sctp_data_size(chunk) + - sizeof(struct sk_buff)); + q->asoc->peer.rwnd += sctp_data_size(chunk); } continue; } @@ -432,8 +431,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, * (Section 7.2.4)), add the data size of those * chunks to the rwnd. */ - q->asoc->peer.rwnd += (sctp_data_size(chunk) + - sizeof(struct sk_buff)); + q->asoc->peer.rwnd += sctp_data_size(chunk); q->outstanding_bytes -= sctp_data_size(chunk); if (chunk->transport) transport->flight_size -= sctp_data_size(chunk); -- cgit From cd7816d14953c8af910af5bb92f488b0b277e29d Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Mon, 19 Dec 2011 22:58:04 +0000 Subject: net: have ipconfig not wait if no dev is available previous commit 3fb72f1e6e6165c5f495e8dc11c5bbd14c73385c makes IP-Config wait for carrier on at least one network device. Before waiting (predefined value 120s), check that at least one device was successfully brought up. Otherwise (e.g. buggy bootloader which does not set the MAC address) there is no point in waiting for carrier. Cc: Micha Nelissen Cc: Holger Brunck Signed-off-by: Gerlando Falauto Signed-off-by: David S. Miller --- net/ipv4/ipconfig.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 0da2afc97f32..99ec116bef14 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -253,6 +253,10 @@ static int __init ic_open_devs(void) } } + /* no point in waiting if we could not bring up at least one device */ + if (!ic_first_dev) + goto have_carrier; + /* wait for a carrier on at least one device */ start = jiffies; while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) { -- cgit From 50345f1ea9cda4618d9c26e590a97ecd4bc7ac75 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 13 Dec 2011 14:49:04 +0000 Subject: SELinux: Fix RCU deref check warning in sel_netport_insert() Fix the following bug in sel_netport_insert() where rcu_dereference() should be rcu_dereference_protected() as sel_netport_lock is held. =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- security/selinux/netport.c:127 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by ossec-rootcheck/3323: #0: (sel_netport_lock){+.....}, at: [] sel_netport_sid+0xbb/0x226 stack backtrace: Pid: 3323, comm: ossec-rootcheck Not tainted 3.1.0-rc8-fsdevel+ #1095 Call Trace: [] lockdep_rcu_dereference+0xa7/0xb0 [] sel_netport_sid+0x1b7/0x226 [] ? sel_netport_avc_callback+0xbc/0xbc [] selinux_socket_bind+0x115/0x230 [] ? might_fault+0x4e/0x9e [] ? might_fault+0x97/0x9e [] security_socket_bind+0x11/0x13 [] sys_bind+0x56/0x95 [] ? sysret_check+0x27/0x62 [] ? trace_hardirqs_on_caller+0x11e/0x155 [] ? audit_syscall_entry+0x17b/0x1ae [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Signed-off-by: David Howells Acked-by: Paul Moore Acked-by: Eric Dumazet Cc: stable@kernel.org Signed-off-by: James Morris --- security/selinux/netport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 0b62bd112461..7b9eb1faf68b 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -123,7 +123,9 @@ static void sel_netport_insert(struct sel_netport *port) if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) { struct sel_netport *tail; tail = list_entry( - rcu_dereference(sel_netport_hash[idx].list.prev), + rcu_dereference_protected( + sel_netport_hash[idx].list.prev, + lockdep_is_held(&sel_netport_lock)), struct sel_netport, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); -- cgit From 7b21a202b87b7f18587bd15ee6bdb477fed0fb43 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 21 Dec 2011 03:54:24 +0000 Subject: firmware: Refer to the co-maintained linux-firmware.git repository David and I are sharing maintenance of this repository. Patches should be sent to both of us. Signed-off-by: Ben Hutchings Signed-off-by: Linus Torvalds --- firmware/README.AddingFirmware | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/README.AddingFirmware b/firmware/README.AddingFirmware index e24cd8986d8b..ea78c3a17eec 100644 --- a/firmware/README.AddingFirmware +++ b/firmware/README.AddingFirmware @@ -12,7 +12,7 @@ here. This directory is _NOT_ for adding arbitrary new firmware images. The place to add those is the separate linux-firmware repository: - git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git + git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git That repository contains all these firmware images which have been extracted from older drivers, as well various new firmware images which @@ -22,6 +22,7 @@ been permitted to redistribute under separate cover. To submit firmware to that repository, please send either a git binary diff or preferably a git pull request to: David Woodhouse + Ben Hutchings Your commit should include an update to the WHENCE file clearly identifying the licence under which the firmware is available, and -- cgit From 9f28a2fc0bd77511f649c0a788c7bf9a5fd04edb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 21 Dec 2011 15:47:16 -0500 Subject: ipv4: reintroduce route cache garbage collector Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) removed IP route cache garbage collector a bit too soon, as this gc was responsible for expired routes cleanup, releasing their neighbour reference. As pointed out by Robert Gladewitz, recent kernels can fill and exhaust their neighbour cache. Reintroduce the garbage collection, since we'll have to wait our neighbour lookups become refcount-less to not depend on this stuff. Reported-by: Robert Gladewitz Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 46af62363b8c..252c512e8a81 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -120,6 +120,7 @@ static int ip_rt_max_size; static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; +static int ip_rt_gc_interval __read_mostly = 60 * HZ; static int ip_rt_gc_min_interval __read_mostly = HZ / 2; static int ip_rt_redirect_number __read_mostly = 9; static int ip_rt_redirect_load __read_mostly = HZ / 50; @@ -133,6 +134,9 @@ static int ip_rt_min_advmss __read_mostly = 256; static int rt_chain_length_max __read_mostly = 20; static int redirect_genid; +static struct delayed_work expires_work; +static unsigned long expires_ljiffies; + /* * Interface to generic destination cache. */ @@ -830,6 +834,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) return ONE; } +static void rt_check_expire(void) +{ + static unsigned int rover; + unsigned int i = rover, goal; + struct rtable *rth; + struct rtable __rcu **rthp; + unsigned long samples = 0; + unsigned long sum = 0, sum2 = 0; + unsigned long delta; + u64 mult; + + delta = jiffies - expires_ljiffies; + expires_ljiffies = jiffies; + mult = ((u64)delta) << rt_hash_log; + if (ip_rt_gc_timeout > 1) + do_div(mult, ip_rt_gc_timeout); + goal = (unsigned int)mult; + if (goal > rt_hash_mask) + goal = rt_hash_mask + 1; + for (; goal > 0; goal--) { + unsigned long tmo = ip_rt_gc_timeout; + unsigned long length; + + i = (i + 1) & rt_hash_mask; + rthp = &rt_hash_table[i].chain; + + if (need_resched()) + cond_resched(); + + samples++; + + if (rcu_dereference_raw(*rthp) == NULL) + continue; + length = 0; + spin_lock_bh(rt_hash_lock_addr(i)); + while ((rth = rcu_dereference_protected(*rthp, + lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { + prefetch(rth->dst.rt_next); + if (rt_is_expired(rth)) { + *rthp = rth->dst.rt_next; + rt_free(rth); + continue; + } + if (rth->dst.expires) { + /* Entry is expired even if it is in use */ + if (time_before_eq(jiffies, rth->dst.expires)) { +nofree: + tmo >>= 1; + rthp = &rth->dst.rt_next; + /* + * We only count entries on + * a chain with equal hash inputs once + * so that entries for different QOS + * levels, and other non-hash input + * attributes don't unfairly skew + * the length computation + */ + length += has_noalias(rt_hash_table[i].chain, rth); + continue; + } + } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) + goto nofree; + + /* Cleanup aged off entries. */ + *rthp = rth->dst.rt_next; + rt_free(rth); + } + spin_unlock_bh(rt_hash_lock_addr(i)); + sum += length; + sum2 += length*length; + } + if (samples) { + unsigned long avg = sum / samples; + unsigned long sd = int_sqrt(sum2 / samples - avg*avg); + rt_chain_length_max = max_t(unsigned long, + ip_rt_gc_elasticity, + (avg + 4*sd) >> FRACT_BITS); + } + rover = i; +} + +/* + * rt_worker_func() is run in process context. + * we call rt_check_expire() to scan part of the hash table + */ +static void rt_worker_func(struct work_struct *work) +{ + rt_check_expire(); + schedule_delayed_work(&expires_work, ip_rt_gc_interval); +} + /* * Perturbation of rt_genid by a small quantity [1..256] * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() @@ -3178,6 +3273,13 @@ static ctl_table ipv4_route_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, + { + .procname = "gc_interval", + .data = &ip_rt_gc_interval, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, { .procname = "redirect_load", .data = &ip_rt_redirect_load, @@ -3388,6 +3490,11 @@ int __init ip_rt_init(void) devinet_init(); ip_fib_init(); + INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); + expires_ljiffies = jiffies; + schedule_delayed_work(&expires_work, + net_random() % ip_rt_gc_interval + ip_rt_gc_interval); + if (ip_rt_proc_init()) printk(KERN_ERR "Unable to create route proc files\n"); #ifdef CONFIG_XFRM -- cgit From c0ed1c14a72ca9ebacd51fb94a8aca488b0d361e Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 21 Dec 2011 16:48:08 -0500 Subject: net: Add a flow_cache_flush_deferred function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flow_cach_flush() might sleep but can be called from atomic context via the xfrm garbage collector. So add a flow_cache_flush_deferred() function and use this if the xfrm garbage colector is invoked from within the packet path. Signed-off-by: Steffen Klassert Acked-by: Timo Teräs Signed-off-by: David S. Miller --- include/net/flow.h | 1 + net/core/flow.c | 12 ++++++++++++ net/xfrm/xfrm_policy.c | 18 ++++++++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/net/flow.h b/include/net/flow.h index a09447749e2d..57f15a7f1cdd 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -207,6 +207,7 @@ extern struct flow_cache_object *flow_cache_lookup( u8 dir, flow_resolve_t resolver, void *ctx); extern void flow_cache_flush(void); +extern void flow_cache_flush_deferred(void); extern atomic_t flow_cache_genid; #endif diff --git a/net/core/flow.c b/net/core/flow.c index 8ae42de9c79e..e318c7e98042 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -358,6 +358,18 @@ void flow_cache_flush(void) put_online_cpus(); } +static void flow_cache_flush_task(struct work_struct *work) +{ + flow_cache_flush(); +} + +static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task); + +void flow_cache_flush_deferred(void) +{ + schedule_work(&flow_cache_flush_work); +} + static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) { struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2118d6446630..9049a5caeb25 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2276,8 +2276,6 @@ static void __xfrm_garbage_collect(struct net *net) { struct dst_entry *head, *next; - flow_cache_flush(); - spin_lock_bh(&xfrm_policy_sk_bundle_lock); head = xfrm_policy_sk_bundles; xfrm_policy_sk_bundles = NULL; @@ -2290,6 +2288,18 @@ static void __xfrm_garbage_collect(struct net *net) } } +static void xfrm_garbage_collect(struct net *net) +{ + flow_cache_flush(); + __xfrm_garbage_collect(net); +} + +static void xfrm_garbage_collect_deferred(struct net *net) +{ + flow_cache_flush_deferred(); + __xfrm_garbage_collect(net); +} + static void xfrm_init_pmtu(struct dst_entry *dst) { do { @@ -2422,7 +2432,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) if (likely(dst_ops->neigh_lookup == NULL)) dst_ops->neigh_lookup = xfrm_neigh_lookup; if (likely(afinfo->garbage_collect == NULL)) - afinfo->garbage_collect = __xfrm_garbage_collect; + afinfo->garbage_collect = xfrm_garbage_collect_deferred; xfrm_policy_afinfo[afinfo->family] = afinfo; } write_unlock_bh(&xfrm_policy_afinfo_lock); @@ -2516,7 +2526,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void switch (event) { case NETDEV_DOWN: - __xfrm_garbage_collect(dev_net(dev)); + xfrm_garbage_collect(dev_net(dev)); } return NOTIFY_DONE; } -- cgit From abf058e10c2614c36ba217405768e8e74853fc80 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 21 Dec 2011 17:31:54 -0500 Subject: USB: Fix usb/isp1760 build on sparc This commit: commit 8f5d621543cb064d2989fc223d3c2bc61a43981e Author: Joachim Foerster Date: Mon Oct 10 18:06:54 2011 +0200 usb/isp1760: Let OF bindings depend on general CONFIG_OF instead of PPC_OF . To be able to use the driver on other OF-aware architectures, too. And add necessary OF related #includes to fix compilation error. Signed-off-by: Joachim Foerster Signed-off-by: Greg Kroah-Hartman enabled the build on all CONFIG_OF architectures, but it cannot do this. This driver depends upon CONFIG_OF_IRQ but not all CONFIG_OF platforms support that infrastructure, in particular Sparc does not so the build fails. Please push a patch like the following to Linus so that this code only gets built where it actually should. -------------------- usb/isp1760: Add missing CONFIG_OF_IRQ dependency on OF code. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-if.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index a7dc1e1d45f2..2ac4ac2e4ef9 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -18,7 +18,7 @@ #include "isp1760-hcd.h" -#ifdef CONFIG_OF +#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) #include #include #include @@ -31,7 +31,7 @@ #include #endif -#ifdef CONFIG_OF +#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) struct isp1760 { struct usb_hcd *hcd; int rst_gpio; @@ -437,7 +437,7 @@ static int __init isp1760_init(void) ret = platform_driver_register(&isp1760_plat_driver); if (!ret) any_ret = 0; -#ifdef CONFIG_OF +#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) ret = platform_driver_register(&isp1760_of_driver); if (!ret) any_ret = 0; @@ -457,7 +457,7 @@ module_init(isp1760_init); static void __exit isp1760_exit(void) { platform_driver_unregister(&isp1760_plat_driver); -#ifdef CONFIG_OF +#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ) platform_driver_unregister(&isp1760_of_driver); #endif #ifdef CONFIG_PCI -- cgit From e6f67b8c05f5e129e126f4409ddac6f25f58ffcb Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 21 Dec 2011 11:05:48 -0600 Subject: vfs: __read_cache_page should use gfp argument rather than GFP_KERNEL lockdep reports a deadlock in jfs because a special inode's rw semaphore is taken recursively. The mapping's gfp mask is GFP_NOFS, but is not used when __read_cache_page() calls add_to_page_cache_lru(). Signed-off-by: Dave Kleikamp Acked-by: Hugh Dickins Acked-by: Al Viro Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- mm/filemap.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index c106d3b3cc64..5f0a3c91fdac 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1828,7 +1828,7 @@ repeat: page = __page_cache_alloc(gfp | __GFP_COLD); if (!page) return ERR_PTR(-ENOMEM); - err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL); + err = add_to_page_cache_lru(page, mapping, index, gfp); if (unlikely(err)) { page_cache_release(page); if (err == -EEXIST) @@ -1925,10 +1925,7 @@ static struct page *wait_on_page_read(struct page *page) * @gfp: the page allocator flags to use if allocating * * This is the same as "read_mapping_page(mapping, index, NULL)", but with - * any new page allocations done using the specified allocation flags. Note - * that the Radix tree operations will still use GFP_KERNEL, so you can't - * expect to do this atomically or anything like that - but you can pass in - * other page requirements. + * any new page allocations done using the specified allocation flags. * * If the page does not get brought uptodate, return -EIO. */ -- cgit From e30e2fdfe56288576ee9e04dbb06b4bd5f282203 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Thu, 22 Dec 2011 02:45:29 +0530 Subject: VFS: Fix race between CPU hotplug and lglocks Currently, the *_global_[un]lock_online() routines are not at all synchronized with CPU hotplug. Soft-lockups detected as a consequence of this race was reported earlier at https://lkml.org/lkml/2011/8/24/185. (Thanks to Cong Meng for finding out that the root-cause of this issue is the race condition between br_write_[un]lock() and CPU hotplug, which results in the lock states getting messed up). Fixing this race by just adding {get,put}_online_cpus() at appropriate places in *_global_[un]lock_online() is not a good option, because, then suddenly br_write_[un]lock() would become blocking, whereas they have been kept as non-blocking all this time, and we would want to keep them that way. So, overall, we want to ensure 3 things: 1. br_write_lock() and br_write_unlock() must remain as non-blocking. 2. The corresponding lock and unlock of the per-cpu spinlocks must not happen for different sets of CPUs. 3. Either prevent any new CPU online operation in between this lock-unlock, or ensure that the newly onlined CPU does not proceed with its corresponding per-cpu spinlock unlocked. To achieve all this: (a) We introduce a new spinlock that is taken by the *_global_lock_online() routine and released by the *_global_unlock_online() routine. (b) We register a callback for CPU hotplug notifications, and this callback takes the same spinlock as above. (c) We maintain a bitmap which is close to the cpu_online_mask, and once it is initialized in the lock_init() code, all future updates to it are done in the callback, under the above spinlock. (d) The above bitmap is used (instead of cpu_online_mask) while locking and unlocking the per-cpu locks. The callback takes the spinlock upon the CPU_UP_PREPARE event. So, if the br_write_lock-unlock sequence is in progress, the callback keeps spinning, thus preventing the CPU online operation till the lock-unlock sequence is complete. This takes care of requirement (3). The bitmap that we maintain remains unmodified throughout the lock-unlock sequence, since all updates to it are managed by the callback, which takes the same spinlock as the one taken by the lock code and released only by the unlock routine. Combining this with (d) above, satisfies requirement (2). Overall, since we use a spinlock (mentioned in (a)) to prevent CPU hotplug operations from racing with br_write_lock-unlock, requirement (1) is also taken care of. By the way, it is to be noted that a CPU offline operation can actually run in parallel with our lock-unlock sequence, because our callback doesn't react to notifications earlier than CPU_DEAD (in order to maintain our bitmap properly). And this means, since we use our own bitmap (which is stale, on purpose) during the lock-unlock sequence, we could end up unlocking the per-cpu lock of an offline CPU (because we had locked it earlier, when the CPU was online), in order to satisfy requirement (2). But this is harmless, though it looks a bit awkward. Debugged-by: Cong Meng Signed-off-by: Srivatsa S. Bhat Signed-off-by: Al Viro Cc: stable@vger.kernel.org --- include/linux/lglock.h | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/include/linux/lglock.h b/include/linux/lglock.h index f549056fb20b..87f402ccec55 100644 --- a/include/linux/lglock.h +++ b/include/linux/lglock.h @@ -22,6 +22,7 @@ #include #include #include +#include /* can make br locks by using local lock for read side, global lock for write */ #define br_lock_init(name) name##_lock_init() @@ -72,9 +73,31 @@ #define DEFINE_LGLOCK(name) \ \ + DEFINE_SPINLOCK(name##_cpu_lock); \ + cpumask_t name##_cpus __read_mostly; \ DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \ DEFINE_LGLOCK_LOCKDEP(name); \ \ + static int \ + name##_lg_cpu_callback(struct notifier_block *nb, \ + unsigned long action, void *hcpu) \ + { \ + switch (action & ~CPU_TASKS_FROZEN) { \ + case CPU_UP_PREPARE: \ + spin_lock(&name##_cpu_lock); \ + cpu_set((unsigned long)hcpu, name##_cpus); \ + spin_unlock(&name##_cpu_lock); \ + break; \ + case CPU_UP_CANCELED: case CPU_DEAD: \ + spin_lock(&name##_cpu_lock); \ + cpu_clear((unsigned long)hcpu, name##_cpus); \ + spin_unlock(&name##_cpu_lock); \ + } \ + return NOTIFY_OK; \ + } \ + static struct notifier_block name##_lg_cpu_notifier = { \ + .notifier_call = name##_lg_cpu_callback, \ + }; \ void name##_lock_init(void) { \ int i; \ LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \ @@ -83,6 +106,11 @@ lock = &per_cpu(name##_lock, i); \ *lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \ } \ + register_hotcpu_notifier(&name##_lg_cpu_notifier); \ + get_online_cpus(); \ + for_each_online_cpu(i) \ + cpu_set(i, name##_cpus); \ + put_online_cpus(); \ } \ EXPORT_SYMBOL(name##_lock_init); \ \ @@ -124,9 +152,9 @@ \ void name##_global_lock_online(void) { \ int i; \ - preempt_disable(); \ + spin_lock(&name##_cpu_lock); \ rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ - for_each_online_cpu(i) { \ + for_each_cpu(i, &name##_cpus) { \ arch_spinlock_t *lock; \ lock = &per_cpu(name##_lock, i); \ arch_spin_lock(lock); \ @@ -137,12 +165,12 @@ void name##_global_unlock_online(void) { \ int i; \ rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ - for_each_online_cpu(i) { \ + for_each_cpu(i, &name##_cpus) { \ arch_spinlock_t *lock; \ lock = &per_cpu(name##_lock, i); \ arch_spin_unlock(lock); \ } \ - preempt_enable(); \ + spin_unlock(&name##_cpu_lock); \ } \ EXPORT_SYMBOL(name##_global_unlock_online); \ \ -- cgit From b9eda06f80b0db61a73bd87c6b0eb67d8aca55ad Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 22 Dec 2011 17:03:29 +1100 Subject: ipv4: using prefetch requires including prefetch.h Signed-off-by: Stephen Rothwell Acked-by: Eric Dumazet Acked-by: David Miller Signed-off-by: Linus Torvalds --- net/ipv4/route.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 252c512e8a81..85cc053d9d6e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include -- cgit From 19d40dcabf1cdf84e1a76c147b7177b5a6c21943 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 21 Dec 2011 17:38:10 -0500 Subject: pata_of_platform: Add missing CONFIG_OF_IRQ dependency. Signed-off-by: David S. Miller Signed-off-by: Jeff Garzik --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6bdedd7cca2c..cf047c406d92 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -820,7 +820,7 @@ config PATA_PLATFORM config PATA_OF_PLATFORM tristate "OpenFirmware platform device PATA support" - depends on PATA_PLATFORM && OF + depends on PATA_PLATFORM && OF && OF_IRQ help This option enables support for generic directly connected ATA devices commonly found on embedded systems with OpenFirmware -- cgit From 7cc8583372a21d98a23b703ad96cab03180b5030 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Dec 2011 13:23:59 -0800 Subject: sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq(). This silently was working for many years and stopped working on Niagara-T3 machines. We need to set the MSIQ to VALID before we can set it's state to IDLE. On Niagara-T3, setting the state to IDLE first was causing HV_EINVAL errors. The hypervisor documentation says, rather ambiguously, that the MSIQ must be "initialized" before one can set the state. I previously understood this to mean merely that a successful setconf() operation has been performed on the MSIQ, which we have done at this point. But it seems to also mean that it has been set VALID too. Signed-off-by: David S. Miller --- arch/sparc/kernel/pci_sun4v.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index b272cda35a01..af5755d20fbe 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -849,10 +849,10 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm, if (!irq) return -ENOMEM; - if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) - return -EINVAL; if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) return -EINVAL; + if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) + return -EINVAL; return irq; } -- cgit From 09cd9270ea52e0f9851528e8ed028073f96b3c34 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 23 Dec 2011 09:56:55 +1100 Subject: md/linear: fix hot-add of devices to linear arrays. commit d70ed2e4fafdbef0800e73942482bb075c21578b broke hot-add to a linear array. After that commit, metadata if not written to devices until they have been fully integrated into the array as determined by saved_raid_disk. That patch arranged to clear that field after a recovery completed. However for linear arrays, there is no recovery - the integration is instantaneous. So we need to explicitly clear the saved_raid_disk field. Signed-off-by: NeilBrown --- drivers/md/linear.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/linear.c b/drivers/md/linear.c index c3273efd08cb..627456542fb3 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -230,6 +230,7 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev) return -EINVAL; rdev->raid_disk = rdev->saved_raid_disk; + rdev->saved_raid_disk = -1; newconf = linear_conf(mddev,mddev->raid_disks+1); -- cgit From 30d7a4836847bdb10b32c78a4879d4aebe0f193b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 23 Dec 2011 09:57:00 +1100 Subject: md/raid5: ensure correct assessment of drives during degraded reshape. While reshaping a degraded array (as when reshaping a RAID0 by first converting it to a degraded RAID4) we currently get confused about which devices are in_sync. In most cases we get it right, but in the region that is being reshaped we need to treat non-failed devices as in-sync when we have the data but haven't actually written it out yet. Reported-by: Adam Kwolek Signed-off-by: NeilBrown --- drivers/md/raid5.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 31670f8d6b65..858fdbb7eb07 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3065,11 +3065,17 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) } } else if (test_bit(In_sync, &rdev->flags)) set_bit(R5_Insync, &dev->flags); - else { + else if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) /* in sync if before recovery_offset */ - if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) - set_bit(R5_Insync, &dev->flags); - } + set_bit(R5_Insync, &dev->flags); + else if (test_bit(R5_UPTODATE, &dev->flags) && + test_bit(R5_Expanded, &dev->flags)) + /* If we've reshaped into here, we assume it is Insync. + * We will shortly update recovery_offset to make + * it official. + */ + set_bit(R5_Insync, &dev->flags); + if (rdev && test_bit(R5_WriteError, &dev->flags)) { clear_bit(R5_Insync, &dev->flags); if (!test_bit(Faulty, &rdev->flags)) { -- cgit From 60fc13702a1b35118c1548e9c257fa038cecb658 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 23 Dec 2011 09:57:19 +1100 Subject: md: don't give up looking for spares on first failure-to-add Before performing a recovery we try to remove any spares that might not be working, then add any that might have become relevant. Currently we abort on the first spare that cannot be added. This is a false optimisation. It is conceivable that - depending on rules in the personality - a subsequent spare might be accepted. Also the loop does other things like count the available spares and reset the 'recovery_offset' value. If we abort early these might not happen properly. So remove the early abort. In particular if you have an array what is undergoing recovery and which has extra spares, then the recovery may not restart after as reboot as the could of 'spares' might end up as zero. Reported-by: Anssi Hannula Signed-off-by: NeilBrown --- drivers/md/md.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index ee981737edfc..f47f1f8ac44b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7360,8 +7360,7 @@ static int remove_and_add_spares(struct mddev *mddev) spares++; md_new_event(mddev); set_bit(MD_CHANGE_DEVS, &mddev->flags); - } else - break; + } } } } -- cgit From 961902c0f8240175729274cd14198872f42072b7 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 23 Dec 2011 09:57:48 +1100 Subject: md/bitmap: It is OK to clear bits during recovery. commit d0a4bb492772ce5c4bdfba3744a99ed6f6fb238f introduced a regression which is annoying but fairly harmless. When writing to an array that is undergoing recovery (a spare in being integrated into the array), writing to the array will set bits in the bitmap, but they will not be cleared when the write completes. For bits covering areas that have not been recovered yet this is not a problem as the recovery will clear the bits. However bits set in already-recovered region will stay set and never be cleared. This doesn't risk data integrity. The only negatives are: - next time there is a crash, more resyncing than necessary will be done. - the bitmap doesn't look clean, which is confusing. While an array is recovering we don't want to update the 'events_cleared' setting in the bitmap but we do still want to clear bits that have very recently been set - providing they were written to the recovering device. So split those two needs - which previously both depended on 'success' and always clear the bit of the write went to all devices. Signed-off-by: NeilBrown --- drivers/md/bitmap.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index b6907118283a..6d03774b176e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1393,9 +1393,6 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto atomic_read(&bitmap->behind_writes), bitmap->mddev->bitmap_info.max_write_behind); } - if (bitmap->mddev->degraded) - /* Never clear bits or update events_cleared when degraded */ - success = 0; while (sectors) { sector_t blocks; @@ -1409,7 +1406,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto return; } - if (success && + if (success && !bitmap->mddev->degraded && bitmap->events_cleared < bitmap->mddev->events) { bitmap->events_cleared = bitmap->mddev->events; bitmap->need_sync = 1; -- cgit From a13861a28b90541aa207532d237e7a940f1b1c7b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 21 Dec 2011 20:00:32 +0000 Subject: bridge: provide a mtu() method for fake_dst_ops Commit 618f9bc74a039da76 (net: Move mtu handling down to the protocol depended handlers) forgot the bridge netfilter case, adding a NULL dereference in ip_fragment(). Reported-by: Chris Boot CC: Steffen Klassert Signed-off-by: Eric Dumazet Acked-by: Steffen Klassert Signed-off-by: David S. Miller --- net/bridge/br_netfilter.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index d6ec3720c77e..08757dc670a4 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -114,12 +114,18 @@ static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const vo return NULL; } +static unsigned int fake_mtu(const struct dst_entry *dst) +{ + return dst->dev->mtu; +} + static struct dst_ops fake_dst_ops = { .family = AF_INET, .protocol = cpu_to_be16(ETH_P_IP), .update_pmtu = fake_update_pmtu, .cow_metrics = fake_cow_metrics, .neigh_lookup = fake_neigh_lookup, + .mtu = fake_mtu, }; /* -- cgit From 7838f2ce36b6ab5c13ef20b1857e3bbd567f1759 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 22 Dec 2011 02:05:07 +0000 Subject: mqprio: Avoid panic if no options are provided Userspace may not provide TCA_OPTIONS, in fact tc currently does so not do so if no arguments are specified on the command line. Return EINVAL instead of panicing. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sched/sch_mqprio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index f88256cbacbf..28de43092330 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -107,7 +107,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) if (!netif_is_multiqueue(dev)) return -EOPNOTSUPP; - if (nla_len(opt) < sizeof(*qopt)) + if (!opt || nla_len(opt) < sizeof(*qopt)) return -EINVAL; qopt = nla_data(opt); -- cgit From e688a604807647c9450f9c12a7cb6d027150a895 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 22 Dec 2011 04:15:53 +0000 Subject: net: introduce DST_NOPEER dst flag Chris Boot reported crashes occurring in ipv6_select_ident(). [ 461.457562] RIP: 0010:[] [] ipv6_select_ident+0x31/0xa7 [ 461.578229] Call Trace: [ 461.580742] [ 461.582870] [] ? udp6_ufo_fragment+0x124/0x1a2 [ 461.589054] [] ? ipv6_gso_segment+0xc0/0x155 [ 461.595140] [] ? skb_gso_segment+0x208/0x28b [ 461.601198] [] ? ipv6_confirm+0x146/0x15e [nf_conntrack_ipv6] [ 461.608786] [] ? nf_iterate+0x41/0x77 [ 461.614227] [] ? dev_hard_start_xmit+0x357/0x543 [ 461.620659] [] ? nf_hook_slow+0x73/0x111 [ 461.626440] [] ? br_parse_ip_options+0x19a/0x19a [bridge] [ 461.633581] [] ? dev_queue_xmit+0x3af/0x459 [ 461.639577] [] ? br_dev_queue_push_xmit+0x72/0x76 [bridge] [ 461.646887] [] ? br_nf_post_routing+0x17d/0x18f [bridge] [ 461.653997] [] ? nf_iterate+0x41/0x77 [ 461.659473] [] ? br_flood+0xfa/0xfa [bridge] [ 461.665485] [] ? nf_hook_slow+0x73/0x111 [ 461.671234] [] ? br_flood+0xfa/0xfa [bridge] [ 461.677299] [] ? nf_bridge_update_protocol+0x20/0x20 [bridge] [ 461.684891] [] ? nf_ct_zone+0xa/0x17 [nf_conntrack] [ 461.691520] [] ? br_flood+0xfa/0xfa [bridge] [ 461.697572] [] ? NF_HOOK.constprop.8+0x3c/0x56 [bridge] [ 461.704616] [] ? nf_bridge_push_encap_header+0x1c/0x26 [bridge] [ 461.712329] [] ? br_nf_forward_finish+0x8a/0x95 [bridge] [ 461.719490] [] ? nf_bridge_pull_encap_header+0x1c/0x27 [bridge] [ 461.727223] [] ? br_nf_forward_ip+0x1c0/0x1d4 [bridge] [ 461.734292] [] ? nf_iterate+0x41/0x77 [ 461.739758] [] ? __br_deliver+0xa0/0xa0 [bridge] [ 461.746203] [] ? nf_hook_slow+0x73/0x111 [ 461.751950] [] ? __br_deliver+0xa0/0xa0 [bridge] [ 461.758378] [] ? NF_HOOK.constprop.4+0x56/0x56 [bridge] This is caused by bridge netfilter special dst_entry (fake_rtable), a special shared entry, where attaching an inetpeer makes no sense. Problem is present since commit 87c48fa3b46 (ipv6: make fragment identifications less predictable) Introduce DST_NOPEER dst flag and make sure ipv6_select_ident() and __ip_select_ident() fallback to the 'no peer attached' handling. Reported-by: Chris Boot Tested-by: Chris Boot Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/dst.h | 1 + net/bridge/br_netfilter.c | 2 +- net/ipv4/route.c | 4 ++-- net/ipv6/ip6_output.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index 6faec1a60216..75766b42660e 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -53,6 +53,7 @@ struct dst_entry { #define DST_NOHASH 0x0008 #define DST_NOCACHE 0x0010 #define DST_NOCOUNT 0x0020 +#define DST_NOPEER 0x0040 short error; short obsolete; diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 08757dc670a4..fa8b8f763580 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -147,7 +147,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) rt->dst.dev = br->dev; rt->dst.path = &rt->dst; dst_init_metrics(&rt->dst, br_dst_default_metrics, true); - rt->dst.flags = DST_NOXFRM; + rt->dst.flags = DST_NOXFRM | DST_NOPEER; rt->dst.ops = &fake_dst_ops; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 85cc053d9d6e..94cdbc55ca7e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1367,7 +1367,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) { struct rtable *rt = (struct rtable *) dst; - if (rt) { + if (rt && !(rt->dst.flags & DST_NOPEER)) { if (rt->peer == NULL) rt_bind_peer(rt, rt->rt_dst, 1); @@ -1378,7 +1378,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) iph->id = htons(inet_getid(rt->peer, more)); return; } - } else + } else if (!rt) printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", __builtin_return_address(0)); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 84d0bd5cac93..ec562713db9b 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -603,7 +603,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) static atomic_t ipv6_fragmentation_id; int old, new; - if (rt) { + if (rt && !(rt->dst.flags & DST_NOPEER)) { struct inet_peer *peer; if (!rt->rt6i_peer) -- cgit From a0a129f8b6cff54ab479324a54aefdab5db4f240 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 22 Dec 2011 13:35:22 +0000 Subject: rps: fix insufficient bounds checking in store_rps_dev_flow_table_cnt() Setting a large rps_flow_cnt like (1 << 30) on 32-bit platform will cause a kernel oops due to insufficient bounds checking. if (count > 1<<30) { /* Enforce a limit to prevent overflow */ return -EINVAL; } count = roundup_pow_of_two(count); table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(count)); Note that the macro RPS_DEV_FLOW_TABLE_SIZE(count) is defined as: ... + (count * sizeof(struct rps_dev_flow)) where sizeof(struct rps_dev_flow) is 8. (1 << 30) * 8 will overflow 32 bits. This patch replaces the magic number (1 << 30) with a symbolic bound. Suggested-by: Eric Dumazet Signed-off-by: Xi Wang Signed-off-by: David S. Miller --- net/core/net-sysfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c71c434a4c05..385aefe53648 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -665,11 +665,14 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue, if (count) { int i; - if (count > 1<<30) { + if (count > INT_MAX) + return -EINVAL; + count = roundup_pow_of_two(count); + if (count > (ULONG_MAX - sizeof(struct rps_dev_flow_table)) + / sizeof(struct rps_dev_flow)) { /* Enforce a limit to prevent overflow */ return -EINVAL; } - count = roundup_pow_of_two(count); table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(count)); if (!table) return -ENOMEM; -- cgit From 0fd7bac6b6157eed6cf0cb86a1e88ba29e57c033 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 21 Dec 2011 07:11:44 +0000 Subject: net: relax rcvbuf limits skb->truesize might be big even for a small packet. Its even bigger after commit 87fb4b7b533 (net: more accurate skb truesize) and big MTU. We should allow queueing at least one packet per receiver, even with a low RCVBUF setting. Reported-by: Michal Simek Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 4 +++- net/core/sock.c | 6 +----- net/packet/af_packet.c | 6 ++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index abb6e0f0c3c3..32e39371fba6 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -637,12 +637,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) /* * Take into account size of receive queue and backlog queue + * Do not take into account this skb truesize, + * to allow even a single big packet to come. */ static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) { unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); - return qsize + skb->truesize > sk->sk_rcvbuf; + return qsize > sk->sk_rcvbuf; } /* The per-socket spinlock must be held here. */ diff --git a/net/core/sock.c b/net/core/sock.c index 4ed7b1d12f5e..b23f174ab84c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -288,11 +288,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) unsigned long flags; struct sk_buff_head *list = &sk->sk_receive_queue; - /* Cast sk->rcvbuf to unsigned... It's pointless, but reduces - number of warnings when compiling with -W --ANK - */ - if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf) { + if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) { atomic_inc(&sk->sk_drops); trace_sock_rcvqueue_full(sk, skb); return -ENOMEM; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 82a6f34d39d0..3891702b81df 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1630,8 +1630,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, if (snaplen > res) snaplen = res; - if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf) + if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) goto drop_n_acct; if (skb_shared(skb)) { @@ -1762,8 +1761,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (po->tp_version <= TPACKET_V2) { if (macoff + snaplen > po->rx_ring.frame_size) { if (po->copy_thresh && - atomic_read(&sk->sk_rmem_alloc) + skb->truesize - < (unsigned)sk->sk_rcvbuf) { + atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) { if (skb_shared(skb)) { copy_skb = skb_clone(skb, GFP_ATOMIC); } else { -- cgit From 8d532b2afb2eacc84588db709ec280a3d1219be3 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 23 Dec 2011 07:53:00 -0500 Subject: Btrfs: fix worker lock misuse in find_worker Dan Carpenter noticed that we were doing a double unlock on the worker lock, and sometimes picking a worker thread without the lock held. This fixes both errors. Signed-off-by: Chris Mason Reported-by: Dan Carpenter --- fs/btrfs/async-thread.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index cb97174e2366..0b394580d860 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -563,8 +563,8 @@ static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers) struct list_head *fallback; int ret; -again: spin_lock_irqsave(&workers->lock, flags); +again: worker = next_worker(workers); if (!worker) { @@ -579,6 +579,7 @@ again: spin_unlock_irqrestore(&workers->lock, flags); /* we're below the limit, start another worker */ ret = __btrfs_start_workers(workers); + spin_lock_irqsave(&workers->lock, flags); if (ret) goto fallback; goto again; -- cgit From 08c422c27f855d27b0b3d9fa30ebd938d4ae6f1f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 23 Dec 2011 07:58:13 -0500 Subject: Btrfs: call d_instantiate after all ops are setup This closes races where btrfs is calling d_instantiate too soon during inode creation. All of the callers of btrfs_add_nondir are updated to instantiate after the inode is fully setup in memory. Signed-off-by: Al Viro Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 740e67bbe249..13b0542015ff 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4590,10 +4590,6 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, int err = btrfs_add_link(trans, dir, inode, dentry->d_name.name, dentry->d_name.len, backref, index); - if (!err) { - d_instantiate(dentry, inode); - return 0; - } if (err > 0) err = -EEXIST; return err; @@ -4655,6 +4651,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, else { init_special_inode(inode, inode->i_mode, rdev); btrfs_update_inode(trans, root, inode); + d_instantiate(dentry, inode); } out_unlock: nr = trans->blocks_used; @@ -4722,6 +4719,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; + d_instantiate(dentry, inode); } out_unlock: nr = trans->blocks_used; @@ -4779,6 +4777,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *parent = dentry->d_parent; err = btrfs_update_inode(trans, root, inode); BUG_ON(err); + d_instantiate(dentry, inode); btrfs_log_new_name(trans, inode, NULL, parent); } @@ -7245,6 +7244,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, drop_inode = 1; out_unlock: + if (!err) + d_instantiate(dentry, inode); nr = trans->blocks_used; btrfs_end_transaction_throttle(trans, root); if (drop_inode) { -- cgit From 0354b48f633ae435acbc01b470a1ce8cfeff3e9f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 16 Dec 2011 18:35:15 +0100 Subject: netfilter: xt_connbytes: handle negation correctly "! --connbytes 23:42" should match if the packet/byte count is not in range. As there is no explict "invert match" toggle in the match structure, userspace swaps the from and to arguments (i.e., as if "--connbytes 42:23" were given). However, "what <= 23 && what >= 42" will always be false. Change things so we use "||" in case "from" is larger than "to". This change may look like it breaks backwards compatibility when "to" is 0. However, older iptables binaries will refuse "connbytes 42:0", and current releases treat it to mean "! --connbytes 0:42", so we should be fine. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_connbytes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index 5b138506690e..9ddf1c3bfb39 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c @@ -87,10 +87,10 @@ connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par) break; } - if (sinfo->count.to) + if (sinfo->count.to >= sinfo->count.from) return what <= sinfo->count.to && what >= sinfo->count.from; - else - return what >= sinfo->count.from; + else /* inverted */ + return what < sinfo->count.to || what > sinfo->count.from; } static int connbytes_mt_check(const struct xt_mtchk_param *par) -- cgit From 5f0a6e2d503896062f641639dacfe5055c2f593b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Dec 2011 21:51:06 -0800 Subject: Linux 3.2-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a43733df3978..ea51081812f3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Saber-toothed Squirrel # *DOCUMENTATION* -- cgit From 03534a415fa9a7390051fa0ce466611ca250ac4d Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 22 Dec 2011 20:40:41 +0100 Subject: Remove Telechips ARM subarch from MAINTAINERS The ARM subarchitecture for Telechips SoCs isi being completely removed, so there's no need for a MAINTAINERS entry. Cc: Thomas Gleixner Cc: Harry Sievers Signed-off-by: Hans J. Koch --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6afba60c3904..5a601eab03ae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1124,13 +1124,6 @@ S: Supported F: arch/arm/mach-shmobile/ F: drivers/sh/ -ARM/TELECHIPS ARM ARCHITECTURE -M: "Hans J. Koch" -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -F: arch/arm/plat-tcc/ -F: arch/arm/mach-tcc8k/ - ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT M: Lennert Buytenhek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -- cgit From 273b5e5189791a9b6d0bffb24568378d767e1711 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 22 Dec 2011 20:46:34 +0100 Subject: arm: Remove TCC subarch from Kconfig/Makefile The Telechips subarchitecture is being completely removed. Cc: Thomas Gleixner Cc: Harry Sievers Signed-off-by: Hans J. Koch --- arch/arm/Kconfig | 12 ------------ arch/arm/Makefile | 2 -- 2 files changed, 14 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 776d76b8cb69..849e3ad93707 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -868,16 +868,6 @@ config ARCH_SHARK Support for the StrongARM based Digital DNARD machine, also known as "Shark" (). -config ARCH_TCC_926 - bool "Telechips TCC ARM926-based systems" - select CLKSRC_MMIO - select CPU_ARM926T - select HAVE_CLK - select CLKDEV_LOOKUP - select GENERIC_CLOCKEVENTS - help - Support for Telechips TCC ARM926-based systems. - config ARCH_U300 bool "ST-Ericsson U300 Series" depends on MMU @@ -1060,8 +1050,6 @@ source "arch/arm/plat-s5p/Kconfig" source "arch/arm/plat-spear/Kconfig" -source "arch/arm/plat-tcc/Kconfig" - if ARCH_S3C2410 source "arch/arm/mach-s3c2410/Kconfig" source "arch/arm/mach-s3c2412/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index dfcf3b033e10..40319d91bb7f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -184,7 +184,6 @@ machine-$(CONFIG_ARCH_EXYNOS4) := exynos machine-$(CONFIG_ARCH_SA1100) := sa1100 machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SHMOBILE) := shmobile -machine-$(CONFIG_ARCH_TCC8K) := tcc8k machine-$(CONFIG_ARCH_TEGRA) := tegra machine-$(CONFIG_ARCH_U300) := u300 machine-$(CONFIG_ARCH_U8500) := ux500 @@ -204,7 +203,6 @@ machine-$(CONFIG_ARCH_ZYNQ) := zynq plat-$(CONFIG_ARCH_MXC) := mxc plat-$(CONFIG_ARCH_OMAP) := omap plat-$(CONFIG_ARCH_S3C64XX) := samsung -plat-$(CONFIG_ARCH_TCC_926) := tcc plat-$(CONFIG_ARCH_ZYNQ) := versatile plat-$(CONFIG_PLAT_IOP) := iop plat-$(CONFIG_PLAT_NOMADIK) := nomadik -- cgit From 00d79e9d0e4b49144177bc07baa015febc822c10 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 22 Dec 2011 21:27:27 +0100 Subject: arm: Remove mach-tcc8k directory The Telechips ARM architecture is being removed. This patch deletes the arch/arm/mach-tcc8k/ folder. Cc: Thomas Gleixner Cc: Harry Sievers Signed-off-by: Hans J. Koch --- arch/arm/mach-tcc8k/Kconfig | 11 - arch/arm/mach-tcc8k/Makefile | 9 - arch/arm/mach-tcc8k/Makefile.boot | 3 - arch/arm/mach-tcc8k/board-tcc8000-sdk.c | 81 ----- arch/arm/mach-tcc8k/clock.c | 580 -------------------------------- arch/arm/mach-tcc8k/common.h | 15 - arch/arm/mach-tcc8k/devices.c | 239 ------------- arch/arm/mach-tcc8k/io.c | 62 ---- arch/arm/mach-tcc8k/irq.c | 111 ------ arch/arm/mach-tcc8k/time.c | 134 -------- 10 files changed, 1245 deletions(-) delete mode 100644 arch/arm/mach-tcc8k/Kconfig delete mode 100644 arch/arm/mach-tcc8k/Makefile delete mode 100644 arch/arm/mach-tcc8k/Makefile.boot delete mode 100644 arch/arm/mach-tcc8k/board-tcc8000-sdk.c delete mode 100644 arch/arm/mach-tcc8k/clock.c delete mode 100644 arch/arm/mach-tcc8k/common.h delete mode 100644 arch/arm/mach-tcc8k/devices.c delete mode 100644 arch/arm/mach-tcc8k/io.c delete mode 100644 arch/arm/mach-tcc8k/irq.c delete mode 100644 arch/arm/mach-tcc8k/time.c diff --git a/arch/arm/mach-tcc8k/Kconfig b/arch/arm/mach-tcc8k/Kconfig deleted file mode 100644 index ad86415d1577..000000000000 --- a/arch/arm/mach-tcc8k/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -if ARCH_TCC8K - -comment "TCC8000 systems:" - -config MACH_TCC8000_SDK - bool "Telechips TCC8000-SDK development kit" - default y - help - Support for the Telechips TCC8000-SDK board. - -endif diff --git a/arch/arm/mach-tcc8k/Makefile b/arch/arm/mach-tcc8k/Makefile deleted file mode 100644 index 9bacf31e49ba..000000000000 --- a/arch/arm/mach-tcc8k/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for TCC8K boards and common files. -# - -# Common support -obj-y += clock.o irq.o time.o io.o devices.o - -# Board specific support -obj-$(CONFIG_MACH_TCC8000_SDK) += board-tcc8000-sdk.o diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot deleted file mode 100644 index 5e02d4156b04..000000000000 --- a/arch/arm/mach-tcc8k/Makefile.boot +++ /dev/null @@ -1,3 +0,0 @@ - zreladdr-y += 0x20008000 -params_phys-y := 0x20000100 -initrd_phys-y := 0x20800000 diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c deleted file mode 100644 index 777a5bb9eed2..000000000000 --- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009 Hans J. Koch - * - * 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. - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include - -#include "common.h" - -#define XI_FREQUENCY 12000000 -#define XTI_FREQUENCY 32768 - -#ifdef CONFIG_MTD_NAND_TCC -/* NAND */ -static struct tcc_nand_platform_data tcc8k_sdk_nand_data = { - .width = 1, - .hw_ecc = 0, -}; -#endif - -static void __init tcc8k_init(void) -{ -#ifdef CONFIG_MTD_NAND_TCC - tcc_nand_device.dev.platform_data = &tcc8k_sdk_nand_data; - platform_device_register(&tcc_nand_device); -#endif -} - -static void __init tcc8k_init_timer(void) -{ - tcc_clocks_init(XI_FREQUENCY, XTI_FREQUENCY); -} - -static struct sys_timer tcc8k_timer = { - .init = tcc8k_init_timer, -}; - -static void __init tcc8k_map_io(void) -{ - tcc8k_map_common_io(); - - /* set PLL0 clock to 96MHz, adapt UART0 divisor */ - __raw_writel(0x00026003, CKC_BASE + PLL0CFG_OFFS); - __raw_writel(0x10000001, CKC_BASE + ACLKUART0_OFFS); - - /* set PLL1 clock to 192MHz */ - __raw_writel(0x00016003, CKC_BASE + PLL1CFG_OFFS); - - /* set PLL2 clock to 48MHz */ - __raw_writel(0x00036003, CKC_BASE + PLL2CFG_OFFS); - - /* with CPU freq higher than 150 MHz, need extra DTCM wait */ - __raw_writel(0x00000001, SCFG_BASE + DTCMWAIT_OFFS); - - /* PLL locking time as specified */ - udelay(300); -} - -MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board") - .atag_offset = 0x100, - .map_io = tcc8k_map_io, - .init_irq = tcc8k_init_irq, - .init_machine = tcc8k_init, - .timer = &tcc8k_timer, -MACHINE_END diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c deleted file mode 100644 index e7cdae5c77a4..000000000000 --- a/arch/arm/mach-tcc8k/clock.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Lowlevel clock handling for Telechips TCC8xxx SoCs - * - * Copyright (C) 2010 by Hans J. Koch - * - * Licensed under the terms of the GPL v2 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "common.h" - -#define BCLKCTR0 (CKC_BASE + BCLKCTR0_OFFS) -#define BCLKCTR1 (CKC_BASE + BCLKCTR1_OFFS) - -#define ACLKREF (CKC_BASE + ACLKREF_OFFS) -#define ACLKUART0 (CKC_BASE + ACLKUART0_OFFS) -#define ACLKUART1 (CKC_BASE + ACLKUART1_OFFS) -#define ACLKUART2 (CKC_BASE + ACLKUART2_OFFS) -#define ACLKUART3 (CKC_BASE + ACLKUART3_OFFS) -#define ACLKUART4 (CKC_BASE + ACLKUART4_OFFS) -#define ACLKI2C (CKC_BASE + ACLKI2C_OFFS) -#define ACLKADC (CKC_BASE + ACLKADC_OFFS) -#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS) -#define ACLKLCD (CKC_BASE + ACLKLCD_OFFS) -#define ACLKSDH0 (CKC_BASE + ACLKSDH0_OFFS) -#define ACLKSDH1 (CKC_BASE + ACLKSDH1_OFFS) -#define ACLKSPI0 (CKC_BASE + ACLKSPI0_OFFS) -#define ACLKSPI1 (CKC_BASE + ACLKSPI1_OFFS) -#define ACLKSPDIF (CKC_BASE + ACLKSPDIF_OFFS) -#define ACLKC3DEC (CKC_BASE + ACLKC3DEC_OFFS) -#define ACLKCAN0 (CKC_BASE + ACLKCAN0_OFFS) -#define ACLKCAN1 (CKC_BASE + ACLKCAN1_OFFS) -#define ACLKGSB0 (CKC_BASE + ACLKGSB0_OFFS) -#define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS) -#define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS) -#define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS) -#define ACLKTCT (CKC_BASE + ACLKTCT_OFFS) -#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) -#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) - -#define ACLK_MAX_DIV (0xfff + 1) - -/* Crystal frequencies */ -static unsigned long xi_rate, xti_rate; - -static void __iomem *pll_cfg_addr(int pll) -{ - switch (pll) { - case 0: return (CKC_BASE + PLL0CFG_OFFS); - case 1: return (CKC_BASE + PLL1CFG_OFFS); - case 2: return (CKC_BASE + PLL2CFG_OFFS); - default: - BUG(); - } -} - -static int pll_enable(int pll, int enable) -{ - u32 reg; - void __iomem *addr = pll_cfg_addr(pll); - - reg = __raw_readl(addr); - if (enable) - reg &= ~PLLxCFG_PD; - else - reg |= PLLxCFG_PD; - - __raw_writel(reg, addr); - return 0; -} - -static int xi_enable(int enable) -{ - u32 reg; - - reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); - if (enable) - reg |= CLKCTRL_XE; - else - reg &= ~CLKCTRL_XE; - - __raw_writel(reg, CKC_BASE + CLKCTRL_OFFS); - return 0; -} - -static int root_clk_enable(enum root_clks src) -{ - switch (src) { - case CLK_SRC_PLL0: return pll_enable(0, 1); - case CLK_SRC_PLL1: return pll_enable(1, 1); - case CLK_SRC_PLL2: return pll_enable(2, 1); - case CLK_SRC_XI: return xi_enable(1); - default: - BUG(); - } - return 0; -} - -static int root_clk_disable(enum root_clks src) -{ - switch (src) { - case CLK_SRC_PLL0: return pll_enable(0, 0); - case CLK_SRC_PLL1: return pll_enable(1, 0); - case CLK_SRC_PLL2: return pll_enable(2, 0); - case CLK_SRC_XI: return xi_enable(0); - default: - BUG(); - } - return 0; -} - -static int enable_clk(struct clk *clk) -{ - u32 reg; - - if (clk->root_id != CLK_SRC_NOROOT) - return root_clk_enable(clk->root_id); - - if (clk->aclkreg) { - reg = __raw_readl(clk->aclkreg); - reg |= ACLK_EN; - __raw_writel(reg, clk->aclkreg); - } - if (clk->bclkctr) { - reg = __raw_readl(clk->bclkctr); - reg |= 1 << clk->bclk_shift; - __raw_writel(reg, clk->bclkctr); - } - return 0; -} - -static void disable_clk(struct clk *clk) -{ - u32 reg; - - if (clk->root_id != CLK_SRC_NOROOT) { - root_clk_disable(clk->root_id); - return; - } - - if (clk->bclkctr) { - reg = __raw_readl(clk->bclkctr); - reg &= ~(1 << clk->bclk_shift); - __raw_writel(reg, clk->bclkctr); - } - if (clk->aclkreg) { - reg = __raw_readl(clk->aclkreg); - reg &= ~ACLK_EN; - __raw_writel(reg, clk->aclkreg); - } -} - -static unsigned long get_rate_pll(int pll) -{ - u32 reg; - unsigned long s, m, p; - void __iomem *addr = pll_cfg_addr(pll); - - reg = __raw_readl(addr); - s = (reg >> 16) & 0x07; - m = (reg >> 8) & 0xff; - p = reg & 0x3f; - - return (m * xi_rate) / (p * (1 << s)); -} - -static unsigned long get_rate_pll_div(int pll) -{ - u32 reg; - unsigned long div = 0; - void __iomem *addr; - - switch (pll) { - case 0: - addr = CKC_BASE + CLKDIVC0_OFFS; - reg = __raw_readl(addr); - if (reg & CLKDIVC0_P0E) - div = (reg >> 24) & 0x3f; - break; - case 1: - addr = CKC_BASE + CLKDIVC0_OFFS; - reg = __raw_readl(addr); - if (reg & CLKDIVC0_P1E) - div = (reg >> 16) & 0x3f; - break; - case 2: - addr = CKC_BASE + CLKDIVC1_OFFS; - reg = __raw_readl(addr); - if (reg & CLKDIVC1_P2E) - div = reg & 0x3f; - break; - } - return get_rate_pll(pll) / (div + 1); -} - -static unsigned long get_rate_xi_div(void) -{ - unsigned long div = 0; - u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS); - - if (reg & CLKDIVC0_XE) - div = (reg >> 8) & 0x3f; - - return xi_rate / (div + 1); -} - -static unsigned long get_rate_xti_div(void) -{ - unsigned long div = 0; - u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS); - - if (reg & CLKDIVC0_XTE) - div = reg & 0x3f; - - return xti_rate / (div + 1); -} - -static unsigned long root_clk_get_rate(enum root_clks src) -{ - switch (src) { - case CLK_SRC_PLL0: return get_rate_pll(0); - case CLK_SRC_PLL1: return get_rate_pll(1); - case CLK_SRC_PLL2: return get_rate_pll(2); - case CLK_SRC_PLL0DIV: return get_rate_pll_div(0); - case CLK_SRC_PLL1DIV: return get_rate_pll_div(1); - case CLK_SRC_PLL2DIV: return get_rate_pll_div(2); - case CLK_SRC_XI: return xi_rate; - case CLK_SRC_XTI: return xti_rate; - case CLK_SRC_XIDIV: return get_rate_xi_div(); - case CLK_SRC_XTIDIV: return get_rate_xti_div(); - default: return 0; - } -} - -static unsigned long aclk_get_rate(struct clk *clk) -{ - u32 reg; - unsigned long div; - unsigned int src; - - reg = __raw_readl(clk->aclkreg); - div = reg & 0x0fff; - src = (reg >> ACLK_SEL_SHIFT) & CLK_SRC_MASK; - return root_clk_get_rate(src) / (div + 1); -} - -static unsigned long aclk_best_div(struct clk *clk, unsigned long rate) -{ - unsigned long div, src, freq, r1, r2; - - if (!rate) - return ACLK_MAX_DIV; - - src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; - src &= CLK_SRC_MASK; - freq = root_clk_get_rate(src); - div = freq / rate; - if (!div) - return 1; - if (div >= ACLK_MAX_DIV) - return ACLK_MAX_DIV; - r1 = freq / div; - r2 = freq / (div + 1); - if ((rate - r2) < (r1 - rate)) - return div + 1; - - return div; -} - -static unsigned long aclk_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned int src; - - src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; - src &= CLK_SRC_MASK; - - return root_clk_get_rate(src) / aclk_best_div(clk, rate); -} - -static int aclk_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg; - - reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; - reg |= aclk_best_div(clk, rate) - 1; - __raw_writel(reg, clk->aclkreg); - return 0; -} - -static unsigned long get_rate_sys(struct clk *clk) -{ - unsigned int src; - - src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK; - return root_clk_get_rate(src); -} - -static unsigned long get_rate_bus(struct clk *clk) -{ - unsigned int reg, sdiv, bdiv, rate; - - reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); - rate = get_rate_sys(clk); - sdiv = (reg >> 20) & 3; - if (sdiv) - rate /= sdiv + 1; - bdiv = (reg >> 4) & 0xff; - if (bdiv) - rate /= bdiv + 1; - return rate; -} - -static unsigned long get_rate_cpu(struct clk *clk) -{ - unsigned int reg, div, fsys, fbus; - - fbus = get_rate_bus(clk); - reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); - if (reg & (1 << 29)) - return fbus; - fsys = get_rate_sys(clk); - div = (reg >> 16) & 0x0f; - return fbus + ((fsys - fbus) * (div + 1)) / 16; -} - -static unsigned long get_rate_root(struct clk *clk) -{ - return root_clk_get_rate(clk->root_id); -} - -static int aclk_set_parent(struct clk *clock, struct clk *parent) -{ - u32 reg; - - if (clock->parent == parent) - return 0; - - clock->parent = parent; - - if (!parent) - return 0; - - if (parent->root_id == CLK_SRC_NOROOT) - return 0; - reg = __raw_readl(clock->aclkreg); - reg &= ~ACLK_SEL_MASK; - reg |= (parent->root_id << ACLK_SEL_SHIFT) & ACLK_SEL_MASK; - __raw_writel(reg, clock->aclkreg); - - return 0; -} - -#define DEFINE_ROOT_CLOCK(name, ri, p) \ - static struct clk name = { \ - .root_id = ri, \ - .get_rate = get_rate_root, \ - .enable = enable_clk, \ - .disable = disable_clk, \ - .parent = p, \ - }; - -#define DEFINE_SPECIAL_CLOCK(name, gr, p) \ - static struct clk name = { \ - .root_id = CLK_SRC_NOROOT, \ - .get_rate = gr, \ - .parent = p, \ - }; - -#define DEFINE_ACLOCK(name, bc, bs, ar) \ - static struct clk name = { \ - .root_id = CLK_SRC_NOROOT, \ - .bclkctr = bc, \ - .bclk_shift = bs, \ - .aclkreg = ar, \ - .get_rate = aclk_get_rate, \ - .set_rate = aclk_set_rate, \ - .round_rate = aclk_round_rate, \ - .enable = enable_clk, \ - .disable = disable_clk, \ - .set_parent = aclk_set_parent, \ - }; - -#define DEFINE_BCLOCK(name, bc, bs, gr, p) \ - static struct clk name = { \ - .root_id = CLK_SRC_NOROOT, \ - .bclkctr = bc, \ - .bclk_shift = bs, \ - .get_rate = gr, \ - .enable = enable_clk, \ - .disable = disable_clk, \ - .parent = p, \ - }; - -DEFINE_ROOT_CLOCK(xi, CLK_SRC_XI, NULL) -DEFINE_ROOT_CLOCK(xti, CLK_SRC_XTI, NULL) -DEFINE_ROOT_CLOCK(xidiv, CLK_SRC_XIDIV, &xi) -DEFINE_ROOT_CLOCK(xtidiv, CLK_SRC_XTIDIV, &xti) -DEFINE_ROOT_CLOCK(pll0, CLK_SRC_PLL0, &xi) -DEFINE_ROOT_CLOCK(pll1, CLK_SRC_PLL1, &xi) -DEFINE_ROOT_CLOCK(pll2, CLK_SRC_PLL2, &xi) -DEFINE_ROOT_CLOCK(pll0div, CLK_SRC_PLL0DIV, &pll0) -DEFINE_ROOT_CLOCK(pll1div, CLK_SRC_PLL1DIV, &pll1) -DEFINE_ROOT_CLOCK(pll2div, CLK_SRC_PLL2DIV, &pll2) - -/* The following 3 clocks are special and are initialized explicitly later */ -DEFINE_SPECIAL_CLOCK(sys, get_rate_sys, NULL) -DEFINE_SPECIAL_CLOCK(bus, get_rate_bus, &sys) -DEFINE_SPECIAL_CLOCK(cpu, get_rate_cpu, &sys) - -DEFINE_ACLOCK(tct, NULL, 0, ACLKTCT) -DEFINE_ACLOCK(tcx, NULL, 0, ACLKTCX) -DEFINE_ACLOCK(tcz, NULL, 0, ACLKTCZ) -DEFINE_ACLOCK(ref, NULL, 0, ACLKREF) -DEFINE_ACLOCK(uart0, BCLKCTR0, 5, ACLKUART0) -DEFINE_ACLOCK(uart1, BCLKCTR0, 23, ACLKUART1) -DEFINE_ACLOCK(uart2, BCLKCTR0, 6, ACLKUART2) -DEFINE_ACLOCK(uart3, BCLKCTR0, 8, ACLKUART3) -DEFINE_ACLOCK(uart4, BCLKCTR1, 6, ACLKUART4) -DEFINE_ACLOCK(i2c, BCLKCTR0, 7, ACLKI2C) -DEFINE_ACLOCK(adc, BCLKCTR0, 10, ACLKADC) -DEFINE_ACLOCK(usbh0, BCLKCTR0, 11, ACLKUSBH) -DEFINE_ACLOCK(lcd, BCLKCTR0, 13, ACLKLCD) -DEFINE_ACLOCK(sd0, BCLKCTR0, 17, ACLKSDH0) -DEFINE_ACLOCK(sd1, BCLKCTR1, 5, ACLKSDH1) -DEFINE_ACLOCK(spi0, BCLKCTR0, 24, ACLKSPI0) -DEFINE_ACLOCK(spi1, BCLKCTR0, 30, ACLKSPI1) -DEFINE_ACLOCK(spdif, BCLKCTR1, 2, ACLKSPDIF) -DEFINE_ACLOCK(c3dec, BCLKCTR1, 9, ACLKC3DEC) -DEFINE_ACLOCK(can0, BCLKCTR1, 10, ACLKCAN0) -DEFINE_ACLOCK(can1, BCLKCTR1, 11, ACLKCAN1) -DEFINE_ACLOCK(gsb0, BCLKCTR1, 13, ACLKGSB0) -DEFINE_ACLOCK(gsb1, BCLKCTR1, 14, ACLKGSB1) -DEFINE_ACLOCK(gsb2, BCLKCTR1, 15, ACLKGSB2) -DEFINE_ACLOCK(gsb3, BCLKCTR1, 16, ACLKGSB3) -DEFINE_ACLOCK(usbh1, BCLKCTR1, 20, ACLKUSBH) - -DEFINE_BCLOCK(dai0, BCLKCTR0, 0, NULL, NULL) -DEFINE_BCLOCK(pic, BCLKCTR0, 1, NULL, NULL) -DEFINE_BCLOCK(tc, BCLKCTR0, 2, NULL, NULL) -DEFINE_BCLOCK(gpio, BCLKCTR0, 3, NULL, NULL) -DEFINE_BCLOCK(usbd, BCLKCTR0, 4, NULL, NULL) -DEFINE_BCLOCK(ecc, BCLKCTR0, 9, NULL, NULL) -DEFINE_BCLOCK(gdma0, BCLKCTR0, 12, NULL, NULL) -DEFINE_BCLOCK(rtc, BCLKCTR0, 15, NULL, NULL) -DEFINE_BCLOCK(nfc, BCLKCTR0, 16, NULL, NULL) -DEFINE_BCLOCK(g2d, BCLKCTR0, 18, NULL, NULL) -DEFINE_BCLOCK(gdma1, BCLKCTR0, 22, NULL, NULL) -DEFINE_BCLOCK(mscl, BCLKCTR0, 25, NULL, NULL) -DEFINE_BCLOCK(bdma, BCLKCTR1, 0, NULL, NULL) -DEFINE_BCLOCK(adma0, BCLKCTR1, 1, NULL, NULL) -DEFINE_BCLOCK(scfg, BCLKCTR1, 3, NULL, NULL) -DEFINE_BCLOCK(cid, BCLKCTR1, 4, NULL, NULL) -DEFINE_BCLOCK(dai1, BCLKCTR1, 7, NULL, NULL) -DEFINE_BCLOCK(adma1, BCLKCTR1, 8, NULL, NULL) -DEFINE_BCLOCK(gps, BCLKCTR1, 12, NULL, NULL) -DEFINE_BCLOCK(gdma2, BCLKCTR1, 17, NULL, NULL) -DEFINE_BCLOCK(gdma3, BCLKCTR1, 18, NULL, NULL) -DEFINE_BCLOCK(ddrc, BCLKCTR1, 19, NULL, NULL) - -#define _REGISTER_CLOCK(d, n, c) \ - { \ - .dev_id = d, \ - .con_id = n, \ - .clk = &c, \ - }, - -static struct clk_lookup lookups[] = { - _REGISTER_CLOCK(NULL, "bus", bus) - _REGISTER_CLOCK(NULL, "cpu", cpu) - _REGISTER_CLOCK(NULL, "tct", tct) - _REGISTER_CLOCK(NULL, "tcx", tcx) - _REGISTER_CLOCK(NULL, "tcz", tcz) - _REGISTER_CLOCK(NULL, "ref", ref) - _REGISTER_CLOCK(NULL, "dai0", dai0) - _REGISTER_CLOCK(NULL, "pic", pic) - _REGISTER_CLOCK(NULL, "tc", tc) - _REGISTER_CLOCK(NULL, "gpio", gpio) - _REGISTER_CLOCK(NULL, "usbd", usbd) - _REGISTER_CLOCK("tcc-uart.0", NULL, uart0) - _REGISTER_CLOCK("tcc-uart.2", NULL, uart2) - _REGISTER_CLOCK("tcc-i2c", NULL, i2c) - _REGISTER_CLOCK("tcc-uart.3", NULL, uart3) - _REGISTER_CLOCK(NULL, "ecc", ecc) - _REGISTER_CLOCK(NULL, "adc", adc) - _REGISTER_CLOCK("tcc-usbh.0", "usb", usbh0) - _REGISTER_CLOCK(NULL, "gdma0", gdma0) - _REGISTER_CLOCK(NULL, "lcd", lcd) - _REGISTER_CLOCK(NULL, "rtc", rtc) - _REGISTER_CLOCK(NULL, "nfc", nfc) - _REGISTER_CLOCK("tcc-mmc.0", NULL, sd0) - _REGISTER_CLOCK(NULL, "g2d", g2d) - _REGISTER_CLOCK(NULL, "gdma1", gdma1) - _REGISTER_CLOCK("tcc-uart.1", NULL, uart1) - _REGISTER_CLOCK("tcc-spi.0", NULL, spi0) - _REGISTER_CLOCK(NULL, "mscl", mscl) - _REGISTER_CLOCK("tcc-spi.1", NULL, spi1) - _REGISTER_CLOCK(NULL, "bdma", bdma) - _REGISTER_CLOCK(NULL, "adma0", adma0) - _REGISTER_CLOCK(NULL, "spdif", spdif) - _REGISTER_CLOCK(NULL, "scfg", scfg) - _REGISTER_CLOCK(NULL, "cid", cid) - _REGISTER_CLOCK("tcc-mmc.1", NULL, sd1) - _REGISTER_CLOCK("tcc-uart.4", NULL, uart4) - _REGISTER_CLOCK(NULL, "dai1", dai1) - _REGISTER_CLOCK(NULL, "adma1", adma1) - _REGISTER_CLOCK(NULL, "c3dec", c3dec) - _REGISTER_CLOCK("tcc-can.0", NULL, can0) - _REGISTER_CLOCK("tcc-can.1", NULL, can1) - _REGISTER_CLOCK(NULL, "gps", gps) - _REGISTER_CLOCK("tcc-gsb.0", NULL, gsb0) - _REGISTER_CLOCK("tcc-gsb.1", NULL, gsb1) - _REGISTER_CLOCK("tcc-gsb.2", NULL, gsb2) - _REGISTER_CLOCK("tcc-gsb.3", NULL, gsb3) - _REGISTER_CLOCK(NULL, "gdma2", gdma2) - _REGISTER_CLOCK(NULL, "gdma3", gdma3) - _REGISTER_CLOCK(NULL, "ddrc", ddrc) - _REGISTER_CLOCK("tcc-usbh.1", "usb", usbh1) -}; - -static struct clk *root_clk_by_index(enum root_clks src) -{ - switch (src) { - case CLK_SRC_PLL0: return &pll0; - case CLK_SRC_PLL1: return &pll1; - case CLK_SRC_PLL2: return &pll2; - case CLK_SRC_PLL0DIV: return &pll0div; - case CLK_SRC_PLL1DIV: return &pll1div; - case CLK_SRC_PLL2DIV: return &pll2div; - case CLK_SRC_XI: return ξ - case CLK_SRC_XTI: return &xti; - case CLK_SRC_XIDIV: return &xidiv; - case CLK_SRC_XTIDIV: return &xtidiv; - default: return NULL; - } -} - -static void find_aclk_parent(struct clk *clk) -{ - unsigned int src; - struct clk *clock; - - if (!clk->aclkreg) - return; - - src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; - src &= CLK_SRC_MASK; - - clock = root_clk_by_index(src); - if (!clock) - return; - - clk->parent = clock; - clk->set_parent = aclk_set_parent; -} - -void __init tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq) -{ - int i; - - xi_rate = xi_freq; - xti_rate = xti_freq; - - /* fixup parents and add the clock */ - for (i = 0; i < ARRAY_SIZE(lookups); i++) { - find_aclk_parent(lookups[i].clk); - clkdev_add(&lookups[i]); - } - tcc8k_timer_init(&tcz, (void __iomem *)TIMER_BASE, INT_TC32); -} diff --git a/arch/arm/mach-tcc8k/common.h b/arch/arm/mach-tcc8k/common.h deleted file mode 100644 index 705690add395..000000000000 --- a/arch/arm/mach-tcc8k/common.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MACH_TCC8K_COMMON_H -#define MACH_TCC8K_COMMON_H - -#include - -extern struct platform_device tcc_nand_device; - -struct clk; - -extern void tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq); -extern void tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq); -extern void tcc8k_init_irq(void); -extern void tcc8k_map_common_io(void); - -#endif diff --git a/arch/arm/mach-tcc8k/devices.c b/arch/arm/mach-tcc8k/devices.c deleted file mode 100644 index 6722ad7c2836..000000000000 --- a/arch/arm/mach-tcc8k/devices.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * linux/arch/arm/mach-tcc8k/devices.c - * - * Copyright (C) Telechips, Inc. - * Copyright (C) 2009 Hans J. Koch - * - * Licensed under the terms of GPL v2. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "common.h" - -static u64 tcc8k_dmamask = DMA_BIT_MASK(32); - -#ifdef CONFIG_MTD_NAND_TCC -/* NAND controller */ -static struct resource tcc_nand_resources[] = { - { - .start = (resource_size_t)NFC_BASE, - .end = (resource_size_t)NFC_BASE + 0x7f, - .flags = IORESOURCE_MEM, - }, { - .start = INT_NFC, - .end = INT_NFC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device tcc_nand_device = { - .name = "tcc_nand", - .id = 0, - .num_resources = ARRAY_SIZE(tcc_nand_resources), - .resource = tcc_nand_resources, -}; -#endif - -#ifdef CONFIG_MMC_TCC8K -/* MMC controller */ -static struct resource tcc8k_mmc0_resource[] = { - { - .start = INT_SD0, - .end = INT_SD0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource tcc8k_mmc1_resource[] = { - { - .start = INT_SD1, - .end = INT_SD1, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device tcc8k_mmc0_device = { - .name = "tcc-mmc", - .id = 0, - .num_resources = ARRAY_SIZE(tcc8k_mmc0_resource), - .resource = tcc8k_mmc0_resource, - .dev = { - .dma_mask = &tcc8k_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - } -}; - -struct platform_device tcc8k_mmc1_device = { - .name = "tcc-mmc", - .id = 1, - .num_resources = ARRAY_SIZE(tcc8k_mmc1_resource), - .resource = tcc8k_mmc1_resource, - .dev = { - .dma_mask = &tcc8k_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - } -}; - -static inline void tcc8k_init_mmc(void) -{ - u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS); - - reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS; - __raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS); - - platform_device_register(&tcc8k_mmc0_device); - platform_device_register(&tcc8k_mmc1_device); -} -#else -static inline void tcc8k_init_mmc(void) { } -#endif - -#ifdef CONFIG_USB_OHCI_HCD -static int tcc8k_ohci_init(struct device *dev) -{ - u32 reg; - - /* Use GPIO PK19 as VBUS control output */ - reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS); - reg &= ~(1 << 19); - __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS); - reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS); - reg &= ~(1 << 19); - __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS); - - reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS); - reg |= (1 << 19); - __raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS); - /* Turn on VBUS */ - reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS); - reg |= (1 << 19); - __raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS); - - return 0; -} - -static struct resource tcc8k_ohci0_resources[] = { - [0] = { - .start = (resource_size_t)USBH0_BASE, - .end = (resource_size_t)USBH0_BASE + 0x5c, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = INT_USBH0, - .end = INT_USBH0, - .flags = IORESOURCE_IRQ, - } -}; - -static struct resource tcc8k_ohci1_resources[] = { - [0] = { - .start = (resource_size_t)USBH1_BASE, - .end = (resource_size_t)USBH1_BASE + 0x5c, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = INT_USBH1, - .end = INT_USBH1, - .flags = IORESOURCE_IRQ, - } -}; - -static struct tccohci_platform_data tcc8k_ohci0_platform_data = { - .controller = 0, - .port_mode = PMM_PERPORT_MODE, - .init = tcc8k_ohci_init, -}; - -static struct tccohci_platform_data tcc8k_ohci1_platform_data = { - .controller = 1, - .port_mode = PMM_PERPORT_MODE, - .init = tcc8k_ohci_init, -}; - -static struct platform_device ohci0_device = { - .name = "tcc-ohci", - .id = 0, - .dev = { - .dma_mask = &tcc8k_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &tcc8k_ohci0_platform_data, - }, - .num_resources = ARRAY_SIZE(tcc8k_ohci0_resources), - .resource = tcc8k_ohci0_resources, -}; - -static struct platform_device ohci1_device = { - .name = "tcc-ohci", - .id = 1, - .dev = { - .dma_mask = &tcc8k_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &tcc8k_ohci1_platform_data, - }, - .num_resources = ARRAY_SIZE(tcc8k_ohci1_resources), - .resource = tcc8k_ohci1_resources, -}; - -static void __init tcc8k_init_usbhost(void) -{ - platform_device_register(&ohci0_device); - platform_device_register(&ohci1_device); -} -#else -static void __init tcc8k_init_usbhost(void) { } -#endif - -/* USB device controller*/ -#ifdef CONFIG_USB_GADGET_TCC8K -static struct resource udc_resources[] = { - [0] = { - .start = INT_USBD, - .end = INT_USBD, - .flags = IORESOURCE_IRQ, - }, - [1] = { - .start = INT_UDMA, - .end = INT_UDMA, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device tcc8k_udc_device = { - .name = "tcc-udc", - .id = 0, - .resource = udc_resources, - .num_resources = ARRAY_SIZE(udc_resources), - .dev = { - .dma_mask = &tcc8k_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static void __init tcc8k_init_usb_gadget(void) -{ - platform_device_register(&tcc8k_udc_device); -} -#else -static void __init tcc8k_init_usb_gadget(void) { } -#endif /* CONFIG_USB_GADGET_TCC83X */ - -static int __init tcc8k_init_devices(void) -{ - tcc8k_init_mmc(); - tcc8k_init_usbhost(); - tcc8k_init_usb_gadget(); - return 0; -} - -arch_initcall(tcc8k_init_devices); diff --git a/arch/arm/mach-tcc8k/io.c b/arch/arm/mach-tcc8k/io.c deleted file mode 100644 index 9b39d7fa658f..000000000000 --- a/arch/arm/mach-tcc8k/io.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * linux/arch/arm/mach-tcc8k/io.c - * - * (C) 2009 Hans J. Koch - * - * derived from TCC83xx io.c - * Copyright (C) Telechips, 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. - */ - -#include -#include -#include - -#include - -#include - -/* - * The machine specific code may provide the extra mapping besides the - * default mapping provided here. - */ -static struct map_desc tcc8k_io_desc[] __initdata = { - { - .virtual = (unsigned long)CS1_BASE_VIRT, - .pfn = __phys_to_pfn(CS1_BASE), - .length = CS1_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)AHB_PERI_BASE_VIRT, - .pfn = __phys_to_pfn(AHB_PERI_BASE), - .length = AHB_PERI_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)APB0_PERI_BASE_VIRT, - .pfn = __phys_to_pfn(APB0_PERI_BASE), - .length = APB0_PERI_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)APB1_PERI_BASE_VIRT, - .pfn = __phys_to_pfn(APB1_PERI_BASE), - .length = APB1_PERI_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)EXT_MEM_CTRL_BASE_VIRT, - .pfn = __phys_to_pfn(EXT_MEM_CTRL_BASE), - .length = EXT_MEM_CTRL_SIZE, - .type = MT_DEVICE, - }, -}; - -/* - * Maps common IO regions for tcc8k. - * - */ -void __init tcc8k_map_common_io(void) -{ - iotable_init(tcc8k_io_desc, ARRAY_SIZE(tcc8k_io_desc)); -} diff --git a/arch/arm/mach-tcc8k/irq.c b/arch/arm/mach-tcc8k/irq.c deleted file mode 100644 index 209fa5c65d4c..000000000000 --- a/arch/arm/mach-tcc8k/irq.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) Telechips, Inc. - * Copyright (C) 2009-2010 Hans J. Koch - * - * Licensed under the terms of the GNU GPL version 2. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -#include "common.h" - -/* Disable IRQ */ -static void tcc8000_mask_ack_irq0(struct irq_data *d) -{ - PIC0_IEN &= ~(1 << d->irq); - PIC0_CREQ |= (1 << d->irq); -} - -static void tcc8000_mask_ack_irq1(struct irq_data *d) -{ - PIC1_IEN &= ~(1 << (d->irq - 32)); - PIC1_CREQ |= (1 << (d->irq - 32)); -} - -static void tcc8000_mask_irq0(struct irq_data *d) -{ - PIC0_IEN &= ~(1 << d->irq); -} - -static void tcc8000_mask_irq1(struct irq_data *d) -{ - PIC1_IEN &= ~(1 << (d->irq - 32)); -} - -static void tcc8000_ack_irq0(struct irq_data *d) -{ - PIC0_CREQ |= (1 << d->irq); -} - -static void tcc8000_ack_irq1(struct irq_data *d) -{ - PIC1_CREQ |= (1 << (d->irq - 32)); -} - -/* Enable IRQ */ -static void tcc8000_unmask_irq0(struct irq_data *d) -{ - PIC0_IEN |= (1 << d->irq); - PIC0_INTOEN |= (1 << d->irq); -} - -static void tcc8000_unmask_irq1(struct irq_data *d) -{ - PIC1_IEN |= (1 << (d->irq - 32)); - PIC1_INTOEN |= (1 << (d->irq - 32)); -} - -static struct irq_chip tcc8000_irq_chip0 = { - .name = "tcc_irq0", - .irq_mask = tcc8000_mask_irq0, - .irq_ack = tcc8000_ack_irq0, - .irq_mask_ack = tcc8000_mask_ack_irq0, - .irq_unmask = tcc8000_unmask_irq0, -}; - -static struct irq_chip tcc8000_irq_chip1 = { - .name = "tcc_irq1", - .irq_mask = tcc8000_mask_irq1, - .irq_ack = tcc8000_ack_irq1, - .irq_mask_ack = tcc8000_mask_ack_irq1, - .irq_unmask = tcc8000_unmask_irq1, -}; - -void __init tcc8k_init_irq(void) -{ - int irqno; - - /* Mask and clear all interrupts */ - PIC0_IEN = 0x00000000; - PIC0_CREQ = 0xffffffff; - PIC1_IEN = 0x00000000; - PIC1_CREQ = 0xffffffff; - - PIC0_MEN0 = 0x00000003; - PIC1_MEN1 = 0x00000003; - PIC1_MEN = 0x00000003; - - /* let all IRQs be level triggered */ - PIC0_TMODE = 0xffffffff; - PIC1_TMODE = 0xffffffff; - /* all IRQs are IRQs (not FIQs) */ - PIC0_IRQSEL = 0xffffffff; - PIC1_IRQSEL = 0xffffffff; - - for (irqno = 0; irqno < NR_IRQS; irqno++) { - if (irqno < 32) - irq_set_chip(irqno, &tcc8000_irq_chip0); - else - irq_set_chip(irqno, &tcc8000_irq_chip1); - irq_set_handler(irqno, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } -} diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c deleted file mode 100644 index a96babe83771..000000000000 --- a/arch/arm/mach-tcc8k/time.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * TCC8000 system timer setup - * - * (C) 2009 Hans J. Koch - * - * Licensed under the terms of the GPL version 2. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "common.h" - -static void __iomem *timer_base; - -static int tcc_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long reg = __raw_readl(timer_base + TC32MCNT_OFFS); - - __raw_writel(reg + evt, timer_base + TC32CMP0_OFFS); - return 0; -} - -static void tcc_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned long tc32irq; - - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS); - tc32irq |= TC32IRQ_IRQEN0; - __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS); - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS); - tc32irq &= ~TC32IRQ_IRQEN0; - __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS); - break; - case CLOCK_EVT_MODE_PERIODIC: - case CLOCK_EVT_MODE_RESUME: - break; - } -} - -static irqreturn_t tcc8k_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* Acknowledge TC32 interrupt by reading TC32IRQ */ - __raw_readl(timer_base + TC32IRQ_OFFS); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device clockevent_tcc = { - .name = "tcc_timer1", - .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, - .set_mode = tcc_set_mode, - .set_next_event = tcc_set_next_event, - .rating = 200, -}; - -static struct irqaction tcc8k_timer_irq = { - .name = "TC32_timer", - .flags = IRQF_DISABLED | IRQF_TIMER, - .handler = tcc8k_timer_interrupt, - .dev_id = &clockevent_tcc, -}; - -static int __init tcc_clockevent_init(struct clk *clock) -{ - unsigned int c = clk_get_rate(clock); - - clocksource_mmio_init(timer_base + TC32MCNT_OFFS, "tcc_tc32", c, - 200, 32, clocksource_mmio_readl_up); - - clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, - clockevent_tcc.shift); - clockevent_tcc.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_tcc); - clockevent_tcc.min_delta_ns = - clockevent_delta2ns(0xff, &clockevent_tcc); - - clockevent_tcc.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_tcc); - - return 0; -} - -void __init tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq) -{ - u32 reg; - - timer_base = base; - tcc8k_timer_irq.irq = irq; - - /* Enable clocks */ - clk_enable(clock); - - /* Initialize 32-bit timer */ - reg = __raw_readl(timer_base + TC32EN_OFFS); - reg &= ~TC32EN_ENABLE; /* Disable timer */ - __raw_writel(reg, timer_base + TC32EN_OFFS); - /* Free running timer, counting from 0 to 0xffffffff */ - __raw_writel(0, timer_base + TC32EN_OFFS); - __raw_writel(0, timer_base + TC32LDV_OFFS); - reg = __raw_readl(timer_base + TC32IRQ_OFFS); - reg |= TC32IRQ_IRQEN0; /* irq at match with CMP0 */ - __raw_writel(reg, timer_base + TC32IRQ_OFFS); - - __raw_writel(TC32EN_ENABLE, timer_base + TC32EN_OFFS); - - tcc_clockevent_init(clock); - setup_irq(irq, &tcc8k_timer_irq); -} -- cgit From 2e3d256de9d3db5a7ca19b61305627a516b54b45 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 22 Dec 2011 21:30:48 +0100 Subject: arm: Remove plat-tcc directory The Telechips ARM architecture is being removed. This patch deletes the arch/arm/plat-tcc/ folder. Cc: Thomas Gleixner Cc: Harry Sievers Signed-off-by: Hans J. Koch --- arch/arm/plat-tcc/Kconfig | 20 - arch/arm/plat-tcc/Makefile | 3 - arch/arm/plat-tcc/clock.c | 179 ------ arch/arm/plat-tcc/include/mach/clock.h | 48 -- arch/arm/plat-tcc/include/mach/debug-macro.S | 32 -- arch/arm/plat-tcc/include/mach/entry-macro.S | 68 --- arch/arm/plat-tcc/include/mach/hardware.h | 43 -- arch/arm/plat-tcc/include/mach/io.h | 23 - arch/arm/plat-tcc/include/mach/irqs.h | 83 --- arch/arm/plat-tcc/include/mach/system.h | 31 - arch/arm/plat-tcc/include/mach/tcc8k-regs.h | 807 --------------------------- arch/arm/plat-tcc/include/mach/timex.h | 5 - arch/arm/plat-tcc/include/mach/uncompress.h | 34 -- arch/arm/plat-tcc/include/mach/vmalloc.h | 10 - arch/arm/plat-tcc/system.c | 25 - 15 files changed, 1411 deletions(-) delete mode 100644 arch/arm/plat-tcc/Kconfig delete mode 100644 arch/arm/plat-tcc/Makefile delete mode 100644 arch/arm/plat-tcc/clock.c delete mode 100644 arch/arm/plat-tcc/include/mach/clock.h delete mode 100644 arch/arm/plat-tcc/include/mach/debug-macro.S delete mode 100644 arch/arm/plat-tcc/include/mach/entry-macro.S delete mode 100644 arch/arm/plat-tcc/include/mach/hardware.h delete mode 100644 arch/arm/plat-tcc/include/mach/io.h delete mode 100644 arch/arm/plat-tcc/include/mach/irqs.h delete mode 100644 arch/arm/plat-tcc/include/mach/system.h delete mode 100644 arch/arm/plat-tcc/include/mach/tcc8k-regs.h delete mode 100644 arch/arm/plat-tcc/include/mach/timex.h delete mode 100644 arch/arm/plat-tcc/include/mach/uncompress.h delete mode 100644 arch/arm/plat-tcc/include/mach/vmalloc.h delete mode 100644 arch/arm/plat-tcc/system.c diff --git a/arch/arm/plat-tcc/Kconfig b/arch/arm/plat-tcc/Kconfig deleted file mode 100644 index 1bf499570f42..000000000000 --- a/arch/arm/plat-tcc/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -if ARCH_TCC_926 - -menu "Telechips ARM926-based CPUs" - -choice - prompt "Telechips CPU type:" - default ARCH_TCC8K - -config ARCH_TCC8K - bool TCC8000 - select USB_ARCH_HAS_OHCI - help - Support for Telechips TCC8000 systems - -endchoice - -source "arch/arm/mach-tcc8k/Kconfig" - -endmenu -endif diff --git a/arch/arm/plat-tcc/Makefile b/arch/arm/plat-tcc/Makefile deleted file mode 100644 index eceabc869b8f..000000000000 --- a/arch/arm/plat-tcc/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# "Telechips Platform Common Modules" - -obj-y := clock.o system.o diff --git a/arch/arm/plat-tcc/clock.c b/arch/arm/plat-tcc/clock.c deleted file mode 100644 index f3ced10d5271..000000000000 --- a/arch/arm/plat-tcc/clock.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Clock framework for Telechips SoCs - * Based on arch/arm/plat-mxc/clock.c - * - * Copyright (C) 2004 - 2005 Nokia corporation - * Written by Tuukka Tikkanen - * Modified for omap shared clock framework by Tony Lindgren - * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * Copyright 2010 Hans J. Koch, hjk@linutronix.de - * - * Licensed under the terms of the GPL v2. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static DEFINE_MUTEX(clocks_mutex); - -/*------------------------------------------------------------------------- - * Standard clock functions defined in include/linux/clk.h - *-------------------------------------------------------------------------*/ - -static void __clk_disable(struct clk *clk) -{ - BUG_ON(clk->refcount == 0); - - if (!(--clk->refcount) && clk->disable) { - /* Unconditionally disable the clock in hardware */ - clk->disable(clk); - /* recursively disable parents */ - if (clk->parent) - __clk_disable(clk->parent); - } -} - -static int __clk_enable(struct clk *clk) -{ - int ret = 0; - - if (clk->refcount++ == 0 && clk->enable) { - if (clk->parent) - ret = __clk_enable(clk->parent); - if (ret) - return ret; - else - return clk->enable(clk); - } - - return 0; -} - -/* This function increments the reference count on the clock and enables the - * clock if not already enabled. The parent clock tree is recursively enabled - */ -int clk_enable(struct clk *clk) -{ - int ret = 0; - - if (!clk) - return -EINVAL; - - mutex_lock(&clocks_mutex); - ret = __clk_enable(clk); - mutex_unlock(&clocks_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_enable); - -/* This function decrements the reference count on the clock and disables - * the clock when reference count is 0. The parent clock tree is - * recursively disabled - */ -void clk_disable(struct clk *clk) -{ - if (!clk) - return; - - mutex_lock(&clocks_mutex); - __clk_disable(clk); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL_GPL(clk_disable); - -/* Retrieve the *current* clock rate. If the clock itself - * does not provide a special calculation routine, ask - * its parent and so on, until one is able to return - * a valid clock rate - */ -unsigned long clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0UL; - - if (clk->get_rate) - return clk->get_rate(clk); - - return clk_get_rate(clk->parent); -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -/* Round the requested clock rate to the nearest supported - * rate that is less than or equal to the requested rate. - * This is dependent on the clock's current parent. - */ -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (!clk) - return 0; - if (!clk->round_rate) - return 0; - - return clk->round_rate(clk, rate); -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -/* Set the clock to the requested clock rate. The rate must - * match a supported rate exactly based on what clk_round_rate returns - */ -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EINVAL; - - if (!clk) - return ret; - if (!clk->set_rate || !rate) - return ret; - - mutex_lock(&clocks_mutex); - ret = clk->set_rate(clk, rate); - mutex_unlock(&clocks_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -/* Set the clock's parent to another clock source */ -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *old; - int ret = -EINVAL; - - if (!clk) - return ret; - if (!clk->set_parent || !parent) - return ret; - - mutex_lock(&clocks_mutex); - old = clk->parent; - if (clk->refcount) - __clk_enable(parent); - ret = clk->set_parent(clk, parent); - if (ret) - old = parent; - if (clk->refcount) - __clk_disable(old); - mutex_unlock(&clocks_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -/* Retrieve the clock's parent clock source */ -struct clk *clk_get_parent(struct clk *clk) -{ - if (!clk) - return NULL; - - return clk->parent; -} -EXPORT_SYMBOL_GPL(clk_get_parent); diff --git a/arch/arm/plat-tcc/include/mach/clock.h b/arch/arm/plat-tcc/include/mach/clock.h deleted file mode 100644 index a12f58ad71a8..000000000000 --- a/arch/arm/plat-tcc/include/mach/clock.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Low level clock header file for Telechips TCC architecture - * (C) 2010 Hans J. Koch - * - * Licensed under the GPL v2. - */ - -#ifndef __ASM_ARCH_TCC_CLOCK_H__ -#define __ASM_ARCH_TCC_CLOCK_H__ - -#ifndef __ASSEMBLY__ - -struct clk { - struct clk *parent; - /* id number of a root clock, 0 for normal clocks */ - int root_id; - /* Reference count of clock enable/disable */ - int refcount; - /* Address of associated BCLKCTRx register. Must be set. */ - void __iomem *bclkctr; - /* Bit position for BCLKCTRx. Must be set. */ - int bclk_shift; - /* Address of ACLKxxx register, if any. */ - void __iomem *aclkreg; - /* get the current clock rate (always a fresh value) */ - unsigned long (*get_rate) (struct clk *); - /* Function ptr to set the clock to a new rate. The rate must match a - supported rate returned from round_rate. Leave blank if clock is not - programmable */ - int (*set_rate) (struct clk *, unsigned long); - /* Function ptr to round the requested clock rate to the nearest - supported rate that is less than or equal to the requested rate. */ - unsigned long (*round_rate) (struct clk *, unsigned long); - /* Function ptr to enable the clock. Leave blank if clock can not - be gated. */ - int (*enable) (struct clk *); - /* Function ptr to disable the clock. Leave blank if clock can not - be gated. */ - void (*disable) (struct clk *); - /* Function ptr to set the parent clock of the clock. */ - int (*set_parent) (struct clk *, struct clk *); -}; - -int clk_register(struct clk *clk); -void clk_unregister(struct clk *clk); - -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_ARCH_MXC_CLOCK_H__ */ diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S deleted file mode 100644 index cf17d04ec30d..000000000000 --- a/arch/arm/plat-tcc/include/mach/debug-macro.S +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 1994-1999 Russell King - * Copyright (C) 2008-2009 Telechips - * Copyright (C) 2009 Hans J. Koch - * - * 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. - * - */ - - .macro addruart, rp, rv, tmp - moveq \rp, #0x90000000 @ physical base address - movne \rv, #0xF1000000 @ virtual base - orr \rp, \rp, #0x00007000 @ UART0 - orr \rv, \rv, #0x00007000 @ UART0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx, #0x44] - .endm - - .macro waituart,rd,rx - .endm - - .macro busyuart,rd,rx -1001: - ldr \rd, [\rx, #0x14] - tst \rd, #0x20 - - beq 1001b - .endm diff --git a/arch/arm/plat-tcc/include/mach/entry-macro.S b/arch/arm/plat-tcc/include/mach/entry-macro.S deleted file mode 100644 index 748f401e4b6d..000000000000 --- a/arch/arm/plat-tcc/include/mach/entry-macro.S +++ /dev/null @@ -1,68 +0,0 @@ -/* - * include/asm-arm/arch-tcc83x/entry-macro.S - * - * Author : - * Created: June 10, 2008 - * Description: Low-level IRQ helper macros for Telechips-based platforms - * - * Copyright (C) 2008-2009 Telechips - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include - - .macro disable_fiq - .endm - - .macro get_irqnr_preamble, base, tmp - .endm - - .macro arch_ret_to_user, tmp1, tmp2 - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \base, =0xF2003000 @ base address of PIC registers - - @@ read MREQ register of PIC0 - - mov \irqnr, #0 - ldr \irqstat, [\base, #0x00000014 ] @ lower 32 interrupts - cmp \irqstat, #0 - bne 1001f - - @@ read MREQ register of PIC1 - - ldr \irqstat, [\base, #0x00000094] @ upper 32 interrupts - cmp \irqstat, #0 - beq 1002f - mov \irqnr, #0x20 - -1001: - movs \tmp, \irqstat, lsl #16 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #16 - - movs \tmp, \irqstat, lsl #8 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #8 - - movs \tmp, \irqstat, lsl #4 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #4 - - movs \tmp, \irqstat, lsl #2 - movne \irqstat, \tmp - addeq \irqnr, \irqnr, #2 - - movs \tmp, \irqstat, lsl #1 - addeq \irqnr, \irqnr, #1 - orrs \base, \base, #1 -1002: - @@ exit here, Z flag unset if IRQ - - .endm diff --git a/arch/arm/plat-tcc/include/mach/hardware.h b/arch/arm/plat-tcc/include/mach/hardware.h deleted file mode 100644 index e70d126ccaf3..000000000000 --- a/arch/arm/plat-tcc/include/mach/hardware.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Author: RidgeRun, Inc. Greg Lonnon - * Reorganized for Linux-2.6 by Tony Lindgren - * and Dirk Behme - * Rewritten by: - * Description: Hardware definitions for TCC8300 processors and boards - * - * Copyright (C) 2001 RidgeRun, Inc. - * Copyright (C) 2008-2009 Telechips - * - * Modifications for mainline (C) 2009 Hans J. Koch - * - * Licensed under the terms of the GNU Pulic License version 2. - */ - -#ifndef __ASM_ARCH_TCC_HARDWARE_H -#define __ASM_ARCH_TCC_HARDWARE_H - -#include -#ifndef __ASSEMBLER__ -#include -#endif -#include - -/* - * ---------------------------------------------------------------------------- - * Clocks - * ---------------------------------------------------------------------------- - */ -#define CLKGEN_REG_BASE 0xfffece00 -#define ARM_CKCTL (CLKGEN_REG_BASE + 0x0) -#define ARM_IDLECT1 (CLKGEN_REG_BASE + 0x4) -#define ARM_IDLECT2 (CLKGEN_REG_BASE + 0x8) -#define ARM_EWUPCT (CLKGEN_REG_BASE + 0xC) -#define ARM_RSTCT1 (CLKGEN_REG_BASE + 0x10) -#define ARM_RSTCT2 (CLKGEN_REG_BASE + 0x14) -#define ARM_SYSST (CLKGEN_REG_BASE + 0x18) -#define ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24) - -/* DPLL control registers */ -#define DPLL_CTL 0xfffecf00 - -#endif /* __ASM_ARCH_TCC_HARDWARE_H */ diff --git a/arch/arm/plat-tcc/include/mach/io.h b/arch/arm/plat-tcc/include/mach/io.h deleted file mode 100644 index 3e911d3ea0f1..000000000000 --- a/arch/arm/plat-tcc/include/mach/io.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * IO definitions for TCC8000 processors and boards - * - * Copyright (C) 1997-1999 Russell King - * Copyright (C) 2008-2009 Telechips - * Copyright (C) 2010 Hans J. Koch - * - * Licensed under the terms of the GNU Public License version 2. - */ - -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -#define IO_SPACE_LIMIT 0xffffffff - -/* - * We don't actually have real ISA nor PCI buses, but there is so many - * drivers out there that might just work if we fake them... - */ -#define __io(a) __typesafe_io(a) -#define __mem_pci(a) (a) - -#endif diff --git a/arch/arm/plat-tcc/include/mach/irqs.h b/arch/arm/plat-tcc/include/mach/irqs.h deleted file mode 100644 index da863894d498..000000000000 --- a/arch/arm/plat-tcc/include/mach/irqs.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * IRQ definitions for TCC8xxx - * - * Copyright (C) 2008-2009 Telechips - * Copyright (C) 2009 Hans J. Koch - * - * Licensed under the terms of the GPL v2. - * - */ - -#ifndef __ASM_ARCH_TCC_IRQS_H -#define __ASM_ARCH_TCC_IRQS_H - -#define NR_IRQS 64 - -/* PIC0 interrupts */ -#define INT_ADMA1 0 -#define INT_BDMA 1 -#define INT_ADMA0 2 -#define INT_GDMA1 3 -#define INT_I2S0RX 4 -#define INT_I2S0TX 5 -#define INT_TC 6 -#define INT_UART0 7 -#define INT_USBD 8 -#define INT_SPI0TX 9 -#define INT_UDMA 10 -#define INT_LIRQ 11 -#define INT_GDMA2 12 -#define INT_GDMA0 13 -#define INT_TC32 14 -#define INT_LCD 15 -#define INT_ADC 16 -#define INT_I2C 17 -#define INT_RTCP 18 -#define INT_RTCA 19 -#define INT_NFC 20 -#define INT_SD0 21 -#define INT_GSB0 22 -#define INT_PK 23 -#define INT_USBH0 24 -#define INT_USBH1 25 -#define INT_G2D 26 -#define INT_ECC 27 -#define INT_SPI0RX 28 -#define INT_UART1 29 -#define INT_MSCL 30 -#define INT_GSB1 31 -/* PIC1 interrupts */ -#define INT_E0 32 -#define INT_E1 33 -#define INT_E2 34 -#define INT_E3 35 -#define INT_E4 36 -#define INT_E5 37 -#define INT_E6 38 -#define INT_E7 39 -#define INT_UART2 40 -#define INT_UART3 41 -#define INT_SPI1TX 42 -#define INT_SPI1RX 43 -#define INT_GSB2 44 -#define INT_SPDIF 45 -#define INT_CDIF 46 -#define INT_VBON 47 -#define INT_VBOFF 48 -#define INT_SD1 49 -#define INT_UART4 50 -#define INT_GDMA3 51 -#define INT_I2S1RX 52 -#define INT_I2S1TX 53 -#define INT_CAN0 54 -#define INT_CAN1 55 -#define INT_GSB3 56 -#define INT_KRST 57 -#define INT_UNUSED 58 -#define INT_SD0D3 59 -#define INT_SD1D3 60 -#define INT_GPS0 61 -#define INT_GPS1 62 -#define INT_GPS2 63 - -#endif /* ASM_ARCH_TCC_IRQS_H */ diff --git a/arch/arm/plat-tcc/include/mach/system.h b/arch/arm/plat-tcc/include/mach/system.h deleted file mode 100644 index 909e6035d843..000000000000 --- a/arch/arm/plat-tcc/include/mach/system.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Author: - * Created: June 10, 2008 - * Description: LINUX SYSTEM FUNCTIONS for TCC83x - * - * Copyright (C) 2008-2009 Telechips - * - * Licensed under the terms of the GPL v2. - * - */ - -#ifndef __ASM_ARCH_SYSTEM_H -#define __ASM_ARCH_SYSTEM_H -#include - -#include -#include - -extern void plat_tcc_reboot(void); - -static inline void arch_idle(void) -{ - cpu_do_idle(); -} - -static inline void arch_reset(char mode, const char *cmd) -{ - plat_tcc_reboot(); -} - -#endif diff --git a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h deleted file mode 100644 index 1d9428295332..000000000000 --- a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h +++ /dev/null @@ -1,807 +0,0 @@ -/* - * Telechips TCC8000 register definitions - * - * (C) 2009 Hans J. Koch - * - * Licensed under the terms of the GPLv2. - */ - -#ifndef TCC8K_REGS_H -#define TCC8K_REGS_H - -#include - -#define EXT_SDRAM_BASE 0x20000000 -#define INT_SRAM_BASE 0x30000000 -#define INT_SRAM_SIZE SZ_32K -#define CS0_BASE 0x40000000 -#define CS1_BASE 0x50000000 -#define CS1_SIZE SZ_64K -#define CS2_BASE 0x60000000 -#define CS3_BASE 0x70000000 -#define AHB_PERI_BASE 0x80000000 -#define AHB_PERI_SIZE SZ_64K -#define APB0_PERI_BASE 0x90000000 -#define APB0_PERI_SIZE SZ_128K -#define APB1_PERI_BASE 0x98000000 -#define APB1_PERI_SIZE SZ_128K -#define DATA_TCM_BASE 0xa0000000 -#define DATA_TCM_SIZE SZ_8K -#define EXT_MEM_CTRL_BASE 0xf0000000 -#define EXT_MEM_CTRL_SIZE SZ_4K - -#define CS1_BASE_VIRT (void __iomem *)0xf7000000 -#define AHB_PERI_BASE_VIRT (void __iomem *)0xf4000000 -#define APB0_PERI_BASE_VIRT (void __iomem *)0xf1000000 -#define APB1_PERI_BASE_VIRT (void __iomem *)0xf2000000 -#define EXT_MEM_CTRL_BASE_VIRT (void __iomem *)0xf3000000 -#define INT_SRAM_BASE_VIRT (void __iomem *)0xf5000000 -#define DATA_TCM_BASE_VIRT (void __iomem *)0xf6000000 - -#define __REG(x) (*((volatile u32 *)(x))) - -/* USB Device Controller Registers */ -#define UDC_BASE (AHB_PERI_BASE_VIRT + 0x8000) -#define UDC_BASE_PHYS (AHB_PERI_BASE + 0x8000) - -#define UDC_IR_OFFS 0x00 -#define UDC_EIR_OFFS 0x04 -#define UDC_EIER_OFFS 0x08 -#define UDC_FAR_OFFS 0x0c -#define UDC_FNR_OFFS 0x10 -#define UDC_EDR_OFFS 0x14 -#define UDC_RT_OFFS 0x18 -#define UDC_SSR_OFFS 0x1c -#define UDC_SCR_OFFS 0x20 -#define UDC_EP0SR_OFFS 0x24 -#define UDC_EP0CR_OFFS 0x28 - -#define UDC_ESR_OFFS 0x2c -#define UDC_ECR_OFFS 0x30 -#define UDC_BRCR_OFFS 0x34 -#define UDC_BWCR_OFFS 0x38 -#define UDC_MPR_OFFS 0x3c -#define UDC_DCR_OFFS 0x40 -#define UDC_DTCR_OFFS 0x44 -#define UDC_DFCR_OFFS 0x48 -#define UDC_DTTCR1_OFFS 0x4c -#define UDC_DTTCR2_OFFS 0x50 -#define UDC_ESR2_OFFS 0x54 - -#define UDC_SCR2_OFFS 0x58 -#define UDC_EP0BUF_OFFS 0x60 -#define UDC_EP1BUF_OFFS 0x64 -#define UDC_EP2BUF_OFFS 0x68 -#define UDC_EP3BUF_OFFS 0x6c -#define UDC_PLICR_OFFS 0xa0 -#define UDC_PCR_OFFS 0xa4 - -#define UDC_UPCR0_OFFS 0xc8 -#define UDC_UPCR1_OFFS 0xcc -#define UDC_UPCR2_OFFS 0xd0 -#define UDC_UPCR3_OFFS 0xd4 - -/* Bits in UDC_EIR */ -#define UDC_EIR_EP0I (1 << 0) -#define UDC_EIR_EP1I (1 << 1) -#define UDC_EIR_EP2I (1 << 2) -#define UDC_EIR_EP3I (1 << 3) -#define UDC_EIR_EPI_MASK 0x0f - -/* Bits in UDC_EIER */ -#define UDC_EIER_EP0IE (1 << 0) -#define UDC_EIER_EP1IE (1 << 1) -#define UDC_EIER_EP2IE (1 << 2) -#define UDC_EIER_EP3IE (1 << 3) - -/* Bits in UDC_FNR */ -#define UDC_FNR_FN_MASK 0x7ff -#define UDC_FNR_SM (1 << 13) -#define UDC_FNR_FTL (1 << 14) - -/* Bits in UDC_SSR */ -#define UDC_SSR_HFRES (1 << 0) -#define UDC_SSR_HFSUSP (1 << 1) -#define UDC_SSR_HFRM (1 << 2) -#define UDC_SSR_SDE (1 << 3) -#define UDC_SSR_HSP (1 << 4) -#define UDC_SSR_DM (1 << 5) -#define UDC_SSR_DP (1 << 6) -#define UDC_SSR_TBM (1 << 7) -#define UDC_SSR_VBON (1 << 8) -#define UDC_SSR_VBOFF (1 << 9) -#define UDC_SSR_EOERR (1 << 10) -#define UDC_SSR_DCERR (1 << 11) -#define UDC_SSR_TCERR (1 << 12) -#define UDC_SSR_BSERR (1 << 13) -#define UDC_SSR_TMERR (1 << 14) -#define UDC_SSR_BAERR (1 << 15) - -/* Bits in UDC_SCR */ -#define UDC_SCR_HRESE (1 << 0) -#define UDC_SCR_HSSPE (1 << 1) -#define UDC_SCR_RRDE (1 << 5) -#define UDC_SCR_SPDEN (1 << 6) -#define UDC_SCR_DIEN (1 << 12) - -/* Bits in UDC_EP0SR */ -#define UDC_EP0SR_RSR (1 << 0) -#define UDC_EP0SR_TST (1 << 1) -#define UDC_EP0SR_SHT (1 << 4) -#define UDC_EP0SR_LWO (1 << 6) - -/* Bits in UDC_EP0CR */ -#define UDC_EP0CR_ESS (1 << 1) - -/* Bits in UDC_ESR */ -#define UDC_ESR_RPS (1 << 0) -#define UDC_ESR_TPS (1 << 1) -#define UDC_ESR_LWO (1 << 4) -#define UDC_ESR_FFS (1 << 6) - -/* Bits in UDC_ECR */ -#define UDC_ECR_ESS (1 << 1) -#define UDC_ECR_CDP (1 << 2) - -#define UDC_ECR_FLUSH (1 << 6) -#define UDC_ECR_DUEN (1 << 7) - -/* Bits in UDC_UPCR0 */ -#define UDC_UPCR0_VBD (1 << 1) -#define UDC_UPCR0_VBDS (1 << 6) -#define UDC_UPCR0_RCD_12 (0x0 << 9) -#define UDC_UPCR0_RCD_24 (0x1 << 9) -#define UDC_UPCR0_RCD_48 (0x2 << 9) -#define UDC_UPCR0_RCS_EXT (0x1 << 11) -#define UDC_UPCR0_RCS_XTAL (0x0 << 11) - -/* Bits in UDC_UPCR1 */ -#define UDC_UPCR1_CDT(x) ((x) << 0) -#define UDC_UPCR1_OTGT(x) ((x) << 3) -#define UDC_UPCR1_SQRXT(x) ((x) << 8) -#define UDC_UPCR1_TXFSLST(x) ((x) << 12) - -/* Bits in UDC_UPCR2 */ -#define UDC_UPCR2_TP (1 << 0) -#define UDC_UPCR2_TXRT(x) ((x) << 2) -#define UDC_UPCR2_TXVRT(x) ((x) << 5) -#define UDC_UPCR2_OPMODE(x) ((x) << 9) -#define UDC_UPCR2_XCVRSEL(x) ((x) << 12) -#define UDC_UPCR2_TM (1 << 14) - -/* USB Host Controller registers */ -#define USBH0_BASE (AHB_PERI_BASE_VIRT + 0xb000) -#define USBH1_BASE (AHB_PERI_BASE_VIRT + 0xb800) - -#define OHCI_INT_ENABLE_OFFS 0x10 - -#define RH_DESCRIPTOR_A_OFFS 0x48 -#define RH_DESCRIPTOR_B_OFFS 0x4c - -#define USBHTCFG0_OFFS 0x100 -#define USBHHCFG0_OFFS 0x104 -#define USBHHCFG1_OFFS 0x104 - -/* DMA controller registers */ -#define DMAC0_BASE (AHB_PERI_BASE + 0x4000) -#define DMAC1_BASE (AHB_PERI_BASE + 0xa000) -#define DMAC2_BASE (AHB_PERI_BASE + 0x4800) -#define DMAC3_BASE (AHB_PERI_BASE + 0xa800) - -#define DMAC_CH_OFFSET(ch) (ch * 0x30) - -#define ST_SADR_OFFS 0x00 -#define SPARAM_OFFS 0x04 -#define C_SADR_OFFS 0x0c -#define ST_DADR_OFFS 0x10 -#define DPARAM_OFFS 0x14 -#define C_DADR_OFFS 0x1c -#define HCOUNT_OFFS 0x20 -#define CHCTRL_OFFS 0x24 -#define RPTCTRL_OFFS 0x28 -#define EXTREQ_A_OFFS 0x2c - -/* Bits in CHCTRL register */ -#define CHCTRL_EN (1 << 0) - -#define CHCTRL_IEN (1 << 2) -#define CHCTRL_FLAG (1 << 3) -#define CHCTRL_WSIZE8 (0 << 4) -#define CHCTRL_WSIZE16 (1 << 4) -#define CHCTRL_WSIZE32 (2 << 4) - -#define CHCTRL_BSIZE1 (0 << 6) -#define CHCTRL_BSIZE2 (1 << 6) -#define CHCTRL_BSIZE4 (2 << 6) -#define CHCTRL_BSIZE8 (3 << 6) - -#define CHCTRL_TYPE_SINGLE_E (0 << 8) -#define CHCTRL_TYPE_HW (1 << 8) -#define CHCTRL_TYPE_SW (2 << 8) -#define CHCTRL_TYPE_SINGLE_L (3 << 8) - -#define CHCTRL_BST (1 << 10) - -/* Use DMA controller 0, channel 2 for USB */ -#define USB_DMA_BASE (DMAC0_BASE + DMAC_CH_OFFSET(2)) - -/* NAND flash controller registers */ -#define NFC_BASE (AHB_PERI_BASE_VIRT + 0xd000) -#define NFC_BASE_PHYS (AHB_PERI_BASE + 0xd000) - -#define NFC_CMD_OFFS 0x00 -#define NFC_LADDR_OFFS 0x04 -#define NFC_BADDR_OFFS 0x08 -#define NFC_SADDR_OFFS 0x0c -#define NFC_WDATA_OFFS 0x10 -#define NFC_LDATA_OFFS 0x20 -#define NFC_SDATA_OFFS 0x40 -#define NFC_CTRL_OFFS 0x50 -#define NFC_PSTART_OFFS 0x54 -#define NFC_RSTART_OFFS 0x58 -#define NFC_DSIZE_OFFS 0x5c -#define NFC_IREQ_OFFS 0x60 -#define NFC_RST_OFFS 0x64 -#define NFC_CTRL1_OFFS 0x68 -#define NFC_MDATA_OFFS 0x70 - -#define NFC_WDATA_PHYS_ADDR (NFC_BASE_PHYS + NFC_WDATA_OFFS) - -/* Bits in NFC_CTRL */ -#define NFC_CTRL_BHLD_MASK (0xf << 0) -#define NFC_CTRL_BPW_MASK (0xf << 4) -#define NFC_CTRL_BSTP_MASK (0xf << 8) -#define NFC_CTRL_CADDR_MASK (0x7 << 12) -#define NFC_CTRL_CADDR_1 (0x0 << 12) -#define NFC_CTRL_CADDR_2 (0x1 << 12) -#define NFC_CTRL_CADDR_3 (0x2 << 12) -#define NFC_CTRL_CADDR_4 (0x3 << 12) -#define NFC_CTRL_CADDR_5 (0x4 << 12) -#define NFC_CTRL_MSK (1 << 15) -#define NFC_CTRL_PSIZE256 (0 << 16) -#define NFC_CTRL_PSIZE512 (1 << 16) -#define NFC_CTRL_PSIZE1024 (2 << 16) -#define NFC_CTRL_PSIZE2048 (3 << 16) -#define NFC_CTRL_PSIZE4096 (4 << 16) -#define NFC_CTRL_PSIZE_MASK (7 << 16) -#define NFC_CTRL_BSIZE1 (0 << 19) -#define NFC_CTRL_BSIZE2 (1 << 19) -#define NFC_CTRL_BSIZE4 (2 << 19) -#define NFC_CTRL_BSIZE8 (3 << 19) -#define NFC_CTRL_BSIZE_MASK (3 << 19) -#define NFC_CTRL_RDY (1 << 21) -#define NFC_CTRL_CS0SEL (1 << 22) -#define NFC_CTRL_CS1SEL (1 << 23) -#define NFC_CTRL_CS2SEL (1 << 24) -#define NFC_CTRL_CS3SEL (1 << 25) -#define NFC_CTRL_CSMASK (0xf << 22) -#define NFC_CTRL_BW (1 << 26) -#define NFC_CTRL_FS (1 << 27) -#define NFC_CTRL_DEN (1 << 28) -#define NFC_CTRL_READ_IEN (1 << 29) -#define NFC_CTRL_PROG_IEN (1 << 30) -#define NFC_CTRL_RDY_IEN (1 << 31) - -/* Bits in NFC_IREQ */ -#define NFC_IREQ_IRQ0 (1 << 0) -#define NFC_IREQ_IRQ1 (1 << 1) -#define NFC_IREQ_IRQ2 (1 << 2) - -#define NFC_IREQ_FLAG0 (1 << 4) -#define NFC_IREQ_FLAG1 (1 << 5) -#define NFC_IREQ_FLAG2 (1 << 6) - -/* MMC controller registers */ -#define MMC0_BASE (AHB_PERI_BASE_VIRT + 0xe000) -#define MMC1_BASE (AHB_PERI_BASE_VIRT + 0xe800) - -/* UART base addresses */ - -#define UART0_BASE (APB0_PERI_BASE_VIRT + 0x07000) -#define UART0_BASE_PHYS (APB0_PERI_BASE + 0x07000) -#define UART1_BASE (APB0_PERI_BASE_VIRT + 0x08000) -#define UART1_BASE_PHYS (APB0_PERI_BASE + 0x08000) -#define UART2_BASE (APB0_PERI_BASE_VIRT + 0x09000) -#define UART2_BASE_PHYS (APB0_PERI_BASE + 0x09000) -#define UART3_BASE (APB0_PERI_BASE_VIRT + 0x0a000) -#define UART3_BASE_PHYS (APB0_PERI_BASE + 0x0a000) -#define UART4_BASE (APB0_PERI_BASE_VIRT + 0x15000) -#define UART4_BASE_PHYS (APB0_PERI_BASE + 0x15000) - -#define UART_BASE UART0_BASE -#define UART_BASE_PHYS UART0_BASE_PHYS - -/* ECC controller */ -#define ECC_CTR_BASE (APB0_PERI_BASE_VIRT + 0xd000) - -#define ECC_CTRL_OFFS 0x00 -#define ECC_BASE_OFFS 0x04 -#define ECC_MASK_OFFS 0x08 -#define ECC_CLEAR_OFFS 0x0c -#define ECC4_0_OFFS 0x10 -#define ECC4_1_OFFS 0x14 - -#define ECC_EADDR0_OFFS 0x50 - -#define ECC_ERRNUM_OFFS 0x90 -#define ECC_IREQ_OFFS 0x94 - -/* Bits in ECC_CTRL */ -#define ECC_CTRL_ECC4_DIEN (1 << 28) -#define ECC_CTRL_ECC8_DIEN (1 << 29) -#define ECC_CTRL_ECC12_DIEN (1 << 30) -#define ECC_CTRL_ECC_DISABLE 0x0 -#define ECC_CTRL_ECC_SLC_ENC 0x8 -#define ECC_CTRL_ECC_SLC_DEC 0x9 -#define ECC_CTRL_ECC4_ENC 0xa -#define ECC_CTRL_ECC4_DEC 0xb -#define ECC_CTRL_ECC8_ENC 0xc -#define ECC_CTRL_ECC8_DEC 0xd -#define ECC_CTRL_ECC12_ENC 0xe -#define ECC_CTRL_ECC12_DEC 0xf - -/* Bits in ECC_IREQ */ -#define ECC_IREQ_E4DI (1 << 4) - -#define ECC_IREQ_E4DF (1 << 20) -#define ECC_IREQ_E4EF (1 << 21) - -/* Interrupt controller */ - -#define PIC0_BASE (APB1_PERI_BASE_VIRT + 0x3000) -#define PIC0_BASE_PHYS (APB1_PERI_BASE + 0x3000) - -#define PIC0_IEN_OFFS 0x00 -#define PIC0_CREQ_OFFS 0x04 -#define PIC0_IREQ_OFFS 0x08 -#define PIC0_IRQSEL_OFFS 0x0c -#define PIC0_SRC_OFFS 0x10 -#define PIC0_MREQ_OFFS 0x14 -#define PIC0_TSTREQ_OFFS 0x18 -#define PIC0_POL_OFFS 0x1c -#define PIC0_IRQ_OFFS 0x20 -#define PIC0_FIQ_OFFS 0x24 -#define PIC0_MIRQ_OFFS 0x28 -#define PIC0_MFIQ_OFFS 0x2c -#define PIC0_TMODE_OFFS 0x30 -#define PIC0_SYNC_OFFS 0x34 -#define PIC0_WKUP_OFFS 0x38 -#define PIC0_TMODEA_OFFS 0x3c -#define PIC0_INTOEN_OFFS 0x40 -#define PIC0_MEN0_OFFS 0x44 -#define PIC0_MEN_OFFS 0x48 - -#define PIC0_IEN __REG(PIC0_BASE + PIC0_IEN_OFFS) -#define PIC0_IEN_PHYS __REG(PIC0_BASE_PHYS + PIC0_IEN_OFFS) -#define PIC0_CREQ __REG(PIC0_BASE + PIC0_CREQ_OFFS) -#define PIC0_CREQ_PHYS __REG(PIC0_BASE_PHYS + PIC0_CREQ_OFFS) -#define PIC0_IREQ __REG(PIC0_BASE + PIC0_IREQ_OFFS) -#define PIC0_IRQSEL __REG(PIC0_BASE + PIC0_IRQSEL_OFFS) -#define PIC0_IRQSEL_PHYS __REG(PIC0_BASE_PHYS + PIC0_IRQSEL_OFFS) -#define PIC0_SRC __REG(PIC0_BASE + PIC0_SRC_OFFS) -#define PIC0_MREQ __REG(PIC0_BASE + PIC0_MREQ_OFFS) -#define PIC0_TSTREQ __REG(PIC0_BASE + PIC0_TSTREQ_OFFS) -#define PIC0_POL __REG(PIC0_BASE + PIC0_POL_OFFS) -#define PIC0_IRQ __REG(PIC0_BASE + PIC0_IRQ_OFFS) -#define PIC0_FIQ __REG(PIC0_BASE + PIC0_FIQ_OFFS) -#define PIC0_MIRQ __REG(PIC0_BASE + PIC0_MIRQ_OFFS) -#define PIC0_MFIQ __REG(PIC0_BASE + PIC0_MFIQ_OFFS) -#define PIC0_TMODE __REG(PIC0_BASE + PIC0_TMODE_OFFS) -#define PIC0_TMODE_PHYS __REG(PIC0_BASE_PHYS + PIC0_TMODE_OFFS) -#define PIC0_SYNC __REG(PIC0_BASE + PIC0_SYNC_OFFS) -#define PIC0_WKUP __REG(PIC0_BASE + PIC0_WKUP_OFFS) -#define PIC0_TMODEA __REG(PIC0_BASE + PIC0_TMODEA_OFFS) -#define PIC0_INTOEN __REG(PIC0_BASE + PIC0_INTOEN_OFFS) -#define PIC0_MEN0 __REG(PIC0_BASE + PIC0_MEN0_OFFS) -#define PIC0_MEN __REG(PIC0_BASE + PIC0_MEN_OFFS) - -#define PIC1_BASE (APB1_PERI_BASE_VIRT + 0x3080) - -#define PIC1_IEN_OFFS 0x00 -#define PIC1_CREQ_OFFS 0x04 -#define PIC1_IREQ_OFFS 0x08 -#define PIC1_IRQSEL_OFFS 0x0c -#define PIC1_SRC_OFFS 0x10 -#define PIC1_MREQ_OFFS 0x14 -#define PIC1_TSTREQ_OFFS 0x18 -#define PIC1_POL_OFFS 0x1c -#define PIC1_IRQ_OFFS 0x20 -#define PIC1_FIQ_OFFS 0x24 -#define PIC1_MIRQ_OFFS 0x28 -#define PIC1_MFIQ_OFFS 0x2c -#define PIC1_TMODE_OFFS 0x30 -#define PIC1_SYNC_OFFS 0x34 -#define PIC1_WKUP_OFFS 0x38 -#define PIC1_TMODEA_OFFS 0x3c -#define PIC1_INTOEN_OFFS 0x40 -#define PIC1_MEN1_OFFS 0x44 -#define PIC1_MEN_OFFS 0x48 - -#define PIC1_IEN __REG(PIC1_BASE + PIC1_IEN_OFFS) -#define PIC1_CREQ __REG(PIC1_BASE + PIC1_CREQ_OFFS) -#define PIC1_IREQ __REG(PIC1_BASE + PIC1_IREQ_OFFS) -#define PIC1_IRQSEL __REG(PIC1_BASE + PIC1_IRQSEL_OFFS) -#define PIC1_SRC __REG(PIC1_BASE + PIC1_SRC_OFFS) -#define PIC1_MREQ __REG(PIC1_BASE + PIC1_MREQ_OFFS) -#define PIC1_TSTREQ __REG(PIC1_BASE + PIC1_TSTREQ_OFFS) -#define PIC1_POL __REG(PIC1_BASE + PIC1_POL_OFFS) -#define PIC1_IRQ __REG(PIC1_BASE + PIC1_IRQ_OFFS) -#define PIC1_FIQ __REG(PIC1_BASE + PIC1_FIQ_OFFS) -#define PIC1_MIRQ __REG(PIC1_BASE + PIC1_MIRQ_OFFS) -#define PIC1_MFIQ __REG(PIC1_BASE + PIC1_MFIQ_OFFS) -#define PIC1_TMODE __REG(PIC1_BASE + PIC1_TMODE_OFFS) -#define PIC1_SYNC __REG(PIC1_BASE + PIC1_SYNC_OFFS) -#define PIC1_WKUP __REG(PIC1_BASE + PIC1_WKUP_OFFS) -#define PIC1_TMODEA __REG(PIC1_BASE + PIC1_TMODEA_OFFS) -#define PIC1_INTOEN __REG(PIC1_BASE + PIC1_INTOEN_OFFS) -#define PIC1_MEN1 __REG(PIC1_BASE + PIC1_MEN1_OFFS) -#define PIC1_MEN __REG(PIC1_BASE + PIC1_MEN_OFFS) - -/* Timer registers */ -#define TIMER_BASE (APB1_PERI_BASE_VIRT + 0x4000) -#define TIMER_BASE_PHYS (APB1_PERI_BASE + 0x4000) - -#define TWDCFG_OFFS 0x70 - -#define TC32EN_OFFS 0x80 -#define TC32LDV_OFFS 0x84 -#define TC32CMP0_OFFS 0x88 -#define TC32CMP1_OFFS 0x8c -#define TC32PCNT_OFFS 0x90 -#define TC32MCNT_OFFS 0x94 -#define TC32IRQ_OFFS 0x98 - -/* Bits in TC32EN */ -#define TC32EN_PRESCALE_MASK 0x00ffffff -#define TC32EN_ENABLE (1 << 24) -#define TC32EN_LOADZERO (1 << 25) -#define TC32EN_STOPMODE (1 << 26) -#define TC32EN_LDM0 (1 << 28) -#define TC32EN_LDM1 (1 << 29) - -/* Bits in TC32IRQ */ -#define TC32IRQ_MSTAT_MASK 0x0000001f -#define TC32IRQ_RSTAT_MASK (0x1f << 8) -#define TC32IRQ_IRQEN0 (1 << 16) -#define TC32IRQ_IRQEN1 (1 << 17) -#define TC32IRQ_IRQEN2 (1 << 18) -#define TC32IRQ_IRQEN3 (1 << 19) -#define TC32IRQ_IRQEN4 (1 << 20) -#define TC32IRQ_RSYNC (1 << 30) -#define TC32IRQ_IRQCLR (1 << 31) - -/* GPIO registers */ -#define GPIOPD_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOPD_DAT_OFFS 0x00 -#define GPIOPD_DOE_OFFS 0x04 -#define GPIOPD_FS0_OFFS 0x08 -#define GPIOPD_FS1_OFFS 0x0c -#define GPIOPD_FS2_OFFS 0x10 -#define GPIOPD_RPU_OFFS 0x30 -#define GPIOPD_RPD_OFFS 0x34 -#define GPIOPD_DV0_OFFS 0x38 -#define GPIOPD_DV1_OFFS 0x3c - -#define GPIOPS_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOPS_DAT_OFFS 0x40 -#define GPIOPS_DOE_OFFS 0x44 -#define GPIOPS_FS0_OFFS 0x48 -#define GPIOPS_FS1_OFFS 0x4c -#define GPIOPS_FS2_OFFS 0x50 -#define GPIOPS_FS3_OFFS 0x54 -#define GPIOPS_RPU_OFFS 0x70 -#define GPIOPS_RPD_OFFS 0x74 -#define GPIOPS_DV0_OFFS 0x78 -#define GPIOPS_DV1_OFFS 0x7c - -#define GPIOPS_FS1_SDH0_BITS 0x000000ff -#define GPIOPS_FS1_SDH1_BITS 0x0000ff00 - -#define GPIOPU_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOPU_DAT_OFFS 0x80 -#define GPIOPU_DOE_OFFS 0x84 -#define GPIOPU_FS0_OFFS 0x88 -#define GPIOPU_FS1_OFFS 0x8c -#define GPIOPU_FS2_OFFS 0x90 -#define GPIOPU_RPU_OFFS 0xb0 -#define GPIOPU_RPD_OFFS 0xb4 -#define GPIOPU_DV0_OFFS 0xb8 -#define GPIOPU_DV1_OFFS 0xbc - -#define GPIOPU_FS0_TXD0 (1 << 0) -#define GPIOPU_FS0_RXD0 (1 << 1) -#define GPIOPU_FS0_CTS0 (1 << 2) -#define GPIOPU_FS0_RTS0 (1 << 3) -#define GPIOPU_FS0_TXD1 (1 << 4) -#define GPIOPU_FS0_RXD1 (1 << 5) -#define GPIOPU_FS0_CTS1 (1 << 6) -#define GPIOPU_FS0_RTS1 (1 << 7) -#define GPIOPU_FS0_TXD2 (1 << 8) -#define GPIOPU_FS0_RXD2 (1 << 9) -#define GPIOPU_FS0_CTS2 (1 << 10) -#define GPIOPU_FS0_RTS2 (1 << 11) -#define GPIOPU_FS0_TXD3 (1 << 12) -#define GPIOPU_FS0_RXD3 (1 << 13) -#define GPIOPU_FS0_CTS3 (1 << 14) -#define GPIOPU_FS0_RTS3 (1 << 15) -#define GPIOPU_FS0_TXD4 (1 << 16) -#define GPIOPU_FS0_RXD4 (1 << 17) -#define GPIOPU_FS0_CTS4 (1 << 18) -#define GPIOPU_FS0_RTS4 (1 << 19) - -#define GPIOFC_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOFC_DAT_OFFS 0xc0 -#define GPIOFC_DOE_OFFS 0xc4 -#define GPIOFC_FS0_OFFS 0xc8 -#define GPIOFC_FS1_OFFS 0xcc -#define GPIOFC_FS2_OFFS 0xd0 -#define GPIOFC_FS3_OFFS 0xd4 -#define GPIOFC_RPU_OFFS 0xf0 -#define GPIOFC_RPD_OFFS 0xf4 -#define GPIOFC_DV0_OFFS 0xf8 -#define GPIOFC_DV1_OFFS 0xfc - -#define GPIOFD_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOFD_DAT_OFFS 0x100 -#define GPIOFD_DOE_OFFS 0x104 -#define GPIOFD_FS0_OFFS 0x108 -#define GPIOFD_FS1_OFFS 0x10c -#define GPIOFD_FS2_OFFS 0x110 -#define GPIOFD_RPU_OFFS 0x130 -#define GPIOFD_RPD_OFFS 0x134 -#define GPIOFD_DV0_OFFS 0x138 -#define GPIOFD_DV1_OFFS 0x13c - -#define GPIOLC_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOLC_DAT_OFFS 0x140 -#define GPIOLC_DOE_OFFS 0x144 -#define GPIOLC_FS0_OFFS 0x148 -#define GPIOLC_FS1_OFFS 0x14c -#define GPIOLC_RPU_OFFS 0x170 -#define GPIOLC_RPD_OFFS 0x174 -#define GPIOLC_DV0_OFFS 0x178 -#define GPIOLC_DV1_OFFS 0x17c - -#define GPIOLD_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOLD_DAT_OFFS 0x180 -#define GPIOLD_DOE_OFFS 0x184 -#define GPIOLD_FS0_OFFS 0x188 -#define GPIOLD_FS1_OFFS 0x18c -#define GPIOLD_FS2_OFFS 0x190 -#define GPIOLD_RPU_OFFS 0x1b0 -#define GPIOLD_RPD_OFFS 0x1b4 -#define GPIOLD_DV0_OFFS 0x1b8 -#define GPIOLD_DV1_OFFS 0x1bc - -#define GPIOAD_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOAD_DAT_OFFS 0x1c0 -#define GPIOAD_DOE_OFFS 0x1c4 -#define GPIOAD_FS0_OFFS 0x1c8 -#define GPIOAD_RPU_OFFS 0x1f0 -#define GPIOAD_RPD_OFFS 0x1f4 -#define GPIOAD_DV0_OFFS 0x1f8 -#define GPIOAD_DV1_OFFS 0x1fc - -#define GPIOXC_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOXC_DAT_OFFS 0x200 -#define GPIOXC_DOE_OFFS 0x204 -#define GPIOXC_FS0_OFFS 0x208 -#define GPIOXC_RPU_OFFS 0x230 -#define GPIOXC_RPD_OFFS 0x234 -#define GPIOXC_DV0_OFFS 0x238 -#define GPIOXC_DV1_OFFS 0x23c - -#define GPIOXC_FS0 __REG(GPIOXC_BASE + GPIOXC_FS0_OFFS) - -#define GPIOXC_FS0_CS0 (1 << 26) -#define GPIOXC_FS0_CS1 (1 << 27) - -#define GPIOXD_BASE (APB1_PERI_BASE_VIRT + 0x5000) - -#define GPIOXD_DAT_OFFS 0x240 -#define GPIOXD_FS0_OFFS 0x248 -#define GPIOXD_RPU_OFFS 0x270 -#define GPIOXD_RPD_OFFS 0x274 -#define GPIOXD_DV0_OFFS 0x278 -#define GPIOXD_DV1_OFFS 0x27c - -#define GPIOPK_BASE (APB1_PERI_BASE_VIRT + 0x1c000) - -#define GPIOPK_RST_OFFS 0x008 -#define GPIOPK_DAT_OFFS 0x100 -#define GPIOPK_DOE_OFFS 0x104 -#define GPIOPK_FS0_OFFS 0x108 -#define GPIOPK_FS1_OFFS 0x10c -#define GPIOPK_FS2_OFFS 0x110 -#define GPIOPK_IRQST_OFFS 0x210 -#define GPIOPK_IRQEN_OFFS 0x214 -#define GPIOPK_IRQPOL_OFFS 0x218 -#define GPIOPK_IRQTM0_OFFS 0x21c -#define GPIOPK_IRQTM1_OFFS 0x220 -#define GPIOPK_CTL_OFFS 0x22c - -#define PMGPIO_BASE (APB1_PERI_BASE_VIRT + 0x10000) -#define BACKUP_RAM_BASE PMGPIO_BASE - -#define PMGPIO_DAT_OFFS 0x800 -#define PMGPIO_DOE_OFFS 0x804 -#define PMGPIO_FS0_OFFS 0x808 -#define PMGPIO_RPU_OFFS 0x810 -#define PMGPIO_RPD_OFFS 0x814 -#define PMGPIO_DV0_OFFS 0x818 -#define PMGPIO_DV1_OFFS 0x81c -#define PMGPIO_EE0_OFFS 0x820 -#define PMGPIO_EE1_OFFS 0x824 -#define PMGPIO_CTL_OFFS 0x828 -#define PMGPIO_DI_OFFS 0x82c -#define PMGPIO_STR_OFFS 0x830 -#define PMGPIO_STF_OFFS 0x834 -#define PMGPIO_POL_OFFS 0x838 -#define PMGPIO_APB_OFFS 0x800 - -/* Clock controller registers */ -#define CKC_BASE ((void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000)) - -#define CLKCTRL_OFFS 0x00 -#define PLL0CFG_OFFS 0x04 -#define PLL1CFG_OFFS 0x08 -#define CLKDIVC0_OFFS 0x0c - -#define BCLKCTR0_OFFS 0x14 -#define SWRESET0_OFFS 0x18 - -#define BCLKCTR1_OFFS 0x60 -#define SWRESET1_OFFS 0x64 -#define PWDCTL_OFFS 0x68 -#define PLL2CFG_OFFS 0x6c -#define CLKDIVC1_OFFS 0x70 - -#define ACLKREF_OFFS 0x80 -#define ACLKI2C_OFFS 0x84 -#define ACLKSPI0_OFFS 0x88 -#define ACLKSPI1_OFFS 0x8c -#define ACLKUART0_OFFS 0x90 -#define ACLKUART1_OFFS 0x94 -#define ACLKUART2_OFFS 0x98 -#define ACLKUART3_OFFS 0x9c -#define ACLKUART4_OFFS 0xa0 -#define ACLKTCT_OFFS 0xa4 -#define ACLKTCX_OFFS 0xa8 -#define ACLKTCZ_OFFS 0xac -#define ACLKADC_OFFS 0xb0 -#define ACLKDAI0_OFFS 0xb4 -#define ACLKDAI1_OFFS 0xb8 -#define ACLKLCD_OFFS 0xbc -#define ACLKSPDIF_OFFS 0xc0 -#define ACLKUSBH_OFFS 0xc4 -#define ACLKSDH0_OFFS 0xc8 -#define ACLKSDH1_OFFS 0xcc -#define ACLKC3DEC_OFFS 0xd0 -#define ACLKEXT_OFFS 0xd4 -#define ACLKCAN0_OFFS 0xd8 -#define ACLKCAN1_OFFS 0xdc -#define ACLKGSB0_OFFS 0xe0 -#define ACLKGSB1_OFFS 0xe4 -#define ACLKGSB2_OFFS 0xe8 -#define ACLKGSB3_OFFS 0xec - -#define PLLxCFG_PD (1 << 31) - -/* CLKCTRL bits */ -#define CLKCTRL_XE (1 << 31) - -/* CLKDIVCx bits */ -#define CLKDIVC0_XTE (1 << 7) -#define CLKDIVC0_XE (1 << 15) -#define CLKDIVC0_P1E (1 << 23) -#define CLKDIVC0_P0E (1 << 31) - -#define CLKDIVC1_P2E (1 << 7) - -/* BCLKCTR0 clock bits */ -#define BCLKCTR0_USBD (1 << 4) -#define BCLKCTR0_ECC (1 << 9) -#define BCLKCTR0_USBH0 (1 << 11) -#define BCLKCTR0_NFC (1 << 16) - -/* BCLKCTR1 clock bits */ -#define BCLKCTR1_USBH1 (1 << 20) - -/* SWRESET0 bits */ -#define SWRESET0_USBD (1 << 4) -#define SWRESET0_USBH0 (1 << 11) - -/* SWRESET1 bits */ -#define SWRESET1_USBH1 (1 << 20) - -/* System clock sources. - * Note: These are the clock sources that serve as parents for - * all other clocks. They have no parents themselves. - * - * These values are used for struct clk->root_id. All clocks - * that are not system clock sources have this value set to - * CLK_SRC_NOROOT. - * The values for system clocks start with CLK_SRC_PLL0 == 0 - * because this gives us exactly the values needed for the lower - * 4 bits of ACLK_* registers. Therefore, CLK_SRC_NOROOT is - * defined as -1 to not disturb the order. - */ -enum root_clks { - CLK_SRC_NOROOT = -1, - CLK_SRC_PLL0 = 0, - CLK_SRC_PLL1, - CLK_SRC_PLL0DIV, - CLK_SRC_PLL1DIV, - CLK_SRC_XI, - CLK_SRC_XIDIV, - CLK_SRC_XTI, - CLK_SRC_XTIDIV, - CLK_SRC_PLL2, - CLK_SRC_PLL2DIV, - CLK_SRC_PK0, - CLK_SRC_PK1, - CLK_SRC_PK2, - CLK_SRC_PK3, - CLK_SRC_PK4, - CLK_SRC_48MHZ -}; - -#define CLK_SRC_MASK 0xf - -/* Bits in ACLK* registers */ -#define ACLK_EN (1 << 28) -#define ACLK_SEL_SHIFT 24 -#define ACLK_SEL_MASK 0x0f000000 -#define ACLK_DIV_MASK 0x00000fff - -/* System configuration registers */ - -#define SCFG_BASE (APB1_PERI_BASE_VIRT + 0x13000) - -#define BMI_OFFS 0x00 -#define AHBCON0_OFFS 0x04 -#define APBPWE_OFFS 0x08 -#define DTCMWAIT_OFFS 0x0c -#define ECCSEL_OFFS 0x10 -#define AHBCON1_OFFS 0x14 -#define SDHCFG_OFFS 0x18 -#define REMAP_OFFS 0x20 -#define LCDSIAE_OFFS 0x24 -#define XMCCFG_OFFS 0xe0 -#define IMCCFG_OFFS 0xe4 - -/* Values for ECCSEL */ -#define ECCSEL_EXTMEM 0x0 -#define ECCSEL_DTCM 0x1 -#define ECCSEL_INT_SRAM 0x2 -#define ECCSEL_AHB 0x3 - -/* Bits in XMCCFG */ -#define XMCCFG_NFCE (1 << 1) -#define XMCCFG_FDXD (1 << 2) - -/* External memory controller registers */ - -#define EMC_BASE EXT_MEM_CTRL_BASE - -#define SDCFG_OFFS 0x00 -#define SDFSM_OFFS 0x04 -#define MCFG_OFFS 0x08 - -#define CSCFG0_OFFS 0x10 -#define CSCFG1_OFFS 0x14 -#define CSCFG2_OFFS 0x18 -#define CSCFG3_OFFS 0x1c - -#define MCFG_SDEN (1 << 4) - -#endif /* TCC8K_REGS_H */ diff --git a/arch/arm/plat-tcc/include/mach/timex.h b/arch/arm/plat-tcc/include/mach/timex.h deleted file mode 100644 index 057acbe651d9..000000000000 --- a/arch/arm/plat-tcc/include/mach/timex.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * A definition needed by arch core code. - * - */ -#define CLOCK_TICK_RATE (HZ * 100000UL) diff --git a/arch/arm/plat-tcc/include/mach/uncompress.h b/arch/arm/plat-tcc/include/mach/uncompress.h deleted file mode 100644 index 7a3e33a27a30..000000000000 --- a/arch/arm/plat-tcc/include/mach/uncompress.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2009 Hans J. Koch - * - * This file is licensed under the terms of the GPL version 2. - */ - -#include -#include - -#include - -unsigned int system_rev; - -#define ID_MASK 0x7fff - -static void putc(int c) -{ - u32 *uart_lsr = (u32 *)(UART_BASE_PHYS + (UART_LSR << 2)); - u32 *uart_tx = (u32 *)(UART_BASE_PHYS + (UART_TX << 2)); - - while (!(*uart_lsr & UART_LSR_THRE)) - barrier(); - *uart_tx = c; -} - -static inline void flush(void) -{ -} - -/* - * nothing to do - */ -#define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/plat-tcc/include/mach/vmalloc.h b/arch/arm/plat-tcc/include/mach/vmalloc.h deleted file mode 100644 index 99414d9c2b94..000000000000 --- a/arch/arm/plat-tcc/include/mach/vmalloc.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Author: - * Created: June 10, 2008 - * - * Copyright (C) 2000 Russell King. - * Copyright (C) 2008-2009 Telechips - * - * Licensed under the terms of the GPL v2. - */ -#define VMALLOC_END 0xf0000000UL diff --git a/arch/arm/plat-tcc/system.c b/arch/arm/plat-tcc/system.c deleted file mode 100644 index cc208fae3e7a..000000000000 --- a/arch/arm/plat-tcc/system.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * System functions for Telechips TCCxxxx SoCs - * - * Copyright (C) Hans J. Koch - * - * Licensed under the terms of the GPL v2. - * - */ - -#include - -#include - -/* System reboot */ -void plat_tcc_reboot(void) -{ - /* Make sure clocks are on */ - __raw_writel(0xffffffff, CKC_BASE + BCLKCTR0_OFFS); - - /* Enable watchdog reset */ - __raw_writel(0x49, TIMER_BASE + TWDCFG_OFFS); - /* Wait for reset */ - while(1) - ; -} -- cgit