This does all the RCU magic inside of it. The caller must call put_cred() on
the credentials so obtained when they're finished with.
+ [*] Note: The result of __task_cred() should not be passed directly to
+ get_cred() as this may race with commit_cred().
+
There are a couple of convenience functions to access bits of another task's
credentials, hiding the RCU magic from the caller:
if (tracer)
tpid = task_pid_nr_ns(tracer, ns);
}
- cred = get_cred((struct cred *) __task_cred(p));
+ cred = get_task_cred(p);
seq_printf(m,
"State:\t%s\n"
"Tgid:\t%d\n"
extern void __put_cred(struct cred *);
extern void exit_creds(struct task_struct *);
extern int copy_creds(struct task_struct *, unsigned long);
+extern const struct cred *get_task_cred(struct task_struct *);
extern struct cred *cred_alloc_blank(void);
extern struct cred *prepare_creds(void);
extern struct cred *prepare_exec_creds(void);
* @task: The task to query
*
* Access the objective credentials of a task. The caller must hold the RCU
- * readlock.
+ * readlock or the task must be dead and unable to change its own credentials.
*
- * The caller must make sure task doesn't go away, either by holding a ref on
- * task or by holding tasklist_lock to prevent it from being unlinked.
+ * The result of this function should not be passed directly to get_cred();
+ * rather get_task_cred() should be used instead.
*/
-#define __task_cred(task) \
- ((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_tasklist_lock_is_held())))
-
-/**
- * get_task_cred - Get another task's objective credentials
- * @task: The task to query
- *
- * Get the objective credentials of a task, pinning them so that they can't go
- * away. Accessing a task's credentials directly is not permitted.
- *
- * The caller must make sure task doesn't go away, either by holding a ref on
- * task or by holding tasklist_lock to prevent it from being unlinked.
- */
-#define get_task_cred(task) \
-({ \
- struct cred *__cred; \
- rcu_read_lock(); \
- __cred = (struct cred *) __task_cred((task)); \
- get_cred(__cred); \
- rcu_read_unlock(); \
- __cred; \
-})
+#define __task_cred(task) \
+ ({ \
+ const struct task_struct *__t = (task); \
+ rcu_dereference_check(__t->real_cred, \
+ rcu_read_lock_held() || \
+ task_is_dead(__t)); \
+ })
/**
* get_current_cred - Get the current task's subjective credentials
#define task_is_traced(task) ((task->state & __TASK_TRACED) != 0)
#define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0)
+#define task_is_dead(task) ((task)->exit_state != 0)
#define task_is_stopped_or_traced(task) \
((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
#define task_contributes_to_load(task) \
}
}
+/**
+ * get_task_cred - Get another task's objective credentials
+ * @task: The task to query
+ *
+ * Get the objective credentials of a task, pinning them so that they can't go
+ * away. Accessing a task's credentials directly is not permitted.
+ *
+ * The caller must also make sure task doesn't get deleted, either by holding a
+ * ref on task or by holding tasklist_lock to prevent it from being unlinked.
+ */
+const struct cred *get_task_cred(struct task_struct *task)
+{
+ const struct cred *cred;
+
+ rcu_read_lock();
+
+ do {
+ cred = __task_cred((task));
+ BUG_ON(!cred);
+ } while (!atomic_inc_not_zero(&((struct cred *)cred)->usage));
+
+ rcu_read_unlock();
+ return cred;
+}
+
/*
* Allocate blank credentials, such that the credentials can be filled in at a
* later date without risk of ENOMEM.
*/
struct hda_multi_out multiout;
unsigned int codec_type;
+
+ /* misc flags */
+ /* PD bit indicates only the update, not the current state */
+ unsigned int old_pin_detect:1;
};
* Unsolicited events
*/
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld);
+
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
{
struct hdmi_spec *spec = codec->spec;
if (index < 0)
return;
+ if (spec->old_pin_detect) {
+ if (pind)
+ hdmi_present_sense(codec, tag, &spec->sink_eld[index]);
+ pind = spec->sink_eld[index].monitor_present;
+ }
+
spec->sink_eld[index].monitor_present = pind;
spec->sink_eld[index].eld_valid = eldv;
codec->spec = spec;
spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+ spec->old_pin_detect = 1;
if (hdmi_parse_codec(codec) < 0) {
codec->spec = NULL;
spec->multiout.max_channels = 8;
spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
+ spec->old_pin_detect = 1;
codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
spec->multiout.max_channels = 2;
spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
+ spec->old_pin_detect = 1;
codec->patch_ops = nvhdmi_patch_ops_2ch;
unsigned nid = 0;
struct alc_spec *spec = codec->spec;
+ spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
+
ass = codec->subsystem_id & 0xffff;
- if (ass != codec->bus->pci->subsystem_device && (ass & 1)) {
- spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
+ if (ass != codec->bus->pci->subsystem_device && (ass & 1))
goto do_sku;
- }
nid = 0x1d;
if (codec->vendor_id == 0x10ec0260)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
+
+static struct snd_pci_quirk beep_white_list[] = {
+ SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
+ {}
+};
+
+static inline int has_cdefine_beep(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ const struct snd_pci_quirk *q;
+ q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
+ if (q)
+ return q->value;
+ return spec->cdefine.enable_pcbeep;
+}
#else
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#define has_cdefine_beep(codec) 0
#endif
/*
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC882_AUTO)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep)
+ if (has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (board_config == ALC882_AUTO)
}
}
- if (!spec->no_analog) {
+ if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
if (err < 0) {
alc_free(codec);
}
if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(codec);
- if (!spec->no_analog && spec->cdefine.enable_pcbeep)
+ if (!spec->no_analog && has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
spec->vmaster_nid = 0x0c;
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC269_AUTO)
if (!spec->cap_mixer)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep)
+ if (has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
if (board_config == ALC269_AUTO)
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC662_AUTO)
if (!spec->cap_mixer)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep) {
+ if (has_cdefine_beep(codec)) {
switch (codec->vendor_id) {
case 0x10ec0662:
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);