From e584bc3cf6865e005bbb4dbabae0bf4b3df59500 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 1 Mar 2010 16:20:37 +0100 Subject: [PATCH 001/114] ALSA: ua101: add Edirol UA-1000 support Add support for the Edirol UA-1000 to the UA-101 driver. Both devices behave the same, so we just have to shuffle around some interface numbers and name strings. Signed-off-by: Clemens Ladisch Signed-off-by: Jaroslav Kysela --- .../sound/alsa/ALSA-Configuration.txt | 2 +- sound/usb/Kconfig | 6 +-- sound/usb/ua101.c | 45 +++++++++++----- sound/usb/usbaudio.c | 53 ------------------- sound/usb/usbaudio.h | 3 +- sound/usb/usbquirks.h | 30 ----------- 6 files changed, 38 insertions(+), 101 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 33df82e3a398..bfcbbf88c44d 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-ua101 ---------------- - Module for the Edirol UA-101 audio/MIDI interface. + Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces. This module supports multiple devices, autoprobe and hotplugging. diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 8c2925814ce4..c570ae3e6d55 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -22,13 +22,13 @@ config SND_USB_AUDIO will be called snd-usb-audio. config SND_USB_UA101 - tristate "Edirol UA-101 driver (EXPERIMENTAL)" + tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)" depends on EXPERIMENTAL select SND_PCM select SND_RAWMIDI help - Say Y here to include support for the Edirol UA-101 audio/MIDI - interface. + Say Y here to include support for the Edirol UA-101 and UA-1000 + audio/MIDI interfaces. To compile this driver as a module, choose M here: the module will be called snd-ua101. diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 4f4ccdf70dd0..047dc1ca84d0 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c @@ -1,5 +1,5 @@ /* - * Edirol UA-101 driver + * Edirol UA-101/UA-1000 driver * Copyright (c) Clemens Ladisch * * This driver is free software: you can redistribute it and/or modify @@ -25,10 +25,10 @@ #include #include "usbaudio.h" -MODULE_DESCRIPTION("Edirol UA-101 driver"); +MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); MODULE_AUTHOR("Clemens Ladisch "); MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}"); +MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); /* I use my UA-1A for testing because I don't have a UA-101 ... */ #define UA1A_HACK @@ -1200,13 +1200,30 @@ static int ua101_probe(struct usb_interface *interface, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &midi_ep }; + static const int intf_numbers[2][3] = { + { /* UA-101 */ + [INTF_PLAYBACK] = 0, + [INTF_CAPTURE] = 1, + [INTF_MIDI] = 2, + }, + { /* UA-1000 */ + [INTF_CAPTURE] = 1, + [INTF_PLAYBACK] = 2, + [INTF_MIDI] = 3, + }, + }; struct snd_card *card; struct ua101 *ua; unsigned int card_index, i; + int is_ua1000; + const char *name; char usb_path[32]; int err; - if (interface->altsetting->desc.bInterfaceNumber != 0) + is_ua1000 = usb_id->idProduct == 0x0044; + + if (interface->altsetting->desc.bInterfaceNumber != + intf_numbers[is_ua1000][0]) return -ENODEV; mutex_lock(&devices_mutex); @@ -1250,9 +1267,11 @@ static int ua101_probe(struct usb_interface *interface, #endif ua->intf[0] = interface; for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { - ua->intf[i] = usb_ifnum_to_if(ua->dev, i); + ua->intf[i] = usb_ifnum_to_if(ua->dev, + intf_numbers[is_ua1000][i]); if (!ua->intf[i]) { - dev_err(&ua->dev->dev, "interface %u not found\n", i); + dev_err(&ua->dev->dev, "interface %u not found\n", + intf_numbers[is_ua1000][i]); err = -ENXIO; goto probe_error; } @@ -1292,11 +1311,12 @@ static int ua101_probe(struct usb_interface *interface, } #endif + name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; strcpy(card->driver, "UA-101"); - strcpy(card->shortname, "UA-101"); + strcpy(card->shortname, name); usb_make_path(ua->dev, usb_path, sizeof(usb_path)); snprintf(ua->card->longname, sizeof(ua->card->longname), - "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed", + "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); @@ -1314,11 +1334,11 @@ static int ua101_probe(struct usb_interface *interface, if (err < 0) goto probe_error; - err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm); + err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); if (err < 0) goto probe_error; ua->pcm->private_data = ua; - strcpy(ua->pcm->name, "UA-101"); + strcpy(ua->pcm->name, name); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); @@ -1389,8 +1409,9 @@ static struct usb_device_id ua101_ids[] = { #ifdef UA1A_HACK { USB_DEVICE(0x0582, 0x0018) }, #endif - { USB_DEVICE(0x0582, 0x007d) }, - { USB_DEVICE(0x0582, 0x008d) }, + { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ + { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ + { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ { } }; MODULE_DEVICE_TABLE(usb, ua101_ids); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8a8f62515b80..7ad8089b233e 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3116,58 +3116,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, return 0; } -/* - * Create a stream for an Edirol UA-1000 interface. - */ -static int create_ua1000_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - const struct snd_usb_audio_quirk *quirk) -{ - static const struct audioformat ua1000_format = { - .format = SNDRV_PCM_FORMAT_S32_LE, - .fmt_type = USB_FORMAT_TYPE_I, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - }; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct audioformat *fp; - int stream, err; - - if (iface->num_altsetting != 2) - return -ENXIO; - alts = &iface->altsetting[1]; - altsd = get_iface_desc(alts); - if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || - altsd->bNumEndpoints != 1) - return -ENXIO; - - fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL); - if (!fp) - return -ENOMEM; - - fp->channels = alts->extra[4]; - fp->iface = altsd->bInterfaceNumber; - fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; - fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->datainterval = parse_datainterval(chip, alts); - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); - - stream = (fp->endpoint & USB_DIR_IN) - ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = add_audio_endpoint(chip, stream, fp); - if (err < 0) { - kfree(fp); - return err; - } - /* FIXME: playback must be synchronized to capture */ - usb_set_interface(chip->dev, fp->iface, 0); - return 0; -} - static int snd_usb_create_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, const struct snd_usb_audio_quirk *quirk); @@ -3416,7 +3364,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_CME] = create_any_midi_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, - [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 9d8cea48fc5f..96c558a76ba6 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -159,7 +159,6 @@ enum quirk_type { QUIRK_MIDI_US122L, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, - QUIRK_AUDIO_EDIROL_UA1000, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, @@ -196,7 +195,7 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ -/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ +/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */ /* for QUIRK_IGNORE_INTERFACE, data is NULL */ diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index e691eba6a83e..977d980fb117 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1015,36 +1015,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - USB_DEVICE(0x0582, 0x0044), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "UA-1000", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UA1000 - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UA1000 - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, { /* has ID 0x0049 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0047), From 20645d70bdcdcc29b1b92011780d233008a8adcf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 Mar 2010 11:14:01 +0100 Subject: [PATCH 002/114] ALSA: hda - Add missing hp_pins definitions for ALC269 quirks In 2.6.33 ACL269 unsol event handler was changed to look up the pre-defined pins, but the headphone pins aren't defined properly in each quirk. This patch adds the missing definitions, and fixes the speaker auto-mute regression on some ASUS (and possibly other) laptops. Signed-off-by: Takashi Iwai Cc: --- sound/pci/hda/patch_realtek.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e8cbe216e912..b9f4689ccd9a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -13561,6 +13561,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, static void alc269_quanta_fl1_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; @@ -13656,6 +13658,8 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec, static void alc269_laptop_dmic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13666,6 +13670,8 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec) static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13676,6 +13682,8 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) static void alc269_laptop_amic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; From 28aedaf7bf6e4b629aea333978e8bb440bd1eb4f Mon Sep 17 00:00:00 2001 From: Norberto Lopes Date: Sun, 28 Feb 2010 20:16:53 +0100 Subject: [PATCH 003/114] ALSA: sound/pci/hda/hda_codec.c: various coding style fixes Signed-off-by: Norberto Lopes Acked-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 69 +++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 76d3c4c049db..5bd7cf45f3a5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, * * Returns 0 if successful, or a negative error code. */ -int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, - struct hda_codec **codecp) +int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, + unsigned int codec_addr, + struct hda_codec **codecp) { struct hda_codec *codec; char component[31]; @@ -1186,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); */ /* FIXME: more better hash key? */ -#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) +#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) @@ -1356,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) if (!codec->no_trigger_sense) { pincap = snd_hda_query_pin_caps(codec, nid); if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ - snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); + snd_hda_codec_read(codec, nid, 0, + AC_VERB_SET_PIN_SENSE, 0); } return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); @@ -1372,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); */ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) { - u32 sense = snd_hda_pin_sense(codec, nid); - return !!(sense & AC_PINSENSE_PRESENCE); + u32 sense = snd_hda_pin_sense(codec, nid); + return !!(sense & AC_PINSENSE_PRESENCE); } EXPORT_SYMBOL_HDA(snd_hda_jack_detect); @@ -1952,7 +1954,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; - + for (s = slaves; *s; s++) { struct snd_kcontrol *sctl; int i = 0; @@ -2439,27 +2441,27 @@ static struct snd_kcontrol_new dig_mixes[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_cmask_get, }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_pmask_get, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_default_get, .put = snd_hda_spdif_default_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), .info = snd_hda_spdif_out_switch_info, .get = snd_hda_spdif_out_switch_get, .put = snd_hda_spdif_out_switch_put, @@ -2610,7 +2612,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new dig_in_ctls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), .info = snd_hda_spdif_in_switch_info, .get = snd_hda_spdif_in_switch_get, .put = snd_hda_spdif_in_switch_put, @@ -2618,7 +2620,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_in_status_get, }, @@ -2883,7 +2885,7 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) int err = snd_hda_codec_build_controls(codec); if (err < 0) { printk(KERN_ERR "hda_codec: cannot build controls" - "for #%d (error %d)\n", codec->addr, err); + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -2979,8 +2981,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, val |= channels - 1; switch (snd_pcm_format_width(format)) { - case 8: val |= 0x00; break; - case 16: val |= 0x10; break; + case 8: + val |= 0x00; + break; + case 16: + val |= 0x10; + break; case 20: case 24: case 32: @@ -3298,7 +3304,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) return audio_idx[type][i]; - snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); + snd_printk(KERN_WARNING "Too many %s devices\n", + snd_hda_pcm_type_name[type]); return -EAGAIN; } @@ -3336,7 +3343,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) err = codec->patch_ops.build_pcms(codec); if (err < 0) { printk(KERN_ERR "hda_codec: cannot build PCMs" - "for #%d (error %d)\n", codec->addr, err); + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -3466,8 +3473,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); /** * snd_hda_check_board_codec_sid_config - compare the current codec - subsystem ID with the - config table + subsystem ID with the + config table This is important for Gateway notebooks with SB450 HDA Audio where the vendor ID of the PCI device is: @@ -3607,7 +3614,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) * * Increment the power-up counter and power up the hardware really when * not turned on yet. - */ + */ void snd_hda_power_up(struct hda_codec *codec) { struct hda_bus *bus = codec->bus; @@ -3636,7 +3643,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); * * Decrement the power-up counter and schedules the power-off work if * the counter rearches to zero. - */ + */ void snd_hda_power_down(struct hda_codec *codec) { --codec->power_count; @@ -3662,7 +3669,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); * * This function is supposed to be set or called from the check_power_status * patch ops. - */ + */ int snd_hda_check_amp_list_power(struct hda_codec *codec, struct hda_loopback_check *check, hda_nid_t nid) @@ -3830,7 +3837,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, { /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) - set_dig_out_convert(codec, nid, + set_dig_out_convert(codec, nid, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, -1); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); @@ -4089,13 +4096,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) /* * Sort an associated group of pins according to their sequence numbers. */ -static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, +static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, int num_pins) { int i, j; short seq; hda_nid_t nid; - + for (i = 0; i < num_pins; i++) { for (j = i + 1; j < num_pins; j++) { if (sequences[i] > sequences[j]) { @@ -4123,7 +4130,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, * is detected, one of speaker of HP pins is assigned as the primary * output, i.e. to line_out_pins[0]. So, line_outs is always positive * if any analog output exists. - * + * * The analog input pins are assigned to input_pins array. * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, * respectively. @@ -4186,9 +4193,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, case AC_JACK_SPEAKER: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (! assoc) + if (!assoc) continue; - if (! assoc_speaker) + if (!assoc_speaker) assoc_speaker = assoc; else if (assoc_speaker != assoc) continue; @@ -4286,7 +4293,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->speaker_outs); sort_pins_by_sequence(cfg->hp_pins, sequences_hp, cfg->hp_outs); - + /* if we have only one mic, make it AUTO_PIN_MIC */ if (!cfg->input_pins[AUTO_PIN_MIC] && cfg->input_pins[AUTO_PIN_FRONT_MIC]) { @@ -4436,7 +4443,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); /** * snd_array_new - get a new element from the given array * @array: the array object - * + * * Get a new element from the given array. If it exceeds the * pre-allocated array size, re-allocate the array. * From 76b53774c51c4eaec646578a2e1b3716befedf1c Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sat, 27 Feb 2010 17:51:03 +0100 Subject: [PATCH 004/114] sound/oss/v_midi.h: Checkpatch cleanup sound/oss/v_midi.h:5: ERROR: code indent should use tabs where possible sound/oss/v_midi.h:7: ERROR: trailing whitespace Signed-off-by: Andrea Gelmini Signed-off-by: Takashi Iwai --- sound/oss/v_midi.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h index 1b86cb45c607..08e2185ee816 100644 --- a/sound/oss/v_midi.h +++ b/sound/oss/v_midi.h @@ -2,9 +2,9 @@ typedef struct vmidi_devc { int dev; /* State variables */ - int opened; + int opened; spinlock_t lock; - + /* MIDI fields */ int my_mididev; int pair_mididev; @@ -12,4 +12,3 @@ typedef struct vmidi_devc { int intr_active; void (*midi_input_intr) (int dev, unsigned char data); } vmidi_devc; - From 3ea49652f679c2b571ca214c605ec80cb056ec10 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sat, 27 Feb 2010 17:51:19 +0100 Subject: [PATCH 005/114] sound/oss/coproc.h: Checkpatch cleanup sound/oss/coproc.h:7: ERROR: trailing whitespace Signed-off-by: Andrea Gelmini Signed-off-by: Takashi Iwai --- sound/oss/coproc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h index 7306346e9ac4..7bec21bbdd88 100644 --- a/sound/oss/coproc.h +++ b/sound/oss/coproc.h @@ -4,7 +4,7 @@ */ /* - * Coprocessor access types + * Coprocessor access types */ #define COPR_CUSTOM 0x0001 /* Custom applications */ #define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ From 7f9320d415fab5c05097c77eea7a77f2f6341f24 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sat, 27 Feb 2010 17:51:29 +0100 Subject: [PATCH 006/114] ALSA: sound/usb/caiaq/midi.h: Checkpatch cleanup sound/usb/caiaq/midi.h:6: ERROR: "foo* bar" should be "foo *bar" Signed-off-by: Andrea Gelmini Acked-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/midi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h index 9d16db027fc3..380f984babc9 100644 --- a/sound/usb/caiaq/midi.h +++ b/sound/usb/caiaq/midi.h @@ -3,6 +3,6 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); -void snd_usb_caiaq_midi_output_done(struct urb* urb); +void snd_usb_caiaq_midi_output_done(struct urb *urb); #endif /* CAIAQ_MIDI_H */ From 0a566ec25627bdd360f7294aa2e52f9d121233b4 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 2 Mar 2010 08:47:20 +0100 Subject: [PATCH 007/114] ALSA: ua101: removing debugging code Remove some code that is no longer needed now that the relevant parts of the driver have been tested. Signed-off-by: Clemens Ladisch Signed-off-by: Jaroslav Kysela --- sound/usb/ua101.c | 55 ----------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 047dc1ca84d0..3d458d3b9962 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c @@ -30,9 +30,6 @@ MODULE_AUTHOR("Clemens Ladisch "); MODULE_LICENSE("GPL v2"); MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); -/* I use my UA-1A for testing because I don't have a UA-101 ... */ -#define UA1A_HACK - /* * Should not be lower than the minimum scheduling delay of the host * controller. Some Intel controllers need more than one frame; as long as @@ -132,9 +129,6 @@ struct ua101 { dma_addr_t dma; } buffers[MAX_MEMORY_BUFFERS]; } capture, playback; - - unsigned int fps[10]; - unsigned int frame_counter; }; static DEFINE_MUTEX(devices_mutex); @@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb) if (do_period_elapsed) snd_pcm_period_elapsed(stream->substream); - /* for debugging: measure the sample rate relative to the USB clock */ - ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames; - if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) { - printk(KERN_DEBUG "capture rate:"); - for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames) - printk(KERN_CONT " %u", ua->fps[frames]); - printk(KERN_CONT "\n"); - memset(ua->fps, 0, sizeof(ua->fps)); - ua->frame_counter = 0; - } return; stream_stopped: @@ -1256,15 +1240,6 @@ static int ua101_probe(struct usb_interface *interface, init_waitqueue_head(&ua->rate_feedback_wait); init_waitqueue_head(&ua->alsa_playback_wait); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { - ua->intf[2] = interface; - ua->intf[0] = usb_ifnum_to_if(ua->dev, 1); - ua->intf[1] = usb_ifnum_to_if(ua->dev, 2); - usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua); - usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua); - } else { -#endif ua->intf[0] = interface; for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { ua->intf[i] = usb_ifnum_to_if(ua->dev, @@ -1283,33 +1258,12 @@ static int ua101_probe(struct usb_interface *interface, goto probe_error; } } -#ifdef UA1A_HACK - } -#endif snd_card_set_dev(card, &interface->dev); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { - ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE; - ua->rate = 44100; - ua->packets_per_second = 1000; - ua->capture.channels = 2; - ua->playback.channels = 2; - ua->capture.frame_bytes = 4; - ua->playback.frame_bytes = 4; - ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2); - ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1); - ua->capture.max_packet_bytes = 192; - ua->playback.max_packet_bytes = 192; - } else { -#endif err = detect_usb_format(ua); if (err < 0) goto probe_error; -#ifdef UA1A_HACK - } -#endif name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; strcpy(card->driver, "UA-101"); @@ -1342,16 +1296,10 @@ static int ua101_probe(struct usb_interface *interface, snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) { -#endif err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], &ua->midi_list, &midi_quirk); if (err < 0) goto probe_error; -#ifdef UA1A_HACK - } -#endif err = snd_card_register(card); if (err < 0) @@ -1406,9 +1354,6 @@ static void ua101_disconnect(struct usb_interface *interface) } static struct usb_device_id ua101_ids[] = { -#ifdef UA1A_HACK - { USB_DEVICE(0x0582, 0x0018) }, -#endif { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ From 864c11080cf365720103042444534a1e94d42bac Mon Sep 17 00:00:00 2001 From: Arseniy Lartsev Date: Tue, 2 Mar 2010 14:52:28 +0300 Subject: [PATCH 008/114] ALSA: usbaudio: Fix wrong bitrate for Creative Creative VF0470 Live Cam This patch works around misbehaviour of Creative Creative VF0470 Live Cam which reports 16 kHz sample rate for audio capture while actually producing 8 kHz stream. Signed-off-by: Arseniy Lartsev Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 20b656e9f90d..ea3eaa53d637 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2581,6 +2581,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof chip->usb_id == USB_ID(0x0d8c, 0x0102)) && fp->altsetting == 5 && fp->maxpacksize == 392) rate = 96000; + /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ + if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) + rate = 8000; fp->rate_table[fp->nr_rates] = rate; if (!fp->rate_min || rate < fp->rate_min) fp->rate_min = rate; From bb1c04784d39b95a4382bd283f3048c4eb859b58 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 25 Feb 2010 11:24:53 +0900 Subject: [PATCH 009/114] ASoC: soc_pcm_open: Add missing bailout tag The codec_dai needs to be shutdown should the machine startup fails. This patch adds another bailout tag for that case and rename the tag for configuration failures. Signed-off-by: Jassi Brar Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a03bac943aaf..c8b0556ef431 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -427,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (!runtime->hw.rates) { printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } if (!runtime->hw.formats) { printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } if (!runtime->hw.channels_min || !runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } /* Symmetry only applies if we've already got an active stream. */ if (cpu_dai->active || codec_dai->active) { ret = soc_pcm_apply_symmetry(substream); if (ret != 0) - goto machine_err; + goto config_err; } pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); @@ -464,10 +464,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&pcm_mutex); return 0; -machine_err: +config_err: if (machine->ops && machine->ops->shutdown) machine->ops->shutdown(substream); +machine_err: + if (codec_dai->ops->shutdown) + codec_dai->ops->shutdown(substream, codec_dai); + codec_dai_err: if (platform->pcm_ops->close) platform->pcm_ops->close(substream); From e555317c083fda01f516d2153589e82514e20e70 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 26 Feb 2010 14:36:54 +0800 Subject: [PATCH 010/114] ASoC: fix ak4104 register array access Don't touch the variable 'reg' to construct the value for the actual SPI transport. This variable is again used to access the driver's register cache, and so random memory is overwritten. Compute the value in-place instead. Signed-off-by: Daniel Mack Acked-by: Liam Girdwood Cc: stable@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/ak4104.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b9ef7e45891d..b68d99fb6af0 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -90,12 +90,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, if (reg >= codec->reg_cache_size) return -EINVAL; - reg &= AK4104_REG_MASK; - reg |= AK4104_WRITE; - /* only write to the hardware if value has changed */ if (cache[reg] != value) { - u8 tmp[2] = { reg, value }; + u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value }; + if (spi_write(spi, tmp, sizeof(tmp))) { dev_err(&spi->dev, "SPI write failed\n"); return -EIO; From fd8d47351d2e241f3168eeb697ce55cc28c75b78 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 3 Mar 2010 19:41:44 +0100 Subject: [PATCH 011/114] ALSA: opti92x: use PnP data to select Master Control port The Master Control port (MC) is available as the last PnP resource (OPT005). Use this value instead fo guessing. Also, add some comments to the code. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/opti9xx/miro.c | 2 +- sound/isa/opti9xx/opti92x-ad1848.c | 120 +++++++++++++++++++---------- 2 files changed, 79 insertions(+), 43 deletions(-) diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index b865e45a8f9b..5913717c1be6 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); return err; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index a4af53b5c1cf..becd90d7536d 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -144,12 +144,8 @@ struct snd_opti9xx { spinlock_t lock; + long wss_base; int irq; - -#ifdef CONFIG_PNP - struct pnp_dev *dev; - struct pnp_dev *devmpu; -#endif /* CONFIG_PNP */ }; static int snd_opti9xx_pnp_is_probed; @@ -159,12 +155,17 @@ static int snd_opti9xx_pnp_is_probed; static struct pnp_card_device_id snd_opti9xx_pnpids[] = { #ifndef OPTi93X /* OPTi 82C924 */ - { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 }, + { .id = "OPT0924", + .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0924 }, /* OPTi 82C925 */ - { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 }, + { .id = "OPT0925", + .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0925 }, #else /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 }, + { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, + .driver_data = 0x0931 }, #endif /* OPTi93X */ { .id = "" } }; @@ -207,24 +208,34 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, chip->hardware = hardware; strcpy(chip->name, snd_opti9xx_names[hardware]); - chip->mc_base_size = opti9xx_mc_size[hardware]; - spin_lock_init(&chip->lock); chip->irq = -1; +#ifndef OPTi93X +#ifdef CONFIG_PNP + if (isapnp && chip->mc_base) + /* PnP resource gives the least 10 bits */ + chip->mc_base |= 0xc00; +#endif /* CONFIG_PNP */ + else { + chip->mc_base = 0xf8c; + chip->mc_base_size = opti9xx_mc_size[hardware]; + } +#else + chip->mc_base_size = opti9xx_mc_size[hardware]; +#endif + switch (hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: - chip->mc_base = 0xf8c; chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; chip->pwd_reg = 3; break; case OPTi9XX_HW_82C924: case OPTi9XX_HW_82C925: - chip->mc_base = 0xf8c; chip->password = 0xe5; chip->pwd_reg = 3; break; @@ -292,7 +303,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, spin_unlock_irqrestore(&chip->lock, flags); return retval; } - + static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, unsigned char value) { @@ -341,7 +352,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long wss_base, + long port, int irq, int dma1, int dma2, long mpu_port, int mpu_irq) { @@ -354,16 +365,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, switch (chip->hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C924: + /* opti 929 mode (?), OPL3 clock output, audio enable */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); + /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); case OPTi9XX_HW_82C925: + /* enable WSS mode */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); + /* OPL3 FM synthesis */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); + /* disable Sound Blaster IRQ and DMA */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); #ifdef CS4231 + /* cs4231/4248 fix enabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); #else + /* cs4231/4248 fix disabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); #endif /* CS4231 */ break; @@ -411,21 +429,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, return -EINVAL; } - switch (wss_base) { - case 0x530: + /* PnP resource says it decodes only 10 bits of address */ + switch (port & 0x3ff) { + case 0x130: + chip->wss_base = 0x530; wss_base_bits = 0x00; break; - case 0x604: + case 0x204: + chip->wss_base = 0x604; wss_base_bits = 0x03; break; - case 0xe80: + case 0x280: + chip->wss_base = 0xe80; wss_base_bits = 0x01; break; - case 0xf40: + case 0x340: + chip->wss_base = 0xf40; wss_base_bits = 0x02; break; default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base); + snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -487,7 +510,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, #endif /* CS4231 || OPTi93X */ #ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, wss_base); + outb(irq_bits << 3 | dma_bits, chip->wss_base); #else /* OPTi93X */ snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); #endif /* OPTi93X */ @@ -729,15 +752,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, { struct pnp_dev *pdev; int err; + struct pnp_dev *devmpu; +#ifndef OPTi93X + struct pnp_dev *devmc; +#endif - chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (chip->dev == NULL) + pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); + if (pdev == NULL) return -EBUSY; - chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - pdev = chip->dev; - err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); @@ -750,9 +773,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; #else - if (pid->driver_data != 0x0924) - port = pnp_port_start(pdev, 1); + devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); + if (devmc == NULL) + return -EBUSY; + + err = pnp_activate_dev(devmc); + if (err < 0) { + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); + return err; + } + + port = pnp_port_start(pdev, 1); fm_port = pnp_port_start(pdev, 2) + 8; + /* + * The MC(0) is never accessed and card does not + * include it in the PnP resource range. OPTI93x include it. + */ + chip->mc_base = pnp_port_start(devmc, 0) - 1; + chip->mc_base_size = pnp_port_len(devmc, 0) + 1; #endif /* OPTi93X */ irq = pnp_irq(pdev, 0); dma1 = pnp_dma(pdev, 0); @@ -760,16 +798,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, dma2 = pnp_dma(pdev, 1); #endif /* CS4231 || OPTi93X */ - pdev = chip->devmpu; - if (pdev && mpu_port > 0) { - err = pnp_activate_dev(pdev); + devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); + + if (devmpu && mpu_port > 0) { + err = pnp_activate_dev(devmpu); if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure\n"); + snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); mpu_port = -1; - chip->devmpu = NULL; } else { - mpu_port = pnp_port_start(pdev, 0); - mpu_irq = pnp_irq(pdev, 0); + mpu_port = pnp_port_start(devmpu, 0); + mpu_irq = pnp_irq(devmpu, 0); } } return pid->driver_data; @@ -824,7 +862,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (error) return error; - error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2, + error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, #ifdef OPTi93X WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, #else @@ -865,10 +903,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) sprintf(card->shortname, "OPTi %s", card->driver); #if defined(CS4231) || defined(OPTi93X) sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, port + 4, irq, dma1, xdma2); + card->shortname, pcm->name, + chip->wss_base + 4, irq, dma1, xdma2); #else sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, port + 4, irq, dma1); + card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); #endif /* CS4231 || OPTi93X */ if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) @@ -1062,9 +1101,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } - if (hw <= OPTi9XX_HW_82C930) - chip->mc_base -= 0x80; - error = snd_opti9xx_read_check(chip); if (error) { snd_printk(KERN_ERR "OPTI chip not found\n"); From faf4eb23d5fcb9a4728766a1e7bce9c6f2b43bd8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 3 Mar 2010 09:16:18 +0100 Subject: [PATCH 012/114] ALSA: oxygen: change || to && In the original code the condition was always true (hopefully) because WM8776_HPLVOL is zero. Signed-off-by: Dan Carpenter Signed-off-by: Clemens Ladisch Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/oxygen/xonar_wm87x6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 7754db166d9e..dbc4b89d74e4 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip, OXYGEN_SPI_CEN_LATCH_CLOCK_LO, (reg << 9) | value); if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER) + if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) value &= ~WM8776_UPDATE; data->wm8776_regs[reg] = value; } From b30477d5e2961bfd90ad4146c517871ca8a6bebc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 3 Mar 2010 11:05:55 +0100 Subject: [PATCH 013/114] ALSA: timer - pass real event in snd_timer_notify1() to instance callback Do not use hardcoded SNDRV_TIMER_EVENT_START value. Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- include/sound/asound.h | 2 +- sound/core/timer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/asound.h b/include/sound/asound.h index 1f57bb92eb5a..098595500632 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -544,7 +544,7 @@ struct snd_rawmidi_status { * Timer section - /dev/snd/timer */ -#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5) +#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) enum { SNDRV_TIMER_CLASS_NONE = -1, diff --git a/sound/core/timer.c b/sound/core/timer.c index 8f8b17ac074d..73943651caed 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); if (ti->ccallback) - ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); + ti->ccallback(ti, event, &tstamp, resolution); if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) return; timer = ti->timer; From e61e642c2a0dc283c52cec76a223ac0699773633 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 3 Mar 2010 11:11:57 +0100 Subject: [PATCH 014/114] ALSA: usbaudio - remove debug "SAMPLE BYTES" printk line Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index ea3eaa53d637..11b0826b8fe6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2483,7 +2483,6 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, sample_width, sample_bytes); } /* check the format byte size */ - printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes); switch (sample_bytes) { case 1: pcm_format = SNDRV_PCM_FORMAT_S8; From 282572b5ab99cf27073210ca60b80dd085e1a469 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Mar 2010 10:13:49 +0300 Subject: [PATCH 015/114] ALSA: riptide: clean up while loop If getpaths() returned an odd number this would be a buffer under-run and an endless loop. It turns out that getpaths() can only return even numbers, but let's make it easy for people auditing code. With the new code you don't need to look at getpaths(). This silences a smatch warning. Signed-off-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/riptide/riptide.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 960a227eb653..ad4462677615 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry, } snd_iprintf(buffer, "Paths:\n"); i = getpaths(cif, p); - while (i--) { - snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]); - i--; + while (i >= 2) { + i -= 2; + snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]); } snd_iprintf(buffer, "\n"); } From 7445dfc159f90b4bc82fd7d898b53d74520e2f83 Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Wed, 3 Mar 2010 15:05:53 +0800 Subject: [PATCH 016/114] ALSA: hda - Support max codecs to 8 for nvidia hda controller Support max codecs to 8 for nvidia hda controller. Change AZX_MAX_CODECS to 8, and add "#define AZX_DEFAULT_CODECS 4" for default driver. Set azx_max_codecs to 8 for nvidia controller. Signed-off-by: Wei Ni Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1adac8cc9592..b1047570e78d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define RIRB_INT_MASK 0x05 /* STATESTS int mask: S3,SD2,SD1,SD0 */ -#define AZX_MAX_CODECS 4 +#define AZX_MAX_CODECS 8 +#define AZX_DEFAULT_CODECS 4 #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) /* SD_CTL bits */ @@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus) /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { + [AZX_DRIVER_NVIDIA] = 8, [AZX_DRIVER_TERA] = 1, }; @@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) codecs = 0; max_slots = azx_max_codecs[chip->driver_type]; if (!max_slots) - max_slots = AZX_MAX_CODECS; + max_slots = AZX_DEFAULT_CODECS; /* First try to probe all given codec slots */ for (c = 0; c < max_slots; c++) { From 25045705d4053925a617ed71c5e4b6888e468765 Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Wed, 3 Mar 2010 15:11:40 +0800 Subject: [PATCH 017/114] ALSA: hda - Support NVIDIA MCP89 and GT21x hdmi audio Support nvidia MCP89 and GT21x 8ch hdmi audio. Add some eld support. Signed-off-by: Wei Ni Signed-off-by: Takashi Iwai --- sound/pci/hda/Kconfig | 2 +- sound/pci/hda/Makefile | 2 +- sound/pci/hda/patch_nvhdmi.c | 1038 ++++++++++++++++++++++++++++++++-- 3 files changed, 990 insertions(+), 52 deletions(-) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 556cff937be7..567348b05b5a 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI config SND_HDA_ELD def_bool y - depends on SND_HDA_CODEC_INTELHDMI + depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI config SND_HDA_CODEC_CIRRUS bool "Build Cirrus Logic codec support" diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 315a1c4f8998..199f4405b3ad 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs := patch_cirrus.o snd-hda-codec-ca0110-objs := patch_ca0110.o snd-hda-codec-conexant-objs := patch_conexant.o snd-hda-codec-via-objs := patch_via.o -snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o +snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o hda_eld.o snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o # common driver diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..1c774f942407 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -32,10 +32,11 @@ /* define below to restrict the supported rates and formats */ /* #define LIMITED_RATE_FMT_SUPPORT */ -struct nvhdmi_spec { - struct hda_multi_out multiout; - - struct hda_pcm pcm_rec; +enum HDACodec { + HDA_CODEC_NVIDIA_MCP7X, + HDA_CODEC_NVIDIA_MCP89, + HDA_CODEC_NVIDIA_GT21X, + HDA_CODEC_INVALID }; #define Nv_VERB_SET_Channel_Allocation 0xF79 @@ -43,15 +44,18 @@ struct nvhdmi_spec { #define Nv_VERB_SET_Audio_Protection_On 0xF98 #define Nv_VERB_SET_Audio_Protection_Off 0xF99 -#define Nv_Master_Convert_nid 0x04 -#define Nv_Master_Pin_nid 0x05 +#define nvhdmi_master_con_nid_7x 0x04 +#define nvhdmi_master_pin_nid_7x 0x05 -static hda_nid_t nvhdmi_convert_nids[4] = { +#define nvhdmi_master_con_nid_89 0x04 +#define nvhdmi_master_pin_nid_89 0x05 + +static hda_nid_t nvhdmi_con_nids_7x[4] = { /*front, rear, clfe, rear_surr */ 0x6, 0x8, 0xa, 0xc, }; -static struct hda_verb nvhdmi_basic_init[] = { +static struct hda_verb nvhdmi_basic_init_7x[] = { /* set audio protect on */ { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, /* enable digital output on pin widget */ @@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = { (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) #endif +#define NVIDIA_89_HDMI_CVTS 1 +#define NVIDIA_89_HDMI_PINS 1 + +static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = { + "NVIDIA HDMI", +}; + +struct nvhdmi_spec { + int num_cvts; + int num_pins; + hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1]; /* audio sources */ + hda_nid_t pin[NVIDIA_89_HDMI_PINS+1]; /* audio sinks */ + hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1]; + struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS]; + struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS]; + struct hda_multi_out multiout; + unsigned int codec_type; +}; + +struct hdmi_audio_infoframe { + u8 type; /* 0x84 */ + u8 ver; /* 0x01 */ + u8 len; /* 0x0a */ + + u8 checksum; /* PB0 */ + u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ + u8 SS01_SF24; + u8 CXT04; + u8 CA; + u8 LFEPBL01_LSV36_DM_INH7; +}; + +/* + * CEA speaker placement: + * + * FLH FCH FRH + * FLW FL FLC FC FRC FR FRW + * + * LFE + * TC + * + * RL RLC RC RRC RR + * + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. + */ +enum cea_speaker_placement { + FL = (1 << 0), /* Front Left */ + FC = (1 << 1), /* Front Center */ + FR = (1 << 2), /* Front Right */ + FLC = (1 << 3), /* Front Left Center */ + FRC = (1 << 4), /* Front Right Center */ + RL = (1 << 5), /* Rear Left */ + RC = (1 << 6), /* Rear Center */ + RR = (1 << 7), /* Rear Right */ + RLC = (1 << 8), /* Rear Left Center */ + RRC = (1 << 9), /* Rear Right Center */ + LFE = (1 << 10), /* Low Frequency Effect */ + FLW = (1 << 11), /* Front Left Wide */ + FRW = (1 << 12), /* Front Right Wide */ + FLH = (1 << 13), /* Front Left High */ + FCH = (1 << 14), /* Front Center High */ + FRH = (1 << 15), /* Front Right High */ + TC = (1 << 16), /* Top Center */ +}; + +/* + * ELD SA bits in the CEA Speaker Allocation data block + */ +static int eld_speaker_allocation_bits[] = { + [0] = FL | FR, + [1] = LFE, + [2] = FC, + [3] = RL | RR, + [4] = RC, + [5] = FLC | FRC, + [6] = RLC | RRC, + /* the following are not defined in ELD yet */ + [7] = FLW | FRW, + [8] = FLH | FRH, + [9] = TC, + [10] = FCH, +}; + +struct cea_channel_speaker_allocation { + int ca_index; + int speakers[8]; + + /* derived values, just for convenience */ + int channels; + int spk_mask; +}; + +/* + * ALSA sequence is: + * + * surround40 surround41 surround50 surround51 surround71 + * ch0 front left = = = = + * ch1 front right = = = = + * ch2 rear left = = = = + * ch3 rear right = = = = + * ch4 LFE center center center + * ch5 LFE LFE + * ch6 side left + * ch7 side right + * + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} + */ +static int hdmi_channel_mapping[0x32][8] = { + /* stereo */ + [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* 2.1 */ + [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* Dolby Surround */ + [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* surround40 */ + [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, + /* 4ch */ + [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, + /* surround41 */ + [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround50 */ + [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround51 */ + [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, + /* 7.1 */ + [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 }, +}; + +/* + * This is an ordered list! + * + * The preceding ones have better chances to be selected by + * hdmi_setup_channel_allocation(). + */ +static struct cea_channel_speaker_allocation channel_allocations[] = { +/* channel: 7 6 5 4 3 2 1 0 */ +{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, + /* 2.1 */ +{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, + /* Dolby Surround */ +{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, + /* surround40 */ +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, + /* surround41 */ +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, + /* surround50 */ +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, + /* surround51 */ +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, + /* 6.1 */ +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, + /* surround71 */ +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, + +{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, +{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, +{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, +{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, +}; + +/* + * HDA/HDMI auto parsing + */ + +static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) +{ + int i; + + for (i = 0; nids[i]; i++) + if (nids[i] == nid) + return i; + + snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); + return -EINVAL; +} + +static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct nvhdmi_spec *spec = codec->spec; + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; + int conn_len, curr; + int index; + + if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { + snd_printk(KERN_WARNING + "HDMI: pin %d wcaps %#x " + "does not support connection list\n", + pin_nid, get_wcaps(codec, pin_nid)); + return -EINVAL; + } + + conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, + HDA_MAX_CONNECTIONS); + if (conn_len > 1) + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + else + curr = 0; + + index = hda_node_index(spec->pin, pin_nid); + if (index < 0) + return -EINVAL; + + spec->pin_cvt[index] = conn_list[curr]; + + return 0; +} + +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + if (!snd_hdmi_get_eld(eld, codec, pin_nid)) + snd_hdmi_show_eld(eld); +} + +static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + int present = snd_hda_pin_sense(codec, pin_nid); + + eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); + eld->eld_valid = !!(present & AC_PINSENSE_ELDV); + + if (present & AC_PINSENSE_ELDV) + hdmi_get_show_eld(codec, pin_nid, eld); +} + +static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct nvhdmi_spec *spec = codec->spec; + + if (spec->num_pins >= NVIDIA_89_HDMI_PINS) { + snd_printk(KERN_WARNING + "HDMI: no space for pin %d \n", pin_nid); + return -EINVAL; + } + + hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); + + spec->pin[spec->num_pins] = pin_nid; + spec->num_pins++; + + /* + * It is assumed that converter nodes come first in the node list and + * hence have been registered and usable now. + */ + return nvhdmi_read_pin_conn(codec, pin_nid); +} + +static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) +{ + struct nvhdmi_spec *spec = codec->spec; + + if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) { + snd_printk(KERN_WARNING + "HDMI: no space for converter %d \n", nid); + return -EINVAL; + } + + spec->cvt[spec->num_cvts] = nid; + spec->num_cvts++; + + return 0; +} + + +static int nvhdmi_parse_codec(struct hda_codec *codec) +{ + hda_nid_t nid; + int i, nodes; + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (!nid || nodes < 0) { + snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); + return -EINVAL; + } + + for (i = 0; i < nodes; i++, nid++) { + unsigned int caps; + unsigned int type; + + caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + + switch (type) { + case AC_WID_AUD_OUT: + if (nvhdmi_add_cvt(codec, nid) < 0) + return -EINVAL; + break; + case AC_WID_PIN: + caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) + continue; + if (nvhdmi_add_pin(codec, nid) < 0) + return -EINVAL; + break; + } + } + + /* + * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event + * can be lost and presence sense verb will become inaccurate if the + * HDA link is powered off at hot plug or hw initialization time. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & + AC_PWRST_EPSS)) + codec->bus->power_keep_link_on = 1; +#endif + + return 0; +} + +/* + * HDMI routines + */ + +#ifdef BE_PARANOID +static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int *packet_index, int *byte_index) +{ + int val; + + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_INDEX, 0); + + *packet_index = val >> 5; + *byte_index = val & 0x1f; +} +#endif + +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int packet_index, int byte_index) +{ + int val; + + val = (packet_index << 5) | (byte_index & 0x1f); + + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); +} + +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, + unsigned char val) +{ + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); +} + +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) +{ + /* Unmute */ + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + /* Enable pin out */ + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); +} + +/* + * Enable Audio InfoFrame Transmission + */ +static void hdmi_start_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_BEST); +} + +/* + * Disable Audio InfoFrame Transmission + */ +static void hdmi_stop_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_DISABLE); +} + +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) +{ + return 1 + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CVT_CHAN_COUNT, 0); +} + +static void hdmi_set_channel_count(struct hda_codec *codec, + hda_nid_t nid, int chs) +{ + if (chs != hdmi_get_channel_count(codec, nid)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); +} + +static void hdmi_debug_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int slot; + + for (i = 0; i < 8; i++) { + slot = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_CHAN_SLOT, i); + printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", + slot >> 4, slot & 0xf); + } +#endif +} + + +/* + * Audio InfoFrame routines + */ + +static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int size; + + size = snd_hdmi_get_eld_size(codec, pin_nid); + printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); + + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); + } +#endif +} + +static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef BE_PARANOID + int i, j; + int size; + int pi, bi; + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + if (size == 0) + continue; + + hdmi_set_dip_index(codec, pin_nid, i, 0x0); + for (j = 1; j < 1000; j++) { + hdmi_write_dip_byte(codec, pin_nid, 0x0); + hdmi_get_dip_index(codec, pin_nid, &pi, &bi); + if (pi != i) + snd_printd(KERN_INFO "dip index %d: %d != %d\n", + bi, pi, i); + if (bi == 0) /* byte index wrapped around */ + break; + } + snd_printd(KERN_INFO + "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", + i, size, j); + } +#endif +} + +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) +{ + ai->checksum = 0; +} + +static void hdmi_fill_audio_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + int i; + + hdmi_debug_dip_size(codec, pin_nid); + hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ + + hdmi_checksum_audio_infoframe(ai); + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) + hdmi_write_dip_byte(codec, pin_nid, bytes[i]); +} + +/* + * Compute derived values in channel_allocations[]. + */ +static void init_channel_allocations(void) +{ + int i, j; + struct cea_channel_speaker_allocation *p; + + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + p = channel_allocations + i; + p->channels = 0; + p->spk_mask = 0; + for (j = 0; j < ARRAY_SIZE(p->speakers); j++) + if (p->speakers[j]) { + p->channels++; + p->spk_mask |= p->speakers[j]; + } + } +} + +/* + * The transformation takes two steps: + * + * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask + * spk_mask => (channel_allocations[]) => ai->CA + * + * TODO: it could select the wrong CA from multiple candidates. +*/ +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, + struct hdmi_audio_infoframe *ai) +{ + struct nvhdmi_spec *spec = codec->spec; + struct hdmi_eld *eld; + int i; + int spk_mask = 0; + int channels = 1 + (ai->CC02_CT47 & 0x7); + char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; + + /* + * CA defaults to 0 for basic stereo audio + */ + if (channels <= 2) + return 0; + + i = hda_node_index(spec->pin_cvt, nid); + if (i < 0) + return 0; + eld = &spec->sink_eld[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 (!eld->spk_alloc) + eld->spk_alloc = 0xffff; + + /* + * expand ELD's speaker allocation mask + * + * ELD tells the speaker mask in a compact(paired) form, + * expand ELD's notions to match the ones used by Audio InfoFrame. + */ + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { + if (eld->spk_alloc & (1 << i)) + spk_mask |= eld_speaker_allocation_bits[i]; + } + + /* search for the first working match in the CA table */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels && + (spk_mask & channel_allocations[i].spk_mask) == + channel_allocations[i].spk_mask) { + ai->CA = channel_allocations[i].ca_index; + break; + } + } + + snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); + snd_printdd(KERN_INFO + "HDMI: select CA 0x%x for %d-channel allocation: %s\n", + ai->CA, channels, buf); + + return ai->CA; +} + +static void hdmi_setup_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + int i; + int ca = ai->CA; + int err; + + if (hdmi_channel_mapping[ca][1] == 0) { + for (i = 0; i < channel_allocations[ca].channels; i++) + hdmi_channel_mapping[ca][i] = i | (i << 4); + for (; i < 8; i++) + hdmi_channel_mapping[ca][i] = 0xf | (i << 4); + } + + for (i = 0; i < 8; i++) { + err = snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_HDMI_CHAN_SLOT, + hdmi_channel_mapping[ca][i]); + if (err) { + snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + break; + } + } + + hdmi_debug_channel_mapping(codec, pin_nid); +} + +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 val; + int i; + + if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) + != AC_DIPXMIT_BEST) + return false; + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) { + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_DATA, 0); + if (val != bytes[i]) + return false; + } + + return true; +} + +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, + struct snd_pcm_substream *substream) +{ + struct nvhdmi_spec *spec = codec->spec; + hda_nid_t pin_nid; + int i; + struct hdmi_audio_infoframe ai = { + .type = 0x84, + .ver = 0x01, + .len = 0x0a, + .CC02_CT47 = substream->runtime->channels - 1, + }; + + hdmi_setup_channel_allocation(codec, nid, &ai); + + for (i = 0; i < spec->num_pins; i++) { + if (spec->pin_cvt[i] != nid) + continue; + if (!spec->sink_eld[i].monitor_present) + continue; + + pin_nid = spec->pin[i]; + if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + hdmi_setup_channel_mapping(codec, pin_nid, &ai); + hdmi_stop_infoframe_trans(codec, pin_nid); + hdmi_fill_audio_infoframe(codec, pin_nid, &ai); + hdmi_start_infoframe_trans(codec, pin_nid); + } + } +} + +/* + * Unsolicited events + */ + +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + struct nvhdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int pind = !!(res & AC_UNSOL_RES_PD); + int eldv = !!(res & AC_UNSOL_RES_ELDV); + int index; + + printk(KERN_INFO + "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", + tag, pind, eldv); + + index = hda_node_index(spec->pin, tag); + if (index < 0) + return; + + spec->sink_eld[index].monitor_present = pind; + spec->sink_eld[index].eld_valid = eldv; + + if (eldv) { + spec->sink_eld[index].monitor_present = 1; + hdmi_get_show_eld(codec, spec->pin[index], + &spec->sink_eld[index]); + /* TODO: do real things about ELD */ + } +} + +static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); + int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); + + printk(KERN_INFO + "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", + tag, + subtag, + cp_state, + cp_ready); + + /* TODO */ + if (cp_state) + ; + if (cp_ready) + ; +} + +static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res) +{ + struct nvhdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + + if (hda_node_index(spec->pin, tag) < 0) { + snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); + return; + } + + if (subtag == 0) + hdmi_intrinsic_event(codec, res); + else + hdmi_non_intrinsic_event(codec, res); +} + +/* + * Callbacks + */ + +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, int format) +{ + int tag; + int fmt; + + tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; + fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); + + snd_printdd("hdmi_setup_stream: " + "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", + nid, + tag == stream_tag ? "" : "new-", + stream_tag, + fmt == format ? "" : "new-", + format); + + if (tag != stream_tag) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + stream_tag << 4); + if (fmt != format) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, format); +} + /* * Controls */ @@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec) { struct nvhdmi_spec *spec = codec->spec; int err; + int i; - err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); - if (err < 0) - return err; + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; i < codec->num_pcms; i++) { + err = snd_hda_create_spdif_out_ctls(codec, + spec->cvt[i]); + if (err < 0) + return err; + } + } else { + err = snd_hda_create_spdif_out_ctls(codec, + spec->multiout.dig_out_nid); + if (err < 0) + return err; + } return 0; } static int nvhdmi_init(struct hda_codec *codec) { - snd_hda_sequence_write(codec, nvhdmi_basic_init); + struct nvhdmi_spec *spec = codec->spec; + int i; + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; spec->pin[i]; i++) { + hdmi_enable_output(codec, spec->pin[i]); + snd_hda_codec_write(codec, spec->pin[i], 0, + AC_VERB_SET_UNSOLICITED_ENABLE, + AC_USRSP_EN | spec->pin[i]); + } + } else { + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); + } return 0; } +static void nvhdmi_free(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec = codec->spec; + int i; + + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; i < spec->num_pins; i++) + snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); + } + + kfree(spec); +} + /* * Digital out */ @@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, +static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { struct nvhdmi_spec *spec = codec->spec; int i; - snd_hda_codec_write(codec, Nv_Master_Convert_nid, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); for (i = 0; i < 4; i++) { /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, + snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID, 0); /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, + snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, 0); } @@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + hdmi_set_channel_count(codec, hinfo->nid, + substream->runtime->channels); + + hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); + + hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); + return 0; +} + static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); /* set the stream format */ - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_STREAM_FORMAT, format); /* turn on again (if needed) */ /* enable and set the channel status audio/data flag */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | channel_id); /* set the stream format */ snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, format); @@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, return 0; } +static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + return 0; +} + static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, format, substream); } -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { + .substreams = 1, + .channels_min = 2, + .rates = SUPPORTED_RATES, + .maxbps = SUPPORTED_MAXBPS, + .formats = SUPPORTED_FORMATS, + .ops = { + .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, + .cleanup = nvhdmi_playback_pcm_cleanup, + }, +}; + +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { .substreams = 1, .channels_min = 2, .channels_max = 8, - .nid = Nv_Master_Convert_nid, + .nid = nvhdmi_master_con_nid_7x, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, .ops = { .open = nvhdmi_dig_playback_pcm_open, - .close = nvhdmi_dig_playback_pcm_close_8ch, + .close = nvhdmi_dig_playback_pcm_close_8ch_7x, .prepare = nvhdmi_dig_playback_pcm_prepare_8ch }, }; @@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { .substreams = 1, .channels_min = 2, .channels_max = 2, - .nid = Nv_Master_Convert_nid, + .nid = nvhdmi_master_con_nid_7x, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, @@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { }, }; -static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) +static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; + int i; + + codec->num_pcms = spec->num_cvts; + codec->pcm_info = info; + + for (i = 0; i < codec->num_pcms; i++, info++) { + unsigned int chans; + + chans = get_wcaps(codec, spec->cvt[i]); + chans = get_wcaps_channels(chans); + + info->name = nvhdmi_pcm_names[i]; + info->pcm_type = HDA_PCM_TYPE_HDMI; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] + = nvhdmi_pcm_digital_playback_8ch_89; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; + } + + return 0; +} + +static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) { struct nvhdmi_spec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm_rec; + struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) info->name = "NVIDIA HDMI"; info->pcm_type = HDA_PCM_TYPE_HDMI; info->stream[SNDRV_PCM_STREAM_PLAYBACK] - = nvhdmi_pcm_digital_playback_8ch; + = nvhdmi_pcm_digital_playback_8ch_7x; return 0; } @@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) { struct nvhdmi_spec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm_rec; + struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) return 0; } -static void nvhdmi_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} +static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { + .build_controls = nvhdmi_build_controls, + .build_pcms = nvhdmi_build_pcms_8ch_89, + .init = nvhdmi_init, + .free = nvhdmi_free, + .unsol_event = nvhdmi_unsol_event, +}; -static struct hda_codec_ops nvhdmi_patch_ops_8ch = { +static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { .build_controls = nvhdmi_build_controls, - .build_pcms = nvhdmi_build_pcms_8ch, + .build_pcms = nvhdmi_build_pcms_8ch_7x, .init = nvhdmi_init, .free = nvhdmi_free, }; @@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { .free = nvhdmi_free, }; -static int patch_nvhdmi_8ch(struct hda_codec *codec) +static int patch_nvhdmi_8ch_89(struct hda_codec *codec) +{ + struct nvhdmi_spec *spec; + int i; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + spec->codec_type = HDA_CODEC_NVIDIA_MCP89; + + if (nvhdmi_parse_codec(codec) < 0) { + codec->spec = NULL; + kfree(spec); + return -EINVAL; + } + codec->patch_ops = nvhdmi_patch_ops_8ch_89; + + for (i = 0; i < spec->num_pins; i++) + snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); + + init_channel_allocations(); + + return 0; +} + +static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) { struct nvhdmi_spec *spec; @@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 8; - spec->multiout.dig_out_nid = Nv_Master_Convert_nid; + spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; + spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; - codec->patch_ops = nvhdmi_patch_ops_8ch; + codec->patch_ops = nvhdmi_patch_ops_8ch_7x; return 0; } @@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = Nv_Master_Convert_nid; + spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; + spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; codec->patch_ops = nvhdmi_patch_ops_2ch; @@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) * patch entries */ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { - { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, + { .id = 0x10de0002, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0003, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0005, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0006, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0007, .name = "MCP79/7A HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de000c, .name = "MCP89 HDMI", + .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000b, .name = "GT21x HDMI", + .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000d, .name = "GT240 HDMI", + .patch = patch_nvhdmi_8ch_89 }, {} /* terminator */ }; @@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"); MODULE_ALIAS("snd-hda-codec-id:10de0007"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); +MODULE_ALIAS("snd-hda-codec-id:10de000c"); +MODULE_ALIAS("snd-hda-codec-id:10de000b"); +MODULE_ALIAS("snd-hda-codec-id:10de000d"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); +MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); static struct hda_codec_preset_list nvhdmi_list = { .preset = snd_hda_preset_nvhdmi, From dd74b4653597d1d321efa13935cb029b4d819343 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 Mar 2010 16:05:24 +0100 Subject: [PATCH 018/114] ALSA: hda - Build hda_eld into snd-hda-codec module Now two modules require hda_eld.o, so we need to put it to the common place instead of building into two individual modules. Signed-off-by: Takashi Iwai --- sound/pci/hda/Makefile | 6 +++--- sound/pci/hda/hda_eld.c | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 199f4405b3ad..24bc195b02da 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o snd-hda-codec-y := hda_codec.o snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o -# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o +snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o @@ -17,8 +17,8 @@ snd-hda-codec-cirrus-objs := patch_cirrus.o snd-hda-codec-ca0110-objs := patch_ca0110.o snd-hda-codec-conexant-objs := patch_conexant.o snd-hda-codec-via-objs := patch_via.o -snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o hda_eld.o -snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o +snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o +snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o # common driver obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4228f2fe5956..dcd22446cfc7 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -331,6 +331,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, AC_DIPSIZE_ELD_BUF); } +EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); int snd_hdmi_get_eld(struct hdmi_eld *eld, struct hda_codec *codec, hda_nid_t nid) @@ -366,6 +367,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, kfree(buf); return ret; } +EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); static void hdmi_show_short_audio_desc(struct cea_sad *a) { @@ -404,6 +406,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) } buf[j] = '\0'; /* necessary when j == 0 */ } +EXPORT_SYMBOL_HDA(snd_print_channel_allocation); void snd_hdmi_show_eld(struct hdmi_eld *e) { @@ -422,6 +425,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) for (i = 0; i < e->sad_count; i++) hdmi_show_short_audio_desc(e->sad + i); } +EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); #ifdef CONFIG_PROC_FS @@ -580,6 +584,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, return 0; } +EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) { @@ -588,5 +593,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) eld->proc_entry = NULL; } } +EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); #endif /* CONFIG_PROC_FS */ From 9919c7619c52d01e89103bca405cc3d4a2b1ac31 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 3 Mar 2010 18:24:26 -0500 Subject: [PATCH 019/114] ALSA: hda: Use LPIB for Dell Latitude 131L BugLink: https://launchpad.net/bugs/530346 The OR has verified that position_fix=1 is necessary to work around errors on his machine. Reported-by: Tom Louwrier Cc: Signed-off-by: Daniel T Chen 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 b1047570e78d..531a0b6a66c1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2268,6 +2268,7 @@ static int azx_dev_free(struct snd_device *device) static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), From 50152dfaa7d09da85588b66fee7e8c7f541f631d Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Thu, 4 Mar 2010 20:33:07 +0200 Subject: [PATCH 020/114] ALSA: fix jazz16 compile (udelay) While trying to compile jazz16 isa sound driver on alpha (2.6.33+git), I found a compile failure in jazz16.c (udelay is unknown). Fix it by including delay.h. Signed-foo-by: Meelis Roos Signed-off-by: Takashi Iwai --- sound/isa/sb/jazz16.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 8d21a3feda3a..8ccbcddf08e1 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include From 2b9ddcb8b2ce6a44f0f969000f16b016caa64294 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 4 Mar 2010 19:46:18 +0100 Subject: [PATCH 021/114] ALSA: usb/audio.h: Fix field order Signed-off-by: Daniel Mack Cc: Clemens Ladisch Signed-off-by: Takashi Iwai --- include/linux/usb/audio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h index 6bb293684eb8..4d3e450e2b03 100644 --- a/include/linux/usb/audio.h +++ b/include/linux/usb/audio.h @@ -269,8 +269,8 @@ struct uac_format_type_i_ext_descriptor { __u8 bLength; __u8 bDescriptorType; __u8 bDescriptorSubtype; - __u8 bSubslotSize; __u8 bFormatType; + __u8 bSubslotSize; __u8 bBitResolution; __u8 bHeaderLength; __u8 bControlSize; From 0321b69569eadbc13242922925a4316754c5f744 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Fri, 5 Mar 2010 09:04:49 -0500 Subject: [PATCH 022/114] ALSA: hda: Use LPIB for a Biostar Microtech board BugLink: https://launchpad.net/bugs/523953 The OR has verified that position_fix=1 is necessary to work around errors on his machine. Reported-by: MMarking Cc: Signed-off-by: Daniel T Chen 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 531a0b6a66c1..c24bffa08c84 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2273,6 +2273,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), {} }; From d2db09b87eb7b547136d5d25ff1df06820e070bf Mon Sep 17 00:00:00 2001 From: Frederik Deweerdt Date: Fri, 5 Mar 2010 16:34:31 +0100 Subject: [PATCH 023/114] ALSA: hda: uninitialized variable fix Commit eaa9b3a748539651f50e3a234c8854e1b42a839a introduced the following uninitialized warning: sound/pci/hda/patch_realtek.c: In function 'set_capture_mixer': sound/pci/hda/patch_realtek.c:4928: warning: 'pin' is used uninitialized in this function sound/pci/hda/patch_realtek.c:4918: note: 'pin' was declared here It appears indeed that 'pin' needs to be initialized to 0. Signed-off-by: Frederik Deweerdt Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b9f4689ccd9a..5d2fbb87b871 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4915,7 +4915,7 @@ static void fixup_automic_adc(struct hda_codec *codec) static void fixup_single_adc(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - hda_nid_t pin; + hda_nid_t pin = 0; int i; /* search for the input pin; there must be only one */ From c90bf2aa94c08a0f48874f64ebdeb5fe973cf02e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sun, 29 Nov 2009 16:58:38 +0200 Subject: [PATCH 024/114] [WATCHDOG] ep93xx: implemented watchdog timer driver for TS-72xx SBCs Technologic Systems TS-72xx SBCs have external glue logic CPLD which includes watchdog timer. This driver implements kernel support for that. Signed-off-by: Mika Westerberg Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/ts72xx_wdt.c | 516 ++++++++++++++++++++++++++++++++++ 3 files changed, 528 insertions(+) create mode 100644 drivers/watchdog/ts72xx_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 3da3f48720a7..1e48d4c45f86 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -289,6 +289,17 @@ config ADX_WATCHDOG Say Y here if you want support for the watchdog timer on Avionic Design Xanthos boards. +config TS72XX_WATCHDOG + tristate "TS-72XX SBC Watchdog" + depends on MACH_TS72XX + help + Technologic Systems TS-7200, TS-7250 and TS-7260 boards have + watchdog timer implemented in a external CPLD chip. Say Y here + if you want to support for the watchdog timer on TS-72XX boards. + + To compile this driver as a module, choose M here: the + module will be called ts72xx_wdt. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 475c61100069..2fd15947deb7 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o +obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c new file mode 100644 index 000000000000..c4a4d37f85af --- /dev/null +++ b/drivers/watchdog/ts72xx_wdt.c @@ -0,0 +1,516 @@ +/* + * Watchdog driver for Technologic Systems TS-72xx based SBCs + * (TS-7200, TS-7250 and TS-7260). These boards have external + * glue logic CPLD chip, which includes programmable watchdog + * timer. + * + * Copyright (c) 2009 Mika Westerberg + * + * This driver is based on ep93xx_wdt and wm831x_wdt drivers. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define TS72XX_WDT_FEED_VAL 0x05 +#define TS72XX_WDT_DEFAULT_TIMEOUT 8 + +static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. " + "(1 <= timeout <= 8, default=" + __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT) + ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +/** + * struct ts72xx_wdt - watchdog control structure + * @lock: lock that protects this structure + * @regval: watchdog timeout value suitable for control register + * @flags: flags controlling watchdog device state + * @control_reg: watchdog control register + * @feed_reg: watchdog feed register + * @pdev: back pointer to platform dev + */ +struct ts72xx_wdt { + struct mutex lock; + int regval; + +#define TS72XX_WDT_BUSY_FLAG 1 +#define TS72XX_WDT_EXPECT_CLOSE_FLAG 2 + int flags; + + void __iomem *control_reg; + void __iomem *feed_reg; + + struct platform_device *pdev; +}; + +struct platform_device *ts72xx_wdt_pdev; + +/* + * TS-72xx Watchdog supports following timeouts (value written + * to control register): + * value description + * ------------------------- + * 0x00 watchdog disabled + * 0x01 250ms + * 0x02 500ms + * 0x03 1s + * 0x04 reserved + * 0x05 2s + * 0x06 4s + * 0x07 8s + * + * Timeouts below 1s are not very usable so we don't + * allow them at all. + * + * We provide two functions that convert between these: + * timeout_to_regval() and regval_to_timeout(). + */ +static const struct { + int timeout; + int regval; +} ts72xx_wdt_map[] = { + { 1, 3 }, + { 2, 5 }, + { 4, 6 }, + { 8, 7 }, +}; + +/** + * timeout_to_regval() - converts given timeout to control register value + * @new_timeout: timeout in seconds to be converted + * + * Function converts given @new_timeout into valid value that can + * be programmed into watchdog control register. When conversion is + * not possible, function returns %-EINVAL. + */ +static int timeout_to_regval(int new_timeout) +{ + int i; + + /* first limit it to 1 - 8 seconds */ + new_timeout = clamp_val(new_timeout, 1, 8); + + for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { + if (ts72xx_wdt_map[i].timeout >= new_timeout) + return ts72xx_wdt_map[i].regval; + } + + return -EINVAL; +} + +/** + * regval_to_timeout() - converts control register value to timeout + * @regval: control register value to be converted + * + * Function converts given @regval to timeout in seconds (1, 2, 4 or 8). + * If @regval cannot be converted, function returns %-EINVAL. + */ +static int regval_to_timeout(int regval) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { + if (ts72xx_wdt_map[i].regval == regval) + return ts72xx_wdt_map[i].timeout; + } + + return -EINVAL; +} + +/** + * ts72xx_wdt_kick() - kick the watchdog + * @wdt: watchdog to be kicked + * + * Called with @wdt->lock held. + */ +static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt) +{ + __raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg); +} + +/** + * ts72xx_wdt_start() - starts the watchdog timer + * @wdt: watchdog to be started + * + * This function programs timeout to watchdog timer + * and starts it. + * + * Called with @wdt->lock held. + */ +static void ts72xx_wdt_start(struct ts72xx_wdt *wdt) +{ + /* + * To program the wdt, it first must be "fed" and + * only after that (within 30 usecs) the configuration + * can be changed. + */ + ts72xx_wdt_kick(wdt); + __raw_writeb((u8)wdt->regval, wdt->control_reg); +} + +/** + * ts72xx_wdt_stop() - stops the watchdog timer + * @wdt: watchdog to be stopped + * + * Called with @wdt->lock held. + */ +static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt) +{ + ts72xx_wdt_kick(wdt); + __raw_writeb(0, wdt->control_reg); +} + +static int ts72xx_wdt_open(struct inode *inode, struct file *file) +{ + struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev); + int regval; + + /* + * Try to convert default timeout to valid register + * value first. + */ + regval = timeout_to_regval(timeout); + if (regval < 0) { + dev_err(&wdt->pdev->dev, + "failed to convert timeout (%d) to register value\n", + timeout); + return -EINVAL; + } + + if (mutex_lock_interruptible(&wdt->lock)) + return -ERESTARTSYS; + + if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) { + mutex_unlock(&wdt->lock); + return -EBUSY; + } + + wdt->flags = TS72XX_WDT_BUSY_FLAG; + wdt->regval = regval; + file->private_data = wdt; + + ts72xx_wdt_start(wdt); + + mutex_unlock(&wdt->lock); + return nonseekable_open(inode, file); +} + +static int ts72xx_wdt_release(struct inode *inode, struct file *file) +{ + struct ts72xx_wdt *wdt = file->private_data; + + if (mutex_lock_interruptible(&wdt->lock)) + return -ERESTARTSYS; + + if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) { + ts72xx_wdt_stop(wdt); + } else { + dev_warn(&wdt->pdev->dev, + "TS-72XX WDT device closed unexpectly. " + "Watchdog timer will not stop!\n"); + /* + * Kick it one more time, to give userland some time + * to recover (for example, respawning the kicker + * daemon). + */ + ts72xx_wdt_kick(wdt); + } + + wdt->flags = 0; + + mutex_unlock(&wdt->lock); + return 0; +} + +static ssize_t ts72xx_wdt_write(struct file *file, + const char __user *data, + size_t len, + loff_t *ppos) +{ + struct ts72xx_wdt *wdt = file->private_data; + + if (!len) + return 0; + + if (mutex_lock_interruptible(&wdt->lock)) + return -ERESTARTSYS; + + ts72xx_wdt_kick(wdt); + + /* + * Support for magic character closing. User process + * writes 'V' into the device, just before it is closed. + * This means that we know that the wdt timer can be + * stopped after user closes the device. + */ + if (!nowayout) { + int i; + + for (i = 0; i < len; i++) { + char c; + + /* In case it was set long ago */ + wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG; + + if (get_user(c, data + i)) { + mutex_unlock(&wdt->lock); + return -EFAULT; + } + if (c == 'V') { + wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG; + break; + } + } + } + + mutex_unlock(&wdt->lock); + return len; +} + +static const struct watchdog_info winfo = { + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "TS-72XX WDT", +}; + +static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct ts72xx_wdt *wdt = file->private_data; + void __user *argp = (void __user *)arg; + int __user *p = (int __user *)argp; + int error = 0; + + if (mutex_lock_interruptible(&wdt->lock)) + return -ERESTARTSYS; + + switch (cmd) { + case WDIOC_GETSUPPORT: + error = copy_to_user(argp, &winfo, sizeof(winfo)); + break; + + case WDIOC_KEEPALIVE: + ts72xx_wdt_kick(wdt); + break; + + case WDIOC_SETOPTIONS: { + int options; + + if (get_user(options, p)) { + error = -EFAULT; + break; + } + + error = -EINVAL; + + if ((options & WDIOS_DISABLECARD) != 0) { + ts72xx_wdt_stop(wdt); + error = 0; + } + if ((options & WDIOS_ENABLECARD) != 0) { + ts72xx_wdt_start(wdt); + error = 0; + } + + break; + } + + case WDIOC_SETTIMEOUT: { + int new_timeout; + + if (get_user(new_timeout, p)) { + error = -EFAULT; + } else { + int regval; + + regval = timeout_to_regval(new_timeout); + if (regval < 0) { + error = -EINVAL; + } else { + ts72xx_wdt_stop(wdt); + wdt->regval = regval; + ts72xx_wdt_start(wdt); + } + } + if (error) + break; + + /*FALLTHROUGH*/ + } + + case WDIOC_GETTIMEOUT: + if (put_user(regval_to_timeout(wdt->regval), p)) + error = -EFAULT; + break; + + default: + error = -ENOTTY; + break; + } + + mutex_unlock(&wdt->lock); + return error; +} + +static const struct file_operations ts72xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = ts72xx_wdt_open, + .release = ts72xx_wdt_release, + .write = ts72xx_wdt_write, + .unlocked_ioctl = ts72xx_wdt_ioctl, +}; + +static struct miscdevice ts72xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ts72xx_wdt_fops, +}; + +static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) +{ + struct ts72xx_wdt *wdt; + struct resource *r1, *r2; + int error = 0; + + wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL); + if (!wdt) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r1) { + dev_err(&pdev->dev, "failed to get memory resource\n"); + error = -ENODEV; + goto fail; + } + + r1 = request_mem_region(r1->start, resource_size(r1), pdev->name); + if (!r1) { + dev_err(&pdev->dev, "cannot request memory region\n"); + error = -EBUSY; + goto fail; + } + + wdt->control_reg = ioremap(r1->start, resource_size(r1)); + if (!wdt->control_reg) { + dev_err(&pdev->dev, "failed to map memory\n"); + error = -ENODEV; + goto fail_free_control; + } + + r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r2) { + dev_err(&pdev->dev, "failed to get memory resource\n"); + error = -ENODEV; + goto fail_unmap_control; + } + + r2 = request_mem_region(r2->start, resource_size(r2), pdev->name); + if (!r2) { + dev_err(&pdev->dev, "cannot request memory region\n"); + error = -EBUSY; + goto fail_unmap_control; + } + + wdt->feed_reg = ioremap(r2->start, resource_size(r2)); + if (!wdt->feed_reg) { + dev_err(&pdev->dev, "failed to map memory\n"); + error = -ENODEV; + goto fail_free_feed; + } + + platform_set_drvdata(pdev, wdt); + ts72xx_wdt_pdev = pdev; + wdt->pdev = pdev; + mutex_init(&wdt->lock); + + error = misc_register(&ts72xx_wdt_miscdev); + if (error) { + dev_err(&pdev->dev, "failed to register miscdev\n"); + goto fail_unmap_feed; + } + + dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); + + return 0; + +fail_unmap_feed: + platform_set_drvdata(pdev, NULL); + iounmap(wdt->feed_reg); +fail_free_feed: + release_mem_region(r2->start, resource_size(r2)); +fail_unmap_control: + iounmap(wdt->control_reg); +fail_free_control: + release_mem_region(r1->start, resource_size(r1)); +fail: + kfree(wdt); + return error; +} + +static __devexit int ts72xx_wdt_remove(struct platform_device *pdev) +{ + struct ts72xx_wdt *wdt = platform_get_drvdata(pdev); + struct resource *res; + int error; + + error = misc_deregister(&ts72xx_wdt_miscdev); + platform_set_drvdata(pdev, NULL); + + iounmap(wdt->control_reg); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + iounmap(wdt->feed_reg); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + release_mem_region(res->start, resource_size(res)); + + kfree(wdt); + return error; +} + +static struct platform_driver ts72xx_wdt_driver = { + .probe = ts72xx_wdt_probe, + .remove = __devexit_p(ts72xx_wdt_remove), + .driver = { + .name = "ts72xx-wdt", + .owner = THIS_MODULE, + }, +}; + +static __init int ts72xx_wdt_init(void) +{ + return platform_driver_register(&ts72xx_wdt_driver); +} +module_init(ts72xx_wdt_init); + +static __exit void ts72xx_wdt_exit(void) +{ + platform_driver_unregister(&ts72xx_wdt_driver); +} +module_exit(ts72xx_wdt_exit); + +MODULE_AUTHOR("Mika Westerberg "); +MODULE_DESCRIPTION("TS-72xx SBC Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ts72xx-wdt"); From 12926dc4167a9af460476a0df17f055398c8b871 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sun, 29 Nov 2009 17:03:03 +0200 Subject: [PATCH 025/114] [WATCHDOG] ep93xx: added platform side support for TS-72xx WDT driver Signed-off-by: Mika Westerberg Signed-off-by: Wim Van Sebroeck --- arch/arm/mach-ep93xx/include/mach/ts72xx.h | 2 ++ arch/arm/mach-ep93xx/ts72xx.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h index 3bd934e9a7f1..93107d88ff3a 100644 --- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h +++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h @@ -65,6 +65,8 @@ #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 #define TS72XX_RTC_DATA_SIZE 0x00001000 +#define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000 +#define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000 #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 259f7822ba52..fac1ec7a60fb 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -166,6 +166,26 @@ static struct platform_device ts72xx_rtc_device = { .num_resources = 0, }; +static struct resource ts72xx_wdt_resources[] = { + { + .start = TS72XX_WDT_CONTROL_PHYS_BASE, + .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = TS72XX_WDT_FEED_PHYS_BASE, + .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ts72xx_wdt_device = { + .name = "ts72xx-wdt", + .id = -1, + .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), + .resource = ts72xx_wdt_resources, +}; + static struct ep93xx_eth_data ts72xx_eth_data = { .phy_id = 1, }; @@ -175,6 +195,7 @@ static void __init ts72xx_init_machine(void) ep93xx_init_devices(); ts72xx_register_flash(); platform_device_register(&ts72xx_rtc_device); + platform_device_register(&ts72xx_wdt_device); ep93xx_register_eth(&ts72xx_eth_data, 1); } From 66aaa7a5592c0d8ca768c77d15d561bd43f514d8 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 4 Feb 2010 20:08:56 +0000 Subject: [PATCH 026/114] [WATCHDOG] support for max63xx watchdog timer chips This driver adds support for the max63{69,70,71,72,73,74} family of watchdog timer chips. It has been tested on an Arcom Zeus (max6369). Signed-off-by: Marc Zyngier Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 5 + drivers/watchdog/Makefile | 1 + drivers/watchdog/max63xx_wdt.c | 397 +++++++++++++++++++++++++++++++++ 3 files changed, 403 insertions(+) create mode 100644 drivers/watchdog/max63xx_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1e48d4c45f86..713b1cef37d3 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -55,6 +55,11 @@ config SOFT_WATCHDOG To compile this driver as a module, choose M here: the module will be called softdog. +config MAX63XX_WATCHDOG + tristate "Max63xx watchdog" + help + Support for memory mapped max63{69,70,71,72,73,74} watchdog timer. + config WM831X_WATCHDOG tristate "WM831x watchdog" depends on MFD_WM831X diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 2fd15947deb7..5e3cb95bb0e9 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -143,4 +143,5 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o # Architecture Independant obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o +obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c new file mode 100644 index 000000000000..6eb91d757604 --- /dev/null +++ b/drivers/watchdog/max63xx_wdt.c @@ -0,0 +1,397 @@ +/* + * drivers/char/watchdog/max63xx_wdt.c + * + * Driver for max63{69,70,71,72,73,74} watchdog timers + * + * Copyright (C) 2009 Marc Zyngier + * + * 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. + * + * This driver assumes the watchdog pins are memory mapped (as it is + * the case for the Arcom Zeus). Should it be connected over GPIOs or + * another interface, some abstraction will have to be introduced. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_HEARTBEAT 60 +#define MAX_HEARTBEAT 60 + +static int heartbeat = DEFAULT_HEARTBEAT; +static int nowayout = WATCHDOG_NOWAYOUT; + +/* + * Memory mapping: a single byte, 3 first lower bits to select bit 3 + * to ping the watchdog. + */ +#define MAX6369_WDSET (7 << 0) +#define MAX6369_WDI (1 << 3) + +static DEFINE_SPINLOCK(io_lock); + +static unsigned long wdt_status; +#define WDT_IN_USE 0 +#define WDT_RUNNING 1 +#define WDT_OK_TO_CLOSE 2 + +static int nodelay; +static struct resource *wdt_mem; +static void __iomem *wdt_base; +static struct platform_device *max63xx_pdev; + +/* + * The timeout values used are actually the absolute minimum the chip + * offers. Typical values on my board are slightly over twice as long + * (10s setting ends up with a 25s timeout), and can be up to 3 times + * the nominal setting (according to the datasheet). So please take + * these values with a grain of salt. Same goes for the initial delay + * "feature". Only max6373/74 have a few settings without this initial + * delay (selected with the "nodelay" parameter). + * + * I also decided to remove from the tables any timeout smaller than a + * second, as it looked completly overkill... + */ + +/* Timeouts in second */ +struct max63xx_timeout { + u8 wdset; + u8 tdelay; + u8 twd; +}; + +static struct max63xx_timeout max6369_table[] = { + { 5, 1, 1 }, + { 6, 10, 10 }, + { 7, 60, 60 }, + { }, +}; + +static struct max63xx_timeout max6371_table[] = { + { 6, 60, 3 }, + { 7, 60, 60 }, + { }, +}; + +static struct max63xx_timeout max6373_table[] = { + { 2, 60, 1 }, + { 5, 0, 1 }, + { 1, 3, 3 }, + { 7, 60, 10 }, + { 6, 0, 10 }, + { }, +}; + +static struct max63xx_timeout *current_timeout; + +static struct max63xx_timeout * +max63xx_select_timeout(struct max63xx_timeout *table, int value) +{ + while (table->twd) { + if (value <= table->twd) { + if (nodelay && table->tdelay == 0) + return table; + + if (!nodelay) + return table; + } + + table++; + } + + return NULL; +} + +static void max63xx_wdt_ping(void) +{ + u8 val; + + spin_lock(&io_lock); + + val = __raw_readb(wdt_base); + + __raw_writeb(val | MAX6369_WDI, wdt_base); + __raw_writeb(val & ~MAX6369_WDI, wdt_base); + + spin_unlock(&io_lock); +} + +static void max63xx_wdt_enable(struct max63xx_timeout *entry) +{ + u8 val; + + if (test_and_set_bit(WDT_RUNNING, &wdt_status)) + return; + + spin_lock(&io_lock); + + val = __raw_readb(wdt_base); + val &= ~MAX6369_WDSET; + val |= entry->wdset; + __raw_writeb(val, wdt_base); + + spin_unlock(&io_lock); + + /* check for a edge triggered startup */ + if (entry->tdelay == 0) + max63xx_wdt_ping(); +} + +static void max63xx_wdt_disable(void) +{ + spin_lock(&io_lock); + + __raw_writeb(3, wdt_base); + + spin_unlock(&io_lock); + + clear_bit(WDT_RUNNING, &wdt_status); +} + +static int max63xx_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) + return -EBUSY; + + max63xx_wdt_enable(current_timeout); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return nonseekable_open(inode, file); +} + +static ssize_t max63xx_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + set_bit(WDT_OK_TO_CLOSE, &wdt_status); + } + } + + max63xx_wdt_ping(); + } + + return len; +} + +static const struct watchdog_info ident = { + .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, + .identity = "max63xx Watchdog", +}; + +static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + max63xx_wdt_ping(); + ret = 0; + break; + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + } + return ret; +} + +static int max63xx_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + max63xx_wdt_disable(); + else + dev_crit(&max63xx_pdev->dev, + "device closed unexpectedly - timer will not stop\n"); + + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + +static const struct file_operations max63xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = max63xx_wdt_write, + .unlocked_ioctl = max63xx_wdt_ioctl, + .open = max63xx_wdt_open, + .release = max63xx_wdt_release, +}; + +static struct miscdevice max63xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &max63xx_wdt_fops, +}; + +static int __devinit max63xx_wdt_probe(struct platform_device *pdev) +{ + int ret = 0; + int size; + struct resource *res; + struct device *dev = &pdev->dev; + struct max63xx_timeout *table; + + table = (struct max63xx_timeout *)pdev->id_entry->driver_data; + + if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) + heartbeat = DEFAULT_HEARTBEAT; + + dev_info(dev, "requesting %ds heartbeat\n", heartbeat); + current_timeout = max63xx_select_timeout(table, heartbeat); + + if (!current_timeout) { + dev_err(dev, "unable to satisfy heartbeat request\n"); + return -EINVAL; + } + + dev_info(dev, "using %ds heartbeat with %ds initial delay\n", + current_timeout->twd, current_timeout->tdelay); + + heartbeat = current_timeout->twd; + + max63xx_pdev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(dev, "failed to get memory region resource\n"); + return -ENOENT; + } + + size = resource_size(res); + wdt_mem = request_mem_region(res->start, size, pdev->name); + + if (wdt_mem == NULL) { + dev_err(dev, "failed to get memory region\n"); + return -ENOENT; + } + + wdt_base = ioremap(res->start, size); + if (!wdt_base) { + dev_err(dev, "failed to map memory region\n"); + ret = -ENOMEM; + goto out_request; + } + + ret = misc_register(&max63xx_wdt_miscdev); + if (ret < 0) { + dev_err(dev, "cannot register misc device\n"); + goto out_unmap; + } + + return 0; + +out_unmap: + iounmap(wdt_base); +out_request: + release_resource(wdt_mem); + kfree(wdt_mem); + + return ret; +} + +static int __devexit max63xx_wdt_remove(struct platform_device *pdev) +{ + misc_deregister(&max63xx_wdt_miscdev); + if (wdt_mem) { + release_resource(wdt_mem); + kfree(wdt_mem); + wdt_mem = NULL; + } + + if (wdt_base) + iounmap(wdt_base); + + return 0; +} + +static struct platform_device_id max63xx_id_table[] = { + { "max6369_wdt", (kernel_ulong_t)max6369_table, }, + { "max6370_wdt", (kernel_ulong_t)max6369_table, }, + { "max6371_wdt", (kernel_ulong_t)max6371_table, }, + { "max6372_wdt", (kernel_ulong_t)max6371_table, }, + { "max6373_wdt", (kernel_ulong_t)max6373_table, }, + { "max6374_wdt", (kernel_ulong_t)max6373_table, }, + { }, +}; +MODULE_DEVICE_TABLE(platform, max63xx_id_table); + +static struct platform_driver max63xx_wdt_driver = { + .probe = max63xx_wdt_probe, + .remove = __devexit_p(max63xx_wdt_remove), + .id_table = max63xx_id_table, + .driver = { + .name = "max63xx_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init max63xx_wdt_init(void) +{ + return platform_driver_register(&max63xx_wdt_driver); +} + +static void __exit max63xx_wdt_exit(void) +{ + platform_driver_unregister(&max63xx_wdt_driver); +} + +module_init(max63xx_wdt_init); +module_exit(max63xx_wdt_exit); + +MODULE_AUTHOR("Marc Zyngier "); +MODULE_DESCRIPTION("max63xx Watchdog Driver"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, + "Watchdog heartbeat period in seconds from 1 to " + __MODULE_STRING(MAX_HEARTBEAT) ", default " + __MODULE_STRING(DEFAULT_HEARTBEAT)); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +module_param(nodelay, int, 0); +MODULE_PARM_DESC(nodelay, + "Force selection of a timeout setting without initial delay " + "(max6373/74 only, default=0)"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); From f538ed9ea0a54ba2121f35f52d63e4025c534909 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 10 Feb 2010 19:34:05 +0000 Subject: [PATCH 027/114] [WATCHDOG] ep93xx: watchdog timer driver for TS-72xx SBCs cleanup Clean-up driver: * make release the reverse of probe so that both are consistent * add WDIOC_GETSTATUS & WDIOC_GETBOOTSTATUS ioctls. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ts72xx_wdt.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index c4a4d37f85af..565a2c3321e5 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -307,6 +307,10 @@ static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, error = copy_to_user(argp, &winfo, sizeof(winfo)); break; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + case WDIOC_KEEPALIVE: ts72xx_wdt_kick(wdt); break; @@ -477,14 +481,14 @@ static __devexit int ts72xx_wdt_remove(struct platform_device *pdev) error = misc_deregister(&ts72xx_wdt_miscdev); platform_set_drvdata(pdev, NULL); - iounmap(wdt->control_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - iounmap(wdt->feed_reg); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); release_mem_region(res->start, resource_size(res)); + iounmap(wdt->control_reg); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + kfree(wdt); return error; } From ec26985be4a22652c323f264cf570e4fbe3610b6 Mon Sep 17 00:00:00 2001 From: Naga Chumbalkar Date: Tue, 9 Feb 2010 00:42:02 +0100 Subject: [PATCH 028/114] [WATCHDOG] iTCO_wdt: clean up probe(), modify err msg It's possible that the platform is not allowing reboot via TCO timer expiration. Also, differentiate between not finding a chipset that has TCO, and the case where TCO is present but the driver fails to initialize for some reason. Signed-off-by: Naga Chumbalkar Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 4bdb7f1a9077..a619b9b74991 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -698,7 +698,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, if (iTCO_wdt_private.iTCO_version == 2) { pci_read_config_dword(pdev, 0xf0, &base_address); if ((base_address & 1) == 0) { - printk(KERN_ERR PFX "RCBA is disabled by harddware\n"); + printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); ret = -ENODEV; goto out; } @@ -708,8 +708,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* Check chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { - printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " - "reboot disabled by hardware\n"); + printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " + "platform may have disabled it\n"); ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ goto out_unmap; } @@ -805,6 +805,7 @@ static void __devexit iTCO_wdt_cleanup(void) static int __devinit iTCO_wdt_probe(struct platform_device *dev) { + int ret = -ENODEV; int found = 0; struct pci_dev *pdev = NULL; const struct pci_device_id *ent; @@ -814,19 +815,17 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev) for_each_pci_dev(pdev) { ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); if (ent) { - if (!(iTCO_wdt_init(pdev, ent, dev))) { - found++; + found++; + ret = iTCO_wdt_init(pdev, ent, dev); + if (!ret) break; - } } } - if (!found) { + if (!found) printk(KERN_INFO PFX "No card detected\n"); - return -ENODEV; - } - return 0; + return ret; } static int __devexit iTCO_wdt_remove(struct platform_device *dev) From cda61c9420028ddd251b60f1445c9eed756991c7 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Mon, 1 Mar 2010 17:06:20 +0000 Subject: [PATCH 029/114] [WATCHDOG] gef_wdt: Author corrections following split of GE Fanuc joint venture This patch corrects author and copyright notices following the split-up of the GE Fanuc joint venture. Signed-off-by: Martyn Welch Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/gef_wdt.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 713b1cef37d3..bdcdbd53da89 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -861,10 +861,10 @@ config TXX9_WDT # POWERPC Architecture config GEF_WDT - tristate "GE Fanuc Watchdog Timer" + tristate "GE Watchdog Timer" depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A ---help--- - Watchdog timer found in a number of GE Fanuc single board computers. + Watchdog timer found in a number of GE single board computers. config MPC5200_WDT bool "MPC52xx Watchdog Timer" diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 734d9806a872..26447bdeac22 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -1,9 +1,9 @@ /* - * GE Fanuc watchdog userspace interface + * GE watchdog userspace interface * - * Author: Martyn Welch + * Author: Martyn Welch * - * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. * * 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 @@ -165,7 +165,7 @@ static long gef_wdt_ioctl(struct file *file, unsigned int cmd, .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 0, - .identity = "GE Fanuc watchdog", + .identity = "GE watchdog", }; switch (cmd) { @@ -311,7 +311,7 @@ static struct of_platform_driver gef_wdt_driver = { static int __init gef_wdt_init(void) { - printk(KERN_INFO "GE Fanuc watchdog driver\n"); + printk(KERN_INFO "GE watchdog driver\n"); return of_register_platform_driver(&gef_wdt_driver); } @@ -323,8 +323,8 @@ static void __exit gef_wdt_exit(void) module_init(gef_wdt_init); module_exit(gef_wdt_exit); -MODULE_AUTHOR("Martyn Welch "); -MODULE_DESCRIPTION("GE Fanuc watchdog driver"); +MODULE_AUTHOR("Martyn Welch "); +MODULE_DESCRIPTION("GE watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS("platform: gef_wdt"); From 4193d13b2c2b694aa59e629e6daf6269d7922f13 Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Sat, 6 Mar 2010 21:06:46 +0100 Subject: [PATCH 030/114] ALSA: hda - Add ASRock mobo to MSI blacklist This avoids a lockup at boot. Signed-off-by: Michele Ballabio 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 94b444e6fed3..e37bffec749a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2358,6 +2358,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) static struct snd_pci_quirk msi_black_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ + SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ {} }; From 42747d712de56cf2087b702d2ad90af114c53138 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 26 Dec 2009 18:55:22 +0000 Subject: [PATCH 031/114] [WATCHDOG] watchdog_info constify make the watchdog_info struct const where possible. Signed-off-by: Wim Van Sebroeck --- arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 2 +- drivers/watchdog/acquirewdt.c | 2 +- drivers/watchdog/advantechwdt.c | 2 +- drivers/watchdog/adx_wdt.c | 2 +- drivers/watchdog/alim1535_wdt.c | 2 +- drivers/watchdog/alim7101_wdt.c | 2 +- drivers/watchdog/ar7_wdt.c | 2 +- drivers/watchdog/at32ap700x_wdt.c | 2 +- drivers/watchdog/at91rm9200_wdt.c | 2 +- drivers/watchdog/bcm47xx_wdt.c | 2 +- drivers/watchdog/bfin_wdt.c | 4 ++-- drivers/watchdog/booke_wdt.c | 2 +- drivers/watchdog/coh901327_wdt.c | 2 +- drivers/watchdog/cpu5wdt.c | 2 +- drivers/watchdog/cpwd.c | 2 +- drivers/watchdog/davinci_wdt.c | 2 +- drivers/watchdog/ep93xx_wdt.c | 2 +- drivers/watchdog/eurotechwdt.c | 2 +- drivers/watchdog/gef_wdt.c | 2 +- drivers/watchdog/geodewdt.c | 2 +- drivers/watchdog/hpwdt.c | 2 +- drivers/watchdog/i6300esb.c | 2 +- drivers/watchdog/iTCO_wdt.c | 2 +- drivers/watchdog/ib700wdt.c | 2 +- drivers/watchdog/indydog.c | 2 +- drivers/watchdog/it8712f_wdt.c | 2 +- drivers/watchdog/it87_wdt.c | 2 +- drivers/watchdog/ixp2000_wdt.c | 2 +- drivers/watchdog/ixp4xx_wdt.c | 2 +- drivers/watchdog/ks8695_wdt.c | 2 +- drivers/watchdog/machzwd.c | 2 +- drivers/watchdog/mixcomwd.c | 2 +- drivers/watchdog/mpc8xxx_wdt.c | 2 +- drivers/watchdog/mpcore_wdt.c | 2 +- drivers/watchdog/mv64x60_wdt.c | 2 +- drivers/watchdog/pc87413_wdt.c | 2 +- drivers/watchdog/pcwd.c | 2 +- drivers/watchdog/pcwd_pci.c | 2 +- drivers/watchdog/pcwd_usb.c | 2 +- drivers/watchdog/pika_wdt.c | 2 +- drivers/watchdog/pnx833x_wdt.c | 2 +- drivers/watchdog/rc32434_wdt.c | 2 +- drivers/watchdog/rdc321x_wdt.c | 2 +- drivers/watchdog/riowd.c | 2 +- drivers/watchdog/sbc_fitpc2_wdt.c | 2 +- drivers/watchdog/sch311x_wdt.c | 2 +- drivers/watchdog/stmp3xxx_wdt.c | 2 +- drivers/watchdog/w83627hf_wdt.c | 2 +- drivers/watchdog/w83977f_wdt.c | 2 +- drivers/watchdog/wdrtas.c | 2 +- drivers/watchdog/wm831x_wdt.c | 2 +- drivers/watchdog/wm8350_wdt.c | 2 +- 52 files changed, 53 insertions(+), 53 deletions(-) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 6f8ebe1085b3..072b948b2e2d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -553,7 +553,7 @@ static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data, return 0; } -static struct watchdog_info mpc5200_wdt_info = { +static const struct watchdog_info mpc5200_wdt_info = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = WDT_IDENTITY, }; diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 4d18c874d963..2ffce4d75443 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -150,7 +150,7 @@ static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int options, retval = -EINVAL; void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 824d076a5cd6..4d40965d2c9f 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -137,7 +137,7 @@ static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c index 9d7d155364f8..a5ca7a6ee133 100644 --- a/drivers/watchdog/adx_wdt.c +++ b/drivers/watchdog/adx_wdt.c @@ -37,7 +37,7 @@ struct adx_wdt { spinlock_t lock; }; -static struct watchdog_info adx_wdt_info = { +static const struct watchdog_info adx_wdt_info = { .identity = "Avionic Design Xanthos Watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 937a80fb61e1..1e9caea8ff8a 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -180,7 +180,7 @@ static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index f90afdb1b255..d8d4da9a483d 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -238,7 +238,7 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2bb95cd308c1..c764c52412e4 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -219,7 +219,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, static long ar7_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .identity = LONGNAME, .firmware_version = 1, .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 037847923dcb..6873376f986c 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -202,7 +202,7 @@ static int at32_wdt_get_status(void) return status; } -static struct watchdog_info at32_wdt_info = { +static const struct watchdog_info at32_wdt_info = { .identity = "at32ap700x watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index b185dafe1494..b3046dc4b56c 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -121,7 +121,7 @@ static int at91_wdt_settimeout(int new_time) return 0; } -static struct watchdog_info at91_wdt_info = { +static const struct watchdog_info at91_wdt_info = { .identity = "at91 watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 751c003864ad..5f245522397b 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -149,7 +149,7 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, return len; } -static struct watchdog_info bcm47xx_wdt_info = { +static const struct watchdog_info bcm47xx_wdt_info = { .identity = DRV_NAME, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 2159e668751c..8c6babb2d652 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -74,7 +74,7 @@ static unsigned int timeout = WATCHDOG_TIMEOUT; static int nowayout = WATCHDOG_NOWAYOUT; -static struct watchdog_info bfin_wdt_info; +static const struct watchdog_info bfin_wdt_info; static unsigned long open_check; static char expect_close; static DEFINE_SPINLOCK(bfin_wdt_spinlock); @@ -388,7 +388,7 @@ static struct miscdevice bfin_wdt_miscdev = { .fops = &bfin_wdt_fops, }; -static struct watchdog_info bfin_wdt_info = { +static const struct watchdog_info bfin_wdt_info = { .identity = "Blackfin Watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index e8380ef65c1c..8b724aad6825 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -121,7 +121,7 @@ static ssize_t booke_wdt_write(struct file *file, const char __user *buf, return count; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "PowerPC Book-E Watchdog", }; diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c index 923cc68dba26..9291506b8b23 100644 --- a/drivers/watchdog/coh901327_wdt.c +++ b/drivers/watchdog/coh901327_wdt.c @@ -257,7 +257,7 @@ static long coh901327_ioctl(struct file *file, unsigned int cmd, struct watchdog_info __user *ident; int __user *i; } uarg; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index 71f6d7eec9a8..edd3475f41db 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c @@ -154,7 +154,7 @@ static long cpu5wdt_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; int __user *p = argp; unsigned int value; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_CARDRESET, .identity = "CPU5 WDT", }; diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 081f2955419e..37ea052d4dee 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -403,7 +403,7 @@ static int cpwd_release(struct inode *inode, struct file *file) static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - static struct watchdog_info info = { + static const struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, .firmware_version = 1, .identity = DRIVER_NAME, diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 887136de1857..56162c87f5d8 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -142,7 +142,7 @@ davinci_wdt_write(struct file *file, const char *data, size_t len, return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .identity = "DaVinci Watchdog", }; diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index cdd55e0d09f8..88ed54e50f74 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -131,7 +131,7 @@ ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, .identity = "EP93xx Watchdog", }; diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 9add3541fb42..d1c4e55b1db0 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -238,7 +238,7 @@ static long eurwdt_ioctl(struct file *file, { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 26447bdeac22..abdbad034a6c 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -161,7 +161,7 @@ static long gef_wdt_ioctl(struct file *file, unsigned int cmd, int timeout; int options; void __user *argp = (void __user *)arg; - static struct watchdog_info info = { + static const struct watchdog_info info = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 0, diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 38252ff828ca..9b49b125ad5a 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -142,7 +142,7 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd, int __user *p = argp; int interval; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index a6c5674c78e6..70c2c24660d0 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -554,7 +554,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data, return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 7ba0b11ec525..2fbe7fea7ee6 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -256,7 +256,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_heartbeat; void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index a619b9b74991..44bc6aa46edf 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -584,7 +584,7 @@ static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, int new_heartbeat; void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 4bef3ddff4a5..0149d8dfc81d 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c @@ -174,7 +174,7 @@ static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index bea8a124a559..1cc5609666d1 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c @@ -111,7 +111,7 @@ static long indydog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 0, .identity = "Hardware Watchdog for SGI IP22", diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index daed48ded7fe..f52c162b1bea 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -236,7 +236,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .identity = "IT8712F Watchdog", .firmware_version = 1, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index cc133c531d08..b709b3b2d1ef 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -421,7 +421,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, return count; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c index 3c79dc587958..e86952a7168c 100644 --- a/drivers/watchdog/ixp2000_wdt.c +++ b/drivers/watchdog/ixp2000_wdt.c @@ -100,7 +100,7 @@ static ssize_t ixp2000_wdt_write(struct file *file, const char *data, } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "IXP2000 Watchdog", diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 147b4d5c63b3..e02c0ecda26b 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c @@ -89,7 +89,7 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "IXP4xx Watchdog", diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index e1c82769b08e..2852bb2e3fd9 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c @@ -145,7 +145,7 @@ static int ks8695_wdt_close(struct inode *inode, struct file *file) return 0; } -static struct watchdog_info ks8695_wdt_info = { +static const struct watchdog_info ks8695_wdt_info = { .identity = "ks8695 watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 47d719717a3b..2d118cf022fc 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -101,7 +101,7 @@ MODULE_PARM_DESC(nowayout, #define PFX "machzwd" -static struct watchdog_info zf_info = { +static const struct watchdog_info zf_info = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ZF-Logic watchdog", diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index 407b025cb104..bc820d16699a 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c @@ -201,7 +201,7 @@ static long mixcomwd_ioctl(struct file *file, void __user *argp = (void __user *)arg; int __user *p = argp; int status; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "MixCOM watchdog", diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 38c588ee694f..4e3941c5e293 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -148,7 +148,7 @@ static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = "MPC8xxx", diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index a2dc07c2ed49..b0646dac924e 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -213,7 +213,7 @@ static ssize_t mpcore_wdt_write(struct file *file, const char *data, return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index a51dbe4c43da..97f8a48d8b78 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -179,7 +179,7 @@ static long mv64x60_wdt_ioctl(struct file *file, int timeout; int options; void __user *argp = (void __user *)arg; - static struct watchdog_info info = { + static const struct watchdog_info info = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 1a2b916e3f8d..d3aa2f1fe61d 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -407,7 +407,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, int __user *i; } uarg; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index aa9512321f3a..06f7922606c0 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -606,7 +606,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int temperature; int new_heartbeat; int __user *argp = (int __user *)arg; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 698f51bff1bc..64374d636f09 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -481,7 +481,7 @@ static long pcipcwd_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_KEEPALIVEPING | diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 052fe451851f..8e4eacc5bb52 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -404,7 +404,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index 2d22e996e996..435ec2aed4fe 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c @@ -52,7 +52,7 @@ static struct { struct timer_list timer; /* The timer that pings the watchdog */ } pikawdt_private; -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .identity = DRV_NAME, .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c index 538ec2c05197..09102f09e681 100644 --- a/drivers/watchdog/pnx833x_wdt.c +++ b/drivers/watchdog/pnx833x_wdt.c @@ -141,7 +141,7 @@ static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd, int options, new_timeout = 0; uint32_t timeout, timeout_left = 0; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, .firmware_version = 0, .identity = "Hardware Watchdog for PNX833x", diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index bf12d06b5877..d4c29b5311a4 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -198,7 +198,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; int new_timeout; unsigned int value; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 4976bfd1fce6..69c6adbd8205 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -149,7 +149,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, { void __user *argp = (void __user *)arg; unsigned int value; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_CARDRESET, .identity = "RDC321x WDT", }; diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index c14ae8676903..ae57bf9e1b03 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -85,7 +85,7 @@ static int riowd_release(struct inode *inode, struct file *filp) static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - static struct watchdog_info info = { + static const struct watchdog_info info = { .options = WDIOF_SETTIMEOUT, .firmware_version = 1, .identity = DRIVER_NAME, diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index e6763d2a567b..8d44c9b6fb5b 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -111,7 +111,7 @@ static ssize_t fitpc2_wdt_write(struct file *file, const char *data, } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = WATCHDOG_NAME, diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 569eb295a7a8..9c40f48804f5 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -250,7 +250,7 @@ static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd, int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c index 5dd952681f32..b3421fd2cda8 100644 --- a/drivers/watchdog/stmp3xxx_wdt.c +++ b/drivers/watchdog/stmp3xxx_wdt.c @@ -94,7 +94,7 @@ static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data, return len; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index f201accc4e3d..0f5288df0091 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -201,7 +201,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; int __user *p = argp; int new_timeout; - static struct watchdog_info ident = { + static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 0560182a1d09..6e6743d1066f 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c @@ -371,7 +371,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, * according to their available features. */ -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = WATCHDOG_NAME, diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 5bfb1f2c5319..94ec22b9e66b 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -312,7 +312,7 @@ static long wdrtas_ioctl(struct file *file, unsigned int cmd, { int __user *argp = (void __user *)arg; int i; - static struct watchdog_info wdinfo = { + static const struct watchdog_info wdinfo = { .options = WDRTAS_SUPPORTED_MASK, .firmware_version = 0, .identity = "wdrtas", diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 775bcd807f31..8c4b2d5bb7da 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -213,7 +213,7 @@ static ssize_t wm831x_wdt_write(struct file *file, return count; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .identity = "WM831x Watchdog", }; diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index a2d2e8eb2282..89dd7b035295 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c @@ -177,7 +177,7 @@ static ssize_t wm8350_wdt_write(struct file *file, return count; } -static struct watchdog_info ident = { +static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .identity = "WM8350 Watchdog", }; From 168b5251adddb1554926cfb94f79a8a28bc6ebe5 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 26 Dec 2009 19:13:00 +0000 Subject: [PATCH 032/114] [WATCHDOG] change reboot_notifier to platform-shutdown method. Platform device drivers can use the .shutdown method to handle soft shutdown's instead of reboot_notifier's. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bfin_wdt.c | 52 +++++++++++-------------------------- drivers/watchdog/txx9wdt.c | 25 +++++------------- 2 files changed, 21 insertions(+), 56 deletions(-) diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 8c6babb2d652..9c7ccd1e9088 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include #include @@ -309,26 +307,6 @@ static long bfin_wdt_ioctl(struct file *file, } } -/** - * bfin_wdt_notify_sys - Notifier Handler - * @this: notifier block - * @code: notifier event - * @unused: unused - * - * Handles specific events, such as turning off the watchdog during a - * shutdown event. - */ -static int bfin_wdt_notify_sys(struct notifier_block *this, - unsigned long code, void *unused) -{ - stampit(); - - if (code == SYS_DOWN || code == SYS_HALT) - bfin_wdt_stop(); - - return NOTIFY_DONE; -} - #ifdef CONFIG_PM static int state_before_suspend; @@ -395,33 +373,21 @@ static const struct watchdog_info bfin_wdt_info = { WDIOF_MAGICCLOSE, }; -static struct notifier_block bfin_wdt_notifier = { - .notifier_call = bfin_wdt_notify_sys, -}; - /** * bfin_wdt_probe - Initialize module * - * Registers the misc device and notifier handler. Actual device + * Registers the misc device. Actual device * initialization is handled by bfin_wdt_open(). */ static int __devinit bfin_wdt_probe(struct platform_device *pdev) { int ret; - ret = register_reboot_notifier(&bfin_wdt_notifier); - if (ret) { - pr_devinit(KERN_ERR PFX - "cannot register reboot notifier (err=%d)\n", ret); - return ret; - } - ret = misc_register(&bfin_wdt_miscdev); if (ret) { pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&bfin_wdt_notifier); return ret; } @@ -434,21 +400,33 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) /** * bfin_wdt_remove - Initialize module * - * Unregisters the misc device and notifier handler. Actual device + * Unregisters the misc device. Actual device * deinitialization is handled by bfin_wdt_close(). */ static int __devexit bfin_wdt_remove(struct platform_device *pdev) { misc_deregister(&bfin_wdt_miscdev); - unregister_reboot_notifier(&bfin_wdt_notifier); return 0; } +/** + * bfin_wdt_shutdown - Soft Shutdown Handler + * + * Handles the soft shutdown event. + */ +static void bfin_wdt_shutdown(struct platform_device *pdev) +{ + stampit(); + + bfin_wdt_stop(); +} + static struct platform_device *bfin_wdt_device; static struct platform_driver bfin_wdt_driver = { .probe = bfin_wdt_probe, .remove = __devexit_p(bfin_wdt_remove), + .shutdown = bfin_wdt_shutdown, .suspend = bfin_wdt_suspend, .resume = bfin_wdt_resume, .driver = { diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index d635566e9307..9e9ed7bfabcb 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -166,14 +165,6 @@ static long txx9wdt_ioctl(struct file *file, unsigned int cmd, } } -static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (code == SYS_DOWN || code == SYS_HALT) - txx9wdt_stop(); - return NOTIFY_DONE; -} - static const struct file_operations txx9wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -189,10 +180,6 @@ static struct miscdevice txx9wdt_miscdev = { .fops = &txx9wdt_fops, }; -static struct notifier_block txx9wdt_notifier = { - .notifier_call = txx9wdt_notify_sys, -}; - static int __init txx9wdt_probe(struct platform_device *dev) { struct resource *res; @@ -221,13 +208,8 @@ static int __init txx9wdt_probe(struct platform_device *dev) if (!txx9wdt_reg) goto exit_busy; - ret = register_reboot_notifier(&txx9wdt_notifier); - if (ret) - goto exit; - ret = misc_register(&txx9wdt_miscdev); if (ret) { - unregister_reboot_notifier(&txx9wdt_notifier); goto exit; } @@ -249,14 +231,19 @@ static int __init txx9wdt_probe(struct platform_device *dev) static int __exit txx9wdt_remove(struct platform_device *dev) { misc_deregister(&txx9wdt_miscdev); - unregister_reboot_notifier(&txx9wdt_notifier); clk_disable(txx9_imclk); clk_put(txx9_imclk); return 0; } +static void txx9wdt_shutdown(struct platform_device *dev) +{ + txx9wdt_stop(); +} + static struct platform_driver txx9wdt_driver = { .remove = __exit_p(txx9wdt_remove), + .shutdown = txx9wdt_shutdown, .driver = { .name = "txx9wdt", .owner = THIS_MODULE, From c1bf3acffcddcf794e3d8a1d25fb8bd4d5912383 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 3 Mar 2010 11:57:40 -0800 Subject: [PATCH 033/114] [WATCHDOG] drivers/watchdog/wdt.c:wdt_ioctl(): make `ident' non-static Making this instance static exposes the code to SMP races, etc. Signed-off-by: Andrew Morton Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdt.c | 2 +- drivers/watchdog/wdt_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 3bbefe9a2634..bfda2e99dd89 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -358,7 +358,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int new_heartbeat; int status; - static struct watchdog_info ident = { + struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| WDIOF_MAGICCLOSE| WDIOF_KEEPALIVEPING, diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index f368dd87083a..7b22e3cdbc81 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -412,7 +412,7 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd, int new_heartbeat; int status; - static struct watchdog_info ident = { + struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| WDIOF_MAGICCLOSE| WDIOF_KEEPALIVEPING, From 77d3d7c1d561f49f755d7390f0764dff90765974 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 5 Feb 2010 17:57:02 +0900 Subject: [PATCH 034/114] driver-core: fix race condition in get_device_parent() sysfs is creating several devices in cuse class concurrently and with CONFIG_SYSFS_DEPRECATED turned off, it triggers the following oops. BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 IP: [] sysfs_addrm_start+0x4a/0xf0 PGD 75bb067 PUD 75be067 PMD 0 Oops: 0000 [#1] PREEMPT SMP last sysfs file: /sys/devices/system/cpu/cpu7/topology/core_siblings CPU 1 Modules linked in: cuse fuse Pid: 4737, comm: osspd Not tainted 2.6.31-work #77 RIP: 0010:[] [] sysfs_addrm_start+0x4a/0xf0 RSP: 0018:ffff88000042f8f8 EFLAGS: 00010296 RAX: ffff88000042ffd8 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff880007eef660 RDI: 0000000000000001 RBP: ffff88000042f918 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: ffffffff81158b0a R12: ffff88000042f928 R13: 00000000fffffff4 R14: 0000000000000000 R15: ffff88000042f9a0 FS: 00007fe93905a950(0000) GS:ffff880008600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000038 CR3: 00000000077c9000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process osspd (pid: 4737, threadinfo ffff88000042e000, task ffff880007eef040) Stack: ffff880005da10e8 0000000011cc8d6e ffff88000042f928 ffff880003d28a28 <0> ffff88000042f988 ffffffff811592d7 0000000000000000 0000000000000000 <0> 0000000000000000 0000000000000000 ffff88000042f958 0000000011cc8d6e Call Trace: [] create_dir+0x67/0xe0 [] sysfs_create_dir+0x58/0xb0 [] ? kobject_add_internal+0xcc/0x220 [] ? vsnprintf+0x3c1/0xb90 [] kobject_add_internal+0x107/0x220 [] kobject_add_varg+0x47/0x80 [] kobject_add+0x53/0x90 [] device_add+0xd4/0x690 [] ? dev_set_name+0x4b/0x70 [] cuse_process_init_reply+0x2b4/0x420 [cuse] ... The problem is that kobject_add_internal() first adds a kobject to the kset and then try to create sysfs directory for it. If the creation fails, it remove the kobject from the kset. get_device_parent() accesses class_dirs kset while only holding class_dirs.list_lock to see whether the cuse class dir exists. But when it exists, it may not have finished initialization yet or may fail and get removed soon. In the above case, the former happened so the second one ends up trying to create subdirectory under NULL sysfs_dirent. Fix it by grabbing a mutex in get_device_parent(). Signed-off-by: Tejun Heo Reported-by: Colin Guthrie Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 282025770429..fb4bc4f5151c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -607,6 +607,7 @@ static struct kobject *get_device_parent(struct device *dev, int retval; if (dev->class) { + static DEFINE_MUTEX(gdp_mutex); struct kobject *kobj = NULL; struct kobject *parent_kobj; struct kobject *k; @@ -623,6 +624,8 @@ static struct kobject *get_device_parent(struct device *dev, else parent_kobj = &parent->kobj; + mutex_lock(&gdp_mutex); + /* find our class-directory at the parent and reference it */ spin_lock(&dev->class->p->class_dirs.list_lock); list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) @@ -631,20 +634,26 @@ static struct kobject *get_device_parent(struct device *dev, break; } spin_unlock(&dev->class->p->class_dirs.list_lock); - if (kobj) + if (kobj) { + mutex_unlock(&gdp_mutex); return kobj; + } /* or create a new class-directory at the parent device */ k = kobject_create(); - if (!k) + if (!k) { + mutex_unlock(&gdp_mutex); return NULL; + } k->kset = &dev->class->p->class_dirs; retval = kobject_add(k, parent_kobj, "%s", dev->class->name); if (retval < 0) { + mutex_unlock(&gdp_mutex); kobject_put(k); return NULL; } /* do not emit an uevent for this simple "glue" directory */ + mutex_unlock(&gdp_mutex); return k; } From a115bc070b1fc57ab23f3972401425927b5b465c Mon Sep 17 00:00:00 2001 From: Radu Voicilas Date: Sat, 12 Dec 2009 01:06:09 -0800 Subject: [PATCH 035/114] kobject-example: Spelling fixes. No change in functionality. Signed-off-by: Radu Voicilas Signed-off-by: Greg Kroah-Hartman --- samples/kobject/kobject-example.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/kobject/kobject-example.c b/samples/kobject/kobject-example.c index 8d9b55a12023..86ea0c3ad975 100644 --- a/samples/kobject/kobject-example.c +++ b/samples/kobject/kobject-example.c @@ -44,7 +44,7 @@ static struct kobj_attribute foo_attribute = __ATTR(foo, 0666, foo_show, foo_store); /* - * More complex function where we determine which varible is being accessed by + * More complex function where we determine which variable is being accessed by * looking at the attribute for the "baz" and "bar" files. */ static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr, @@ -79,7 +79,7 @@ static struct kobj_attribute bar_attribute = /* - * Create a group of attributes so that we can create and destory them all + * Create a group of attributes so that we can create and destroy them all * at once. */ static struct attribute *attrs[] = { From 20ef9f46a9abe3c25d9f2834f6cc86bfab46d609 Mon Sep 17 00:00:00 2001 From: Radu Voicilas Date: Sat, 12 Dec 2009 01:06:10 -0800 Subject: [PATCH 036/114] kset-example: Spelling fixes. No change in functionality. Signed-off-by: Radu Voicilas Signed-off-by: Greg Kroah-Hartman --- samples/kobject/kset-example.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index 45b7d56fb541..7c6088140528 100644 --- a/samples/kobject/kset-example.c +++ b/samples/kobject/kset-example.c @@ -127,7 +127,7 @@ static struct foo_attribute foo_attribute = __ATTR(foo, 0666, foo_show, foo_store); /* - * More complex function where we determine which varible is being accessed by + * More complex function where we determine which variable is being accessed by * looking at the attribute for the "baz" and "bar" files. */ static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, @@ -161,7 +161,7 @@ static struct foo_attribute bar_attribute = __ATTR(bar, 0666, b_show, b_store); /* - * Create a group of attributes so that we can create and destory them all + * Create a group of attributes so that we can create and destroy them all * at once. */ static struct attribute *foo_default_attrs[] = { From ecdf6ceb8cf4756bd4214bf9755755752b6015f5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Dec 2009 20:11:20 -0800 Subject: [PATCH 037/114] Driver core: add platform_create_bundle() helper Many legacy-style module create singleton platform devices themselves, along with corresponding platform driver. Instead of replicating error handling code in all such drivers, provide a helper that allocates and registers a single platform device and a driver and binds them together. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 58 +++++++++++++++++++++++++++++++++ include/linux/platform_device.h | 5 +++ 2 files changed, 63 insertions(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 58efaf2f1259..937d58021d1b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -548,6 +548,64 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, } EXPORT_SYMBOL_GPL(platform_driver_probe); +/** + * platform_create_bundle - register driver and create corresponding device + * @driver: platform driver structure + * @probe: the driver probe routine, probably from an __init section + * @res: set of resources that needs to be allocated for the device + * @n_res: number of resources + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Use this in legacy-style modules that probe hardware directly and + * register a single platform device and corresponding platform driver. + */ +struct platform_device * __init_or_module platform_create_bundle( + struct platform_driver *driver, + int (*probe)(struct platform_device *), + struct resource *res, unsigned int n_res, + const void *data, size_t size) +{ + struct platform_device *pdev; + int error; + + pdev = platform_device_alloc(driver->driver.name, -1); + if (!pdev) { + error = -ENOMEM; + goto err_out; + } + + if (res) { + error = platform_device_add_resources(pdev, res, n_res); + if (error) + goto err_pdev_put; + } + + if (data) { + error = platform_device_add_data(pdev, data, size); + if (error) + goto err_pdev_put; + } + + error = platform_device_add(pdev); + if (error) + goto err_pdev_put; + + error = platform_driver_probe(driver, probe); + if (error) + goto err_pdev_del; + + return pdev; + +err_pdev_del: + platform_device_del(pdev); +err_pdev_put: + platform_device_put(pdev); +err_out: + return ERR_PTR(error); +} +EXPORT_SYMBOL_GPL(platform_create_bundle); + /* modalias support enables more hands-off userspace setup: * (a) environment variable lets new-style hotplug events work once system is * fully running: "modprobe $MODALIAS" diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 71ff887ca44e..25e64b43e644 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -77,6 +77,11 @@ extern int platform_driver_probe(struct platform_driver *driver, #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) +extern struct platform_device *platform_create_bundle(struct platform_driver *driver, + int (*probe)(struct platform_device *), + struct resource *res, unsigned int n_res, + const void *data, size_t size); + /* early platform driver interface */ struct early_platform_driver { const char *class_str; From 3d03ba4d1dd2246adff5a9ff1194a539b3bc05a7 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 1 Jan 2010 15:43:28 +0800 Subject: [PATCH 038/114] driver core: make platform_device_id table const The platform ID table is normally const, force that by adding the attribute. Signed-off-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 25e64b43e644..2c2d035bfb92 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -21,7 +21,7 @@ struct platform_device { u32 num_resources; struct resource * resource; - struct platform_device_id *id_entry; + const struct platform_device_id *id_entry; /* arch specific additions */ struct pdev_archdata archdata; From c9be0a36f9bf392a7984473124a67a12964df11f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:47:58 +0100 Subject: [PATCH 039/114] sysdev: Pass attribute in sysdev_class attributes show/store Passing the attribute to the low level IO functions allows all kinds of cleanups, by sharing low level IO code without requiring an own function for every piece of data. Also drivers can extend the attributes with own data fields and use that in the low level function. Similar to sysdev_attributes and normal attributes. This is a tree-wide sweep, converting everything in one go. No functional changes in this patch other than passing the new argument everywhere. Tested on x86, the non x86 parts are uncompiled. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- arch/mips/txx9/generic/7segled.c | 5 +++- arch/s390/kernel/smp.c | 8 ++++-- arch/s390/kernel/time.c | 49 ++++++++++++++++++++++++-------- drivers/base/cpu.c | 9 ++++-- drivers/base/node.c | 17 +++++++---- drivers/base/sys.c | 4 +-- drivers/cpuidle/sysfs.c | 4 +++ include/linux/sysdev.h | 6 ++-- kernel/perf_event.c | 13 +++++++-- kernel/sched.c | 4 +++ 10 files changed, 89 insertions(+), 30 deletions(-) diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c index 727ab21b6618..7f8416f86222 100644 --- a/arch/mips/txx9/generic/7segled.c +++ b/arch/mips/txx9/generic/7segled.c @@ -58,13 +58,16 @@ static ssize_t raw_store(struct sys_device *dev, static SYSDEV_ATTR(ascii, 0200, NULL, ascii_store); static SYSDEV_ATTR(raw, 0200, NULL, raw_store); -static ssize_t map_seg7_show(struct sysdev_class *class, char *buf) +static ssize_t map_seg7_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); return sizeof(txx9_seg7map); } static ssize_t map_seg7_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, const char *buf, size_t size) { if (size != sizeof(txx9_seg7map)) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8b10127c00ad..e2121099f03b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1020,7 +1020,9 @@ int __ref smp_rescan_cpus(void) return rc; } -static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf, +static ssize_t __ref rescan_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) { int rc; @@ -1041,7 +1043,9 @@ static ssize_t dispatching_show(struct sysdev_class *class, char *buf) return count; } -static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf, +static ssize_t dispatching_store(struct sysdev_class *dev, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) { int val, rc; diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index a8f93f1705ad..75894c281710 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -1116,14 +1116,18 @@ static struct sys_device etr_port1_dev = { /* * ETR class attributes */ -static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf) +static ssize_t etr_stepping_port_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return sprintf(buf, "%i\n", etr_port0.esw.p); } static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL); -static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf) +static ssize_t etr_stepping_mode_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { char *mode_str; @@ -1584,7 +1588,9 @@ static struct sysdev_class stp_sysclass = { .name = "stp", }; -static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf) +static ssize_t stp_ctn_id_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online) return -ENODATA; @@ -1594,7 +1600,9 @@ static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); -static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf) +static ssize_t stp_ctn_type_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online) return -ENODATA; @@ -1603,7 +1611,9 @@ static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); -static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf) +static ssize_t stp_dst_offset_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online || !(stp_info.vbits & 0x2000)) return -ENODATA; @@ -1612,7 +1622,9 @@ static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); -static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf) +static ssize_t stp_leap_seconds_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online || !(stp_info.vbits & 0x8000)) return -ENODATA; @@ -1621,7 +1633,9 @@ static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); -static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf) +static ssize_t stp_stratum_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online) return -ENODATA; @@ -1630,7 +1644,9 @@ static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL); -static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf) +static ssize_t stp_time_offset_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online || !(stp_info.vbits & 0x0800)) return -ENODATA; @@ -1639,7 +1655,9 @@ static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL); -static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf) +static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online || !(stp_info.vbits & 0x4000)) return -ENODATA; @@ -1649,7 +1667,9 @@ static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(time_zone_offset, 0400, stp_time_zone_offset_show, NULL); -static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf) +static ssize_t stp_timing_mode_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online) return -ENODATA; @@ -1658,7 +1678,9 @@ static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); -static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf) +static ssize_t stp_timing_state_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { if (!stp_online) return -ENODATA; @@ -1667,12 +1689,15 @@ static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf) static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL); -static ssize_t stp_online_show(struct sysdev_class *class, char *buf) +static ssize_t stp_online_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return sprintf(buf, "%i\n", stp_online); } static ssize_t stp_online_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, const char *buf, size_t count) { unsigned int value; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 958bd1540c30..fd1b2f9b7b8f 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -151,7 +151,8 @@ static ssize_t print_cpus_map(char *buf, const struct cpumask *map) } #define print_cpus_func(type) \ -static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ +static ssize_t print_cpus_##type(struct sysdev_class *class, \ + struct sysdev_class_attribute *attr, char *buf) \ { \ return print_cpus_map(buf, cpu_##type##_mask); \ } \ @@ -165,7 +166,8 @@ print_cpus_func(present); /* * Print values for NR_CPUS and offlined cpus */ -static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf) +static ssize_t print_cpus_kernel_max(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); return n; @@ -175,7 +177,8 @@ static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ unsigned int total_cpus; -static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf) +static ssize_t print_cpus_offline(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { int n = 0, len = PAGE_SIZE-2; cpumask_var_t offline; diff --git a/drivers/base/node.c b/drivers/base/node.c index 70122791683d..85c9d30d7004 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -544,23 +544,29 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) return n; } -static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf) +static ssize_t print_nodes_possible(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { return print_nodes_state(N_POSSIBLE, buf); } -static ssize_t print_nodes_online(struct sysdev_class *class, char *buf) +static ssize_t print_nodes_online(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return print_nodes_state(N_ONLINE, buf); } static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class, - char *buf) + struct sysdev_class_attribute *attr, + char *buf) { return print_nodes_state(N_NORMAL_MEMORY, buf); } -static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf) +static ssize_t print_nodes_has_cpu(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return print_nodes_state(N_CPU, buf); } @@ -573,7 +579,8 @@ static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL); #ifdef CONFIG_HIGHMEM static ssize_t print_nodes_has_high_memory(struct sysdev_class *class, - char *buf) + struct sysdev_class_attribute *attr, + char *buf) { return print_nodes_state(N_HIGH_MEMORY, buf); } diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 0d903909af7e..a38445c0f8c5 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -89,7 +89,7 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->show) - return class_attr->show(class, buffer); + return class_attr->show(class, class_attr, buffer); return -EIO; } @@ -100,7 +100,7 @@ static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->store) - return class_attr->store(class, buffer, count); + return class_attr->store(class, class_attr, buffer, count); return -EIO; } diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 97b003839fb6..c9cefacabf37 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -22,6 +22,7 @@ static int __init cpuidle_sysfs_setup(char *unused) __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); static ssize_t show_available_governors(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { ssize_t i = 0; @@ -41,6 +42,7 @@ static ssize_t show_available_governors(struct sysdev_class *class, } static ssize_t show_current_driver(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { ssize_t ret; @@ -56,6 +58,7 @@ static ssize_t show_current_driver(struct sysdev_class *class, } static ssize_t show_current_governor(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { ssize_t ret; @@ -71,6 +74,7 @@ static ssize_t show_current_governor(struct sysdev_class *class, } static ssize_t store_current_governor(struct sysdev_class *class, + struct sysdev_class_attribute *attr, const char *buf, size_t count) { char gov_name[CPUIDLE_NAME_LEN]; diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index f395bb3fa2f2..c2458fa8376c 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -41,8 +41,10 @@ struct sysdev_class { struct sysdev_class_attribute { struct attribute attr; - ssize_t (*show)(struct sysdev_class *, char *); - ssize_t (*store)(struct sysdev_class *, const char *, size_t); + ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *, + char *); + ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *, + const char *, size_t); }; #define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 8e352c756ba7..f40560b86544 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -5481,13 +5481,16 @@ void __init perf_event_init(void) register_cpu_notifier(&perf_cpu_nb); } -static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, char *buf) +static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", perf_reserved_percpu); } static ssize_t perf_set_reserve_percpu(struct sysdev_class *class, + struct sysdev_class_attribute *attr, const char *buf, size_t count) { @@ -5516,13 +5519,17 @@ perf_set_reserve_percpu(struct sysdev_class *class, return count; } -static ssize_t perf_show_overcommit(struct sysdev_class *class, char *buf) +static ssize_t perf_show_overcommit(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", perf_overcommit); } static ssize_t -perf_set_overcommit(struct sysdev_class *class, const char *buf, size_t count) +perf_set_overcommit(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) { unsigned long val; int err; diff --git a/kernel/sched.c b/kernel/sched.c index b47ceeec1a91..150b6988de49 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -7406,11 +7406,13 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt) #ifdef CONFIG_SCHED_MC static ssize_t sched_mc_power_savings_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *page) { return sprintf(page, "%u\n", sched_mc_power_savings); } static ssize_t sched_mc_power_savings_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, const char *buf, size_t count) { return sched_power_savings_store(buf, count, 0); @@ -7422,11 +7424,13 @@ static SYSDEV_CLASS_ATTR(sched_mc_power_savings, 0644, #ifdef CONFIG_SCHED_SMT static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev, + struct sysdev_class_attribute *attr, char *page) { return sprintf(page, "%u\n", sched_smt_power_savings); } static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev, + struct sysdev_class_attribute *attr, const char *buf, size_t count) { return sched_power_savings_store(buf, count, 1); From b15f562fc2f5429f27e5dfb0b0ee5ec44f661986 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:47:59 +0100 Subject: [PATCH 040/114] sysdev: Convert node driver class attributes to be data driven Using the new attribute argument convert the node driver class attributes to carry the node state. Then use a shared function to do what a lot of individual functions did before. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 65 +++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/drivers/base/node.c b/drivers/base/node.c index 85c9d30d7004..aa8bc4bff4f6 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -544,59 +544,29 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) return n; } -static ssize_t print_nodes_possible(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) -{ - return print_nodes_state(N_POSSIBLE, buf); -} - -static ssize_t print_nodes_online(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - char *buf) -{ - return print_nodes_state(N_ONLINE, buf); -} - -static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - char *buf) -{ - return print_nodes_state(N_NORMAL_MEMORY, buf); -} - -static ssize_t print_nodes_has_cpu(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - char *buf) -{ - return print_nodes_state(N_CPU, buf); -} - -static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL); -static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL); -static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory, - NULL); -static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL); +struct node_attr { + struct sysdev_class_attribute attr; + enum node_states state; +}; -#ifdef CONFIG_HIGHMEM -static ssize_t print_nodes_has_high_memory(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - char *buf) +static ssize_t show_node_state(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { - return print_nodes_state(N_HIGH_MEMORY, buf); + struct node_attr *na = container_of(attr, struct node_attr, attr); + return print_nodes_state(na->state, buf); } -static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory, - NULL); -#endif +#define _NODE_ATTR(name, state) \ + { _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state } -struct sysdev_class_attribute *node_state_attr[] = { - &attr_possible, - &attr_online, - &attr_has_normal_memory, +static struct node_attr node_state_attr[] = { + _NODE_ATTR(possible, N_POSSIBLE), + _NODE_ATTR(online, N_ONLINE), + _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY), + _NODE_ATTR(has_cpu, N_CPU), #ifdef CONFIG_HIGHMEM - &attr_has_high_memory, + _NODE_ATTR(has_high_memory, N_HIGH_MEMORY), #endif - &attr_has_cpu, }; static int node_states_init(void) @@ -604,9 +574,10 @@ static int node_states_init(void) int i; int err = 0; + BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); for (i = 0; i < NR_NODE_STATES; i++) { int ret; - ret = sysdev_class_create_file(&node_class, node_state_attr[i]); + ret = sysdev_class_create_file(&node_class, &node_state_attr[i].attr); if (!err) err = ret; } From 265d2e2e31c5f6dc1b20ae1653a17fdba706f79e Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:00 +0100 Subject: [PATCH 041/114] sysdev: Convert cpu driver sysdev class attributes Using the new attribute argument convert the cpu driver class attributes to carry the node state. Then use a shared function to do what a lot of individual functions did before. This eliminates an ugly macro. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index fd1b2f9b7b8f..b04ecfc63b51 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -141,27 +141,32 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); /* * Print cpu online, possible, present, and system maps */ -static ssize_t print_cpus_map(char *buf, const struct cpumask *map) + +struct cpu_attr { + struct sysdev_class_attribute attr; + const struct cpumask *const * const map; +}; + +static ssize_t show_cpus_attr(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { - int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map); + struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); + int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map)); buf[n++] = '\n'; buf[n] = '\0'; return n; } -#define print_cpus_func(type) \ -static ssize_t print_cpus_##type(struct sysdev_class *class, \ - struct sysdev_class_attribute *attr, char *buf) \ -{ \ - return print_cpus_map(buf, cpu_##type##_mask); \ -} \ -static struct sysdev_class_attribute attr_##type##_map = \ - _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) +#define _CPU_ATTR(name, map) \ + { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } -print_cpus_func(online); -print_cpus_func(possible); -print_cpus_func(present); +static struct cpu_attr cpu_attrs[] = { + _CPU_ATTR(online, &cpu_online_mask), + _CPU_ATTR(possible, &cpu_possible_mask), + _CPU_ATTR(present, &cpu_present_mask), +}; /* * Print values for NR_CPUS and offlined cpus @@ -208,9 +213,9 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); static struct sysdev_class_attribute *cpu_state_attr[] = { - &attr_online_map, - &attr_possible_map, - &attr_present_map, + &cpu_attrs[0].attr, + &cpu_attrs[1].attr, + &cpu_attrs[2].attr, &attr_kernel_max, &attr_offline, }; From 1c205ae18db53ff72985dd79f3baaf2dbaba6db7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:01 +0100 Subject: [PATCH 042/114] sysfs: Add sysfs_add/remove_files utility functions Adding/Removing a whole array of attributes is very common. Add a standard utility function to do this with a simple function call, instead of requiring drivers to open code this. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 20 ++++++++++++++++++++ include/linux/sysfs.h | 14 ++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index dc30d9e31683..50b725bcc3f3 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -542,6 +542,18 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) } +int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) +{ + int err = 0; + int i; + + for (i = 0; ptr[i] && !err; i++) + err = sysfs_create_file(kobj, ptr[i]); + if (err) + while (--i >= 0) + sysfs_remove_file(kobj, ptr[i]); + return err; +} /** * sysfs_add_file_to_group - add an attribute file to a pre-existing group. @@ -614,6 +626,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) sysfs_hash_and_remove(kobj->sd, attr->name); } +void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) +{ + int i; + for (i = 0; ptr[i]; i++) + sysfs_remove_file(kobj, ptr[i]); +} /** * sysfs_remove_file_from_group - remove an attribute file from a group. @@ -732,3 +750,5 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback); EXPORT_SYMBOL_GPL(sysfs_create_file); EXPORT_SYMBOL_GPL(sysfs_remove_file); +EXPORT_SYMBOL_GPL(sysfs_remove_files); +EXPORT_SYMBOL_GPL(sysfs_create_files); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index cfa83083a2d4..3e8526582146 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -94,9 +94,12 @@ int __must_check sysfs_move_dir(struct kobject *kobj, int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr); +int __must_check sysfs_create_files(struct kobject *kobj, + const struct attribute **attr); int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); +void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr); @@ -164,6 +167,12 @@ static inline int sysfs_create_file(struct kobject *kobj, return 0; } +static inline int sysfs_create_files(struct kobject *kobj, + const struct attribute **attr) +{ + return 0; +} + static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { @@ -175,6 +184,11 @@ static inline void sysfs_remove_file(struct kobject *kobj, { } +static inline void sysfs_remove_files(struct kobject *kobj, + const struct attribute **attr) +{ +} + static inline int sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr) { From 38457ab3a0d36320370c715145ba6da514127194 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:02 +0100 Subject: [PATCH 043/114] sysfs: Add attribute array to sysdev classes Add a attribute array that is automatically registered and unregistered to struct sysdev_class. This is similar to what struct class has. A lot of drivers add list of attributes, so it's better to do this easily in the common sysdev layer. This adds a new field to struct sysdev_class. I audited the whole tree and there are no dynamically allocated sysdev classes, so this is fully compatible. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 9 ++++++++- include/linux/sysdev.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/base/sys.c b/drivers/base/sys.c index a38445c0f8c5..747c99e0568b 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -145,13 +145,20 @@ int sysdev_class_register(struct sysdev_class *cls) if (retval) return retval; - return kset_register(&cls->kset); + retval = kset_register(&cls->kset); + if (!retval && cls->attrs) + retval = sysfs_create_files(&cls->kset.kobj, + (const struct attribute **)cls->attrs); + return retval; } void sysdev_class_unregister(struct sysdev_class *cls) { pr_debug("Unregistering sysdev class '%s'\n", kobject_name(&cls->kset.kobj)); + if (cls->attrs) + sysfs_remove_files(&cls->kset.kobj, + (const struct attribute **)cls->attrs); kset_unregister(&cls->kset); } diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index c2458fa8376c..b6244f9b533f 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -27,10 +27,12 @@ struct sys_device; +struct sysdev_class_attribute; struct sysdev_class { const char *name; struct list_head drivers; + struct sysdev_class_attribute **attrs; /* Default operations for these types of devices */ int (*shutdown)(struct sys_device *); From e1a7e29a266ba3313a873d302b352521403bd155 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:03 +0100 Subject: [PATCH 044/114] sysdev: Convert node driver Use sysdev_class attribute arrays in node driver Convert the node driver to sysdev_class attribute arrays. This greatly cleans up the code and remove a lot of code. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 57 ++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index b04ecfc63b51..fb456b729803 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -13,8 +13,11 @@ #include "base.h" +static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; + struct sysdev_class cpu_sysdev_class = { .name = "cpu", + .attrs = cpu_sysdev_class_attrs, }; EXPORT_SYMBOL(cpu_sysdev_class); @@ -90,20 +93,6 @@ static ssize_t cpu_release_store(struct class *class, const char *buf, static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); - -int __init cpu_probe_release_init(void) -{ - int rc; - - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &class_attr_probe.attr); - if (!rc) - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &class_attr_release.attr); - - return rc; -} -device_initcall(cpu_probe_release_init); #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -162,6 +151,7 @@ static ssize_t show_cpus_attr(struct sysdev_class *class, #define _CPU_ATTR(name, map) \ { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } +/* Keep in sync with cpu_sysdev_class_attrs */ static struct cpu_attr cpu_attrs[] = { _CPU_ATTR(online, &cpu_online_mask), _CPU_ATTR(possible, &cpu_possible_mask), @@ -212,29 +202,6 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, } static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); -static struct sysdev_class_attribute *cpu_state_attr[] = { - &cpu_attrs[0].attr, - &cpu_attrs[1].attr, - &cpu_attrs[2].attr, - &attr_kernel_max, - &attr_offline, -}; - -static int cpu_states_init(void) -{ - int i; - int err = 0; - - for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) { - int ret; - ret = sysdev_class_create_file(&cpu_sysdev_class, - cpu_state_attr[i]); - if (!err) - err = ret; - } - return err; -} - /* * register_cpu - Setup a sysfs device for a CPU. * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -280,9 +247,6 @@ int __init cpu_dev_init(void) int err; err = sysdev_class_register(&cpu_sysdev_class); - if (!err) - err = cpu_states_init(); - #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) if (!err) err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); @@ -290,3 +254,16 @@ int __init cpu_dev_init(void) return err; } + +static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE + &class_attr_probe.attr, + &class_attr_release.attr, +#endif + &cpu_attrs[0].attr, + &cpu_attrs[1].attr, + &cpu_attrs[2].attr, + &attr_kernel_max, + &attr_offline, + NULL +}; From 3701cde6e35245e26f63252f46c62e8a790fa996 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:04 +0100 Subject: [PATCH 045/114] sysdev: Use sysdev_class attribute arrays in node driver Convert the node driver to sysdev_class attribute arrays. This greatly cleans up the code and remove a lot of code. Saves ~150 bytes of code on x86-64. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/base/node.c b/drivers/base/node.c index aa8bc4bff4f6..ad43185ec15a 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -16,8 +16,11 @@ #include #include +static struct sysdev_class_attribute *node_state_attrs[]; + static struct sysdev_class node_class = { .name = "node", + .attrs = node_state_attrs, }; @@ -569,29 +572,27 @@ static struct node_attr node_state_attr[] = { #endif }; -static int node_states_init(void) -{ - int i; - int err = 0; - - BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); - for (i = 0; i < NR_NODE_STATES; i++) { - int ret; - ret = sysdev_class_create_file(&node_class, &node_state_attr[i].attr); - if (!err) - err = ret; - } - return err; -} +static struct sysdev_class_attribute *node_state_attrs[] = { + &node_state_attr[0].attr, + &node_state_attr[1].attr, + &node_state_attr[2].attr, + &node_state_attr[3].attr, +#ifdef CONFIG_HIGHMEM + &node_state_attr[4].attr, +#endif + NULL +}; #define NODE_CALLBACK_PRI 2 /* lower than SLAB */ static int __init register_node_type(void) { int ret; + BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); + BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES); + ret = sysdev_class_register(&node_class); if (!ret) { - ret = node_states_init(); hotplug_memory_notifier(node_memory_callback, NODE_CALLBACK_PRI); } From 1e395ab3d9b6aa09c5f0aa46a1b0a6fc5bd33133 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:05 +0100 Subject: [PATCH 046/114] sysdev: Add sysdev_create/remove_files Allow to create/remove arrays of sysdev attributes Just wrappers around sysfs_create/move_files Will be used later to clean up some drivers. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- include/linux/sysdev.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index b6244f9b533f..1154c29f4101 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h @@ -123,6 +123,19 @@ struct sysdev_attribute { extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); +/* Create/remove NULL terminated attribute list */ +static inline int +sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a) +{ + return sysfs_create_files(&d->kobj, (const struct attribute **)a); +} + +static inline void +sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a) +{ + return sysfs_remove_files(&d->kobj, (const struct attribute **)a); +} + struct sysdev_ext_attribute { struct sysdev_attribute attr; void *var; From 8564a6c140317de04a71eb203bdbb58845d69f9c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:06 +0100 Subject: [PATCH 047/114] sysdev: Fix type of sysdev class attribute in memory driver This attribute is really a sysdev_class attribute, not a plain class attribute. They are identical in layout currently, but this might not always be the case. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bd025059711f..563656ad75a1 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,17 +309,18 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct class *class, char *buf) +print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, + char *buf) { return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_block_size_bytes.attr); + &attr_block_size_bytes.attr); } /* From 5fbcae57db69128c14080a7a5a42d0626bfe155c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Feb 2010 11:19:24 +0100 Subject: [PATCH 048/114] sysdev: fix missing s390 conversion In linux-next "sysdev: Pass attribute in sysdev_class attributes show/store" forgot to convert one place in s390 code. Here is the missing part. Cc: Andi Kleen Cc: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/smp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e2121099f03b..29f65bce55e1 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1033,7 +1033,9 @@ static ssize_t __ref rescan_store(struct sysdev_class *class, static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); #endif /* CONFIG_HOTPLUG_CPU */ -static ssize_t dispatching_show(struct sysdev_class *class, char *buf) +static ssize_t dispatching_show(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { ssize_t count; From 28812fe11a21826ba4c97c6c7971a619987cd912 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:07 +0100 Subject: [PATCH 049/114] driver-core: Add attribute argument to class_attribute show/store Passing the attribute to the low level IO functions allows all kinds of cleanups, by sharing low level IO code without requiring an own function for every piece of data. Also drivers can extend the attributes with own data fields and use that in the low level function. This makes the class attributes the same as sysdev_class attributes and plain attributes. This will allow further cleanups in drivers. Full tree sweep converting all users. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 4 ++-- drivers/base/cpu.c | 8 ++++++-- drivers/base/firmware_class.c | 8 ++++++-- drivers/base/memory.c | 11 ++++++++--- drivers/block/osdblk.c | 12 +++++++++--- drivers/block/pktcdvd.c | 12 +++++++++--- drivers/gpio/gpiolib.c | 8 ++++++-- drivers/gpu/drm/drm_sysfs.c | 3 ++- drivers/infiniband/core/ucm.c | 4 +++- drivers/infiniband/core/user_mad.c | 4 +++- drivers/infiniband/core/uverbs_main.c | 4 +++- drivers/misc/phantom.c | 2 +- drivers/mtd/ubi/build.c | 3 ++- drivers/net/bonding/bond_sysfs.c | 5 ++++- drivers/staging/asus_oled/asus_oled.c | 4 +++- drivers/uwb/driver.c | 5 ++++- include/linux/device.h | 6 ++++-- net/bluetooth/l2cap.c | 4 +++- net/bluetooth/rfcomm/core.c | 4 +++- net/bluetooth/rfcomm/sock.c | 4 +++- net/bluetooth/sco.c | 4 +++- 21 files changed, 87 insertions(+), 32 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 6e2c3b064f53..34a2de9c5385 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -31,7 +31,7 @@ static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, ssize_t ret = -EIO; if (class_attr->show) - ret = class_attr->show(cp->class, buf); + ret = class_attr->show(cp->class, class_attr, buf); return ret; } @@ -43,7 +43,7 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, ssize_t ret = -EIO; if (class_attr->store) - ret = class_attr->store(cp->class, buf, count); + ret = class_attr->store(cp->class, class_attr, buf, count); return ret; } diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index fb456b729803..9121c77b77fa 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -79,13 +79,17 @@ void unregister_cpu(struct cpu *cpu) } #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE -static ssize_t cpu_probe_store(struct class *class, const char *buf, +static ssize_t cpu_probe_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { return arch_cpu_probe(buf, count); } -static ssize_t cpu_release_store(struct class *class, const char *buf, +static ssize_t cpu_release_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { return arch_cpu_release(buf, count); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a95024166b66..6604fb33d072 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -69,7 +69,9 @@ fw_load_abort(struct firmware_priv *fw_priv) } static ssize_t -firmware_timeout_show(struct class *class, char *buf) +firmware_timeout_show(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", loading_timeout); } @@ -87,7 +89,9 @@ firmware_timeout_show(struct class *class, char *buf) * Note: zero means 'wait forever'. **/ static ssize_t -firmware_timeout_store(struct class *class, const char *buf, size_t count) +firmware_timeout_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { loading_timeout = simple_strtol(buf, NULL, 10); if (loading_timeout < 0) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 563656ad75a1..495f15e92d4c 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -331,7 +331,8 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct class *class, const char *buf, size_t count) +memory_probe_store(struct class *class, struct class_attribute *attr, + const char *buf, size_t count) { u64 phys_addr; int nid; @@ -368,7 +369,9 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct class *class, const char *buf, size_t count) +store_soft_offline_page(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { int ret; u64 pfn; @@ -385,7 +388,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count) /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct class *class, const char *buf, size_t count) +store_hard_offline_page(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { int ret; u64 pfn; diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index a808b1530b3b..eb2091aa1c19 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -476,7 +476,9 @@ static void class_osdblk_release(struct class *cls) kfree(cls); } -static ssize_t class_osdblk_list(struct class *c, char *data) +static ssize_t class_osdblk_list(struct class *c, + struct class_attribute *attr, + char *data) { int n = 0; struct list_head *tmp; @@ -500,7 +502,9 @@ static ssize_t class_osdblk_list(struct class *c, char *data) return n; } -static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) +static ssize_t class_osdblk_add(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) { struct osdblk_device *osdev; ssize_t rc; @@ -592,7 +596,9 @@ static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) return rc; } -static ssize_t class_osdblk_remove(struct class *c, const char *buf, +static ssize_t class_osdblk_remove(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) { struct osdblk_device *osdev = NULL; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index b72935b8f203..73d815d3f1b2 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -337,7 +337,9 @@ static void class_pktcdvd_release(struct class *cls) { kfree(cls); } -static ssize_t class_pktcdvd_show_map(struct class *c, char *data) +static ssize_t class_pktcdvd_show_map(struct class *c, + struct class_attribute *attr, + char *data) { int n = 0; int idx; @@ -356,7 +358,9 @@ static ssize_t class_pktcdvd_show_map(struct class *c, char *data) return n; } -static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, +static ssize_t class_pktcdvd_store_add(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) { unsigned int major, minor; @@ -376,7 +380,9 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, return -EINVAL; } -static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf, +static ssize_t class_pktcdvd_store_remove(struct class *c, + struct class_attribute *attr, + const char *buf, size_t count) { unsigned int major, minor; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9006fdb26fea..6d1b86661e63 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,7 +623,9 @@ static const struct attribute_group gpiochip_attr_group = { * /sys/class/gpio/unexport ... write-only * integer N ... number of GPIO to unexport */ -static ssize_t export_store(struct class *class, const char *buf, size_t len) +static ssize_t export_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t len) { long gpio; int status; @@ -653,7 +655,9 @@ static ssize_t export_store(struct class *class, const char *buf, size_t len) return status ? : len; } -static ssize_t unexport_store(struct class *class, const char *buf, size_t len) +static ssize_t unexport_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t len) { long gpio; int status; diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 7e42b7e9d43a..b95aaf23596e 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -71,7 +71,8 @@ static int drm_class_resume(struct device *dev) } /* Display the version of drm_core. This doesn't work right in current design */ -static ssize_t version_show(struct class *dev, char *buf) +static ssize_t version_show(struct class *dev, struct class_attribute *attr, + char *buf) { return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 1b09b735c5a8..02e209ff33fd 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -1336,7 +1336,9 @@ static void ib_ucm_remove_one(struct ib_device *device) device_unregister(&ucm_dev->dev); } -static ssize_t show_abi_version(struct class *class, char *buf) +static ssize_t show_abi_version(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION); } diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 02d360cfc2f7..d0de8f265f45 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -965,7 +965,9 @@ static ssize_t show_port(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(port, S_IRUGO, show_port, NULL); -static ssize_t show_abi_version(struct class *class, char *buf) +static ssize_t show_abi_version(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 4fa2e6516441..60879399207a 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -691,7 +691,9 @@ static ssize_t show_dev_abi_version(struct device *device, } static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); -static ssize_t show_abi_version(struct class *class, char *buf) +static ssize_t show_abi_version(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION); } diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 04c27266f567..d30ae9560309 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c @@ -497,7 +497,7 @@ static struct pci_driver phantom_pci_driver = { .resume = phantom_resume }; -static ssize_t phantom_show_version(struct class *cls, char *buf) +static ssize_t phantom_show_version(struct class *cls, struct class_attribute *attr, char *buf) { return sprintf(buf, PHANTOM_VERSION "\n"); } diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index bc45ef9af17d..fad40aa6f099 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -89,7 +89,8 @@ DEFINE_MUTEX(ubi_devices_mutex); static DEFINE_SPINLOCK(ubi_devices_lock); /* "Show" method for files in '//class/ubi/' */ -static ssize_t ubi_version_show(struct class *class, char *buf) +static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", UBI_VERSION); } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 5acd557cea9b..b8bec086daa1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -51,7 +51,9 @@ * "show" function for the bond_masters attribute. * The class parameter is ignored. */ -static ssize_t bonding_show_bonds(struct class *cls, char *buf) +static ssize_t bonding_show_bonds(struct class *cls, + struct class_attribute *attr, + char *buf) { struct net *net = current->nsproxy->net_ns; struct bond_net *bn = net_generic(net, bond_net_id); @@ -98,6 +100,7 @@ static struct net_device *bond_get_by_name(struct net *net, const char *ifname) */ static ssize_t bonding_store_bonds(struct class *cls, + struct class_attribute *attr, const char *buffer, size_t count) { struct net *net = current->nsproxy->net_ns; diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index cadb6f7321ad..7d93f50a0a64 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -770,7 +770,9 @@ static struct usb_driver oled_driver = { .id_table = id_table, }; -static ssize_t version_show(struct class *dev, char *buf) +static ssize_t version_show(struct class *dev, + struct class_attribute *attr, + char *buf) { return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n", ASUS_OLED_VERSION); diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index da77e41de990..08bd6dbfd4a6 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c @@ -74,13 +74,16 @@ unsigned long beacon_timeout_ms = 500; static -ssize_t beacon_timeout_ms_show(struct class *class, char *buf) +ssize_t beacon_timeout_ms_show(struct class *class, + struct class_attribute *attr, + char *buf) { return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms); } static ssize_t beacon_timeout_ms_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) { unsigned long bt; diff --git a/include/linux/device.h b/include/linux/device.h index b30527db3ac0..190f8d30d1d3 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -251,8 +251,10 @@ extern struct device *class_find_device(struct class *class, struct class_attribute { struct attribute attr; - ssize_t (*show)(struct class *class, char *buf); - ssize_t (*store)(struct class *class, const char *buf, size_t count); + ssize_t (*show)(struct class *class, struct class_attribute *attr, + char *buf); + ssize_t (*store)(struct class *class, struct class_attribute *attr, + const char *buf, size_t count); }; #define CLASS_ATTR(_name, _mode, _show, _store) \ diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 400efa26ddba..4db7ae2fe07d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3937,7 +3937,9 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl return 0; } -static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) +static ssize_t l2cap_sysfs_show(struct class *dev, + struct class_attribute *attr, + char *buf) { struct sock *sk; struct hlist_node *node; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 89f4a59eb82b..db8a68e1a5ba 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2098,7 +2098,9 @@ static struct hci_cb rfcomm_cb = { .security_cfm = rfcomm_security_cfm }; -static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf) +static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, + struct class_attribute *attr, + char *buf) { struct rfcomm_session *s; struct list_head *pp, *p; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4b5968dda673..ca87d6ac6a20 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -1061,7 +1061,9 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * return result; } -static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) +static ssize_t rfcomm_sock_sysfs_show(struct class *dev, + struct class_attribute *attr, + char *buf) { struct sock *sk; struct hlist_node *node; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index dd8f6ec57dce..f93b939539bc 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -953,7 +953,9 @@ static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) return 0; } -static ssize_t sco_sysfs_show(struct class *dev, char *buf) +static ssize_t sco_sysfs_show(struct class *dev, + struct class_attribute *attr, + char *buf) { struct sock *sk; struct hlist_node *node; From 869dfc875e32fd832385fd52ce54525a10401ed6 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:08 +0100 Subject: [PATCH 050/114] driver core: Add class_attr_string for simple read-only string Several drivers just export a static string as class attributes. Use the new extensible attribute support to define a simple CLASS_ATTR_STRING() macro for this. This will allow to remove code from drivers in followon patches. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 10 ++++++++++ include/linux/device.h | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/base/class.c b/drivers/base/class.c index 34a2de9c5385..2e297cc4cd3d 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -490,6 +490,16 @@ void class_interface_unregister(struct class_interface *class_intf) class_put(parent); } +ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, + char *buf) +{ + struct class_attribute_string *cs; + cs = container_of(attr, struct class_attribute_string, attr); + return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); +} + +EXPORT_SYMBOL_GPL(show_class_attr_string); + struct class_compat { struct kobject *kobj; }; diff --git a/include/linux/device.h b/include/linux/device.h index 190f8d30d1d3..f95d5bfe8248 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -265,6 +265,23 @@ extern int __must_check class_create_file(struct class *class, extern void class_remove_file(struct class *class, const struct class_attribute *attr); +/* Simple class attribute that is just a static string */ + +struct class_attribute_string { + struct class_attribute attr; + char *str; +}; + +/* Currently read-only only */ +#define _CLASS_ATTR_STRING(_name, _mode, _str) \ + { __ATTR(_name, _mode, show_class_attr_string, NULL), _str } +#define CLASS_ATTR_STRING(_name, _mode, _str) \ + struct class_attribute_string class_attr_##_name = \ + _CLASS_ATTR_STRING(_name, _mode, _str) + +extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, + char *buf); + struct class_interface { struct list_head node; struct class *class; From 0933e2d98d1b170ef62d48e18157f5dc43b58217 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 5 Jan 2010 12:48:09 +0100 Subject: [PATCH 051/114] driver core: Convert some drivers to CLASS_ATTR_STRING Convert some drivers who export a single string as class attribute to the new class_attr_string functions. This removes redundant code all over. Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_sysfs.c | 19 ++++++++----------- drivers/infiniband/core/ucm.c | 15 +++++---------- drivers/infiniband/core/user_mad.c | 11 +++-------- drivers/infiniband/core/uverbs_main.c | 11 +++-------- drivers/misc/phantom.c | 13 ++++--------- drivers/staging/asus_oled/asus_oled.c | 15 ++++----------- 6 files changed, 27 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index b95aaf23596e..014ce24761b9 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -70,20 +70,17 @@ static int drm_class_resume(struct device *dev) return 0; } -/* Display the version of drm_core. This doesn't work right in current design */ -static ssize_t version_show(struct class *dev, struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, - CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); -} - static char *drm_devnode(struct device *dev, mode_t *mode) { return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); } -static CLASS_ATTR(version, S_IRUGO, version_show, NULL); +static CLASS_ATTR_STRING(version, S_IRUGO, + CORE_NAME " " + __stringify(CORE_MAJOR) "." + __stringify(CORE_MINOR) "." + __stringify(CORE_PATCHLEVEL) " " + CORE_DATE); /** * drm_sysfs_create - create a struct drm_sysfs_class structure @@ -110,7 +107,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name) class->suspend = drm_class_suspend; class->resume = drm_class_resume; - err = class_create_file(class, &class_attr_version); + err = class_create_file(class, &class_attr_version.attr); if (err) goto err_out_class; @@ -133,7 +130,7 @@ void drm_sysfs_destroy(void) { if ((drm_class == NULL) || (IS_ERR(drm_class))) return; - class_remove_file(drm_class, &class_attr_version); + class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); } diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 02e209ff33fd..017d6e24448f 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -1336,13 +1336,8 @@ static void ib_ucm_remove_one(struct ib_device *device) device_unregister(&ucm_dev->dev); } -static ssize_t show_abi_version(struct class *class, - struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION); -} -static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); +static CLASS_ATTR_STRING(abi_version, S_IRUGO, + __stringify(IB_USER_CM_ABI_VERSION)); static int __init ib_ucm_init(void) { @@ -1355,7 +1350,7 @@ static int __init ib_ucm_init(void) goto error1; } - ret = class_create_file(&cm_class, &class_attr_abi_version); + ret = class_create_file(&cm_class, &class_attr_abi_version.attr); if (ret) { printk(KERN_ERR "ucm: couldn't create abi_version attribute\n"); goto error2; @@ -1369,7 +1364,7 @@ static int __init ib_ucm_init(void) return 0; error3: - class_remove_file(&cm_class, &class_attr_abi_version); + class_remove_file(&cm_class, &class_attr_abi_version.attr); error2: unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); error1: @@ -1379,7 +1374,7 @@ static int __init ib_ucm_init(void) static void __exit ib_ucm_cleanup(void) { ib_unregister_client(&ucm_client); - class_remove_file(&cm_class, &class_attr_abi_version); + class_remove_file(&cm_class, &class_attr_abi_version.attr); unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); if (overflow_maj) unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES); diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index d0de8f265f45..04b585e86cb2 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -965,13 +965,8 @@ static ssize_t show_port(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(port, S_IRUGO, show_port, NULL); -static ssize_t show_abi_version(struct class *class, - struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); -} -static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); +static CLASS_ATTR_STRING(abi_version, S_IRUGO, + __stringify(IB_USER_MAD_ABI_VERSION)); static dev_t overflow_maj; static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS); @@ -1196,7 +1191,7 @@ static int __init ib_umad_init(void) goto out_chrdev; } - ret = class_create_file(umad_class, &class_attr_abi_version); + ret = class_create_file(umad_class, &class_attr_abi_version.attr); if (ret) { printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); goto out_class; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 60879399207a..d805cf365c8d 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -691,13 +691,8 @@ static ssize_t show_dev_abi_version(struct device *device, } static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); -static ssize_t show_abi_version(struct class *class, - struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION); -} -static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); +static CLASS_ATTR_STRING(abi_version, S_IRUGO, + __stringify(IB_USER_VERBS_ABI_VERSION)); static dev_t overflow_maj; static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES); @@ -843,7 +838,7 @@ static int __init ib_uverbs_init(void) goto out_chrdev; } - ret = class_create_file(uverbs_class, &class_attr_abi_version); + ret = class_create_file(uverbs_class, &class_attr_abi_version.attr); if (ret) { printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); goto out_class; diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index d30ae9560309..779aa8ebe4cf 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c @@ -497,12 +497,7 @@ static struct pci_driver phantom_pci_driver = { .resume = phantom_resume }; -static ssize_t phantom_show_version(struct class *cls, struct class_attribute *attr, char *buf) -{ - return sprintf(buf, PHANTOM_VERSION "\n"); -} - -static CLASS_ATTR(version, 0444, phantom_show_version, NULL); +static CLASS_ATTR_STRING(version, 0444, PHANTOM_VERSION); static int __init phantom_init(void) { @@ -515,7 +510,7 @@ static int __init phantom_init(void) printk(KERN_ERR "phantom: can't register phantom class\n"); goto err; } - retval = class_create_file(phantom_class, &class_attr_version); + retval = class_create_file(phantom_class, &class_attr_version.attr); if (retval) { printk(KERN_ERR "phantom: can't create sysfs version file\n"); goto err_class; @@ -541,7 +536,7 @@ static int __init phantom_init(void) err_unchr: unregister_chrdev_region(dev, PHANTOM_MAX_MINORS); err_attr: - class_remove_file(phantom_class, &class_attr_version); + class_remove_file(phantom_class, &class_attr_version.attr); err_class: class_destroy(phantom_class); err: @@ -554,7 +549,7 @@ static void __exit phantom_exit(void) unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS); - class_remove_file(phantom_class, &class_attr_version); + class_remove_file(phantom_class, &class_attr_version.attr); class_destroy(phantom_class); pr_debug("phantom: module successfully removed\n"); diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index 7d93f50a0a64..7ebecc92c61b 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -770,15 +770,8 @@ static struct usb_driver oled_driver = { .id_table = id_table, }; -static ssize_t version_show(struct class *dev, - struct class_attribute *attr, - char *buf) -{ - return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n", - ASUS_OLED_VERSION); -} - -static CLASS_ATTR(version, S_IRUGO, version_show, NULL); +static CLASS_ATTR_STRING(version, S_IRUGO, + ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION); static int __init asus_oled_init(void) { @@ -790,7 +783,7 @@ static int __init asus_oled_init(void) return PTR_ERR(oled_class); } - retval = class_create_file(oled_class, &class_attr_version); + retval = class_create_file(oled_class, &class_attr_version.attr); if (retval) { err("Error creating class version file"); goto error; @@ -812,7 +805,7 @@ static int __init asus_oled_init(void) static void __exit asus_oled_exit(void) { - class_remove_file(oled_class, &class_attr_version); + class_remove_file(oled_class, &class_attr_version.attr); class_destroy(oled_class); usb_deregister(&oled_driver); From 5e31d76f2817bd50258a092a7c5b15b3006fd61c Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 13 Jan 2010 14:16:36 +0100 Subject: [PATCH 052/114] Driver-Core: devtmpfs - reset inode permissions before unlinking Before unlinking the inode, reset the current permissions of possible references like hardlinks, so granted permissions can not be retained across the device lifetime by creating hardlinks, in the unusual case that there is a user-writable directory on the same filesystem. Signed-off-by: Kay Sievers Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 42ae452b36b0..dac478c6e460 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -301,6 +301,19 @@ int devtmpfs_delete_node(struct device *dev) if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { + struct iattr newattrs; + /* + * before unlinking this node, reset permissions + * of possible references like hardlinks + */ + newattrs.ia_uid = 0; + newattrs.ia_gid = 0; + newattrs.ia_mode = stat.mode & ~0777; + newattrs.ia_valid = + ATTR_UID|ATTR_GID|ATTR_MODE; + mutex_lock(&dentry->d_inode->i_mutex); + notify_change(dentry, &newattrs); + mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) From 4237e5fd3e07da268029cd4862cf551d9a74e33f Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Jan 2010 22:47:57 +0100 Subject: [PATCH 053/114] Driver-Core: devtmpfs - remove EXPERIMENTAL and flush out the description All major distros enable devtmpfs on recent systems, so remove the EXPERIMENTAL flag, and make the description a bit more instructive. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ee377270beb9..8021e19fa1ea 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -9,29 +9,36 @@ config UEVENT_HELPER_PATH every uevent. config DEVTMPFS - bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)" + bool "Maintain a devtmpfs filesystem to mount at /dev" depends on HOTPLUG && SHMEM && TMPFS help - This creates a tmpfs filesystem, and mounts it at bootup - and mounts it at /dev. The kernel driver core creates device - nodes for all registered devices in that filesystem. All device - nodes are owned by root and have the default mode of 0600. - Userspace can add and delete the nodes as needed. This is - intended to simplify bootup, and make it possible to delay - the initial coldplug at bootup done by udev in userspace. - It should also provide a simpler way for rescue systems - to bring up a kernel with dynamic major/minor numbers. - Meaningful symlinks, permissions and device ownership must - still be handled by userspace. - If unsure, say N here. + This creates a tmpfs filesystem instance early at bootup. + In this filesystem, the kernel driver core maintains device + nodes with their default names and permissions for all + registered devices with an assigned major/minor number. + Userspace can modify the filesystem content as needed, add + symlinks, and apply needed permissions. + It provides a fully functional /dev directory, where usually + udev runs on top, managing permissions and adding meaningful + symlinks. + In very limited environments, it may provide a sufficient + functional /dev without any further help. It also allows simple + rescue systems, and reliably handles dynamic major/minor numbers. config DEVTMPFS_MOUNT - bool "Automount devtmpfs at /dev" + bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs" depends on DEVTMPFS help - This will mount devtmpfs at /dev if the kernel mounts the root - filesystem. It will not affect initramfs based mounting. - If unsure, say N here. + This will instruct the kernel to automatically mount the + devtmpfs filesystem at /dev, directly after the kernel has + mounted the root filesystem. The behavior can be overridden + with the commandline parameter: devtmpfs.mount=0|1. + This option does not affect initramfs based booting, here + the devtmpfs filesystem always needs to be mounted manually + after the roots is mounted. + With this option enabled, it allows to bring up a system in + rescue mode with init=/bin/sh, even when the /dev directory + on the rootfs is completely empty. config STANDALONE bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL From 7934779a69f1184f29d786b89e77dd14519bd226 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Jan 2010 22:49:39 +0100 Subject: [PATCH 054/114] Driver-Core: disable /sbin/hotplug by default No recent mainstream system uses the /sbin/hotplug fork-bomb any more. Disable it by default to reflect how it is used these days. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 8021e19fa1ea..fd52c48ee762 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -3,10 +3,18 @@ menu "Generic Driver Options" config UEVENT_HELPER_PATH string "path to uevent helper" depends on HOTPLUG - default "/sbin/hotplug" + default "" help Path to uevent helper program forked by the kernel for every uevent. + Before the switch to the netlink-based uevent source, this was + used to hook hotplug scripts into kernel device events. It + usually pointed to a shell script at /sbin/hotplug. + This should not be used today, because usual systems create + many events at bootup or device discovery in a very short time + frame. One forked process per event can create so many processes + that it creates a high system load, or on smaller systems + it is known to create out-of-memory situations during bootup. config DEVTMPFS bool "Maintain a devtmpfs filesystem to mount at /dev" From 3f5468c9ae293cbca43e4ffe6ca3b3235189042a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Jan 2010 22:54:37 +0100 Subject: [PATCH 055/114] Driver-Core: require valid action string in uevent trigger No longer fall back to "add" and warn, but always require a valid action-string written to the "uevent" file. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index fb4bc4f5151c..f6c73a9e3d95 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -306,15 +306,10 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, { enum kobject_action action; - if (kobject_action_type(buf, count, &action) == 0) { + if (kobject_action_type(buf, count, &action) == 0) kobject_uevent(&dev->kobj, action); - goto out; - } - - dev_err(dev, "uevent: unsupported action-string; this will " - "be ignored in a future kernel version\n"); - kobject_uevent(&dev->kobj, KOBJ_ADD); -out: + else + dev_err(dev, "uevent: unknown action-string\n"); return count; } From 1e5289c97bba2d8ee7239a416bc3f28743362cd9 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Jan 2010 14:43:53 -0800 Subject: [PATCH 056/114] sysfs: Cache the last sysfs_dirent to improve readdir scalability v2 When sysfs_readdir stops short we now cache the next sysfs_dirent to return to user space in filp->private_data. There is no impact on the rest of sysfs by doing this and in the common case it allows us to pick up exactly where we left off with no seeking. Additionally I drop and regrab the sysfs_mutex around filldir to avoid a page fault abritrarily increasing the hold time on the sysfs_mutex. v2: Returned to using INT_MAX as the EOF condition. seekdir is ambiguous unless all directory entries have a unique f_pos value. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14949 Signed-off-by: Eric W. Biederman Cc: Linus Torvalds Cc: stable Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 82 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 699f371b9f12..5c4703d751b5 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -837,11 +837,46 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) return (sd->s_mode >> 12) & 15; } +static int sysfs_dir_release(struct inode *inode, struct file *filp) +{ + sysfs_put(filp->private_data); + return 0; +} + +static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd, + ino_t ino, struct sysfs_dirent *pos) +{ + if (pos) { + int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && + pos->s_parent == parent_sd && + ino == pos->s_ino; + sysfs_put(pos); + if (valid) + return pos; + } + pos = NULL; + if ((ino > 1) && (ino < INT_MAX)) { + pos = parent_sd->s_dir.children; + while (pos && (ino > pos->s_ino)) + pos = pos->s_sibling; + } + return pos; +} + +static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd, + ino_t ino, struct sysfs_dirent *pos) +{ + pos = sysfs_dir_pos(parent_sd, ino, pos); + if (pos) + pos = pos->s_sibling; + return pos; +} + static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dentry *dentry = filp->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; - struct sysfs_dirent *pos; + struct sysfs_dirent *pos = filp->private_data; ino_t ino; if (filp->f_pos == 0) { @@ -857,29 +892,31 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; } - if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { - mutex_lock(&sysfs_mutex); - - /* Skip the dentries we have already reported */ - pos = parent_sd->s_dir.children; - while (pos && (filp->f_pos > pos->s_ino)) - pos = pos->s_sibling; - - for ( ; pos; pos = pos->s_sibling) { - const char * name; - int len; - - name = pos->s_name; - len = strlen(name); - filp->f_pos = ino = pos->s_ino; + mutex_lock(&sysfs_mutex); + for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos); + pos; + pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) { + const char * name; + unsigned int type; + int len, ret; + + name = pos->s_name; + len = strlen(name); + ino = pos->s_ino; + type = dt_type(pos); + filp->f_pos = ino; + filp->private_data = sysfs_get(pos); - if (filldir(dirent, name, len, filp->f_pos, ino, - dt_type(pos)) < 0) - break; - } - if (!pos) - filp->f_pos = INT_MAX; mutex_unlock(&sysfs_mutex); + ret = filldir(dirent, name, len, filp->f_pos, ino, type); + mutex_lock(&sysfs_mutex); + if (ret < 0) + break; + } + mutex_unlock(&sysfs_mutex); + if ((filp->f_pos > 1) && !pos) { /* EOF */ + filp->f_pos = INT_MAX; + filp->private_data = NULL; } return 0; } @@ -888,5 +925,6 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) const struct file_operations sysfs_dir_operations = { .read = generic_read_dir, .readdir = sysfs_readdir, + .release = sysfs_dir_release, .llseek = generic_file_llseek, }; From 985fc176a6c03836454629be2f2a611ccc7c7002 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 13 Jan 2010 21:18:15 -0500 Subject: [PATCH 057/114] driver-core: firmware_class: remove base.h header inclusion base.h is used by base drivers for sharing internal structures. Turns out firmware_class does not depend on it at all so remove it. Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 6604fb33d072..07977484cb3c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -19,7 +19,6 @@ #include #include #include -#include "base.h" #define to_dev(obj) container_of(obj, struct device, kobj) From 9cd43611ccfb46632bfa7d19f688924ea93f1613 Mon Sep 17 00:00:00 2001 From: Emese Revfy Date: Thu, 31 Dec 2009 14:52:51 +0100 Subject: [PATCH 058/114] kobject: Constify struct kset_uevent_ops Constify struct kset_uevent_ops. This is part of the ops structure constification effort started by Arjan van de Ven et al. Benefits of this constification: * prevents modification of data that is shared (referenced) by many other structure instances at runtime * detects/prevents accidental (but not intentional) modification attempts on archs that enforce read-only kernel data at runtime * potentially better optimized code as the compiler can assume that the const data cannot be changed * the compiler/linker move const data into .rodata and therefore exclude them from false sharing Signed-off-by: Emese Revfy Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- drivers/base/core.c | 2 +- drivers/base/memory.c | 2 +- fs/gfs2/sys.c | 2 +- include/linux/kobject.h | 10 +++++----- kernel/params.c | 2 +- lib/kobject.c | 4 ++-- lib/kobject_uevent.c | 2 +- mm/slub.c | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c0c5a43d9fb3..2afe599eb35d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -154,7 +154,7 @@ static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) return 0; } -static struct kset_uevent_ops bus_uevent_ops = { +static const struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; diff --git a/drivers/base/core.c b/drivers/base/core.c index f6c73a9e3d95..58ec1069f4b0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -252,7 +252,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, return retval; } -static struct kset_uevent_ops device_uevent_ops = { +static const struct kset_uevent_ops device_uevent_ops = { .filter = dev_uevent_filter, .name = dev_uevent_name, .uevent = dev_uevent, diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 495f15e92d4c..2f8691511190 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -44,7 +44,7 @@ static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uev return retval; } -static struct kset_uevent_ops memory_uevent_ops = { +static const struct kset_uevent_ops memory_uevent_ops = { .name = memory_uevent_name, .uevent = memory_uevent, }; diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index b5f1a46133c8..543503010ed0 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -574,7 +574,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, return 0; } -static struct kset_uevent_ops gfs2_uevent_ops = { +static const struct kset_uevent_ops gfs2_uevent_ops = { .uevent = gfs2_uevent, }; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 58ae8e00fcdd..57a1eaae9096 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -118,9 +118,9 @@ struct kobj_uevent_env { }; struct kset_uevent_ops { - int (*filter)(struct kset *kset, struct kobject *kobj); - const char *(*name)(struct kset *kset, struct kobject *kobj); - int (*uevent)(struct kset *kset, struct kobject *kobj, + int (* const filter)(struct kset *kset, struct kobject *kobj); + const char *(* const name)(struct kset *kset, struct kobject *kobj); + int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); }; @@ -155,14 +155,14 @@ struct kset { struct list_head list; spinlock_t list_lock; struct kobject kobj; - struct kset_uevent_ops *uevent_ops; + const struct kset_uevent_ops *uevent_ops; }; extern void kset_init(struct kset *kset); extern int __must_check kset_register(struct kset *kset); extern void kset_unregister(struct kset *kset); extern struct kset * __must_check kset_create_and_add(const char *name, - struct kset_uevent_ops *u, + const struct kset_uevent_ops *u, struct kobject *parent_kobj); static inline struct kset *to_kset(struct kobject *kobj) diff --git a/kernel/params.c b/kernel/params.c index 8d95f5451b22..48370be3c0a1 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -736,7 +736,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj) return 0; } -static struct kset_uevent_ops module_uevent_ops = { +static const struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; diff --git a/lib/kobject.c b/lib/kobject.c index b512b746d2af..cecf5a0ef6e1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -789,7 +789,7 @@ static struct kobj_type kset_ktype = { * If the kset was not able to be created, NULL will be returned. */ static struct kset *kset_create(const char *name, - struct kset_uevent_ops *uevent_ops, + const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; @@ -832,7 +832,7 @@ static struct kset *kset_create(const char *name, * If the kset was not able to be created, NULL will be returned. */ struct kset *kset_create_and_add(const char *name, - struct kset_uevent_ops *uevent_ops, + const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 920a3ca6e259..c9d3a3e8405d 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -95,7 +95,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, const char *subsystem; struct kobject *top_kobj; struct kset *kset; - struct kset_uevent_ops *uevent_ops; + const struct kset_uevent_ops *uevent_ops; u64 seq; int i = 0; int retval = 0; diff --git a/mm/slub.c b/mm/slub.c index 0bfd3863d521..a26753c12dcd 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4409,7 +4409,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj) return 0; } -static struct kset_uevent_ops slab_uevent_ops = { +static const struct kset_uevent_ops slab_uevent_ops = { .filter = uevent_filter, }; From c607cf0c20903f22919c187d1db4f3256c58f0c5 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 15 Jan 2010 13:23:51 +0100 Subject: [PATCH 059/114] HOWTO: Updates on subsystem trees, patchwork, -next (vs. -mm) One of the roles which -mm fulfilled some time ago (to offer an integration testing ground) has been taken over by -next. This is still news to Documentation/HOWTO, so mention it there. Also add a word on how patchwork is used to track patches as they make their way into subsystem trees. Remove some arbitrary links to subsystem repositories; they can all be found in the MAINTAINERS database. Acked-by: Randy Dunlap Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- Documentation/HOWTO | 113 ++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 77 deletions(-) diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 8495fc970391..f5395af88a41 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -221,8 +221,8 @@ branches. These different branches are: - main 2.6.x kernel tree - 2.6.x.y -stable kernel tree - 2.6.x -git kernel patches - - 2.6.x -mm kernel patches - subsystem specific kernel trees and patches + - the 2.6.x -next kernel tree for integration tests 2.6.x kernel tree ----------------- @@ -232,7 +232,7 @@ process is as follows: - As soon as a new kernel is released a two weeks window is open, during this period of time maintainers can submit big diffs to Linus, usually the patches that have already been included in the - -mm kernel for a few weeks. The preferred way to submit big changes + -next kernel for a few weeks. The preferred way to submit big changes is using git (the kernel's source management tool, more information can be found at http://git.or.cz/) but plain patches are also just fine. @@ -293,84 +293,43 @@ daily and represent the current state of Linus' tree. They are more experimental than -rc kernels since they are generated automatically without even a cursory glance to see if they are sane. -2.6.x -mm kernel patches ------------------------- -These are experimental kernel patches released by Andrew Morton. Andrew -takes all of the different subsystem kernel trees and patches and mushes -them together, along with a lot of patches that have been plucked from -the linux-kernel mailing list. This tree serves as a proving ground for -new features and patches. Once a patch has proved its worth in -mm for -a while Andrew or the subsystem maintainer pushes it on to Linus for -inclusion in mainline. - -It is heavily encouraged that all new patches get tested in the -mm tree -before they are sent to Linus for inclusion in the main kernel tree. Code -which does not make an appearance in -mm before the opening of the merge -window will prove hard to merge into the mainline. - -These kernels are not appropriate for use on systems that are supposed -to be stable and they are more risky to run than any of the other -branches. - -If you wish to help out with the kernel development process, please test -and use these kernel releases and provide feedback to the linux-kernel -mailing list if you have any problems, and if everything works properly. - -In addition to all the other experimental patches, these kernels usually -also contain any changes in the mainline -git kernels available at the -time of release. - -The -mm kernels are not released on a fixed schedule, but usually a few --mm kernels are released in between each -rc kernel (1 to 3 is common). - Subsystem Specific kernel trees and patches ------------------------------------------- -A number of the different kernel subsystem developers expose their -development trees so that others can see what is happening in the -different areas of the kernel. These trees are pulled into the -mm -kernel releases as described above. - -Here is a list of some of the different kernel trees available: - git trees: - - Kbuild development tree, Sam Ravnborg - git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git - - - ACPI development tree, Len Brown - git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git - - - Block development tree, Jens Axboe - git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git - - - DRM development tree, Dave Airlie - git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git - - - ia64 development tree, Tony Luck - git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git - - - infiniband, Roland Dreier - git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git - - - libata, Jeff Garzik - git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git - - - network drivers, Jeff Garzik - git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git - - - pcmcia, Dominik Brodowski - git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git - - - SCSI, James Bottomley - git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git - - - x86, Ingo Molnar - git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git - - quilt trees: - - USB, Driver Core, and I2C, Greg Kroah-Hartman - kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ +The maintainers of the various kernel subsystems --- and also many +kernel subsystem developers --- expose their current state of +development in source repositories. That way, others can see what is +happening in the different areas of the kernel. In areas where +development is rapid, a developer may be asked to base his submissions +onto such a subsystem kernel tree so that conflicts between the +submission and other already ongoing work are avoided. + +Most of these repositories are git trees, but there are also other SCMs +in use, or patch queues being published as quilt series. Addresses of +these subsystem repositories are listed in the MAINTAINERS file. Many +of them can be browsed at http://git.kernel.org/. + +Before a proposed patch is committed to such a subsystem tree, it is +subject to review which primarily happens on mailing lists (see the +respective section below). For several kernel subsystems, this review +process is tracked with the tool patchwork. Patchwork offers a web +interface which shows patch postings, any comments on a patch or +revisions to it, and maintainers can mark patches as under review, +accepted, or rejected. Most of these patchwork sites are listed at +http://patchwork.kernel.org/ or http://patchwork.ozlabs.org/. + +2.6.x -next kernel tree for integration tests +--------------------------------------------- +Before updates from subsystem trees are merged into the mainline 2.6.x +tree, they need to be integration-tested. For this purpose, a special +testing repository exists into which virtually all subsystem trees are +pulled on an almost daily basis: + http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git + http://linux.f-seidel.de/linux-next/pmwiki/ + +This way, the -next kernel gives a summary outlook onto what will be +expected to go into the mainline kernel at the next merge period. +Adventurous testers are very welcome to runtime-test the -next kernel. - Other kernel trees can be found listed at http://git.kernel.org/ and in - the MAINTAINERS file. Bug Reporting ------------- From 6c1733aca0b48db4d0e660d54976a1cca25b5eaf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Jan 2010 15:07:59 -0800 Subject: [PATCH 060/114] sysdev: fix up the probe/release attributes These should be sysdev attributes, not class attributes. This patch should resolve the problem. Thanks to Stephen Rothwell for pointing out the problem. Reported-by: Stephen Rothwell Cc: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 9121c77b77fa..7036e8e96ab8 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -79,24 +79,24 @@ void unregister_cpu(struct cpu *cpu) } #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE -static ssize_t cpu_probe_store(struct class *class, - struct class_attribute *attr, +static ssize_t cpu_probe_store(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { return arch_cpu_probe(buf, count); } -static ssize_t cpu_release_store(struct class *class, - struct class_attribute *attr, +static ssize_t cpu_release_store(struct sys_device *dev, + struct sysdev_attribute *attr, const char *buf, size_t count) { return arch_cpu_release(buf, count); } -static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); -static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); +static SYSDEV_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +static SYSDEV_ATTR(release, S_IWUSR, NULL, cpu_release_store); #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -261,8 +261,8 @@ int __init cpu_dev_init(void) static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE - &class_attr_probe.attr, - &class_attr_release.attr, + &attr_probe, + &attr_release, #endif &cpu_attrs[0].attr, &cpu_attrs[1].attr, From 52cf25d0ab7f78eeecc59ac652ed5090f69b619e Mon Sep 17 00:00:00 2001 From: Emese Revfy Date: Tue, 19 Jan 2010 02:58:23 +0100 Subject: [PATCH 061/114] Driver core: Constify struct sysfs_ops in struct kobj_type Constify struct sysfs_ops. This is part of the ops structure constification effort started by Arjan van de Ven et al. Benefits of this constification: * prevents modification of data that is shared (referenced) by many other structure instances at runtime * detects/prevents accidental (but not intentional) modification attempts on archs that enforce read-only kernel data at runtime * potentially better optimized code as the compiler can assume that the const data cannot be changed * the compiler/linker move const data into .rodata and therefore exclude them from false sharing Signed-off-by: Emese Revfy Acked-by: David Teigland Acked-by: Matt Domsch Acked-by: Maciej Sosnowski Acked-by: Hans J. Koch Acked-by: Pekka Enberg Acked-by: Jens Axboe Acked-by: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman --- Documentation/kobject.txt | 2 +- arch/ia64/kernel/topology.c | 2 +- arch/powerpc/kernel/cacheinfo.c | 2 +- arch/sh/kernel/cpu/sh4/sq.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/mcheck/mce_amd.c | 2 +- block/blk-integrity.c | 2 +- block/blk-sysfs.c | 2 +- block/elevator.c | 2 +- drivers/base/bus.c | 4 ++-- drivers/base/class.c | 2 +- drivers/base/core.c | 2 +- drivers/base/sys.c | 4 ++-- drivers/block/pktcdvd.c | 2 +- drivers/cpufreq/cpufreq.c | 2 +- drivers/cpuidle/sysfs.c | 4 ++-- drivers/dma/ioat/dma.c | 2 +- drivers/dma/ioat/dma.h | 2 +- drivers/edac/edac_device_sysfs.c | 6 +++--- drivers/edac/edac_mc_sysfs.c | 4 ++-- drivers/edac/edac_pci_sysfs.c | 4 ++-- drivers/firmware/edd.c | 2 +- drivers/firmware/efivars.c | 2 +- drivers/firmware/iscsi_ibft.c | 2 +- drivers/firmware/memmap.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/ttm/ttm_memory.c | 2 +- drivers/infiniband/core/cm.c | 2 +- drivers/infiniband/core/sysfs.c | 2 +- drivers/md/dm-sysfs.c | 2 +- drivers/md/md.c | 4 ++-- drivers/net/ibmveth.c | 2 +- drivers/net/iseries_veth.c | 4 ++-- drivers/parisc/pdc_stable.c | 2 +- drivers/pci/hotplug/fakephp.c | 2 +- drivers/pci/slot.c | 2 +- drivers/uio/uio.c | 4 ++-- drivers/uwb/wlp/sysfs.c | 3 +-- drivers/video/omap2/dss/manager.c | 2 +- drivers/video/omap2/dss/overlay.c | 2 +- drivers/xen/sys-hypervisor.c | 2 +- fs/btrfs/sysfs.c | 4 ++-- fs/dlm/lockspace.c | 2 +- fs/ext4/super.c | 2 +- fs/gfs2/sys.c | 2 +- fs/ocfs2/cluster/masklog.c | 2 +- fs/sysfs/file.c | 8 ++++---- include/linux/kobject.h | 4 ++-- kernel/params.c | 2 +- lib/kobject.c | 2 +- mm/slub.c | 2 +- net/bridge/br_private.h | 2 +- net/bridge/br_sysfs_if.c | 2 +- samples/kobject/kset-example.c | 2 +- 54 files changed, 69 insertions(+), 70 deletions(-) diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index c79ab996dada..bdb13817e1e9 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt @@ -266,7 +266,7 @@ kobj_type: struct kobj_type { void (*release)(struct kobject *); - struct sysfs_ops *sysfs_ops; + const struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; }; diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 8f060352e129..b3a5818088d9 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -282,7 +282,7 @@ static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * return ret; } -static struct sysfs_ops cache_sysfs_ops = { +static const struct sysfs_ops cache_sysfs_ops = { .show = cache_show }; diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index bb37b1d19a58..01fe9ce28379 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -642,7 +642,7 @@ static struct kobj_attribute *cache_index_opt_attrs[] = { &cache_assoc_attr, }; -static struct sysfs_ops cache_index_ops = { +static const struct sysfs_ops cache_index_ops = { .show = cache_index_show, }; diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index fc065f9da6e5..14726eef1ce0 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -326,7 +326,7 @@ static struct attribute *sq_sysfs_attrs[] = { NULL, }; -static struct sysfs_ops sq_sysfs_ops = { +static const struct sysfs_ops sq_sysfs_ops = { .show = sq_sysfs_show, .store = sq_sysfs_store, }; diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index eddb1bdd1b8f..b3eeb66c0a51 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -903,7 +903,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops sysfs_ops = { +static const struct sysfs_ops sysfs_ops = { .show = show, .store = store, }; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 83a3d1f4efca..cda932ca3ade 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -388,7 +388,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops threshold_ops = { +static const struct sysfs_ops threshold_ops = { .show = show, .store = store, }; diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 15c630813b1c..96e83c2bdb94 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -278,7 +278,7 @@ static struct attribute *integrity_attrs[] = { NULL, }; -static struct sysfs_ops integrity_ops = { +static const struct sysfs_ops integrity_ops = { .show = &integrity_attr_show, .store = &integrity_attr_store, }; diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index e85442415db3..2ae2cb3f362f 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -450,7 +450,7 @@ static void blk_release_queue(struct kobject *kobj) kmem_cache_free(blk_requestq_cachep, q); } -static struct sysfs_ops queue_sysfs_ops = { +static const struct sysfs_ops queue_sysfs_ops = { .show = queue_attr_show, .store = queue_attr_store, }; diff --git a/block/elevator.c b/block/elevator.c index ee3a883840f2..df75676f6671 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -892,7 +892,7 @@ elv_attr_store(struct kobject *kobj, struct attribute *attr, return error; } -static struct sysfs_ops elv_sysfs_ops = { +static const struct sysfs_ops elv_sysfs_ops = { .show = elv_attr_show, .store = elv_attr_store, }; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2afe599eb35d..cca1aa10054c 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -70,7 +70,7 @@ static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops driver_sysfs_ops = { +static const struct sysfs_ops driver_sysfs_ops = { .show = drv_attr_show, .store = drv_attr_store, }; @@ -115,7 +115,7 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops bus_sysfs_ops = { +static const struct sysfs_ops bus_sysfs_ops = { .show = bus_attr_show, .store = bus_attr_store, }; diff --git a/drivers/base/class.c b/drivers/base/class.c index 2e297cc4cd3d..0147f476b8a9 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -63,7 +63,7 @@ static void class_release(struct kobject *kobj) kfree(cp); } -static struct sysfs_ops class_sysfs_ops = { +static const struct sysfs_ops class_sysfs_ops = { .show = class_attr_show, .store = class_attr_store, }; diff --git a/drivers/base/core.c b/drivers/base/core.c index 58ec1069f4b0..b0d6646a2814 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -100,7 +100,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops dev_sysfs_ops = { +static const struct sysfs_ops dev_sysfs_ops = { .show = dev_attr_show, .store = dev_attr_store, }; diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 747c99e0568b..8980feec5d14 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -54,7 +54,7 @@ sysdev_store(struct kobject *kobj, struct attribute *attr, return -EIO; } -static struct sysfs_ops sysfs_ops = { +static const struct sysfs_ops sysfs_ops = { .show = sysdev_show, .store = sysdev_store, }; @@ -104,7 +104,7 @@ static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, return -EIO; } -static struct sysfs_ops sysfs_class_ops = { +static const struct sysfs_ops sysfs_class_ops = { .show = sysdev_class_show, .store = sysdev_class_store, }; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 73d815d3f1b2..39c8514442eb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -284,7 +284,7 @@ static ssize_t kobj_pkt_store(struct kobject *kobj, return len; } -static struct sysfs_ops kobj_pkt_ops = { +static const struct sysfs_ops kobj_pkt_ops = { .show = kobj_pkt_show, .store = kobj_pkt_store }; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 67bc2ece7b4b..2d5d575e889d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -766,7 +766,7 @@ static void cpufreq_sysfs_release(struct kobject *kobj) complete(&policy->kobj_unregister); } -static struct sysfs_ops sysfs_ops = { +static const struct sysfs_ops sysfs_ops = { .show = show, .store = store, }; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index c9cefacabf37..8719b36e1a4d 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -195,7 +195,7 @@ static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr, return ret; } -static struct sysfs_ops cpuidle_sysfs_ops = { +static const struct sysfs_ops cpuidle_sysfs_ops = { .show = cpuidle_show, .store = cpuidle_store, }; @@ -281,7 +281,7 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, return ret; } -static struct sysfs_ops cpuidle_state_sysfs_ops = { +static const struct sysfs_ops cpuidle_state_sysfs_ops = { .show = cpuidle_state_show, }; diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index af14c9a5b8d4..0099340b9616 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -1138,7 +1138,7 @@ ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page) return entry->show(&chan->common, page); } -struct sysfs_ops ioat_sysfs_ops = { +const struct sysfs_ops ioat_sysfs_ops = { .show = ioat_attr_show, }; diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 4f747a254074..86b97ac8774e 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -346,7 +346,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan, unsigned long *phys_complete); void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type); void ioat_kobject_del(struct ioatdma_device *device); -extern struct sysfs_ops ioat_sysfs_ops; +extern const struct sysfs_ops ioat_sysfs_ops; extern struct ioat_sysfs_entry ioat_version_attr; extern struct ioat_sysfs_entry ioat_cap_attr; #endif /* IOATDMA_H */ diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index 53764577035f..5fdedbc0f545 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -137,7 +137,7 @@ static ssize_t edac_dev_ctl_info_store(struct kobject *kobj, } /* edac_dev file operations for an 'ctl_info' */ -static struct sysfs_ops device_ctl_info_ops = { +static const struct sysfs_ops device_ctl_info_ops = { .show = edac_dev_ctl_info_show, .store = edac_dev_ctl_info_store }; @@ -373,7 +373,7 @@ static ssize_t edac_dev_instance_store(struct kobject *kobj, } /* edac_dev file operations for an 'instance' */ -static struct sysfs_ops device_instance_ops = { +static const struct sysfs_ops device_instance_ops = { .show = edac_dev_instance_show, .store = edac_dev_instance_store }; @@ -476,7 +476,7 @@ static ssize_t edac_dev_block_store(struct kobject *kobj, } /* edac_dev file operations for a 'block' */ -static struct sysfs_ops device_block_ops = { +static const struct sysfs_ops device_block_ops = { .show = edac_dev_block_show, .store = edac_dev_block_store }; diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index e1d4ce083481..88840e9fa3e0 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -245,7 +245,7 @@ static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, return -EIO; } -static struct sysfs_ops csrowfs_ops = { +static const struct sysfs_ops csrowfs_ops = { .show = csrowdev_show, .store = csrowdev_store }; @@ -575,7 +575,7 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, } /* Intermediate show/store table */ -static struct sysfs_ops mci_ops = { +static const struct sysfs_ops mci_ops = { .show = mcidev_show, .store = mcidev_store }; diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index fb60a877d768..bef94e3d9944 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -121,7 +121,7 @@ static ssize_t edac_pci_instance_store(struct kobject *kobj, } /* fs_ops table */ -static struct sysfs_ops pci_instance_ops = { +static const struct sysfs_ops pci_instance_ops = { .show = edac_pci_instance_show, .store = edac_pci_instance_store }; @@ -261,7 +261,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, return -EIO; } -static struct sysfs_ops edac_pci_sysfs_ops = { +static const struct sysfs_ops edac_pci_sysfs_ops = { .show = edac_pci_dev_show, .store = edac_pci_dev_store }; diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 9e4f59dc7f1e..110e24e50883 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -122,7 +122,7 @@ edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) return ret; } -static struct sysfs_ops edd_attr_ops = { +static const struct sysfs_ops edd_attr_ops = { .show = edd_attr_show, }; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index f4f709d1370b..082f06ecd327 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -362,7 +362,7 @@ static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops efivar_attr_ops = { +static const struct sysfs_ops efivar_attr_ops = { .show = efivar_attr_show, .store = efivar_attr_store, }; diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index a3600e3ed0fa..ed2801c378de 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -519,7 +519,7 @@ static ssize_t ibft_show_attribute(struct kobject *kobj, return ret; } -static struct sysfs_ops ibft_attr_ops = { +static const struct sysfs_ops ibft_attr_ops = { .show = ibft_show_attribute, }; diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index 20f645743ead..d59f7cad2269 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -74,7 +74,7 @@ static struct attribute *def_attrs[] = { NULL }; -static struct sysfs_ops memmap_attr_ops = { +static const struct sysfs_ops memmap_attr_ops = { .show = memmap_attr_show, }; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c7320ce4567d..89c38c49066f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -128,7 +128,7 @@ static struct attribute *ttm_bo_global_attrs[] = { NULL }; -static struct sysfs_ops ttm_bo_global_ops = { +static const struct sysfs_ops ttm_bo_global_ops = { .show = &ttm_bo_global_show }; diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index f5245c02b8fd..eb143e04d402 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -152,7 +152,7 @@ static struct attribute *ttm_mem_zone_attrs[] = { NULL }; -static struct sysfs_ops ttm_mem_zone_ops = { +static const struct sysfs_ops ttm_mem_zone_ops = { .show = &ttm_mem_zone_show, .store = &ttm_mem_zone_store }; diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 5130fc55b8e2..764787ebe8d8 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3597,7 +3597,7 @@ static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr, atomic_long_read(&group->counter[cm_attr->index])); } -static struct sysfs_ops cm_counter_ops = { +static const struct sysfs_ops cm_counter_ops = { .show = cm_show_counter }; diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 158a214da2f7..1558bb7fc74d 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -79,7 +79,7 @@ static ssize_t port_attr_show(struct kobject *kobj, return port_attr->show(p, port_attr, buf); } -static struct sysfs_ops port_sysfs_ops = { +static const struct sysfs_ops port_sysfs_ops = { .show = port_attr_show }; diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index f91b40942e07..84d2b91e4efb 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c @@ -75,7 +75,7 @@ static struct attribute *dm_attrs[] = { NULL, }; -static struct sysfs_ops dm_sysfs_ops = { +static const struct sysfs_ops dm_sysfs_ops = { .show = dm_attr_show, }; diff --git a/drivers/md/md.c b/drivers/md/md.c index a20a71e5efd3..fdc1890b6ac5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2642,7 +2642,7 @@ static void rdev_free(struct kobject *ko) mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj); kfree(rdev); } -static struct sysfs_ops rdev_sysfs_ops = { +static const struct sysfs_ops rdev_sysfs_ops = { .show = rdev_attr_show, .store = rdev_attr_store, }; @@ -4059,7 +4059,7 @@ static void md_free(struct kobject *ko) kfree(mddev); } -static struct sysfs_ops md_sysfs_ops = { +static const struct sysfs_ops md_sysfs_ops = { .show = md_attr_show, .store = md_attr_store, }; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index f2b937966950..0bc777bac9b4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1577,7 +1577,7 @@ static struct attribute * veth_pool_attrs[] = { NULL, }; -static struct sysfs_ops veth_pool_ops = { +static const struct sysfs_ops veth_pool_ops = { .show = veth_pool_show, .store = veth_pool_store, }; diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 966de5d69521..e6e972d9b7ca 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -384,7 +384,7 @@ static struct attribute *veth_cnx_default_attrs[] = { NULL }; -static struct sysfs_ops veth_cnx_sysfs_ops = { +static const struct sysfs_ops veth_cnx_sysfs_ops = { .show = veth_cnx_attribute_show }; @@ -441,7 +441,7 @@ static struct attribute *veth_port_default_attrs[] = { NULL }; -static struct sysfs_ops veth_port_sysfs_ops = { +static const struct sysfs_ops veth_port_sysfs_ops = { .show = veth_port_attribute_show }; diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 0bc5d474b168..1062b8ffe244 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -481,7 +481,7 @@ pdcspath_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops pdcspath_attr_ops = { +static const struct sysfs_ops pdcspath_attr_ops = { .show = pdcspath_attr_show, .store = pdcspath_attr_store, }; diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 6151389fd903..0a894efd4b9b 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -73,7 +73,7 @@ static void legacy_release(struct kobject *kobj) } static struct kobj_type legacy_ktype = { - .sysfs_ops = &(struct sysfs_ops){ + .sysfs_ops = &(const struct sysfs_ops){ .store = legacy_store, .show = legacy_show }, .release = &legacy_release, diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 49c9e6c9779a..f75a44d37fbe 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -29,7 +29,7 @@ static ssize_t pci_slot_attr_store(struct kobject *kobj, return attribute->store ? attribute->store(slot, buf, len) : -EIO; } -static struct sysfs_ops pci_slot_sysfs_ops = { +static const struct sysfs_ops pci_slot_sysfs_ops = { .show = pci_slot_attr_show, .store = pci_slot_attr_store, }; diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index e941367dd28f..4de382acd8f2 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -129,7 +129,7 @@ static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr, return entry->show(mem, buf); } -static struct sysfs_ops map_sysfs_ops = { +static const struct sysfs_ops map_sysfs_ops = { .show = map_type_show, }; @@ -217,7 +217,7 @@ static ssize_t portio_type_show(struct kobject *kobj, struct attribute *attr, return entry->show(port, buf); } -static struct sysfs_ops portio_sysfs_ops = { +static const struct sysfs_ops portio_sysfs_ops = { .show = portio_type_show, }; diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c index 0370399ff4bb..6627c94cc854 100644 --- a/drivers/uwb/wlp/sysfs.c +++ b/drivers/uwb/wlp/sysfs.c @@ -615,8 +615,7 @@ ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static -struct sysfs_ops wss_sysfs_ops = { +static const struct sysfs_ops wss_sysfs_ops = { .show = wlp_wss_attr_show, .store = wlp_wss_attr_store, }; diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 913142d4cab1..9acef00c47ea 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -341,7 +341,7 @@ static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, return manager_attr->store(manager, buf, size); } -static struct sysfs_ops manager_sysfs_ops = { +static const struct sysfs_ops manager_sysfs_ops = { .show = manager_attr_show, .store = manager_attr_store, }; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 0c5bea263ac6..aed3f3194347 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -320,7 +320,7 @@ static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, return overlay_attr->store(overlay, buf, size); } -static struct sysfs_ops overlay_sysfs_ops = { +static const struct sysfs_ops overlay_sysfs_ops = { .show = overlay_attr_show, .store = overlay_attr_store, }; diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index ae5cb05a1a1c..bb71ab2336c8 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -426,7 +426,7 @@ static ssize_t hyp_sysfs_store(struct kobject *kobj, return 0; } -static struct sysfs_ops hyp_sysfs_ops = { +static const struct sysfs_ops hyp_sysfs_ops = { .show = hyp_sysfs_show, .store = hyp_sysfs_store, }; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index a240b6fa81df..4ce16ef702a3 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -164,12 +164,12 @@ static void btrfs_root_release(struct kobject *kobj) complete(&root->kobj_unregister); } -static struct sysfs_ops btrfs_super_attr_ops = { +static const struct sysfs_ops btrfs_super_attr_ops = { .show = btrfs_super_attr_show, .store = btrfs_super_attr_store, }; -static struct sysfs_ops btrfs_root_attr_ops = { +static const struct sysfs_ops btrfs_root_attr_ops = { .show = btrfs_root_attr_show, .store = btrfs_root_attr_store, }; diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 26a8bd40400a..f994a7dfda85 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -148,7 +148,7 @@ static void lockspace_kobj_release(struct kobject *k) kfree(ls); } -static struct sysfs_ops dlm_attr_ops = { +static const struct sysfs_ops dlm_attr_ops = { .show = dlm_attr_show, .store = dlm_attr_store, }; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2b83b96cb2eb..ce84a6ed4a48 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2358,7 +2358,7 @@ static void ext4_sb_release(struct kobject *kobj) } -static struct sysfs_ops ext4_attr_ops = { +static const struct sysfs_ops ext4_attr_ops = { .show = ext4_attr_show, .store = ext4_attr_store, }; diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 543503010ed0..419042f7f0b6 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -49,7 +49,7 @@ static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr, return a->store ? a->store(sdp, buf, len) : len; } -static struct sysfs_ops gfs2_attr_ops = { +static const struct sysfs_ops gfs2_attr_ops = { .show = gfs2_attr_show, .store = gfs2_attr_store, }; diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index b39da877b12f..3bb928a2bf7d 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -136,7 +136,7 @@ static ssize_t mlog_store(struct kobject *obj, struct attribute *attr, return mlog_mask_store(mlog_attr->mask, buf, count); } -static struct sysfs_ops mlog_attr_ops = { +static const struct sysfs_ops mlog_attr_ops = { .show = mlog_show, .store = mlog_store, }; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 50b725bcc3f3..ced2299f1c9a 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -53,7 +53,7 @@ struct sysfs_buffer { size_t count; loff_t pos; char * page; - struct sysfs_ops * ops; + const struct sysfs_ops * ops; struct mutex mutex; int needs_read_fill; int event; @@ -75,7 +75,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer { struct sysfs_dirent *attr_sd = dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; - struct sysfs_ops * ops = buffer->ops; + const struct sysfs_ops * ops = buffer->ops; int ret = 0; ssize_t count; @@ -199,7 +199,7 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t { struct sysfs_dirent *attr_sd = dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; - struct sysfs_ops * ops = buffer->ops; + const struct sysfs_ops * ops = buffer->ops; int rc; /* need attr_sd for attr and ops, its parent for kobj */ @@ -335,7 +335,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; struct sysfs_buffer *buffer; - struct sysfs_ops *ops; + const struct sysfs_ops *ops; int error = -EACCES; char *p; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 57a1eaae9096..3950d3c2850d 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -106,7 +106,7 @@ extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); struct kobj_type { void (*release)(struct kobject *kobj); - struct sysfs_ops *sysfs_ops; + const struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; }; @@ -132,7 +132,7 @@ struct kobj_attribute { const char *buf, size_t count); }; -extern struct sysfs_ops kobj_sysfs_ops; +extern const struct sysfs_ops kobj_sysfs_ops; /** * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. diff --git a/kernel/params.c b/kernel/params.c index 48370be3c0a1..68396d73c838 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -722,7 +722,7 @@ static ssize_t module_attr_store(struct kobject *kobj, return ret; } -static struct sysfs_ops module_sysfs_ops = { +static const struct sysfs_ops module_sysfs_ops = { .show = module_attr_show, .store = module_attr_store, }; diff --git a/lib/kobject.c b/lib/kobject.c index cecf5a0ef6e1..8115eb1bbf4d 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -700,7 +700,7 @@ static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -struct sysfs_ops kobj_sysfs_ops = { +const struct sysfs_ops kobj_sysfs_ops = { .show = kobj_attr_show, .store = kobj_attr_store, }; diff --git a/mm/slub.c b/mm/slub.c index a26753c12dcd..a2b8969ba6d0 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4390,7 +4390,7 @@ static void kmem_cache_release(struct kobject *kobj) kfree(s); } -static struct sysfs_ops slab_sysfs_ops = { +static const struct sysfs_ops slab_sysfs_ops = { .show = slab_attr_show, .store = slab_attr_store, }; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1cf2cef78584..fef0384e3c0b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -423,7 +423,7 @@ extern void br_ifinfo_notify(int event, struct net_bridge_port *port); #ifdef CONFIG_SYSFS /* br_sysfs_if.c */ -extern struct sysfs_ops brport_sysfs_ops; +extern const struct sysfs_ops brport_sysfs_ops; extern int br_sysfs_addif(struct net_bridge_port *p); /* br_sysfs_br.c */ diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 696596cd3384..0b9916489d6b 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -238,7 +238,7 @@ static ssize_t brport_store(struct kobject * kobj, return ret; } -struct sysfs_ops brport_sysfs_ops = { +const struct sysfs_ops brport_sysfs_ops = { .show = brport_show, .store = brport_store, }; diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index 7c6088140528..3b126d1f8599 100644 --- a/samples/kobject/kset-example.c +++ b/samples/kobject/kset-example.c @@ -87,7 +87,7 @@ static ssize_t foo_attr_store(struct kobject *kobj, } /* Our custom sysfs_ops that we will associate with our ktype later on */ -static struct sysfs_ops foo_sysfs_ops = { +static const struct sysfs_ops foo_sysfs_ops = { .show = foo_attr_show, .store = foo_attr_store, }; From 831fad2f75f0d7bfc339de81173e7068a3c72276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 26 Jan 2010 09:35:00 +0100 Subject: [PATCH 062/114] Driver core: make struct platform_driver.id_table const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a warning on several pxa based machines: arch/arm/mach-pxa/ssp.c:475: warning: initialization discards qualifiers from pointer target type Signed-off-by: Uwe Kleine-König Acked-by: Vikram Dhillon Acked-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- include/linux/platform_device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 937d58021d1b..575e08bc6630 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -636,7 +636,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) } static const struct platform_device_id *platform_match_id( - struct platform_device_id *id, + const struct platform_device_id *id, struct platform_device *pdev) { while (id->name[0]) { diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 2c2d035bfb92..212da17d06af 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -62,7 +62,7 @@ struct platform_driver { int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; - struct platform_device_id *id_table; + const struct platform_device_id *id_table; }; extern int platform_driver_register(struct platform_driver *); From 91a99dfc6b57f2e956d10d41123234fad3399212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:49 +0100 Subject: [PATCH 063/114] platform-drivers: move probe to .devinit.text in arch/arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to a probe callback is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Andrew Morton Cc: Ben Dooks Cc: Dmitry Baryshkov Cc: Eric Miao Cc: Liam Girdwood Cc: Paul Sokolovsky Cc: Richard Purdie Cc: Russell King Acked-by: Arnaud Patard Acked-by: Dmitry Eremin-Solenikov Acked-by: Kristoffer Ericson Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/corgi_ssp.c | 2 +- arch/arm/mach-pxa/sharpsl_pm.c | 2 +- arch/arm/mach-s3c2410/h1940-bluetooth.c | 2 +- arch/arm/mach-sa1100/jornada720_ssp.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index a5ee70735e04..1d9bc118ee32 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -204,7 +204,7 @@ void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo) ssp_machinfo = machinfo; } -static int __init corgi_ssp_probe(struct platform_device *dev) +static int __devinit corgi_ssp_probe(struct platform_device *dev) { int ret; diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 67229a1ef55c..463d874bb867 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -900,7 +900,7 @@ static struct platform_suspend_ops sharpsl_pm_ops = { }; #endif -static int __init sharpsl_pm_probe(struct platform_device *pdev) +static int __devinit sharpsl_pm_probe(struct platform_device *pdev) { int ret; diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c index b7d1f8d27bc2..a3f3c7b1ca38 100644 --- a/arch/arm/mach-s3c2410/h1940-bluetooth.c +++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c @@ -56,7 +56,7 @@ static const struct rfkill_ops h1940bt_rfkill_ops = { .set_block = h1940bt_set_block, }; -static int __init h1940bt_probe(struct platform_device *pdev) +static int __devinit h1940bt_probe(struct platform_device *pdev) { struct rfkill *rfk; int ret = 0; diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index 506a5e5a9ad5..9b6dee5d16db 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -130,7 +130,7 @@ void jornada_ssp_end(void) }; EXPORT_SYMBOL(jornada_ssp_end); -static int __init jornada_ssp_probe(struct platform_device *dev) +static int __devinit jornada_ssp_probe(struct platform_device *dev) { int ret; From 1b07193b34c1bc1c184e2d53a62633a73ea9b0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:50 +0100 Subject: [PATCH 064/114] platform-drivers: move probe to .devinit.text in drivers/scsi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to a probe callback is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Andrew Morton Cc: David Brownell Cc: Dmitri Vorobiev Cc: Henrik Kretzschmar Cc: James Bottomley Cc: Kay Sievers Cc: peter fuerst Cc: Thomas Bogendoerfer Acked-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sgiwd93.c | 2 +- drivers/scsi/sni_53c710.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 0807b260268b..fef0e3c75b16 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -226,7 +226,7 @@ static struct scsi_host_template sgiwd93_template = { .use_clustering = DISABLE_CLUSTERING, }; -static int __init sgiwd93_probe(struct platform_device *pdev) +static int __devinit sgiwd93_probe(struct platform_device *pdev) { struct sgiwd93_platform_data *pd = pdev->dev.platform_data; unsigned char *wdregs = pd->wdregs; diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c index 37b3359e863e..56cf0bb4ed1f 100644 --- a/drivers/scsi/sni_53c710.c +++ b/drivers/scsi/sni_53c710.c @@ -64,7 +64,7 @@ static struct scsi_host_template snirm710_template = { .module = THIS_MODULE, }; -static int __init snirm710_probe(struct platform_device *dev) +static int __devinit snirm710_probe(struct platform_device *dev) { unsigned long base; struct NCR_700_Host_Parameters *hostdata; From c2e13037e6794bd0d9de3f9ecabf5615f15c160b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:51 +0100 Subject: [PATCH 065/114] platform-drivers: move probe to .devinit.text in drivers/video MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to a probe callback is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Adrian Bunk Cc: Alberto Mardegan Cc: Andrew Morton Cc: Andriy Skulysh Cc: Antonino Daplas Cc: Anton Vorontsov Cc: Ben Dooks Cc: Chandramouli Narayanan Cc: Christoph Hellwig Cc: Frans Pop Cc: Geert Uytterhoeven Cc: Greg Kroah-Hartman Cc: Helge Deller Cc: Huang Ying Cc: Ian Molton Cc: Joshua Kinard Cc: Kaj-Michael Lang Cc: Krzysztof Helt Cc: linux-fbdev-devel@lists.sourceforge.net Cc: Maciej W. Rozycki Cc: Magnus Damm Cc: Martin Michlmayr Cc: Matthias Kaehlcke Cc: Paul Mundt Cc: Pavel Machek Cc: Philipp Zabel Cc: Richard Purdie Cc: Roel Kluin Cc: Roland Stigge Cc: Russell King Cc: Thomas Bogendoerfer Cc: Vincent Sanders Cc: Yoichi Yuasa Acked-by: Ralf Baechle Acked-by: Arnaud Patard Acked-by: James Simmons Acked-by: Peter Jones Acked-by: Jaya Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/video/acornfb.c | 2 +- drivers/video/arcfb.c | 2 +- drivers/video/cobalt_lcdfb.c | 2 +- drivers/video/efifb.c | 2 +- drivers/video/epson1355fb.c | 2 +- drivers/video/gbefb.c | 2 +- drivers/video/hgafb.c | 2 +- drivers/video/hitfb.c | 2 +- drivers/video/q40fb.c | 2 +- drivers/video/s3c2410fb.c | 4 ++-- drivers/video/sa1100fb.c | 2 +- drivers/video/sgivwfb.c | 2 +- drivers/video/sh_mobile_lcdcfb.c | 2 +- drivers/video/vesafb.c | 2 +- drivers/video/vfb.c | 2 +- drivers/video/vga16fb.c | 2 +- drivers/video/w100fb.c | 2 +- 17 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 0bcc59eb37fa..43d7d5067361 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1221,7 +1221,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) printk("acornfb: freed %dK memory\n", mb_freed); } -static int __init acornfb_probe(struct platform_device *dev) +static int __devinit acornfb_probe(struct platform_device *dev) { unsigned long size; u_int h_sync, v_sync; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index c3431691c9f2..01554d696528 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -504,7 +504,7 @@ static struct fb_ops arcfb_ops = { .fb_ioctl = arcfb_ioctl, }; -static int __init arcfb_probe(struct platform_device *dev) +static int __devinit arcfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 108b89e09a80..5eb61b5adfe8 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -287,7 +287,7 @@ static struct fb_ops cobalt_lcd_fbops = { .fb_cursor = cobalt_lcdfb_cursor, }; -static int __init cobalt_lcdfb_probe(struct platform_device *dev) +static int __devinit cobalt_lcdfb_probe(struct platform_device *dev) { struct fb_info *info; struct resource *res; diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index d25df51bb0d2..581d2dbf675a 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -210,7 +210,7 @@ static int __init efifb_setup(char *options) return 0; } -static int __init efifb_probe(struct platform_device *dev) +static int __devinit efifb_probe(struct platform_device *dev) { struct fb_info *info; int err; diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 2735b79e52a1..6d755bb3a2bc 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -602,7 +602,7 @@ static int epson1355fb_remove(struct platform_device *dev) return 0; } -int __init epson1355fb_probe(struct platform_device *dev) +int __devinit epson1355fb_probe(struct platform_device *dev) { struct epson1355_par *default_par; struct fb_info *info; diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 695fa013fe7e..5643a35c1746 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1128,7 +1128,7 @@ static int __init gbefb_setup(char *options) return 0; } -static int __init gbefb_probe(struct platform_device *p_dev) +static int __devinit gbefb_probe(struct platform_device *p_dev) { int i, ret = 0; struct fb_info *info; diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 0129c044f6d6..db9b785b56eb 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = { * Initialization */ -static int __init hgafb_probe(struct platform_device *pdev) +static int __devinit hgafb_probe(struct platform_device *pdev) { struct fb_info *info; diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 73c83a8de2d3..bf78779199c6 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -325,7 +325,7 @@ static struct fb_ops hitfb_ops = { .fb_imageblit = cfb_imageblit, }; -static int __init hitfb_probe(struct platform_device *dev) +static int __devinit hitfb_probe(struct platform_device *dev) { unsigned short lcdclor, ldr3, ldvndr; struct fb_info *info; diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 4beac1df617b..de40a626dc76 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -85,7 +85,7 @@ static struct fb_ops q40fb_ops = { .fb_imageblit = cfb_imageblit, }; -static int __init q40fb_probe(struct platform_device *dev) +static int __devinit q40fb_probe(struct platform_device *dev) { struct fb_info *info; diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index aac661225c78..2b094dec4a56 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -1004,12 +1004,12 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev, return ret; } -static int __init s3c2410fb_probe(struct platform_device *pdev) +static int __devinit s3c2410fb_probe(struct platform_device *pdev) { return s3c24xxfb_probe(pdev, DRV_S3C2410); } -static int __init s3c2412fb_probe(struct platform_device *pdev) +static int __devinit s3c2412fb_probe(struct platform_device *pdev) { return s3c24xxfb_probe(pdev, DRV_S3C2412); } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index cdaa873a6054..e8b76d65a070 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1435,7 +1435,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) return fbi; } -static int __init sa1100fb_probe(struct platform_device *pdev) +static int __devinit sa1100fb_probe(struct platform_device *pdev) { struct sa1100fb_info *fbi; int ret, irq; diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index f86012239bff..7a3a5e28eca1 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options) /* * Initialisation */ -static int __init sgivwfb_probe(struct platform_device *dev) +static int __devinit sgivwfb_probe(struct platform_device *dev) { struct sgivw_par *par; struct fb_info *info; diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 8d7653e56df5..bbd1dbf4026a 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -943,7 +943,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { static int sh_mobile_lcdc_remove(struct platform_device *pdev); -static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) +static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) { struct fb_info *info; struct sh_mobile_lcdc_priv *priv; diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index bd37ee1f6a25..ef4128c8e57a 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -226,7 +226,7 @@ static int __init vesafb_setup(char *options) return 0; } -static int __init vesafb_probe(struct platform_device *dev) +static int __devinit vesafb_probe(struct platform_device *dev) { struct fb_info *info; int i, err; diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 050d432c7d95..b8ab995fbda7 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -479,7 +479,7 @@ static int __init vfb_setup(char *options) * Initialisation */ -static int __init vfb_probe(struct platform_device *dev) +static int __devinit vfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 5b2938903ac2..76d8dae5b1bb 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1293,7 +1293,7 @@ static int vga16fb_setup(char *options) } #endif -static int __init vga16fb_probe(struct platform_device *dev) +static int __devinit vga16fb_probe(struct platform_device *dev) { struct fb_info *info; struct vga16fb_par *par; diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 2376f688ec8b..5d223959778a 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -628,7 +628,7 @@ static int w100fb_resume(struct platform_device *dev) #endif -int __init w100fb_probe(struct platform_device *pdev) +int __devinit w100fb_probe(struct platform_device *pdev) { int err = -EIO; struct w100fb_mach_info *inf; From ea79632d90754409b11388410bbe23b62394401d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:52 +0100 Subject: [PATCH 066/114] x86: move hp-wmi's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to hp_wmi_bios_setup is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Frans Pop Cc: Larry Finger Cc: Len Brown Cc: Helge Deller Cc: Andrew Morton Acked-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/hp-wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 3aa57da8b43b..7ccf33c08967 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -57,7 +57,7 @@ enum hp_wmi_radio { HPWMI_WWAN = 2, }; -static int __init hp_wmi_bios_setup(struct platform_device *device); +static int __devinit hp_wmi_bios_setup(struct platform_device *device); static int __exit hp_wmi_bios_remove(struct platform_device *device); static int hp_wmi_resume_handler(struct device *device); @@ -447,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_tablet); } -static int __init hp_wmi_bios_setup(struct platform_device *device) +static int __devinit hp_wmi_bios_setup(struct platform_device *device) { int err; int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); From 1139aea97a6325270bda6c86ea1c9711a0c21e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:53 +0100 Subject: [PATCH 067/114] i2c: move i2c_omap's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to omap_i2c_probe is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Kalle Jokiniemi Cc: Tony Lindgren Cc: Paul Walmsley Cc: Richard Woodruff Cc: chandra shekhar Cc: Jason P Marini Cc: Syed Mohammed Khasim Cc: Jarkko Nikula Cc: Juha Yrjola Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 913abd7c172f..c7c237537f81 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -850,7 +850,7 @@ static const struct i2c_algorithm omap_i2c_algo = { .functionality = omap_i2c_func, }; -static int __init +static int __devinit omap_i2c_probe(struct platform_device *pdev) { struct omap_i2c_dev *dev; From a96b9121862bbd18e00c865d9516e0a98bb135ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:54 +0100 Subject: [PATCH 068/114] w1: move omap_hdq's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to omap_hdq_probe is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Cc: Stanley.Miao Acked-by: Evgeniy Polyakov Cc: Andrew Morton Cc: Madhusudhan Chikkature Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/omap_hdq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 0d92969404c3..22977d30f89e 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -72,7 +72,7 @@ struct hdq_data { int init_trans; }; -static int __init omap_hdq_probe(struct platform_device *pdev); +static int __devinit omap_hdq_probe(struct platform_device *pdev); static int omap_hdq_remove(struct platform_device *pdev); static struct platform_driver omap_hdq_driver = { @@ -558,7 +558,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) return; } -static int __init omap_hdq_probe(struct platform_device *pdev) +static int __devinit omap_hdq_probe(struct platform_device *pdev) { struct hdq_data *hdq_data; struct resource *res; From ea180ca4d6fbeeb8f8bea4a175d2b84b9129b693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:55 +0100 Subject: [PATCH 069/114] media: move omap24xxcam's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to omap24xxcam_probe is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Acked-by: Sakari Ailus Acked-by: Trilok Soni Cc: Hans Verkuil Cc: Mauro Carvalho Chehab Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/omap24xxcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 7400eacb4d64..142c327afb32 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1735,7 +1735,7 @@ static struct v4l2_int_device omap24xxcam = { * */ -static int __init omap24xxcam_probe(struct platform_device *pdev) +static int __devinit omap24xxcam_probe(struct platform_device *pdev) { struct omap24xxcam_device *cam; struct resource *mem; From 57f1e87523bdb6c39659ead7c0f72eea9e520fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 4 Feb 2010 20:56:56 +0100 Subject: [PATCH 070/114] auxdisplay: move cfag12864bfb's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to cfag12864bfb_probe is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Acked-by: Miguel Ojeda Cc: Andrew Morton Cc: Avuton Olrich Cc: Antonino Daplas Signed-off-by: Greg Kroah-Hartman --- drivers/auxdisplay/cfag12864bfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c index fe3a865be4e5..b0ca5a47f47d 100644 --- a/drivers/auxdisplay/cfag12864bfb.c +++ b/drivers/auxdisplay/cfag12864bfb.c @@ -81,7 +81,7 @@ static struct fb_ops cfag12864bfb_ops = { .fb_mmap = cfag12864bfb_mmap, }; -static int __init cfag12864bfb_probe(struct platform_device *device) +static int __devinit cfag12864bfb_probe(struct platform_device *device) { int ret = -EINVAL; struct fb_info *info = framebuffer_alloc(0, &device->dev); From 8f314cfc1259d3f5039b142ce6fdc90367c22d82 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Tue, 9 Feb 2010 20:13:49 +0100 Subject: [PATCH 071/114] UIO: Add a driver for Hilscher netX-based fieldbus cards This patch adds a Userspace IO driver for netX-based fieldbus cards by Hilscher (see http://www.hilscher.com). ATM, cifX and comX cards are supported. The userspace part for this driver is provided by Hilscher and should come with the card. The driver is in use for several months now and has been tested by people at Hilscher and Linutronix. Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 11 +++ drivers/uio/Makefile | 1 + drivers/uio/uio_netx.c | 172 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 drivers/uio/uio_netx.c diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 8aa1955f35ed..069b1443be6c 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -94,4 +94,15 @@ config UIO_PCI_GENERIC primarily, for virtualization scenarios. If you compile this as a module, it will be called uio_pci_generic. +config UIO_NETX + tristate "Hilscher NetX Card driver" + depends on PCI + help + Driver for Hilscher NetX based fieldbus cards (cifX, comX). + This driver requires a userspace component that comes with the card + or is available from Hilscher (http://www.hilscher.com). + + To compile this driver as a module, choose M here; the module + will be called uio_netx. + endif diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index 73b2e7516729..aa7d0333fa78 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_SMX) += uio_smx.o obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o +obj-$(CONFIG_UIO_NETX) += uio_netx.o diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c new file mode 100644 index 000000000000..afbf0bd55cc9 --- /dev/null +++ b/drivers/uio/uio_netx.c @@ -0,0 +1,172 @@ +/* + * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX). + * See http://www.hilscher.com for details. + * + * (C) 2007 Hans J. Koch + * (C) 2008 Manuel Traut + * + * Licensed under GPL version 2 only. + * + */ + +#include +#include +#include +#include +#include + +#define PCI_VENDOR_ID_HILSCHER 0x15CF +#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000 +#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235 +#define PCI_SUBDEVICE_ID_NXPCA 0x3335 + +#define DPM_HOST_INT_EN0 0xfff0 +#define DPM_HOST_INT_STAT0 0xffe0 + +#define DPM_HOST_INT_MASK 0xe600ffff +#define DPM_HOST_INT_GLOBAL_EN 0x80000000 + +static irqreturn_t netx_handler(int irq, struct uio_info *dev_info) +{ + void __iomem *int_enable_reg = dev_info->mem[0].internal_addr + + DPM_HOST_INT_EN0; + void __iomem *int_status_reg = dev_info->mem[0].internal_addr + + DPM_HOST_INT_STAT0; + + /* Is one of our interrupts enabled and active ? */ + if (!(ioread32(int_enable_reg) & ioread32(int_status_reg) + & DPM_HOST_INT_MASK)) + return IRQ_NONE; + + /* Disable interrupt */ + iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN, + int_enable_reg); + return IRQ_HANDLED; +} + +static int __devinit netx_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct uio_info *info; + int bar; + + info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (pci_enable_device(dev)) + goto out_free; + + if (pci_request_regions(dev, "netx")) + goto out_disable; + + switch (id->device) { + case PCI_DEVICE_ID_HILSCHER_NETX: + bar = 0; + info->name = "netx"; + break; + default: + bar = 2; + info->name = "netx_plx"; + } + + /* BAR0 or 2 points to the card's dual port memory */ + info->mem[0].addr = pci_resource_start(dev, bar); + if (!info->mem[0].addr) + goto out_release; + info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar), + pci_resource_len(dev, bar)); + + if (!info->mem[0].internal_addr) + goto out_release; + + info->mem[0].size = pci_resource_len(dev, bar); + info->mem[0].memtype = UIO_MEM_PHYS; + info->irq = dev->irq; + info->irq_flags = IRQF_SHARED; + info->handler = netx_handler; + info->version = "0.0.1"; + + /* Make sure all interrupts are disabled */ + iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); + + if (uio_register_device(&dev->dev, info)) + goto out_unmap; + + pci_set_drvdata(dev, info); + dev_info(&dev->dev, "Found %s card, registered UIO device.\n", + info->name); + + return 0; + +out_unmap: + iounmap(info->mem[0].internal_addr); +out_release: + pci_release_regions(dev); +out_disable: + pci_disable_device(dev); +out_free: + kfree(info); + return -ENODEV; +} + +static void netx_pci_remove(struct pci_dev *dev) +{ + struct uio_info *info = pci_get_drvdata(dev); + + /* Disable all interrupts */ + iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); + uio_unregister_device(info); + pci_release_regions(dev); + pci_disable_device(dev); + pci_set_drvdata(dev, NULL); + iounmap(info->mem[0].internal_addr); + + kfree(info); +} + +static struct pci_device_id netx_pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_HILSCHER, + .device = PCI_DEVICE_ID_HILSCHER_NETX, + .subvendor = 0, + .subdevice = 0, + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9030, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_SUBDEVICE_ID_NXSB_PCA, + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9030, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_SUBDEVICE_ID_NXPCA, + }, + { 0, } +}; + +static struct pci_driver netx_pci_driver = { + .name = "netx", + .id_table = netx_pci_ids, + .probe = netx_pci_probe, + .remove = netx_pci_remove, +}; + +static int __init netx_init_module(void) +{ + return pci_register_driver(&netx_pci_driver); +} + +static void __exit netx_exit_module(void) +{ + pci_unregister_driver(&netx_pci_driver); +} + +module_init(netx_init_module); +module_exit(netx_exit_module); + +MODULE_DEVICE_TABLE(pci, netx_pci_ids); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); From 0a965eb9f69caf0fb331d45556da8bab1c8dcb11 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Thu, 11 Feb 2010 15:38:53 +0100 Subject: [PATCH 072/114] UIO: minor Kconfig fixes Two trivial fixes for the Userspace IO Kconfig file: 1) uio_sercos3 is a PCI driver, so let it depend on PCI. 2) "default n" under UIO_PCI_GENERIC is luxury since it is already the default. Acked-by: John Ogness Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 069b1443be6c..6dd2a290f323 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -74,6 +74,7 @@ config UIO_AEC config UIO_SERCOS3 tristate "Automata Sercos III PCI card driver" + depends on PCI help Userspace I/O interface for the Sercos III PCI card from Automata GmbH. The userspace part of this driver will be @@ -87,7 +88,6 @@ config UIO_SERCOS3 config UIO_PCI_GENERIC tristate "Generic driver for PCI 2.3 and PCI Express cards" depends on PCI - default n help Generic driver that you can bind, dynamically, to any PCI 2.3 compliant and PCI Express card. It is useful, From d6e976c0d258c9547a308bd8a9a82ec93e2bc6e2 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Wed, 10 Feb 2010 20:12:42 +0100 Subject: [PATCH 073/114] UIO: Remove SMX Cryptengine driver Ben Nizette, the author of this driver, told me in a private mail that this project has been cancelled. He suggested to remove the driver for now, and will come back with a new version should the hardware really exist. This patch completely removes the driver. Signed-off-by: Hans J. Koch Acked-by: Ben Nizette Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 11 ---- drivers/uio/Makefile | 1 - drivers/uio/uio_smx.c | 140 ------------------------------------------ 3 files changed, 152 deletions(-) delete mode 100644 drivers/uio/uio_smx.c diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 6dd2a290f323..1da73ecd9799 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -44,17 +44,6 @@ config UIO_PDRV_GENIRQ If you don't know what to do here, say N. -config UIO_SMX - tristate "SMX cryptengine UIO interface" - help - Userspace IO interface to the Cryptography engine found on the - Nias Digital SMX boards. These will be available from Q4 2008 - from http://www.niasdigital.com. The userspace part of this - driver will be released under the GPL at the same time as the - hardware and will be able to be downloaded from the same site. - - If you compile this as a module, it will be called uio_smx. - config UIO_AEC tristate "AEC video timestamp device" depends on PCI diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index aa7d0333fa78..18fd818c5b97 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_UIO) += uio.o obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o -obj-$(CONFIG_UIO_SMX) += uio_smx.o obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c deleted file mode 100644 index 44054a650a8a..000000000000 --- a/drivers/uio/uio_smx.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * UIO SMX Cryptengine driver. - * - * (C) 2008 Nias Digital P/L - * - * 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 - -#define DRV_NAME "smx-ce" -#define DRV_VERSION "0.03" - -#define SMX_CSR 0x00000000 -#define SMX_EnD 0x00000001 -#define SMX_RUN 0x00000002 -#define SMX_DRDY 0x00000004 -#define SMX_ERR 0x00000008 - -static irqreturn_t smx_handler(int irq, struct uio_info *dev_info) -{ - void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR; - - u32 status = ioread32(csr); - - if (!(status & SMX_DRDY)) - return IRQ_NONE; - - /* Disable interrupt */ - iowrite32(status & ~SMX_DRDY, csr); - return IRQ_HANDLED; -} - -static int __devinit smx_ce_probe(struct platform_device *dev) -{ - - int ret = -ENODEV; - struct uio_info *info; - struct resource *regs; - - info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - regs = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(&dev->dev, "No memory resource specified\n"); - goto out_free; - } - - info->mem[0].addr = regs->start; - if (!info->mem[0].addr) { - dev_err(&dev->dev, "Invalid memory resource\n"); - goto out_free; - } - - info->mem[0].size = regs->end - regs->start + 1; - info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size); - - if (!info->mem[0].internal_addr) { - dev_err(&dev->dev, "Can't remap memory address range\n"); - goto out_free; - } - - info->mem[0].memtype = UIO_MEM_PHYS; - - info->name = "smx-ce"; - info->version = "0.03"; - - info->irq = platform_get_irq(dev, 0); - if (info->irq < 0) { - ret = info->irq; - dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n"); - goto out_unmap; - } - - info->irq_flags = IRQF_SHARED; - info->handler = smx_handler; - - platform_set_drvdata(dev, info); - - ret = uio_register_device(&dev->dev, info); - - if (ret) - goto out_unmap; - - return 0; - -out_unmap: - iounmap(info->mem[0].internal_addr); -out_free: - kfree(info); - - return ret; -} - -static int __devexit smx_ce_remove(struct platform_device *dev) -{ - struct uio_info *info = platform_get_drvdata(dev); - - uio_unregister_device(info); - platform_set_drvdata(dev, NULL); - iounmap(info->mem[0].internal_addr); - - kfree(info); - - return 0; -} - -static struct platform_driver smx_ce_driver = { - .probe = smx_ce_probe, - .remove = __devexit_p(smx_ce_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init smx_ce_init_module(void) -{ - return platform_driver_register(&smx_ce_driver); -} -module_init(smx_ce_init_module); - -static void __exit smx_ce_exit_module(void) -{ - platform_driver_unregister(&smx_ce_driver); -} -module_exit(smx_ce_exit_module); - -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR("Ben Nizette "); From 3c31f07ad0dab02fe17195d32a965d57fd947707 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 14 Feb 2010 14:18:53 +0000 Subject: [PATCH 074/114] Driver core: Fix first line of kernel-doc for a few functions The function name must be followed by a space, hypen, space, and a short description. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 2 +- drivers/base/platform.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 07977484cb3c..d0dc26ad5387 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -613,7 +613,7 @@ request_firmware_work_func(void *arg) } /** - * request_firmware_nowait: asynchronous version of request_firmware + * request_firmware_nowait - asynchronous version of request_firmware * @module: module requesting the firmware * @uevent: sends uevent to copy the firmware image if this flag * is non-zero else the firmware copy must be done manually. diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 575e08bc6630..1ba9d617d241 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -128,7 +128,7 @@ struct platform_object { }; /** - * platform_device_put + * platform_device_put - destroy a platform device * @pdev: platform device to free * * Free all memory associated with a platform device. This function must @@ -152,7 +152,7 @@ static void platform_device_release(struct device *dev) } /** - * platform_device_alloc + * platform_device_alloc - create a platform device * @name: base name of the device we're adding * @id: instance id * @@ -177,7 +177,7 @@ struct platform_device *platform_device_alloc(const char *name, int id) EXPORT_SYMBOL_GPL(platform_device_alloc); /** - * platform_device_add_resources + * platform_device_add_resources - add resources to a platform device * @pdev: platform device allocated by platform_device_alloc to add resources to * @res: set of resources that needs to be allocated for the device * @num: number of resources @@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev, EXPORT_SYMBOL_GPL(platform_device_add_resources); /** - * platform_device_add_data + * platform_device_add_data - add platform-specific data to a platform device * @pdev: platform device allocated by platform_device_alloc to add resources to * @data: platform specific data for this platform device * @size: size of platform specific data @@ -344,7 +344,7 @@ void platform_device_unregister(struct platform_device *pdev) EXPORT_SYMBOL_GPL(platform_device_unregister); /** - * platform_device_register_simple + * platform_device_register_simple - add a platform-level device and its resources * @name: base name of the device we're adding * @id: instance id * @res: set of resources that needs to be allocated for the device @@ -396,7 +396,7 @@ struct platform_device *platform_device_register_simple(const char *name, EXPORT_SYMBOL_GPL(platform_device_register_simple); /** - * platform_device_register_data + * platform_device_register_data - add a platform-level device with platform-specific data * @parent: parent device for the device we're adding * @name: base name of the device we're adding * @id: instance id @@ -473,7 +473,7 @@ static void platform_drv_shutdown(struct device *_dev) } /** - * platform_driver_register + * platform_driver_register - register a driver for platform-level devices * @drv: platform driver structure */ int platform_driver_register(struct platform_driver *drv) @@ -491,7 +491,7 @@ int platform_driver_register(struct platform_driver *drv) EXPORT_SYMBOL_GPL(platform_driver_register); /** - * platform_driver_unregister + * platform_driver_unregister - unregister a driver for platform-level devices * @drv: platform driver structure */ void platform_driver_unregister(struct platform_driver *drv) From e72ceb8ccac5f770b3e696e09bb673dca7024b20 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Feb 2010 15:18:38 -0800 Subject: [PATCH 075/114] sysfs: Remove sysfs_get/put_active_two It turns out that holding an active reference on a directory is pointless. The purpose of the active references are to allows us to block when removing sysfs entries that have custom methods so we don't remove modules while running modular code and to keep those custom methods from accessing data structures after the files have been removed. Further sysfs_remove_dir remove all elements in the directory before removing the directory itself, so there is no chance we will remove a directory with active children. Signed-off-by: Eric W. Biederman Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 50 ++++++++++++++++++++++++------------------------ fs/sysfs/dir.c | 43 ++--------------------------------------- fs/sysfs/file.c | 18 ++++++++--------- fs/sysfs/sysfs.h | 4 ++-- 4 files changed, 38 insertions(+), 77 deletions(-) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index a0a500af24a1..e9d293593e52 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -54,14 +54,14 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) int rc; /* need attr_sd for attr, its parent for kobj */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; rc = -EIO; if (attr->read) rc = attr->read(kobj, attr, buffer, off, count); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return rc; } @@ -125,14 +125,14 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) int rc; /* need attr_sd for attr, its parent for kobj */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; rc = -EIO; if (attr->write) rc = attr->write(kobj, attr, buffer, offset, count); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return rc; } @@ -184,12 +184,12 @@ static void bin_vma_open(struct vm_area_struct *vma) if (!bb->vm_ops || !bb->vm_ops->open) return; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return; bb->vm_ops->open(vma); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); } static void bin_vma_close(struct vm_area_struct *vma) @@ -201,12 +201,12 @@ static void bin_vma_close(struct vm_area_struct *vma) if (!bb->vm_ops || !bb->vm_ops->close) return; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return; bb->vm_ops->close(vma); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); } static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -219,12 +219,12 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) if (!bb->vm_ops || !bb->vm_ops->fault) return VM_FAULT_SIGBUS; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return VM_FAULT_SIGBUS; ret = bb->vm_ops->fault(vma, vmf); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return ret; } @@ -241,12 +241,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) if (!bb->vm_ops->page_mkwrite) return 0; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return VM_FAULT_SIGBUS; ret = bb->vm_ops->page_mkwrite(vma, vmf); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return ret; } @@ -261,12 +261,12 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr, if (!bb->vm_ops || !bb->vm_ops->access) return -EINVAL; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -EINVAL; ret = bb->vm_ops->access(vma, addr, buf, len, write); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return ret; } @@ -281,12 +281,12 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new) if (!bb->vm_ops || !bb->vm_ops->set_policy) return 0; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -EINVAL; ret = bb->vm_ops->set_policy(vma, new); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return ret; } @@ -301,12 +301,12 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma, if (!bb->vm_ops || !bb->vm_ops->get_policy) return vma->vm_policy; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return vma->vm_policy; pol = bb->vm_ops->get_policy(vma, addr); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return pol; } @@ -321,12 +321,12 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, if (!bb->vm_ops || !bb->vm_ops->migrate) return 0; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return 0; ret = bb->vm_ops->migrate(vma, from, to, flags); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return ret; } #endif @@ -356,7 +356,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) /* need attr_sd for attr, its parent for kobj */ rc = -ENODEV; - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) goto out_unlock; rc = -EINVAL; @@ -384,7 +384,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) bb->vm_ops = vma->vm_ops; vma->vm_ops = &bin_vm_ops; out_put: - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); out_unlock: mutex_unlock(&bb->mutex); @@ -399,7 +399,7 @@ static int open(struct inode * inode, struct file * file) int error; /* binary file operations requires both @sd and its parent */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; error = -EACCES; @@ -426,11 +426,11 @@ static int open(struct inode * inode, struct file * file) mutex_unlock(&sysfs_bin_lock); /* open succeeded, put active references */ - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return 0; err_out: - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); kfree(bb); return error; } diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5c4703d751b5..1bdc42f4fd93 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -93,7 +93,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) * RETURNS: * Pointer to @sd on success, NULL on failure. */ -static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) +struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) { if (unlikely(!sd)) return NULL; @@ -124,7 +124,7 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) * Put an active reference to @sd. This function is noop if @sd * is NULL. */ -static void sysfs_put_active(struct sysfs_dirent *sd) +void sysfs_put_active(struct sysfs_dirent *sd) { struct completion *cmpl; int v; @@ -144,45 +144,6 @@ static void sysfs_put_active(struct sysfs_dirent *sd) complete(cmpl); } -/** - * sysfs_get_active_two - get active references to sysfs_dirent and parent - * @sd: sysfs_dirent of interest - * - * Get active reference to @sd and its parent. Parent's active - * reference is grabbed first. This function is noop if @sd is - * NULL. - * - * RETURNS: - * Pointer to @sd on success, NULL on failure. - */ -struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) -{ - if (sd) { - if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) - return NULL; - if (unlikely(!sysfs_get_active(sd))) { - sysfs_put_active(sd->s_parent); - return NULL; - } - } - return sd; -} - -/** - * sysfs_put_active_two - put active references to sysfs_dirent and parent - * @sd: sysfs_dirent of interest - * - * Put active references to @sd and its parent. This function is - * noop if @sd is NULL. - */ -void sysfs_put_active_two(struct sysfs_dirent *sd) -{ - if (sd) { - sysfs_put_active(sd); - sysfs_put_active(sd->s_parent); - } -} - /** * sysfs_deactivate - deactivate sysfs_dirent * @sd: sysfs_dirent to deactivate diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index ced2299f1c9a..40961366e929 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -85,13 +85,13 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer return -ENOMEM; /* need attr_sd for attr and ops, its parent for kobj */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; buffer->event = atomic_read(&attr_sd->s_attr.open->event); count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); /* * The code works fine with PAGE_SIZE return but it's likely to @@ -203,12 +203,12 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t int rc; /* need attr_sd for attr and ops, its parent for kobj */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return rc; } @@ -344,7 +344,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) memmove(last_sysfs_file, p, strlen(p) + 1); /* need attr_sd for attr and ops, its parent for kobj */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) return -ENODEV; /* every kobject with an attribute needs a ktype assigned */ @@ -393,13 +393,13 @@ static int sysfs_open_file(struct inode *inode, struct file *file) goto err_free; /* open succeeded, put active references */ - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return 0; err_free: kfree(buffer); err_out: - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); return error; } @@ -437,12 +437,12 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) struct sysfs_open_dirent *od = attr_sd->s_attr.open; /* need parent for the kobj, grab both */ - if (!sysfs_get_active_two(attr_sd)) + if (!sysfs_get_active(attr_sd)) goto trigger; poll_wait(filp, &od->poll, wait); - sysfs_put_active_two(attr_sd); + sysfs_put_active(attr_sd); if (buffer->event != atomic_read(&od->event)) goto trigger; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cdd9377a6e06..bb7723c4f5a5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -124,8 +124,8 @@ extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); -struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); -void sysfs_put_active_two(struct sysfs_dirent *sd); +struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); +void sysfs_put_active(struct sysfs_dirent *sd); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *parent_sd); int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); From a2db6842873c8e5a70652f278d469128cb52db70 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Feb 2010 15:20:00 -0800 Subject: [PATCH 076/114] sysfs: Only take active references on attributes. If we exclude directories and symlinks from the set of sysfs dirents where we need active references we are left with sysfs attributes (binary or not). - Tweak sysfs_deactivate to only do something on attributes - Move lockdep initialization into sysfs_file_add_mode to limit it to just attributes. Signed-off-by: Eric W. Biederman Acked-by: WANG Cong Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 5 ++++- fs/sysfs/file.c | 1 + fs/sysfs/sysfs.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 1bdc42f4fd93..481fdec09f4e 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -156,6 +156,10 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) int v; BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); + + if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) + return; + sd->s_sibling = (void *)&wait; rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); @@ -315,7 +319,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); - sysfs_dirent_init_lockdep(sd); sd->s_name = name; sd->s_mode = mode; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 40961366e929..e222b2582746 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -509,6 +509,7 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, if (!sd) return -ENOMEM; sd->s_attr.attr = (void *)attr; + sysfs_dirent_init_lockdep(sd); sysfs_addrm_start(&acxt, dir_sd); rc = sysfs_add_one(&acxt, sd); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index bb7723c4f5a5..7db6884f4206 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -79,6 +79,7 @@ struct sysfs_dirent { #define SYSFS_KOBJ_BIN_ATTR 0x0004 #define SYSFS_KOBJ_LINK 0x0008 #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) +#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK #define SYSFS_FLAG_REMOVED 0x0200 From 6992f5334995af474c2b58d010d08bc597f0f2fe Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Feb 2010 15:21:53 -0800 Subject: [PATCH 077/114] sysfs: Use one lockdep class per sysfs attribute. Acknowledge that the logical sysfs rwsem has one instance per sysfs attribute with different locking depencencies for different attributes. There is a sysfs idiom where writing to one sysfs file causes the addition or removal of other sysfs files. Lumping all of the sysfs attributes together in one lock class causes lockdep to generate lots of false positives. This introduces the requirement that non-static sysfs attributes need to be initialized with sysfs_attr_init or sysfs_bin_attr_init. Strictly speaking this requirement only exists when lockdep is enabled, and when lockdep is enabled we get a bit fat warning if this requirement is not met. Signed-off-by: Eric W. Biederman Acked-by: WANG Cong Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 7 +++++-- include/linux/sysfs.h | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7db6884f4206..37e0e086233c 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -92,9 +92,12 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) #ifdef CONFIG_DEBUG_LOCK_ALLOC #define sysfs_dirent_init_lockdep(sd) \ do { \ - static struct lock_class_key __key; \ + struct attribute *attr = sd->s_attr.attr; \ + struct lock_class_key *key = attr->key; \ + if (!key) \ + key = &attr->skey; \ \ - lockdep_init_map(&sd->dep_map, "s_active", &__key, 0); \ + lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ } while(0) #else #define sysfs_dirent_init_lockdep(sd) do {} while(0) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 3e8526582146..006c359e63c0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -15,6 +15,7 @@ #include #include #include +#include #include struct kobject; @@ -29,8 +30,23 @@ struct attribute { const char *name; struct module *owner; mode_t mode; +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lock_class_key *key; + struct lock_class_key skey; +#endif }; +#ifdef CONFIG_DEBUG_LOCK_ALLOC +#define sysfs_attr_init(attr) \ +do { \ + static struct lock_class_key __key; \ + \ + (attr)->key = &__key; \ +} while(0) +#else +#define sysfs_attr_init(attr) do {} while(0) +#endif + struct attribute_group { const char *name; mode_t (*is_visible)(struct kobject *, @@ -74,6 +90,8 @@ struct bin_attribute { struct vm_area_struct *vma); }; +#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&bin_attr->attr) + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); From a07e4156a2ee6359d31a44946d7ee7f85dbf6bca Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Feb 2010 15:23:05 -0800 Subject: [PATCH 078/114] sysfs: Use sysfs_attr_init and sysfs_bin_attr_init on dynamic attributes These are the non-static sysfs attributes that exist on my test machine. Fix them to use sysfs_attr_init or sysfs_bin_attr_init as appropriate. It simply requires making a sysfs attribute present to see this. So this is a little bit tedious but otherwise not too bad. Signed-off-by: Eric W. Biederman Acked-by: WANG Cong Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 1 + drivers/acpi/system.c | 2 ++ drivers/pci/pci-sysfs.c | 5 +++++ kernel/params.c | 1 + 4 files changed, 9 insertions(+) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index a8aacd4b513c..28cba46bf32c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -2044,6 +2044,7 @@ static __init void mce_init_banks(void) struct mce_bank *b = &mce_banks[i]; struct sysdev_attribute *a = &b->attr; + sysfs_attr_init(&a->attr); a->attr.name = b->attrname; snprintf(b->attrname, ATTR_LEN, "bank%d", i); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index a206a12da78a..743f2445e2a1 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -101,6 +101,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, struct acpi_table_header *header = NULL; struct acpi_table_attr *attr = NULL; + sysfs_attr_init(&table_attr->attr.attr); if (table_header->signature[0] != '\0') memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); @@ -475,6 +476,7 @@ void acpi_irq_stats_init(void) goto fail; strncpy(name, buffer, strlen(buffer) + 1); + sysfs_attr_init(&counter_attrs[i].attr); counter_attrs[i].attr.name = name; counter_attrs[i].attr.mode = 0644; counter_attrs[i].show = counter_show; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 807224ec8351..9fa183cfb0e9 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -642,6 +642,7 @@ void pci_create_legacy_files(struct pci_bus *b) if (!b->legacy_io) goto kzalloc_err; + sysfs_bin_attr_init(&b->legacy_io); b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; @@ -654,6 +655,7 @@ void pci_create_legacy_files(struct pci_bus *b) goto legacy_io_err; /* Allocated above after the legacy_io struct */ + sysfs_bin_attr_init(&b->legacy_mem); b->legacy_mem = b->legacy_io + 1; b->legacy_mem->attr.name = "legacy_mem"; b->legacy_mem->size = 1024*1024; @@ -800,6 +802,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) if (res_attr) { char *res_attr_name = (char *)(res_attr + 1); + sysfs_bin_attr_init(res_attr); if (write_combine) { pdev->res_attr_wc[num] = res_attr; sprintf(res_attr_name, "resource%d_wc", num); @@ -972,6 +975,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) if (!attr) return -ENOMEM; + sysfs_bin_attr_init(attr); attr->size = dev->vpd->len; attr->attr.name = "vpd"; attr->attr.mode = S_IRUSR | S_IWUSR; @@ -1038,6 +1042,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) retval = -ENOMEM; goto err_resource_files; } + sysfs_bin_attr_init(attr); attr->size = rom_size; attr->attr.name = "rom"; attr->attr.mode = S_IRUSR; diff --git a/kernel/params.c b/kernel/params.c index 68396d73c838..d55a53ec9234 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -516,6 +516,7 @@ static __modinit int add_sysfs_param(struct module_kobject *mk, new->grp.attrs = attrs; /* Tack new one on the end. */ + sysfs_attr_init(&new->attrs[num].mattr.attr); new->attrs[num].param = kp; new->attrs[num].mattr.show = param_attr_show; new->attrs[num].mattr.store = param_attr_store; From 35960258ed388cdcebdb71df35fd5126978ca325 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 04:35:32 -0800 Subject: [PATCH 079/114] sysfs: Document sysfs_attr_init and sysfs_bin_attr_init I have added a new requirement to the external sysfs interface that dynamically allocated sysfs attributes must call sysfs_attr_init if lockdep is enabled. For the time being callying sysfs_attr_init is only mandatory if lockdep is enabled, so we can live with a few unconverted instances until we find them all. As this is part of the public interface of sysfs it is a good idea to document these pseudo functions so someone inspeciting the code can find out what has happened. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 006c359e63c0..5b8f80f5aca6 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -36,6 +36,16 @@ struct attribute { #endif }; +/** + * sysfs_attr_init - initialize a dynamically allocated sysfs attribute + * @attr: struct attribute to initialize + * + * Initialize a dynamically allocated struct attribute so we can + * make lockdep happy. This is a new requirement for attributes + * and initially this is only needed when lockdep is enabled. + * Lockdep gives a nice error when your attribute is added to + * sysfs if you don't have this. + */ #ifdef CONFIG_DEBUG_LOCK_ALLOC #define sysfs_attr_init(attr) \ do { \ @@ -90,6 +100,16 @@ struct bin_attribute { struct vm_area_struct *vma); }; +/** + * sysfs_bin_attr_init - initialize a dynamically allocated bin_attribute + * @attr: struct bin_attribute to initialize + * + * Initialize a dynamically allocated struct bin_attribute so we + * can make lockdep happy. This is a new requirement for + * attributes and initially this is only needed when lockdep is + * enabled. Lockdep gives a nice error when your attribute is + * added to sysfs if you don't have this. + */ #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&bin_attr->attr) struct sysfs_ops { From 361795b1eb7c08e9e65a2ebb4a4e536294d378a2 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 13:41:56 -0800 Subject: [PATCH 080/114] sysfs: Use sysfs_attr_init and sysfs_bin_attr_init on module dynamic attributes A little more whack-a-mole annotating the dynamic sysfs attributes. I had everything built into my earlier test kernel, and so I missed these. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index e5538d5f00ad..c968d3606dca 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1085,6 +1085,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, if (sattr->name == NULL) goto out; sect_attrs->nsections++; + sysfs_attr_init(&sattr->mattr.attr); sattr->mattr.show = module_sect_show; sattr->mattr.store = NULL; sattr->mattr.attr.name = sattr->name; @@ -1180,6 +1181,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, if (sect_empty(&sechdrs[i])) continue; if (sechdrs[i].sh_type == SHT_NOTE) { + sysfs_bin_attr_init(nattr); nattr->attr.name = mod->sect_attrs->attrs[loaded].name; nattr->attr.mode = S_IRUGO; nattr->size = sechdrs[i].sh_size; @@ -1252,6 +1254,7 @@ int module_add_modinfo_attrs(struct module *mod) if (!attr->test || (attr->test && attr->test(mod))) { memcpy(temp_attr, attr, sizeof(*temp_attr)); + sysfs_attr_init(&temp_attr->attr); error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); ++temp_attr; } From b35c74dab64f4c212f36d868419108556c9cf3e2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 20 Feb 2010 16:43:02 +0100 Subject: [PATCH 081/114] sysfs: windfarm: init sysfs attributes This is required for lockdep. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/macintosh/windfarm_core.c | 1 + drivers/macintosh/windfarm_smu_controls.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 437f55c5d18d..419795f4a2aa 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -321,6 +321,7 @@ int wf_register_sensor(struct wf_sensor *new_sr) kref_init(&new_sr->ref); list_add(&new_sr->link, &wf_sensors); + sysfs_attr_init(&new_sr->attr.attr); new_sr->attr.attr.name = new_sr->name; new_sr->attr.attr.mode = 0444; new_sr->attr.show = wf_show_sensor; diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 6c68b9e5f5c4..43137b421f92 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -173,6 +173,7 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, fct->fan_type = pwm_fan; fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN; + sysfs_attr_init(&fct->ctrl.attr.attr); /* We use the name & location here the same way we do for SMU sensors, * see the comment in windfarm_smu_sensors.c. The locations are a bit From f8d4f618fed5a4978afada52166bc2efaf7656d1 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:23 -0800 Subject: [PATCH 082/114] sysfs: Serialize updates to the vfs inode The vfs depends upon filesystem methods to update the vfs inode. Sysfs adds to the normal number of places where the vfs inode is updated by also updatng the vfs inode in sysfs_refresh_inode. Typically the inode mutex is used to serialize updates to the vfs inode, but grabbing the inode mutex in sysfs_permission and sysfs_getattr causes deadlocks, because sometimes the vfs calls those operations with the inode mutex held. Therefore sysfs can not use the inode mutex to serial updates to the vfs inode. The sysfs_mutex is acquired in all of the routines where sysfs updates the vfs inode, and with a small change we can consistently protext sysfs vfs inode updates with the sysfs_mutex. To protect the sysfs vfs inode updates with the sysfs_mutex simply requires extending the scope of sysfs_mutex in sysfs_setattr over inode_setattr, and over inode_change_ok (so we have an unchanging inode when we perform the check). Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 6a06a1d1ea7b..0d09f6c6efab 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -111,20 +111,20 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) if (!sd) return -EINVAL; + mutex_lock(&sysfs_mutex); error = inode_change_ok(inode, iattr); if (error) - return error; + goto out; iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); if (error) - return error; + goto out; - mutex_lock(&sysfs_mutex); error = sysfs_sd_setattr(sd, iattr); +out: mutex_unlock(&sysfs_mutex); - return error; } From 19c38b632d4554329986021fd66bdea468cf452c Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:24 -0800 Subject: [PATCH 083/114] sysfs: Pack sysfs_dirent more tightly. Placing the 16bit s_mode between a pointer and a long doesn't pack well especailly on 64bit where we wast 48 bits. So move s_mode and declare it as a unsigned short. This is the sysfs backing store after all we don't need fields extra large just in case someday we want userspace to be able to use a larger value. Acked-by: Tejun Heo Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/sysfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 37e0e086233c..5a3192a08442 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -66,8 +66,8 @@ struct sysfs_dirent { }; unsigned int s_flags; + unsigned short s_mode; ino_t s_ino; - umode_t s_mode; struct sysfs_inode_attrs *s_iattr; }; From 7cb32942d91a501b2df944928ccc9e6590ab237b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:25 -0800 Subject: [PATCH 084/114] sysfs: Implement sysfs_rename_link Because of rename ordering problems we occassionally give false warnings about invalid sysfs operations. So using sysfs_rename create a sysfs_rename_link function that doesn't need strange workarounds. Cc: Benjamin Thery Cc: Daniel Lezcano Acked-by: Serge Hallyn Acked-by: Tejun Heo Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/symlink.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 9 +++++++++ 2 files changed, 47 insertions(+) diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index c5eff49fa41b..1b9a3a1e8a17 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -123,6 +123,44 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) sysfs_hash_and_remove(parent_sd, name); } +/** + * sysfs_rename_link - rename symlink in object's directory. + * @kobj: object we're acting for. + * @targ: object we're pointing to. + * @old: previous name of the symlink. + * @new: new name of the symlink. + * + * A helper function for the common rename symlink idiom. + */ +int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, + const char *old, const char *new) +{ + struct sysfs_dirent *parent_sd, *sd = NULL; + int result; + + if (!kobj) + parent_sd = &sysfs_root; + else + parent_sd = kobj->sd; + + result = -ENOENT; + sd = sysfs_get_dirent(parent_sd, old); + if (!sd) + goto out; + + result = -EINVAL; + if (sysfs_type(sd) != SYSFS_KOBJ_LINK) + goto out; + if (sd->s_symlink.target_sd->s_dir.kobj != targ) + goto out; + + result = sysfs_rename(sd, parent_sd, new); + +out: + sysfs_put(sd); + return result; +} + static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd, char *path) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 5b8f80f5aca6..d77cde6d0498 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -151,6 +151,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj, const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); +int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name); + int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int sysfs_update_group(struct kobject *kobj, @@ -255,6 +258,12 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } +static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, + const char *old_name, const char *new_name) +{ + return 0; +} + static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { From 2354dcc7218853a6537ec722be40fde9a11c413b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:26 -0800 Subject: [PATCH 085/114] driver core: Use sysfs_rename_link in device_rename Don't open code the renaming of symlinks in sysfs instead use the new helper function sysfs_rename_link Acked-by: Tejun Heo Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index b0d6646a2814..ef55df34ddd0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1578,22 +1578,16 @@ int device_rename(struct device *dev, char *new_name) if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); if (new_class_name) { - error = sysfs_create_link_nowarn(&dev->parent->kobj, - &dev->kobj, - new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); + error = sysfs_rename_link(&dev->parent->kobj, + &dev->kobj, + old_class_name, + new_class_name); } } #else if (dev->class) { - error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev_name(dev)); - if (error) - goto out; - sysfs_remove_link(&dev->class->p->class_subsys.kobj, - old_device_name); + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, new_name); } #endif From fac2622bbad4d7e3a32c53e631e018b80ec631dc Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:27 -0800 Subject: [PATCH 086/114] sysfs: Pass super_block to sysfs_get_inode Currently sysfs_get_inode magically returns an inode on sysfs_sb. Make the super_block parameter explicit and the code becomes clearer. Acked-by: Tejun Heo Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 2 +- fs/sysfs/inode.c | 5 +++-- fs/sysfs/mount.c | 2 +- fs/sysfs/sysfs.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 481fdec09f4e..590717861c7a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -645,7 +645,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, } /* attach dentry and inode */ - inode = sysfs_get_inode(sd); + inode = sysfs_get_inode(dir->i_sb, sd); if (!inode) { ret = ERR_PTR(-ENOMEM); goto out_unlock; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 0d09f6c6efab..082daaecac1b 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -283,6 +283,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) /** * sysfs_get_inode - get inode for sysfs_dirent + * @sb: super block * @sd: sysfs_dirent to allocate inode for * * Get inode for @sd. If such inode doesn't exist, a new inode @@ -295,11 +296,11 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) * RETURNS: * Pointer to allocated inode on success, NULL on failure. */ -struct inode * sysfs_get_inode(struct sysfs_dirent *sd) +struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) { struct inode *inode; - inode = iget_locked(sysfs_sb, sd->s_ino); + inode = iget_locked(sb, sd->s_ino); if (inode && (inode->i_state & I_NEW)) sysfs_init_inode(sd, inode); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 49749955ccaf..89db07e489b0 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -54,7 +54,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) /* get root inode, initialize and unlock it */ mutex_lock(&sysfs_mutex); - inode = sysfs_get_inode(&sysfs_root); + inode = sysfs_get_inode(sb, &sysfs_root); mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 5a3192a08442..7593d71d92f8 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -172,7 +172,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) /* * inode.c */ -struct inode *sysfs_get_inode(struct sysfs_dirent *sd); +struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); void sysfs_delete_inode(struct inode *inode); int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); int sysfs_permission(struct inode *inode, int mask); From 0f4288ec6fcc1a47d1fa0241ec1c6dacd5a09e96 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 12 Feb 2010 19:22:28 -0800 Subject: [PATCH 087/114] sysfs: Kill unused sysfs_sb variable. Now that there are no more users we can remove the sysfs_sb variable. Acked-by: Tejun Heo Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/mount.c | 2 -- fs/sysfs/sysfs.h | 1 - 2 files changed, 3 deletions(-) diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 89db07e489b0..0cb10884a2fc 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -23,7 +23,6 @@ static struct vfsmount *sysfs_mount; -struct super_block * sysfs_sb = NULL; struct kmem_cache *sysfs_dir_cachep; static const struct super_operations sysfs_ops = { @@ -50,7 +49,6 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_magic = SYSFS_MAGIC; sb->s_op = &sysfs_ops; sb->s_time_gran = 1; - sysfs_sb = sb; /* get root inode, initialize and unlock it */ mutex_lock(&sysfs_mutex); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7593d71d92f8..30f5a44fb5d3 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -115,7 +115,6 @@ struct sysfs_addrm_cxt { * mount.c */ extern struct sysfs_dirent sysfs_root; -extern struct super_block *sysfs_sb; extern struct kmem_cache *sysfs_dir_cachep; /* From 62e877b893e6350c900d381f353aa62ed48dcc97 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 1 Mar 2010 20:38:36 +1100 Subject: [PATCH 088/114] sysfs: fix for thinko with sysfs_bin_attr_init() After merging the final tree, today's linux-next build (powerpc allyesconfig) failed like this: drivers/pci/pci-sysfs.c: In function 'pci_create_legacy_files': drivers/pci/pci-sysfs.c:645: error: lvalue required as unary '&' operand drivers/pci/pci-sysfs.c:658: error: lvalue required as unary '&' operand Caused by commit "sysfs: Use sysfs_attr_init and sysfs_bin_attr_init on dynamic attributes" interacting with commit "sysfs: Use one lockdep class per sysfs attribute") both from the driver-core tree. Signed-off-by: Stephen Rothwell Cc: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 4 ++-- include/linux/sysfs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 9fa183cfb0e9..de296452c957 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -642,7 +642,7 @@ void pci_create_legacy_files(struct pci_bus *b) if (!b->legacy_io) goto kzalloc_err; - sysfs_bin_attr_init(&b->legacy_io); + sysfs_bin_attr_init(b->legacy_io); b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; @@ -655,7 +655,7 @@ void pci_create_legacy_files(struct pci_bus *b) goto legacy_io_err; /* Allocated above after the legacy_io struct */ - sysfs_bin_attr_init(&b->legacy_mem); + sysfs_bin_attr_init(b->legacy_mem); b->legacy_mem = b->legacy_io + 1; b->legacy_mem->attr.name = "legacy_mem"; b->legacy_mem->size = 1024*1024; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d77cde6d0498..f0496b3d1811 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -110,7 +110,7 @@ struct bin_attribute { * enabled. Lockdep gives a nice error when your attribute is * added to sysfs if you don't have this. */ -#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&bin_attr->attr) +#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr) struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); From 8e9394ce2412254ec69fd2a4f3e44a66eade2297 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 17 Feb 2010 10:57:05 -0800 Subject: [PATCH 089/114] Driver core: create lock/unlock functions for struct device In the future, we are going to be changing the lock type for struct device (once we get the lockdep infrastructure properly worked out) To make that changeover easier, and to possibly burry the lock in a different part of struct device, let's create some functions to lock and unlock a device so that no out-of-core code needs to be changed in the future. This patch creates the device_lock/unlock/trylock() functions, and converts all in-tree users to them. Cc: Thomas Gleixner Cc: Jean Delvare Cc: Dave Young Cc: Ming Lei Cc: Jiri Kosina Cc: Phil Carmody Cc: Arjan van de Ven Cc: Cornelia Huck Cc: Rafael J. Wysocki Cc: Pavel Machek Cc: Len Brown Cc: Magnus Damm Cc: Alan Stern Cc: Randy Dunlap Cc: Stefan Richter Cc: David Brownell Cc: Vegard Nossum Cc: Jesse Barnes Cc: Alex Chiang Cc: Kenji Kaneshige Cc: Andrew Morton Cc: Andrew Patterson Cc: Yu Zhao Cc: Dominik Brodowski Cc: Samuel Ortiz Cc: Wolfram Sang Cc: CHENG Renquan Cc: Oliver Neukum Cc: Frans Pop Cc: David Vrabel Cc: Kay Sievers Cc: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 20 +++++++++--------- drivers/base/dd.c | 38 +++++++++++++++++----------------- drivers/base/power/main.c | 20 +++++++++--------- drivers/firewire/core-device.c | 5 ++--- drivers/ieee1394/nodemgr.c | 5 ++--- drivers/pci/bus.c | 4 ++-- drivers/pci/pci.c | 4 ++-- drivers/pcmcia/ds.c | 8 +++---- drivers/usb/core/driver.c | 4 ++-- drivers/uwb/umc-bus.c | 4 ++-- drivers/uwb/uwb-internal.h | 4 ++-- include/linux/device.h | 17 ++++++++++++++- include/linux/usb.h | 6 +++--- 13 files changed, 76 insertions(+), 63 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index cca1aa10054c..71f6af5c8b0b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -173,10 +173,10 @@ static ssize_t driver_unbind(struct device_driver *drv, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == drv) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); device_release_driver(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); err = count; } put_device(dev); @@ -200,12 +200,12 @@ static ssize_t driver_bind(struct device_driver *drv, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); err = driver_probe_device(drv, dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); if (err > 0) { /* success */ @@ -744,10 +744,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, if (!dev->driver) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); ret = device_attach(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); } return ret < 0 ? ret : 0; } @@ -779,10 +779,10 @@ int device_reprobe(struct device *dev) { if (dev->driver) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); device_release_driver(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); } return bus_rescan_devices_helper(dev, NULL); } diff --git a/drivers/base/dd.c b/drivers/base/dd.c index ee95c76bfd3d..c89291f8a16b 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev) * for before calling this. (It is ok to call with no other effort * from a driver's probe() method.) * - * This function must be called with @dev->sem held. + * This function must be called with the device lock held. */ int device_bind_driver(struct device *dev) { @@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe); * This function returns -ENODEV if the device is not registered, * 1 if the device is bound successfully and 0 otherwise. * - * This function must be called with @dev->sem held. When called for a - * USB interface, @dev->parent->sem must be held as well. + * This function must be called with @dev lock held. When called for a + * USB interface, @dev->parent lock must be held as well. */ int driver_probe_device(struct device_driver *drv, struct device *dev) { @@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data) * 0 if no matching driver was found; * -ENODEV if the device is not registered. * - * When called for a USB interface, @dev->parent->sem must be held. + * When called for a USB interface, @dev->parent lock must be held. */ int device_attach(struct device *dev) { int ret = 0; - down(&dev->sem); + device_lock(dev); if (dev->driver) { ret = device_bind_driver(dev); if (ret == 0) @@ -253,7 +253,7 @@ int device_attach(struct device *dev) ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_put_sync(dev); } - up(&dev->sem); + device_unlock(dev); return ret; } EXPORT_SYMBOL_GPL(device_attach); @@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data) return 0; if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); if (!dev->driver) driver_probe_device(drv, dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); return 0; } @@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv) EXPORT_SYMBOL_GPL(driver_attach); /* - * __device_release_driver() must be called with @dev->sem held. - * When called for a USB interface, @dev->parent->sem must be held as well. + * __device_release_driver() must be called with @dev lock held. + * When called for a USB interface, @dev->parent lock must be held as well. */ static void __device_release_driver(struct device *dev) { @@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev) * @dev: device. * * Manually detach device from driver. - * When called for a USB interface, @dev->parent->sem must be held. + * When called for a USB interface, @dev->parent lock must be held. */ void device_release_driver(struct device *dev) { @@ -352,9 +352,9 @@ void device_release_driver(struct device *dev) * within their ->remove callback for the same device, they * will deadlock right here. */ - down(&dev->sem); + device_lock(dev); __device_release_driver(dev); - up(&dev->sem); + device_unlock(dev); } EXPORT_SYMBOL_GPL(device_release_driver); @@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv) spin_unlock(&drv->p->klist_devices.k_lock); if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); if (dev->driver == drv) __device_release_driver(dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); put_device(dev); } } diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0e26a6f6fd48..d477f4dc5e51 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -35,8 +35,8 @@ * because children are guaranteed to be discovered after parents, and * are inserted at the back of the list on discovery. * - * Since device_pm_add() may be called with a device semaphore held, - * we must never try to acquire a device semaphore while holding + * Since device_pm_add() may be called with a device lock held, + * we must never try to acquire a device lock while holding * dpm_list_mutex. */ @@ -508,7 +508,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) TRACE_RESUME(0); dpm_wait(dev->parent, async); - down(&dev->sem); + device_lock(dev); dev->power.status = DPM_RESUMING; @@ -543,7 +543,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) } } End: - up(&dev->sem); + device_unlock(dev); complete_all(&dev->power.completion); TRACE_RESUME(error); @@ -629,7 +629,7 @@ static void dpm_resume(pm_message_t state) */ static void device_complete(struct device *dev, pm_message_t state) { - down(&dev->sem); + device_lock(dev); if (dev->class && dev->class->pm && dev->class->pm->complete) { pm_dev_dbg(dev, state, "completing class "); @@ -646,7 +646,7 @@ static void device_complete(struct device *dev, pm_message_t state) dev->bus->pm->complete(dev); } - up(&dev->sem); + device_unlock(dev); } /** @@ -809,7 +809,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) int error = 0; dpm_wait_for_children(dev, async); - down(&dev->sem); + device_lock(dev); if (async_error) goto End; @@ -849,7 +849,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) dev->power.status = DPM_OFF; End: - up(&dev->sem); + device_unlock(dev); complete_all(&dev->power.completion); return error; @@ -938,7 +938,7 @@ static int device_prepare(struct device *dev, pm_message_t state) { int error = 0; - down(&dev->sem); + device_lock(dev); if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { pm_dev_dbg(dev, state, "preparing "); @@ -962,7 +962,7 @@ static int device_prepare(struct device *dev, pm_message_t state) suspend_report_result(dev->class->pm->prepare, error); } End: - up(&dev->sem); + device_unlock(dev); return error; } diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 014cabd3afda..5db0518c66da 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -828,9 +827,9 @@ static int update_unit(struct device *dev, void *data) struct fw_driver *driver = (struct fw_driver *)dev->driver; if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { - down(&dev->sem); + device_lock(dev); driver->update(unit); - up(&dev->sem); + device_unlock(dev); } return 0; diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 5122b5a8aa2d..18350213479e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "csr.h" @@ -1397,9 +1396,9 @@ static int update_pdrv(struct device *dev, void *data) pdrv = container_of(drv, struct hpsb_protocol_driver, driver); if (pdrv->update) { - down(&ud->device.sem); + device_lock(&ud->device); error = pdrv->update(ud); - up(&ud->device.sem); + device_unlock(&ud->device); } if (error) device_release_driver(&ud->device); diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 712250f5874a..26301cb25e7f 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -288,9 +288,9 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), next = dev->bus_list.next; /* Run device routines with the device locked */ - down(&dev->dev.sem); + device_lock(&dev->dev); retval = cb(dev, userdata); - up(&dev->dev.sem); + device_unlock(&dev->dev); if (retval) break; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 77b493b3d97b..897fa5ccdb78 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2486,7 +2486,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) if (!probe) { pci_block_user_cfg_access(dev); /* block PM suspend, driver probe, etc. */ - down(&dev->dev.sem); + device_lock(&dev->dev); } rc = pci_dev_specific_reset(dev, probe); @@ -2508,7 +2508,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) rc = pci_parent_bus_reset(dev, probe); done: if (!probe) { - up(&dev->dev.sem); + device_unlock(&dev->dev); pci_unblock_user_cfg_access(dev); } diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0f98be4450b7..ad93ebd7b2a2 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -971,9 +971,9 @@ static int runtime_suspend(struct device *dev) { int rc; - down(&dev->sem); + device_lock(dev); rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND); - up(&dev->sem); + device_unlock(dev); return rc; } @@ -981,9 +981,9 @@ static int runtime_resume(struct device *dev) { int rc; - down(&dev->sem); + device_lock(dev); rc = pcmcia_dev_resume(dev); - up(&dev->sem); + device_unlock(dev); return rc; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a7037bf81688..f3c233806fa3 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -489,10 +489,10 @@ void usb_driver_release_interface(struct usb_driver *driver, if (device_is_registered(dev)) { device_release_driver(dev); } else { - down(&dev->sem); + device_lock(dev); usb_unbind_interface(dev); dev->driver = NULL; - up(&dev->sem); + device_unlock(dev); } } EXPORT_SYMBOL_GPL(usb_driver_release_interface); diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index cdd6c8efc9f8..5fad4e791b3e 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c @@ -62,12 +62,12 @@ int umc_controller_reset(struct umc_dev *umc) struct device *parent = umc->dev.parent; int ret = 0; - if(down_trylock(&parent->sem)) + if (device_trylock(parent)) return -EAGAIN; ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); if (ret >= 0) ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper); - up(&parent->sem); + device_unlock(parent); return ret; } diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index d5bcfc1c227a..157485c862c0 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h @@ -366,12 +366,12 @@ struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) { - down(&uwb_dev->dev.sem); + device_lock(&uwb_dev->dev); } static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev) { - up(&uwb_dev->dev.sem); + device_unlock(&uwb_dev->dev); } #endif /* #ifndef __UWB_INTERNAL_H__ */ diff --git a/include/linux/device.h b/include/linux/device.h index f95d5bfe8248..182192892d45 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -106,7 +106,7 @@ extern int bus_unregister_notifier(struct bus_type *bus, /* All 4 notifers below get called with the target struct device * * as an argument. Note that those functions are likely to be called - * with the device semaphore held in the core, so be careful. + * with the device lock held in the core, so be careful. */ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ @@ -508,6 +508,21 @@ static inline bool device_async_suspend_enabled(struct device *dev) return !!dev->power.async_suspend; } +static inline void device_lock(struct device *dev) +{ + down(&dev->sem); +} + +static inline int device_trylock(struct device *dev) +{ + return down_trylock(&dev->sem); +} + +static inline void device_unlock(struct device *dev) +{ + up(&dev->sem); +} + void driver_init(void); /* diff --git a/include/linux/usb.h b/include/linux/usb.h index 3492abf82e75..8c9f053111bb 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -512,9 +512,9 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); /* USB device locking */ -#define usb_lock_device(udev) down(&(udev)->dev.sem) -#define usb_unlock_device(udev) up(&(udev)->dev.sem) -#define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem) +#define usb_lock_device(udev) device_lock(&(udev)->dev) +#define usb_unlock_device(udev) device_unlock(&(udev)->dev) +#define usb_trylock_device(udev) device_trylock(&(udev)->dev) extern int usb_lock_device_for_reset(struct usb_device *udev, const struct usb_interface *iface); From 46d0e9e091ba5dd29cac7543e97084540da9c4b7 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Sat, 9 Jan 2010 21:16:52 +0800 Subject: [PATCH 090/114] msi-laptop: Support standard ec 66/62 command on MSI notebook and nebook Suppport standard ec 66/62 command on MSI notebook and nebook. MSI netbook and notebook already support 66/62 command, so, add new get_state function, and put the old model to non-standard model, but driver still support those old model. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 43 ++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 759763d18e4c..323e99460c9f 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -66,6 +66,11 @@ #define MSI_EC_COMMAND_WIRELESS 0x10 #define MSI_EC_COMMAND_LCD_LEVEL 0x11 +#define MSI_STANDARD_EC_COMMAND_ADDRESS 0x2e +#define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0) +#define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1) +#define MSI_STANDARD_EC_WLAN_MASK (1 << 3) + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -74,6 +79,9 @@ static int auto_brightness; module_param(auto_brightness, int, 0); MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); +static bool old_ec_model; +static int wlan_s, bluetooth_s; + /* Hardware access */ static int set_lcd_level(int level) @@ -148,6 +156,22 @@ static int get_wireless_state(int *wlan, int *bluetooth) return 0; } +static int get_wireless_state_ec_standard(void) +{ + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); + if (result < 0) + return -1; + + wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK); + + bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK); + + return 0; +} + /* Backlight device stuff */ static int bl_get_brightness(struct backlight_device *b) @@ -176,7 +200,12 @@ static ssize_t show_wlan(struct device *dev, int ret, enabled; - ret = get_wireless_state(&enabled, NULL); + if (old_ec_model) { + ret = get_wireless_state(&enabled, NULL); + } else { + ret = get_wireless_state_ec_standard(); + enabled = wlan_s; + } if (ret < 0) return ret; @@ -189,7 +218,12 @@ static ssize_t show_bluetooth(struct device *dev, int ret, enabled; - ret = get_wireless_state(NULL, &enabled); + if (old_ec_model) { + ret = get_wireless_state(NULL, &enabled); + } else { + ret = get_wireless_state_ec_standard(); + enabled = bluetooth_s; + } if (ret < 0) return ret; @@ -339,8 +373,8 @@ static int __init msi_init(void) if (acpi_disabled) return -ENODEV; - if (!force && !dmi_check_system(msi_dmi_table)) - return -ENODEV; + if (force || dmi_check_system(msi_dmi_table)) + old_ec_model = 1; if (auto_brightness < 0 || auto_brightness > 2) return -EINVAL; @@ -435,3 +469,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARIN MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); +MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*"); From fc0dc4c926e6b7afe680aecf809f48eef3faa182 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Sat, 9 Jan 2010 23:17:07 +0800 Subject: [PATCH 091/114] msi-laptop: Add threeg sysfs file for support query 3G state by standard 66/62 ec command Add threeg sysfs file for support query 3G state by standard 66/62 ec command, the MSI standard ec interface supported this feature. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 323e99460c9f..1784d5588d41 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -70,6 +70,7 @@ #define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0) #define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1) #define MSI_STANDARD_EC_WLAN_MASK (1 << 3) +#define MSI_STANDARD_EC_3G_MASK (1 << 4) static int force; module_param(force, bool, 0); @@ -80,7 +81,7 @@ module_param(auto_brightness, int, 0); MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); static bool old_ec_model; -static int wlan_s, bluetooth_s; +static int wlan_s, bluetooth_s, threeg_s; /* Hardware access */ @@ -169,6 +170,8 @@ static int get_wireless_state_ec_standard(void) bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK); + threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK); + return 0; } @@ -230,6 +233,23 @@ static ssize_t show_bluetooth(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t show_threeg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + int ret; + + /* old msi ec not support 3G */ + if (old_ec_model) + return -1; + + ret = get_wireless_state_ec_standard(); + if (ret < 0) + return ret; + + return sprintf(buf, "%i\n", threeg_s); +} + static ssize_t show_lcd_level(struct device *dev, struct device_attribute *attr, char *buf) { @@ -292,6 +312,7 @@ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); +static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); static struct attribute *msipf_attributes[] = { &dev_attr_lcd_level.attr, @@ -412,6 +433,12 @@ static int __init msi_init(void) if (ret) goto fail_platform_device2; + if (!old_ec_model) { + ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); + if (ret) + goto fail_platform_device2; + } + /* Disable automatic brightness control by default because * this module was probably loaded to do brightness control in * software. */ @@ -446,6 +473,8 @@ static void __exit msi_cleanup(void) { sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); + if (!old_ec_model) + device_remove_file(&msipf_device->dev, &dev_attr_threeg); platform_device_unregister(msipf_device); platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); From 472ea12d1a265c868e1605abb59bf21f595eedfc Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Fri, 22 Jan 2010 00:15:59 +0800 Subject: [PATCH 092/114] msi-laptop: Support some MSI 3G netbook that is need load SCM Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, those netbook will load the SCM (windows app) to disable the original Wlan/Bluetooth control by BIOS when user press fn key, then control Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user cann't on/off 3G module on those 3G netbook. On Linux, msi-laptop driver will do the same thing to disable the original BIOS control, then might need use HAL or other userland application to do the software control that simulate with SCM. e.g. MSI N034 netbook Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 238 ++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 1784d5588d41..ff21d1acf3be 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -58,6 +58,7 @@ #include #include #include +#include #define MSI_DRIVER_VERSION "0.5" @@ -72,6 +73,10 @@ #define MSI_STANDARD_EC_WLAN_MASK (1 << 3) #define MSI_STANDARD_EC_3G_MASK (1 << 4) +/* For set SCM load flag to disable BIOS fn key */ +#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d +#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -83,6 +88,19 @@ MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disab static bool old_ec_model; static int wlan_s, bluetooth_s, threeg_s; +/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, + * those netbook will load the SCM (windows app) to disable the original + * Wlan/Bluetooth control by BIOS when user press fn key, then control + * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user + * cann't on/off 3G module on those 3G netbook. + * On Linux, msi-laptop driver will do the same thing to disable the + * original BIOS control, then might need use HAL or other userland + * application to do the software control that simulate with SCM. + * e.g. MSI N034 netbook + */ +static bool load_scm_model; +static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg; + /* Hardware access */ static int set_lcd_level(int level) @@ -139,6 +157,35 @@ static int set_auto_brightness(int enable) return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); } +static ssize_t set_device_state(const char *buf, size_t count, u8 mask) +{ + int status; + u8 wdata = 0, rdata; + int result; + + if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1)) + return -EINVAL; + + /* read current device state */ + result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); + if (result < 0) + return -EINVAL; + + if (!!(rdata & mask) != status) { + /* reverse device bit */ + if (rdata & mask) + wdata = rdata & ~mask; + else + wdata = rdata | mask; + + result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata); + if (result < 0) + return -EINVAL; + } + + return count; +} + static int get_wireless_state(int *wlan, int *bluetooth) { u8 wdata = 0, rdata; @@ -215,6 +262,12 @@ static ssize_t show_wlan(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t store_wlan(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK); +} + static ssize_t show_bluetooth(struct device *dev, struct device_attribute *attr, char *buf) { @@ -233,6 +286,12 @@ static ssize_t show_bluetooth(struct device *dev, return sprintf(buf, "%i\n", enabled); } +static ssize_t store_bluetooth(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK); +} + static ssize_t show_threeg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -250,6 +309,12 @@ static ssize_t show_threeg(struct device *dev, return sprintf(buf, "%i\n", threeg_s); } +static ssize_t store_threeg(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK); +} + static ssize_t show_lcd_level(struct device *dev, struct device_attribute *attr, char *buf) { @@ -387,6 +452,169 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { { } }; +static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { + { + .ident = "MSI N034", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "MICRO-STAR INTERNATIONAL CO., LTD"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"), + DMI_MATCH(DMI_CHASSIS_VENDOR, + "MICRO-STAR INTERNATIONAL CO., LTD") + }, + .callback = dmi_check_cb + }, + { } +}; + +static int rfkill_bluetooth_set(void *data, bool blocked) +{ + /* Do something with blocked...*/ + /* + * blocked == false is on + * blocked == true is off + */ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); + + return 0; +} + +static int rfkill_wlan_set(void *data, bool blocked) +{ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK); + + return 0; +} + +static int rfkill_threeg_set(void *data, bool blocked) +{ + if (blocked) + set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK); + else + set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK); + + return 0; +} + +static struct rfkill_ops rfkill_bluetooth_ops = { + .set_block = rfkill_bluetooth_set +}; + +static struct rfkill_ops rfkill_wlan_ops = { + .set_block = rfkill_wlan_set +}; + +static struct rfkill_ops rfkill_threeg_ops = { + .set_block = rfkill_threeg_set +}; + +static void rfkill_cleanup(void) +{ + if (rfk_bluetooth) { + rfkill_unregister(rfk_bluetooth); + rfkill_destroy(rfk_bluetooth); + } + + if (rfk_threeg) { + rfkill_unregister(rfk_threeg); + rfkill_destroy(rfk_threeg); + } + + if (rfk_wlan) { + rfkill_unregister(rfk_wlan); + rfkill_destroy(rfk_wlan); + } +} + +static int rfkill_init(struct platform_device *sdev) +{ + /* add rfkill */ + int retval; + + rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev, + RFKILL_TYPE_BLUETOOTH, + &rfkill_bluetooth_ops, NULL); + if (!rfk_bluetooth) { + retval = -ENOMEM; + goto err_bluetooth; + } + retval = rfkill_register(rfk_bluetooth); + if (retval) + goto err_bluetooth; + + rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN, + &rfkill_wlan_ops, NULL); + if (!rfk_wlan) { + retval = -ENOMEM; + goto err_wlan; + } + retval = rfkill_register(rfk_wlan); + if (retval) + goto err_wlan; + + rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN, + &rfkill_threeg_ops, NULL); + if (!rfk_threeg) { + retval = -ENOMEM; + goto err_threeg; + } + retval = rfkill_register(rfk_threeg); + if (retval) + goto err_threeg; + + return 0; + +err_threeg: + rfkill_destroy(rfk_threeg); + if (rfk_wlan) + rfkill_unregister(rfk_wlan); +err_wlan: + rfkill_destroy(rfk_wlan); + if (rfk_bluetooth) + rfkill_unregister(rfk_bluetooth); +err_bluetooth: + rfkill_destroy(rfk_bluetooth); + + return retval; +} + +static int load_scm_model_init(struct platform_device *sdev) +{ + u8 data; + int result; + + /* allow userland write sysfs file */ + dev_attr_bluetooth.store = store_bluetooth; + dev_attr_wlan.store = store_wlan; + dev_attr_threeg.store = store_threeg; + dev_attr_bluetooth.attr.mode |= S_IWUSR; + dev_attr_wlan.attr.mode |= S_IWUSR; + dev_attr_threeg.attr.mode |= S_IWUSR; + + /* disable hardware control by fn key */ + result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); + if (result < 0) + return result; + + result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, + data | MSI_STANDARD_EC_SCM_LOAD_MASK); + if (result < 0) + return result; + + /* initial rfkill */ + result = rfkill_init(sdev); + if (result < 0) + return result; + + return 0; +} + static int __init msi_init(void) { int ret; @@ -397,6 +625,9 @@ static int __init msi_init(void) if (force || dmi_check_system(msi_dmi_table)) old_ec_model = 1; + if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) + load_scm_model = 1; + if (auto_brightness < 0 || auto_brightness > 2) return -EINVAL; @@ -429,6 +660,11 @@ static int __init msi_init(void) if (ret) goto fail_platform_device1; + if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) { + ret = -EINVAL; + goto fail_platform_device1; + } + ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); if (ret) goto fail_platform_device2; @@ -479,6 +715,8 @@ static void __exit msi_cleanup(void) platform_driver_unregister(&msipf_driver); backlight_device_unregister(msibl_device); + rfkill_cleanup(); + /* Enable automatic brightness control again */ if (auto_brightness != 2) set_auto_brightness(1); From ec766278ba927f3d3c75211ea7697aae37f327f0 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Wed, 27 Jan 2010 00:13:45 +0800 Subject: [PATCH 093/114] msi-laptop: Add resume method for set the SCM load again Implement the resume method for set the load SCM flag after system reusme. Without this patch, the wifi function key on SCM model will back to BIOS control mode then confuse with the userland software control. e.g. MSI N034 Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index ff21d1acf3be..af1b62f76117 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -77,6 +77,8 @@ #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) +static int msi_laptop_resume(struct platform_device *device); + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -395,7 +397,8 @@ static struct platform_driver msipf_driver = { .driver = { .name = "msi-laptop-pf", .owner = THIS_MODULE, - } + }, + .resume = msi_laptop_resume, }; static struct platform_device *msipf_device; @@ -584,6 +587,27 @@ static int rfkill_init(struct platform_device *sdev) return retval; } +static int msi_laptop_resume(struct platform_device *device) +{ + u8 data; + int result; + + if (!load_scm_model) + return 0; + + /* set load SCM to disable hardware control by fn key */ + result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); + if (result < 0) + return result; + + result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, + data | MSI_STANDARD_EC_SCM_LOAD_MASK); + if (result < 0) + return result; + + return 0; +} + static int load_scm_model_init(struct platform_device *sdev) { u8 data; From e22388e71b8787b26dc33d023e5c1eec58865541 Mon Sep 17 00:00:00 2001 From: "Lee, Chun-Yi" Date: Wed, 27 Jan 2010 12:23:00 +0800 Subject: [PATCH 094/114] msi-laptop: Detect 3G device exists by standard ec command Detect 3G device exists by standard ec command. Driver will not create the threeg sysfs file and threeg rfkill interface if there have no internal 3G device in MSI notebook/netbook. Signed-off-by: Lee, Chun-Yi Cc: Lennart Poettering Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/msi-laptop.c | 44 ++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index af1b62f76117..c2b05da4289a 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -79,6 +79,8 @@ static int msi_laptop_resume(struct platform_device *device); +#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f + static int force; module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); @@ -89,6 +91,7 @@ MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disab static bool old_ec_model; static int wlan_s, bluetooth_s, threeg_s; +static int threeg_exists; /* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, * those netbook will load the SCM (windows app) to disable the original @@ -224,6 +227,20 @@ static int get_wireless_state_ec_standard(void) return 0; } +static int get_threeg_exists(void) +{ + u8 rdata; + int result; + + result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata); + if (result < 0) + return -1; + + threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK); + + return 0; +} + /* Backlight device stuff */ static int bl_get_brightness(struct backlight_device *b) @@ -561,15 +578,17 @@ static int rfkill_init(struct platform_device *sdev) if (retval) goto err_wlan; - rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, RFKILL_TYPE_WWAN, - &rfkill_threeg_ops, NULL); - if (!rfk_threeg) { - retval = -ENOMEM; - goto err_threeg; + if (threeg_exists) { + rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, + RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL); + if (!rfk_threeg) { + retval = -ENOMEM; + goto err_threeg; + } + retval = rfkill_register(rfk_threeg); + if (retval) + goto err_threeg; } - retval = rfkill_register(rfk_threeg); - if (retval) - goto err_threeg; return 0; @@ -649,6 +668,9 @@ static int __init msi_init(void) if (force || dmi_check_system(msi_dmi_table)) old_ec_model = 1; + if (!old_ec_model) + get_threeg_exists(); + if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) load_scm_model = 1; @@ -694,7 +716,9 @@ static int __init msi_init(void) goto fail_platform_device2; if (!old_ec_model) { - ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); + if (threeg_exists) + ret = device_create_file(&msipf_device->dev, + &dev_attr_threeg); if (ret) goto fail_platform_device2; } @@ -733,7 +757,7 @@ static void __exit msi_cleanup(void) { sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); - if (!old_ec_model) + if (!old_ec_model && threeg_exists) device_remove_file(&msipf_device->dev, &dev_attr_threeg); platform_device_unregister(msipf_device); platform_driver_unregister(&msipf_driver); From 410c17651998944630a95fbb286a50362de2dbb0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 3 Feb 2010 14:24:28 -0800 Subject: [PATCH 095/114] msi-laptop: depends on RFKILL msi-laptop uses rfkill*() interfaces so it should depend on RFKILL. msi-laptop.c:(.text+0x1fcd1b): undefined reference to `rfkill_alloc' msi-laptop.c:(.text+0x1fcd76): undefined reference to `rfkill_register' msi-laptop.c:(.text+0x1fcdc8): undefined reference to `rfkill_destroy' msi-laptop.c:(.text+0x1fcdd9): undefined reference to `rfkill_unregister' This repairs "msi-laptop: Detect 3G device exists by standard ec command", which is in some gregkh tree. Signed-off-by: Randy Dunlap Cc: Lennart Poettering Cc: Lee, Chun-Yi Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index cd2ee6fce1b4..e631dbeafd79 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -150,6 +150,7 @@ config MSI_LAPTOP tristate "MSI Laptop Extras" depends on ACPI depends on BACKLIGHT_CLASS_DEVICE + depends on RFKILL ---help--- This is a driver for laptops built by MSI (MICRO-STAR INTERNATIONAL): From 079d88ccc374d2c1a850b8a83595ba4c907fb3df Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Mon, 8 Mar 2010 10:44:23 +0800 Subject: [PATCH 096/114] ALSA: hdmi - merge common code for intelhdmi and nvhdmi Create patch_hdmi.c to hold common code from intelhdmi and nvhdmi. For now the patch_hdmi.c file is simply included by patch_intelhdmi.c and patch_nvhdmi.c, and does not represent a real codec. There are no behavior changes to intelhdmi. However nvhdmi made several changes when copying code out of intelhdmi, which are all reverted in this patch. Wei Ni confirmed that the reverted code actually works fine. Tested-by: Wei Ni Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 845 ++++++++++++++++++++++++++++++++ sound/pci/hda/patch_intelhdmi.c | 821 +------------------------------ sound/pci/hda/patch_nvhdmi.c | 829 +------------------------------ 3 files changed, 882 insertions(+), 1613 deletions(-) create mode 100644 sound/pci/hda/patch_hdmi.c diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c new file mode 100644 index 000000000000..b2ab39670dda --- /dev/null +++ b/sound/pci/hda/patch_hdmi.c @@ -0,0 +1,845 @@ +/* + * + * patch_hdmi.c - routines for HDMI/DisplayPort codecs + * + * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. + * + * Authors: + * Wu Fengguang + * + * Maintained by: + * Wu Fengguang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +struct hdmi_spec { + int num_cvts; + int num_pins; + hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */ + hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */ + + /* + * source connection for each pin + */ + hda_nid_t pin_cvt[MAX_HDMI_PINS+1]; + + /* + * HDMI sink attached to each pin + */ + struct hdmi_eld sink_eld[MAX_HDMI_PINS]; + + /* + * export one pcm per pipe + */ + struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; + + /* + * nvhdmi specific + */ + struct hda_multi_out multiout; + unsigned int codec_type; +}; + + +struct hdmi_audio_infoframe { + u8 type; /* 0x84 */ + u8 ver; /* 0x01 */ + u8 len; /* 0x0a */ + + u8 checksum; /* PB0 */ + u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ + u8 SS01_SF24; + u8 CXT04; + u8 CA; + u8 LFEPBL01_LSV36_DM_INH7; + u8 reserved[5]; /* PB6 - PB10 */ +}; + +/* + * CEA speaker placement: + * + * FLH FCH FRH + * FLW FL FLC FC FRC FR FRW + * + * LFE + * TC + * + * RL RLC RC RRC RR + * + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. + */ +enum cea_speaker_placement { + FL = (1 << 0), /* Front Left */ + FC = (1 << 1), /* Front Center */ + FR = (1 << 2), /* Front Right */ + FLC = (1 << 3), /* Front Left Center */ + FRC = (1 << 4), /* Front Right Center */ + RL = (1 << 5), /* Rear Left */ + RC = (1 << 6), /* Rear Center */ + RR = (1 << 7), /* Rear Right */ + RLC = (1 << 8), /* Rear Left Center */ + RRC = (1 << 9), /* Rear Right Center */ + LFE = (1 << 10), /* Low Frequency Effect */ + FLW = (1 << 11), /* Front Left Wide */ + FRW = (1 << 12), /* Front Right Wide */ + FLH = (1 << 13), /* Front Left High */ + FCH = (1 << 14), /* Front Center High */ + FRH = (1 << 15), /* Front Right High */ + TC = (1 << 16), /* Top Center */ +}; + +/* + * ELD SA bits in the CEA Speaker Allocation data block + */ +static int eld_speaker_allocation_bits[] = { + [0] = FL | FR, + [1] = LFE, + [2] = FC, + [3] = RL | RR, + [4] = RC, + [5] = FLC | FRC, + [6] = RLC | RRC, + /* the following are not defined in ELD yet */ + [7] = FLW | FRW, + [8] = FLH | FRH, + [9] = TC, + [10] = FCH, +}; + +struct cea_channel_speaker_allocation { + int ca_index; + int speakers[8]; + + /* derived values, just for convenience */ + int channels; + int spk_mask; +}; + +/* + * ALSA sequence is: + * + * surround40 surround41 surround50 surround51 surround71 + * ch0 front left = = = = + * ch1 front right = = = = + * ch2 rear left = = = = + * ch3 rear right = = = = + * ch4 LFE center center center + * ch5 LFE LFE + * ch6 side left + * ch7 side right + * + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} + */ +static int hdmi_channel_mapping[0x32][8] = { + /* stereo */ + [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* 2.1 */ + [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* Dolby Surround */ + [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* surround40 */ + [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, + /* 4ch */ + [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, + /* surround41 */ + [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround50 */ + [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround51 */ + [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, + /* 7.1 */ + [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, +}; + +/* + * This is an ordered list! + * + * The preceding ones have better chances to be selected by + * hdmi_setup_channel_allocation(). + */ +static struct cea_channel_speaker_allocation channel_allocations[] = { +/* channel: 7 6 5 4 3 2 1 0 */ +{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, + /* 2.1 */ +{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, + /* Dolby Surround */ +{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, + /* surround40 */ +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, + /* surround41 */ +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, + /* surround50 */ +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, + /* surround51 */ +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, + /* 6.1 */ +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, + /* surround71 */ +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, + +{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, +{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, +{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, +{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, +}; + + +/* + * HDMI routines + */ + +static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) +{ + int i; + + for (i = 0; nids[i]; i++) + if (nids[i] == nid) + return i; + + snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); + return -EINVAL; +} + +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + if (!snd_hdmi_get_eld(eld, codec, pin_nid)) + snd_hdmi_show_eld(eld); +} + +#ifdef BE_PARANOID +static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int *packet_index, int *byte_index) +{ + int val; + + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_INDEX, 0); + + *packet_index = val >> 5; + *byte_index = val & 0x1f; +} +#endif + +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int packet_index, int byte_index) +{ + int val; + + val = (packet_index << 5) | (byte_index & 0x1f); + + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); +} + +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, + unsigned char val) +{ + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); +} + +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) +{ + /* Unmute */ + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + /* Enable pin out */ + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); +} + +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) +{ + return 1 + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CVT_CHAN_COUNT, 0); +} + +static void hdmi_set_channel_count(struct hda_codec *codec, + hda_nid_t nid, int chs) +{ + if (chs != hdmi_get_channel_count(codec, nid)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); +} + + +/* + * Channel mapping routines + */ + +/* + * Compute derived values in channel_allocations[]. + */ +static void init_channel_allocations(void) +{ + int i, j; + struct cea_channel_speaker_allocation *p; + + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + p = channel_allocations + i; + p->channels = 0; + p->spk_mask = 0; + for (j = 0; j < ARRAY_SIZE(p->speakers); j++) + if (p->speakers[j]) { + p->channels++; + p->spk_mask |= p->speakers[j]; + } + } +} + +/* + * The transformation takes two steps: + * + * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask + * spk_mask => (channel_allocations[]) => ai->CA + * + * TODO: it could select the wrong CA from multiple candidates. +*/ +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, + struct hdmi_audio_infoframe *ai) +{ + struct hdmi_spec *spec = codec->spec; + struct hdmi_eld *eld; + int i; + int spk_mask = 0; + int channels = 1 + (ai->CC02_CT47 & 0x7); + char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; + + /* + * CA defaults to 0 for basic stereo audio + */ + if (channels <= 2) + return 0; + + i = hda_node_index(spec->pin_cvt, nid); + if (i < 0) + return 0; + eld = &spec->sink_eld[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 (!eld->spk_alloc) + eld->spk_alloc = 0xffff; + + /* + * expand ELD's speaker allocation mask + * + * ELD tells the speaker mask in a compact(paired) form, + * expand ELD's notions to match the ones used by Audio InfoFrame. + */ + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { + if (eld->spk_alloc & (1 << i)) + spk_mask |= eld_speaker_allocation_bits[i]; + } + + /* search for the first working match in the CA table */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels && + (spk_mask & channel_allocations[i].spk_mask) == + channel_allocations[i].spk_mask) { + ai->CA = channel_allocations[i].ca_index; + break; + } + } + + snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); + snd_printdd(KERN_INFO + "HDMI: select CA 0x%x for %d-channel allocation: %s\n", + ai->CA, channels, buf); + + return ai->CA; +} + +static void hdmi_debug_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int slot; + + for (i = 0; i < 8; i++) { + slot = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_CHAN_SLOT, i); + printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", + slot >> 4, slot & 0xf); + } +#endif +} + + +static void hdmi_setup_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + int i; + int ca = ai->CA; + int err; + + if (hdmi_channel_mapping[ca][1] == 0) { + for (i = 0; i < channel_allocations[ca].channels; i++) + hdmi_channel_mapping[ca][i] = i | (i << 4); + for (; i < 8; i++) + hdmi_channel_mapping[ca][i] = 0xf | (i << 4); + } + + for (i = 0; i < 8; i++) { + err = snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_HDMI_CHAN_SLOT, + hdmi_channel_mapping[ca][i]); + if (err) { + snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + break; + } + } + + hdmi_debug_channel_mapping(codec, pin_nid); +} + + +/* + * Audio InfoFrame routines + */ + +/* + * Enable Audio InfoFrame Transmission + */ +static void hdmi_start_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_BEST); +} + +/* + * Disable Audio InfoFrame Transmission + */ +static void hdmi_stop_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_DISABLE); +} + +static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int size; + + size = snd_hdmi_get_eld_size(codec, pin_nid); + printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); + + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); + } +#endif +} + +static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef BE_PARANOID + int i, j; + int size; + int pi, bi; + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + if (size == 0) + continue; + + hdmi_set_dip_index(codec, pin_nid, i, 0x0); + for (j = 1; j < 1000; j++) { + hdmi_write_dip_byte(codec, pin_nid, 0x0); + hdmi_get_dip_index(codec, pin_nid, &pi, &bi); + if (pi != i) + snd_printd(KERN_INFO "dip index %d: %d != %d\n", + bi, pi, i); + if (bi == 0) /* byte index wrapped around */ + break; + } + snd_printd(KERN_INFO + "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", + i, size, j); + } +#endif +} + +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 sum = 0; + int i; + + ai->checksum = 0; + + for (i = 0; i < sizeof(*ai); i++) + sum += bytes[i]; + + ai->checksum = -sum; +} + +static void hdmi_fill_audio_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + int i; + + hdmi_debug_dip_size(codec, pin_nid); + hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ + + hdmi_checksum_audio_infoframe(ai); + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) + hdmi_write_dip_byte(codec, pin_nid, bytes[i]); +} + +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 val; + int i; + + if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) + != AC_DIPXMIT_BEST) + return false; + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) { + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_DATA, 0); + if (val != bytes[i]) + return false; + } + + return true; +} + +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, + struct snd_pcm_substream *substream) +{ + struct hdmi_spec *spec = codec->spec; + hda_nid_t pin_nid; + int i; + struct hdmi_audio_infoframe ai = { + .type = 0x84, + .ver = 0x01, + .len = 0x0a, + .CC02_CT47 = substream->runtime->channels - 1, + }; + + hdmi_setup_channel_allocation(codec, nid, &ai); + + for (i = 0; i < spec->num_pins; i++) { + if (spec->pin_cvt[i] != nid) + continue; + if (!spec->sink_eld[i].monitor_present) + continue; + + pin_nid = spec->pin[i]; + if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + hdmi_setup_channel_mapping(codec, pin_nid, &ai); + hdmi_stop_infoframe_trans(codec, pin_nid); + hdmi_fill_audio_infoframe(codec, pin_nid, &ai); + hdmi_start_infoframe_trans(codec, pin_nid); + } + } +} + + +/* + * Unsolicited events + */ + +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + struct hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int pind = !!(res & AC_UNSOL_RES_PD); + int eldv = !!(res & AC_UNSOL_RES_ELDV); + int index; + + printk(KERN_INFO + "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", + tag, pind, eldv); + + index = hda_node_index(spec->pin, tag); + if (index < 0) + return; + + spec->sink_eld[index].monitor_present = pind; + spec->sink_eld[index].eld_valid = eldv; + + if (pind && eldv) { + hdmi_get_show_eld(codec, spec->pin[index], + &spec->sink_eld[index]); + /* TODO: do real things about ELD */ + } +} + +static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); + int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); + + printk(KERN_INFO + "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", + tag, + subtag, + cp_state, + cp_ready); + + /* TODO */ + if (cp_state) + ; + if (cp_ready) + ; +} + + +static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) +{ + struct hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + + if (hda_node_index(spec->pin, tag) < 0) { + snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); + return; + } + + if (subtag == 0) + hdmi_intrinsic_event(codec, res); + else + hdmi_non_intrinsic_event(codec, res); +} + +/* + * Callbacks + */ + +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, int format) +{ + int tag; + int fmt; + + tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; + fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); + + snd_printdd("hdmi_setup_stream: " + "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", + nid, + tag == stream_tag ? "" : "new-", + stream_tag, + fmt == format ? "" : "new-", + format); + + if (tag != stream_tag) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + stream_tag << 4); + if (fmt != format) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, format); +} + +/* + * HDA/HDMI auto parsing + */ + +static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec = codec->spec; + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; + int conn_len, curr; + int index; + + if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { + snd_printk(KERN_WARNING + "HDMI: pin %d wcaps %#x " + "does not support connection list\n", + pin_nid, get_wcaps(codec, pin_nid)); + return -EINVAL; + } + + conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, + HDA_MAX_CONNECTIONS); + if (conn_len > 1) + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + else + curr = 0; + + index = hda_node_index(spec->pin, pin_nid); + if (index < 0) + return -EINVAL; + + spec->pin_cvt[index] = conn_list[curr]; + + return 0; +} + +static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + int present = snd_hda_pin_sense(codec, pin_nid); + + eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); + eld->eld_valid = !!(present & AC_PINSENSE_ELDV); + + if (present & AC_PINSENSE_ELDV) + hdmi_get_show_eld(codec, pin_nid, eld); +} + +static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec->num_pins >= MAX_HDMI_PINS) { + snd_printk(KERN_WARNING + "HDMI: no space for pin %d\n", pin_nid); + return -EINVAL; + } + + hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); + + spec->pin[spec->num_pins] = pin_nid; + spec->num_pins++; + + /* + * It is assumed that converter nodes come first in the node list and + * hence have been registered and usable now. + */ + return hdmi_read_pin_conn(codec, pin_nid); +} + +static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec->num_cvts >= MAX_HDMI_CVTS) { + snd_printk(KERN_WARNING + "HDMI: no space for converter %d\n", nid); + return -EINVAL; + } + + spec->cvt[spec->num_cvts] = nid; + spec->num_cvts++; + + return 0; +} + +static int hdmi_parse_codec(struct hda_codec *codec) +{ + hda_nid_t nid; + int i, nodes; + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (!nid || nodes < 0) { + snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); + return -EINVAL; + } + + for (i = 0; i < nodes; i++, nid++) { + unsigned int caps; + unsigned int type; + + caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + + switch (type) { + case AC_WID_AUD_OUT: + if (hdmi_add_cvt(codec, nid) < 0) + return -EINVAL; + break; + case AC_WID_PIN: + caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) + continue; + if (hdmi_add_pin(codec, nid) < 0) + return -EINVAL; + break; + } + } + + /* + * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event + * can be lost and presence sense verb will become inaccurate if the + * HDA link is powered off at hot plug or hw initialization time. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & + AC_PWRST_EPSS)) + codec->bus->power_keep_link_on = 1; +#endif + + return 0; +} + diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 918f40378d52..88d035104cc5 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -40,815 +40,20 @@ * * The HDA correspondence of pipes/ports are converter/pin nodes. */ -#define INTEL_HDMI_CVTS 2 -#define INTEL_HDMI_PINS 3 +#define MAX_HDMI_CVTS 2 +#define MAX_HDMI_PINS 3 -static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = { +#include "patch_hdmi.c" + +static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { "INTEL HDMI 0", "INTEL HDMI 1", }; -struct intel_hdmi_spec { - int num_cvts; - int num_pins; - hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */ - hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */ - - /* - * source connection for each pin - */ - hda_nid_t pin_cvt[INTEL_HDMI_PINS+1]; - - /* - * HDMI sink attached to each pin - */ - struct hdmi_eld sink_eld[INTEL_HDMI_PINS]; - - /* - * export one pcm per pipe - */ - struct hda_pcm pcm_rec[INTEL_HDMI_CVTS]; -}; - -struct hdmi_audio_infoframe { - u8 type; /* 0x84 */ - u8 ver; /* 0x01 */ - u8 len; /* 0x0a */ - - u8 checksum; /* PB0 */ - u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; - u8 reserved[5]; /* PB6 - PB10 */ -}; - -/* - * CEA speaker placement: - * - * FLH FCH FRH - * FLW FL FLC FC FRC FR FRW - * - * LFE - * TC - * - * RL RLC RC RRC RR - * - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. - */ -enum cea_speaker_placement { - FL = (1 << 0), /* Front Left */ - FC = (1 << 1), /* Front Center */ - FR = (1 << 2), /* Front Right */ - FLC = (1 << 3), /* Front Left Center */ - FRC = (1 << 4), /* Front Right Center */ - RL = (1 << 5), /* Rear Left */ - RC = (1 << 6), /* Rear Center */ - RR = (1 << 7), /* Rear Right */ - RLC = (1 << 8), /* Rear Left Center */ - RRC = (1 << 9), /* Rear Right Center */ - LFE = (1 << 10), /* Low Frequency Effect */ - FLW = (1 << 11), /* Front Left Wide */ - FRW = (1 << 12), /* Front Right Wide */ - FLH = (1 << 13), /* Front Left High */ - FCH = (1 << 14), /* Front Center High */ - FRH = (1 << 15), /* Front Right High */ - TC = (1 << 16), /* Top Center */ -}; - -/* - * ELD SA bits in the CEA Speaker Allocation data block - */ -static int eld_speaker_allocation_bits[] = { - [0] = FL | FR, - [1] = LFE, - [2] = FC, - [3] = RL | RR, - [4] = RC, - [5] = FLC | FRC, - [6] = RLC | RRC, - /* the following are not defined in ELD yet */ - [7] = FLW | FRW, - [8] = FLH | FRH, - [9] = TC, - [10] = FCH, -}; - -struct cea_channel_speaker_allocation { - int ca_index; - int speakers[8]; - - /* derived values, just for convenience */ - int channels; - int spk_mask; -}; - -/* - * ALSA sequence is: - * - * surround40 surround41 surround50 surround51 surround71 - * ch0 front left = = = = - * ch1 front right = = = = - * ch2 rear left = = = = - * ch3 rear right = = = = - * ch4 LFE center center center - * ch5 LFE LFE - * ch6 side left - * ch7 side right - * - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} - */ -static int hdmi_channel_mapping[0x32][8] = { - /* stereo */ - [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* 2.1 */ - [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* Dolby Surround */ - [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* surround40 */ - [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, - /* 4ch */ - [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, - /* surround41 */ - [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround50 */ - [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround51 */ - [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, - /* 7.1 */ - [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, -}; - -/* - * This is an ordered list! - * - * The preceding ones have better chances to be selected by - * hdmi_setup_channel_allocation(). - */ -static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 7 6 5 4 3 2 1 0 */ -{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, - /* 2.1 */ -{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, - /* Dolby Surround */ -{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, - /* surround40 */ -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, - /* surround41 */ -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, - /* surround50 */ -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* surround51 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, - /* surround71 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, - -{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, -{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, -{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, -{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -}; - -/* - * HDA/HDMI auto parsing - */ - -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) -{ - int i; - - for (i = 0; nids[i]; i++) - if (nids[i] == nid) - return i; - - snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); - return -EINVAL; -} - -static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; - int conn_len, curr; - int index; - - if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", - pin_nid, get_wcaps(codec, pin_nid)); - return -EINVAL; - } - - conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, - HDA_MAX_CONNECTIONS); - if (conn_len > 1) - curr = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); - else - curr = 0; - - index = hda_node_index(spec->pin, pin_nid); - if (index < 0) - return -EINVAL; - - spec->pin_cvt[index] = conn_list[curr]; - - return 0; -} - -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); -} - -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - int present = snd_hda_pin_sense(codec, pin_nid); - - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - - if (present & AC_PINSENSE_ELDV) - hdmi_get_show_eld(codec, pin_nid, eld); -} - -static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - - if (spec->num_pins >= INTEL_HDMI_PINS) { - snd_printk(KERN_WARNING - "HDMI: no space for pin %d \n", pin_nid); - return -EINVAL; - } - - hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); - - spec->pin[spec->num_pins] = pin_nid; - spec->num_pins++; - - /* - * It is assumed that converter nodes come first in the node list and - * hence have been registered and usable now. - */ - return intel_hdmi_read_pin_conn(codec, pin_nid); -} - -static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - - if (spec->num_cvts >= INTEL_HDMI_CVTS) { - snd_printk(KERN_WARNING - "HDMI: no space for converter %d \n", nid); - return -EINVAL; - } - - spec->cvt[spec->num_cvts] = nid; - spec->num_cvts++; - - return 0; -} - -static int intel_hdmi_parse_codec(struct hda_codec *codec) -{ - hda_nid_t nid; - int i, nodes; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); - return -EINVAL; - } - - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; - - caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); - type = get_wcaps_type(caps); - - if (!(caps & AC_WCAP_DIGITAL)) - continue; - - switch (type) { - case AC_WID_AUD_OUT: - if (intel_hdmi_add_cvt(codec, nid) < 0) - return -EINVAL; - break; - case AC_WID_PIN: - caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) - continue; - if (intel_hdmi_add_pin(codec, nid) < 0) - return -EINVAL; - break; - } - } - - /* - * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event - * can be lost and presence sense verb will become inaccurate if the - * HDA link is powered off at hot plug or hw initialization time. - */ -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & - AC_PWRST_EPSS)) - codec->bus->power_keep_link_on = 1; -#endif - - return 0; -} - -/* - * HDMI routines - */ - -#ifdef BE_PARANOID -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int *packet_index, int *byte_index) -{ - int val; - - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_INDEX, 0); - - *packet_index = val >> 5; - *byte_index = val & 0x1f; -} -#endif - -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int packet_index, int byte_index) -{ - int val; - - val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); -} - -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char val) -{ - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); -} - -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) -{ - /* Unmute */ - if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* Enable pin out */ - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); -} - -/* - * Enable Audio InfoFrame Transmission - */ -static void hdmi_start_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_BEST); -} - -/* - * Disable Audio InfoFrame Transmission - */ -static void hdmi_stop_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_DISABLE); -} - -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) -{ - return 1 + snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CVT_CHAN_COUNT, 0); -} - -static void hdmi_set_channel_count(struct hda_codec *codec, - hda_nid_t nid, int chs) -{ - if (chs != hdmi_get_channel_count(codec, nid)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); -} - -static void hdmi_debug_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int slot; - - for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_CHAN_SLOT, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", - slot >> 4, slot & 0xf); - } -#endif -} - - -/* - * Audio InfoFrame routines - */ - -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int size; - - size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); - - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); - } -#endif -} - -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef BE_PARANOID - int i, j; - int size; - int pi, bi; - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - if (size == 0) - continue; - - hdmi_set_dip_index(codec, pin_nid, i, 0x0); - for (j = 1; j < 1000; j++) { - hdmi_write_dip_byte(codec, pin_nid, 0x0); - hdmi_get_dip_index(codec, pin_nid, &pi, &bi); - if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", - bi, pi, i); - if (bi == 0) /* byte index wrapped around */ - break; - } - snd_printd(KERN_INFO - "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", - i, size, j); - } -#endif -} - -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 sum = 0; - int i; - - ai->checksum = 0; - - for (i = 0; i < sizeof(*ai); i++) - sum += bytes[i]; - - ai->checksum = - sum; -} - -static void hdmi_fill_audio_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - int i; - - hdmi_debug_dip_size(codec, pin_nid); - hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ - - hdmi_checksum_audio_infoframe(ai); - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) - hdmi_write_dip_byte(codec, pin_nid, bytes[i]); -} - -/* - * Compute derived values in channel_allocations[]. - */ -static void init_channel_allocations(void) -{ - int i, j; - struct cea_channel_speaker_allocation *p; - - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - p = channel_allocations + i; - p->channels = 0; - p->spk_mask = 0; - for (j = 0; j < ARRAY_SIZE(p->speakers); j++) - if (p->speakers[j]) { - p->channels++; - p->spk_mask |= p->speakers[j]; - } - } -} - -/* - * The transformation takes two steps: - * - * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask - * spk_mask => (channel_allocations[]) => ai->CA - * - * TODO: it could select the wrong CA from multiple candidates. -*/ -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, - struct hdmi_audio_infoframe *ai) -{ - struct intel_hdmi_spec *spec = codec->spec; - struct hdmi_eld *eld; - int i; - int spk_mask = 0; - int channels = 1 + (ai->CC02_CT47 & 0x7); - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - - /* - * CA defaults to 0 for basic stereo audio - */ - if (channels <= 2) - return 0; - - i = hda_node_index(spec->pin_cvt, nid); - if (i < 0) - return 0; - eld = &spec->sink_eld[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 (!eld->spk_alloc) - eld->spk_alloc = 0xffff; - - /* - * expand ELD's speaker allocation mask - * - * ELD tells the speaker mask in a compact(paired) form, - * expand ELD's notions to match the ones used by Audio InfoFrame. - */ - for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { - if (eld->spk_alloc & (1 << i)) - spk_mask |= eld_speaker_allocation_bits[i]; - } - - /* search for the first working match in the CA table */ - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - if (channels == channel_allocations[i].channels && - (spk_mask & channel_allocations[i].spk_mask) == - channel_allocations[i].spk_mask) { - ai->CA = channel_allocations[i].ca_index; - break; - } - } - - snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd(KERN_INFO - "HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ai->CA, channels, buf); - - return ai->CA; -} - -static void hdmi_setup_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - int i; - int ca = ai->CA; - int err; - - if (hdmi_channel_mapping[ca][1] == 0) { - for (i = 0; i < channel_allocations[ca].channels; i++) - hdmi_channel_mapping[ca][i] = i | (i << 4); - for (; i < 8; i++) - hdmi_channel_mapping[ca][i] = 0xf | (i << 4); - } - - for (i = 0; i < 8; i++) { - err = snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - hdmi_channel_mapping[ca][i]); - if (err) { - snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); - break; - } - } - - hdmi_debug_channel_mapping(codec, pin_nid); -} - -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 val; - int i; - - if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) - != AC_DIPXMIT_BEST) - return false; - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) { - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_DATA, 0); - if (val != bytes[i]) - return false; - } - - return true; -} - -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, - struct snd_pcm_substream *substream) -{ - struct intel_hdmi_spec *spec = codec->spec; - hda_nid_t pin_nid; - int i; - struct hdmi_audio_infoframe ai = { - .type = 0x84, - .ver = 0x01, - .len = 0x0a, - .CC02_CT47 = substream->runtime->channels - 1, - }; - - hdmi_setup_channel_allocation(codec, nid, &ai); - - for (i = 0; i < spec->num_pins; i++) { - if (spec->pin_cvt[i] != nid) - continue; - if (!spec->sink_eld[i].monitor_present) - continue; - - pin_nid = spec->pin[i]; - if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { - hdmi_setup_channel_mapping(codec, pin_nid, &ai); - hdmi_stop_infoframe_trans(codec, pin_nid); - hdmi_fill_audio_infoframe(codec, pin_nid, &ai); - hdmi_start_infoframe_trans(codec, pin_nid); - } - } -} - - /* - * Unsolicited events + * HDMI callbacks */ -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - struct intel_hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int pind = !!(res & AC_UNSOL_RES_PD); - int eldv = !!(res & AC_UNSOL_RES_ELDV); - int index; - - printk(KERN_INFO - "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - tag, pind, eldv); - - index = hda_node_index(spec->pin, tag); - if (index < 0) - return; - - spec->sink_eld[index].monitor_present = pind; - spec->sink_eld[index].eld_valid = eldv; - - if (pind && eldv) { - hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]); - /* TODO: do real things about ELD */ - } -} - -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); - int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - - printk(KERN_INFO - "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", - tag, - subtag, - cp_state, - cp_ready); - - /* TODO */ - if (cp_state) - ; - if (cp_ready) - ; -} - - -static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct intel_hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - - if (hda_node_index(spec->pin, tag) < 0) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); - return; - } - - if (subtag == 0) - hdmi_intrinsic_event(codec, res); - else - hdmi_non_intrinsic_event(codec, res); -} - -/* - * Callbacks - */ - -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, int format) -{ - int tag; - int fmt; - - tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; - fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", - nid, - tag == stream_tag ? "" : "new-", - stream_tag, - fmt == format ? "" : "new-", - format); - - if (tag != stream_tag) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4); - if (fmt != format) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, format); -} - static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -882,7 +87,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = { static int intel_hdmi_build_pcms(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; int i; @@ -908,7 +113,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec) static int intel_hdmi_build_controls(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int err; int i; @@ -923,7 +128,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) static int intel_hdmi_init(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; for (i = 0; spec->pin[i]; i++) { @@ -937,7 +142,7 @@ static int intel_hdmi_init(struct hda_codec *codec) static void intel_hdmi_free(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; for (i = 0; i < spec->num_pins; i++) @@ -951,12 +156,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = { .free = intel_hdmi_free, .build_pcms = intel_hdmi_build_pcms, .build_controls = intel_hdmi_build_controls, - .unsol_event = intel_hdmi_unsol_event, + .unsol_event = hdmi_unsol_event, }; static int patch_intel_hdmi(struct hda_codec *codec) { - struct intel_hdmi_spec *spec; + struct hdmi_spec *spec; int i; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -964,7 +169,7 @@ static int patch_intel_hdmi(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - if (intel_hdmi_parse_codec(codec) < 0) { + if (hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 1c774f942407..70669a246902 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -29,6 +29,15 @@ #include "hda_codec.h" #include "hda_local.h" +#define MAX_HDMI_CVTS 1 +#define MAX_HDMI_PINS 1 + +#include "patch_hdmi.c" + +static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { + "NVIDIA HDMI", +}; + /* define below to restrict the supported rates and formats */ /* #define LIMITED_RATE_FMT_SUPPORT */ @@ -83,802 +92,12 @@ static struct hda_verb nvhdmi_basic_init_7x[] = { (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) #endif -#define NVIDIA_89_HDMI_CVTS 1 -#define NVIDIA_89_HDMI_PINS 1 - -static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = { - "NVIDIA HDMI", -}; - -struct nvhdmi_spec { - int num_cvts; - int num_pins; - hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1]; /* audio sources */ - hda_nid_t pin[NVIDIA_89_HDMI_PINS+1]; /* audio sinks */ - hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1]; - struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS]; - struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS]; - struct hda_multi_out multiout; - unsigned int codec_type; -}; - -struct hdmi_audio_infoframe { - u8 type; /* 0x84 */ - u8 ver; /* 0x01 */ - u8 len; /* 0x0a */ - - u8 checksum; /* PB0 */ - u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; -}; - -/* - * CEA speaker placement: - * - * FLH FCH FRH - * FLW FL FLC FC FRC FR FRW - * - * LFE - * TC - * - * RL RLC RC RRC RR - * - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. - */ -enum cea_speaker_placement { - FL = (1 << 0), /* Front Left */ - FC = (1 << 1), /* Front Center */ - FR = (1 << 2), /* Front Right */ - FLC = (1 << 3), /* Front Left Center */ - FRC = (1 << 4), /* Front Right Center */ - RL = (1 << 5), /* Rear Left */ - RC = (1 << 6), /* Rear Center */ - RR = (1 << 7), /* Rear Right */ - RLC = (1 << 8), /* Rear Left Center */ - RRC = (1 << 9), /* Rear Right Center */ - LFE = (1 << 10), /* Low Frequency Effect */ - FLW = (1 << 11), /* Front Left Wide */ - FRW = (1 << 12), /* Front Right Wide */ - FLH = (1 << 13), /* Front Left High */ - FCH = (1 << 14), /* Front Center High */ - FRH = (1 << 15), /* Front Right High */ - TC = (1 << 16), /* Top Center */ -}; - -/* - * ELD SA bits in the CEA Speaker Allocation data block - */ -static int eld_speaker_allocation_bits[] = { - [0] = FL | FR, - [1] = LFE, - [2] = FC, - [3] = RL | RR, - [4] = RC, - [5] = FLC | FRC, - [6] = RLC | RRC, - /* the following are not defined in ELD yet */ - [7] = FLW | FRW, - [8] = FLH | FRH, - [9] = TC, - [10] = FCH, -}; - -struct cea_channel_speaker_allocation { - int ca_index; - int speakers[8]; - - /* derived values, just for convenience */ - int channels; - int spk_mask; -}; - -/* - * ALSA sequence is: - * - * surround40 surround41 surround50 surround51 surround71 - * ch0 front left = = = = - * ch1 front right = = = = - * ch2 rear left = = = = - * ch3 rear right = = = = - * ch4 LFE center center center - * ch5 LFE LFE - * ch6 side left - * ch7 side right - * - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} - */ -static int hdmi_channel_mapping[0x32][8] = { - /* stereo */ - [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* 2.1 */ - [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* Dolby Surround */ - [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* surround40 */ - [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, - /* 4ch */ - [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, - /* surround41 */ - [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround50 */ - [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround51 */ - [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, - /* 7.1 */ - [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 }, -}; - -/* - * This is an ordered list! - * - * The preceding ones have better chances to be selected by - * hdmi_setup_channel_allocation(). - */ -static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 7 6 5 4 3 2 1 0 */ -{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, - /* 2.1 */ -{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, - /* Dolby Surround */ -{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, - /* surround40 */ -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, - /* surround41 */ -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, - /* surround50 */ -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* surround51 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, - /* surround71 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, - -{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, -{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, -{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, -{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -}; - -/* - * HDA/HDMI auto parsing - */ - -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) -{ - int i; - - for (i = 0; nids[i]; i++) - if (nids[i] == nid) - return i; - - snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); - return -EINVAL; -} - -static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct nvhdmi_spec *spec = codec->spec; - hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; - int conn_len, curr; - int index; - - if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", - pin_nid, get_wcaps(codec, pin_nid)); - return -EINVAL; - } - - conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, - HDA_MAX_CONNECTIONS); - if (conn_len > 1) - curr = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); - else - curr = 0; - - index = hda_node_index(spec->pin, pin_nid); - if (index < 0) - return -EINVAL; - - spec->pin_cvt[index] = conn_list[curr]; - - return 0; -} - -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); -} - -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - int present = snd_hda_pin_sense(codec, pin_nid); - - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - - if (present & AC_PINSENSE_ELDV) - hdmi_get_show_eld(codec, pin_nid, eld); -} - -static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct nvhdmi_spec *spec = codec->spec; - - if (spec->num_pins >= NVIDIA_89_HDMI_PINS) { - snd_printk(KERN_WARNING - "HDMI: no space for pin %d \n", pin_nid); - return -EINVAL; - } - - hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); - - spec->pin[spec->num_pins] = pin_nid; - spec->num_pins++; - - /* - * It is assumed that converter nodes come first in the node list and - * hence have been registered and usable now. - */ - return nvhdmi_read_pin_conn(codec, pin_nid); -} - -static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) -{ - struct nvhdmi_spec *spec = codec->spec; - - if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) { - snd_printk(KERN_WARNING - "HDMI: no space for converter %d \n", nid); - return -EINVAL; - } - - spec->cvt[spec->num_cvts] = nid; - spec->num_cvts++; - - return 0; -} - - -static int nvhdmi_parse_codec(struct hda_codec *codec) -{ - hda_nid_t nid; - int i, nodes; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); - return -EINVAL; - } - - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; - - caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); - type = get_wcaps_type(caps); - - if (!(caps & AC_WCAP_DIGITAL)) - continue; - - switch (type) { - case AC_WID_AUD_OUT: - if (nvhdmi_add_cvt(codec, nid) < 0) - return -EINVAL; - break; - case AC_WID_PIN: - caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) - continue; - if (nvhdmi_add_pin(codec, nid) < 0) - return -EINVAL; - break; - } - } - - /* - * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event - * can be lost and presence sense verb will become inaccurate if the - * HDA link is powered off at hot plug or hw initialization time. - */ -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & - AC_PWRST_EPSS)) - codec->bus->power_keep_link_on = 1; -#endif - - return 0; -} - -/* - * HDMI routines - */ - -#ifdef BE_PARANOID -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int *packet_index, int *byte_index) -{ - int val; - - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_INDEX, 0); - - *packet_index = val >> 5; - *byte_index = val & 0x1f; -} -#endif - -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int packet_index, int byte_index) -{ - int val; - - val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); -} - -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char val) -{ - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); -} - -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) -{ - /* Unmute */ - if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* Enable pin out */ - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); -} - -/* - * Enable Audio InfoFrame Transmission - */ -static void hdmi_start_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_BEST); -} - -/* - * Disable Audio InfoFrame Transmission - */ -static void hdmi_stop_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_DISABLE); -} - -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) -{ - return 1 + snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CVT_CHAN_COUNT, 0); -} - -static void hdmi_set_channel_count(struct hda_codec *codec, - hda_nid_t nid, int chs) -{ - if (chs != hdmi_get_channel_count(codec, nid)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); -} - -static void hdmi_debug_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int slot; - - for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_CHAN_SLOT, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", - slot >> 4, slot & 0xf); - } -#endif -} - - -/* - * Audio InfoFrame routines - */ - -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int size; - - size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); - - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); - } -#endif -} - -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef BE_PARANOID - int i, j; - int size; - int pi, bi; - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - if (size == 0) - continue; - - hdmi_set_dip_index(codec, pin_nid, i, 0x0); - for (j = 1; j < 1000; j++) { - hdmi_write_dip_byte(codec, pin_nid, 0x0); - hdmi_get_dip_index(codec, pin_nid, &pi, &bi); - if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", - bi, pi, i); - if (bi == 0) /* byte index wrapped around */ - break; - } - snd_printd(KERN_INFO - "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", - i, size, j); - } -#endif -} - -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) -{ - ai->checksum = 0; -} - -static void hdmi_fill_audio_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - int i; - - hdmi_debug_dip_size(codec, pin_nid); - hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ - - hdmi_checksum_audio_infoframe(ai); - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) - hdmi_write_dip_byte(codec, pin_nid, bytes[i]); -} - -/* - * Compute derived values in channel_allocations[]. - */ -static void init_channel_allocations(void) -{ - int i, j; - struct cea_channel_speaker_allocation *p; - - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - p = channel_allocations + i; - p->channels = 0; - p->spk_mask = 0; - for (j = 0; j < ARRAY_SIZE(p->speakers); j++) - if (p->speakers[j]) { - p->channels++; - p->spk_mask |= p->speakers[j]; - } - } -} - -/* - * The transformation takes two steps: - * - * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask - * spk_mask => (channel_allocations[]) => ai->CA - * - * TODO: it could select the wrong CA from multiple candidates. -*/ -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, - struct hdmi_audio_infoframe *ai) -{ - struct nvhdmi_spec *spec = codec->spec; - struct hdmi_eld *eld; - int i; - int spk_mask = 0; - int channels = 1 + (ai->CC02_CT47 & 0x7); - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - - /* - * CA defaults to 0 for basic stereo audio - */ - if (channels <= 2) - return 0; - - i = hda_node_index(spec->pin_cvt, nid); - if (i < 0) - return 0; - eld = &spec->sink_eld[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 (!eld->spk_alloc) - eld->spk_alloc = 0xffff; - - /* - * expand ELD's speaker allocation mask - * - * ELD tells the speaker mask in a compact(paired) form, - * expand ELD's notions to match the ones used by Audio InfoFrame. - */ - for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { - if (eld->spk_alloc & (1 << i)) - spk_mask |= eld_speaker_allocation_bits[i]; - } - - /* search for the first working match in the CA table */ - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - if (channels == channel_allocations[i].channels && - (spk_mask & channel_allocations[i].spk_mask) == - channel_allocations[i].spk_mask) { - ai->CA = channel_allocations[i].ca_index; - break; - } - } - - snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd(KERN_INFO - "HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ai->CA, channels, buf); - - return ai->CA; -} - -static void hdmi_setup_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - int i; - int ca = ai->CA; - int err; - - if (hdmi_channel_mapping[ca][1] == 0) { - for (i = 0; i < channel_allocations[ca].channels; i++) - hdmi_channel_mapping[ca][i] = i | (i << 4); - for (; i < 8; i++) - hdmi_channel_mapping[ca][i] = 0xf | (i << 4); - } - - for (i = 0; i < 8; i++) { - err = snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - hdmi_channel_mapping[ca][i]); - if (err) { - snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); - break; - } - } - - hdmi_debug_channel_mapping(codec, pin_nid); -} - -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 val; - int i; - - if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) - != AC_DIPXMIT_BEST) - return false; - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) { - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_DATA, 0); - if (val != bytes[i]) - return false; - } - - return true; -} - -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, - struct snd_pcm_substream *substream) -{ - struct nvhdmi_spec *spec = codec->spec; - hda_nid_t pin_nid; - int i; - struct hdmi_audio_infoframe ai = { - .type = 0x84, - .ver = 0x01, - .len = 0x0a, - .CC02_CT47 = substream->runtime->channels - 1, - }; - - hdmi_setup_channel_allocation(codec, nid, &ai); - - for (i = 0; i < spec->num_pins; i++) { - if (spec->pin_cvt[i] != nid) - continue; - if (!spec->sink_eld[i].monitor_present) - continue; - - pin_nid = spec->pin[i]; - if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { - hdmi_setup_channel_mapping(codec, pin_nid, &ai); - hdmi_stop_infoframe_trans(codec, pin_nid); - hdmi_fill_audio_infoframe(codec, pin_nid, &ai); - hdmi_start_infoframe_trans(codec, pin_nid); - } - } -} - -/* - * Unsolicited events - */ - -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - struct nvhdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int pind = !!(res & AC_UNSOL_RES_PD); - int eldv = !!(res & AC_UNSOL_RES_ELDV); - int index; - - printk(KERN_INFO - "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - tag, pind, eldv); - - index = hda_node_index(spec->pin, tag); - if (index < 0) - return; - - spec->sink_eld[index].monitor_present = pind; - spec->sink_eld[index].eld_valid = eldv; - - if (eldv) { - spec->sink_eld[index].monitor_present = 1; - hdmi_get_show_eld(codec, spec->pin[index], - &spec->sink_eld[index]); - /* TODO: do real things about ELD */ - } -} - -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); - int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - - printk(KERN_INFO - "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", - tag, - subtag, - cp_state, - cp_ready); - - /* TODO */ - if (cp_state) - ; - if (cp_ready) - ; -} - -static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct nvhdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - - if (hda_node_index(spec->pin, tag) < 0) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); - return; - } - - if (subtag == 0) - hdmi_intrinsic_event(codec, res); - else - hdmi_non_intrinsic_event(codec, res); -} - -/* - * Callbacks - */ - -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, int format) -{ - int tag; - int fmt; - - tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; - fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", - nid, - tag == stream_tag ? "" : "new-", - stream_tag, - fmt == format ? "" : "new-", - format); - - if (tag != stream_tag) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - stream_tag << 4); - if (fmt != format) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, format); -} - /* * Controls */ static int nvhdmi_build_controls(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int err; int i; @@ -902,7 +121,7 @@ static int nvhdmi_build_controls(struct hda_codec *codec) static int nvhdmi_init(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { @@ -920,7 +139,7 @@ static int nvhdmi_init(struct hda_codec *codec) static void nvhdmi_free(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) @@ -939,7 +158,7 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_open(codec, &spec->multiout); } @@ -947,7 +166,7 @@ static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, @@ -968,7 +187,7 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_close(codec, &spec->multiout); } @@ -1121,7 +340,7 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, unsigned int format, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, format, substream); } @@ -1170,7 +389,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; int i; @@ -1196,7 +415,7 @@ static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; @@ -1212,7 +431,7 @@ static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; @@ -1231,7 +450,7 @@ static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { .build_pcms = nvhdmi_build_pcms_8ch_89, .init = nvhdmi_init, .free = nvhdmi_free, - .unsol_event = nvhdmi_unsol_event, + .unsol_event = hdmi_unsol_event, }; static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { @@ -1250,7 +469,7 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { static int patch_nvhdmi_8ch_89(struct hda_codec *codec) { - struct nvhdmi_spec *spec; + struct hdmi_spec *spec; int i; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -1260,7 +479,7 @@ static int patch_nvhdmi_8ch_89(struct hda_codec *codec) codec->spec = spec; spec->codec_type = HDA_CODEC_NVIDIA_MCP89; - if (nvhdmi_parse_codec(codec) < 0) { + if (hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; @@ -1277,7 +496,7 @@ static int patch_nvhdmi_8ch_89(struct hda_codec *codec) static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) { - struct nvhdmi_spec *spec; + struct hdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -1297,7 +516,7 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) static int patch_nvhdmi_2ch(struct hda_codec *codec) { - struct nvhdmi_spec *spec; + struct hdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) From 2abbf4391fb56dfa97221ed6796782537d15196f Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Mon, 8 Mar 2010 10:45:38 +0800 Subject: [PATCH 097/114] ALSA: hdmi - show debug message on changing audio infoframe Also change printk level for the two others. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index b2ab39670dda..2c2bafbf0258 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -398,9 +398,8 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, } snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd(KERN_INFO - "HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ai->CA, channels, buf); + snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", + ai->CA, channels, buf); return ai->CA; } @@ -442,7 +441,8 @@ static void hdmi_setup_channel_mapping(struct hda_codec *codec, AC_VERB_SET_HDMI_CHAN_SLOT, hdmi_channel_mapping[ca][i]); if (err) { - snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + snd_printdd(KERN_NOTICE + "HDMI: channel mapping failed\n"); break; } } @@ -599,6 +599,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, pin_nid = spec->pin[i]; if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + snd_printdd("hdmi_setup_audio_infoframe: " + "cvt=%d pin=%d channels=%d\n", + nid, pin_nid, + substream->runtime->channels); hdmi_setup_channel_mapping(codec, pin_nid, &ai); hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_fill_audio_infoframe(codec, pin_nid, &ai); From 39f3be72c1a1b20d7e6e35717afa2ddb89259650 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 8 Mar 2010 11:02:38 +0000 Subject: [PATCH 098/114] [WATCHDOG] i6300esb: fix unlock register with Before you can read or write from the i6300esb memeory mapped registers, you need to unlock these. This is done by writing the magic numbers 0x80 and 0x86 to the reload register. The size of the reload register is 32bit though. Also binary 11 is hex 0x03 and not 0x11. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/i6300esb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 2fbe7fea7ee6..3e00dc5b5a20 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -65,7 +65,7 @@ /* Config register bits */ #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ #define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ -#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ +#define ESB_WDT_INTTYPE (0x03 << 0) /* Interrupt type on timer1 timeout */ /* Reload register bits */ #define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ @@ -111,8 +111,8 @@ MODULE_PARM_DESC(nowayout, */ static inline void esb_unlock_registers(void) { - writeb(ESB_UNLOCK1, ESB_RELOAD_REG); - writeb(ESB_UNLOCK2, ESB_RELOAD_REG); + writew(ESB_UNLOCK1, ESB_RELOAD_REG); + writew(ESB_UNLOCK2, ESB_RELOAD_REG); } static int esb_timer_start(void) From 596a95cdf0ba35ea353fb5b65750f596d712041e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 8 Mar 2010 12:25:14 +0100 Subject: [PATCH 099/114] [S390] uaccess: make sure copy_from_user_overflow is builtin If there is no in kernel image caller modules will suffer: ERROR: "copy_from_user_overflow" [net/core/pktgen.ko] undefined! ERROR: "copy_from_user_overflow" [net/can/can-raw.ko] undefined! ERROR: "copy_from_user_overflow" [fs/cifs/cifs.ko] undefined! Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/lib/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index cd54a1c352af..761ab8b56afc 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -2,7 +2,8 @@ # Makefile for s390-specific library files.. # -lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o +lib-y += delay.o string.o uaccess_std.o uaccess_pt.o +obj-y += usercopy.o obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o From 91a970d9889c7d6f451ee91ed361d0f0119d3778 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 8 Mar 2010 12:25:15 +0100 Subject: [PATCH 100/114] [S390] hvc_iucv: allocate memory buffers for IUCV in zone DMA The device driver must allocate memory for IUCV buffers with GFP_DMA, because IUCV cannot address memory above 2GB (31bit addresses only). Because the IUCV ignores the higher bits of the address, sending and receiving IUCV data with this driver might cause memory corruptions. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- drivers/char/hvc_iucv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 21681a81cc35..37b0542a4eeb 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -139,6 +139,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) * * This function allocates a new struct iucv_tty_buffer element and, optionally, * allocates an internal data buffer with the specified size @size. + * The internal data buffer is always allocated with GFP_DMA which is + * required for receiving and sending data with IUCV. * Note: The total message size arises from the internal buffer size and the * members of the iucv_tty_msg structure. * The function returns NULL if memory allocation has failed. @@ -154,7 +156,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) if (size > 0) { bufp->msg.length = MSG_SIZE(size); - bufp->mbuf = kmalloc(bufp->msg.length, flags); + bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); if (!bufp->mbuf) { mempool_free(bufp, hvc_iucv_mempool); return NULL; @@ -237,7 +239,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, if (!rb->mbuf) { /* message not yet received ... */ /* allocate mem to store msg data; if no memory is available * then leave the buffer on the list and re-try later */ - rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC); + rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); if (!rb->mbuf) return -ENOMEM; From 52898025cf7d458d029c18773d0ef49b4789d829 Mon Sep 17 00:00:00 2001 From: Nigel Hislop Date: Mon, 8 Mar 2010 12:25:16 +0100 Subject: [PATCH 101/114] [S390] dasd: security and PSF update patch for EMC CKD ioctl Remove the PSF order/suborder check from the Symmetrix CKD dasd ioctl. In exchange restrict the ioctl to CAP_SYS_ADMIN and CAP_SYS_RAWIO. Signed-off-by: Nigel Hislop Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1cca21aafaba..d7163f904f40 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2839,8 +2839,13 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) char *psf_data, *rssd_result; struct dasd_ccw_req *cqr; struct ccw1 *ccw; + char psf0, psf1; int rc; + if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) + return -EACCES; + psf0 = psf1 = 0; + /* Copy parms from caller */ rc = -EFAULT; if (copy_from_user(&usrparm, argp, sizeof(usrparm))) @@ -2869,12 +2874,8 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) (void __user *)(unsigned long) usrparm.psf_data, usrparm.psf_data_len)) goto out_free; - - /* sanity check on syscall header */ - if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { - rc = -EINVAL; - goto out_free; - } + psf0 = psf_data[0]; + psf1 = psf_data[1]; /* setup CCWs for PSF + RSSD */ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device); @@ -2925,7 +2926,9 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) kfree(rssd_result); kfree(psf_data); out: - DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); + DBF_DEV_EVENT(DBF_WARNING, device, + "Symmetrix ioctl (0x%02x 0x%02x): rc=%d", + (int) psf0, (int) psf1, rc); return rc; } From a290156f479af436f94ac23f5729a1e33c94293b Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 8 Mar 2010 12:25:17 +0100 Subject: [PATCH 102/114] [S390] cio: fix init_count in case of recognition after steal lock After we try to steal a lock on a ccw device in boxed state, we have to restart device recognition and potentially reprobing. In this case ccw_device_init_count was erroneously decreased twice. This patch fixes the issue. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index c6abb75c4615..6d229f3523a0 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -764,7 +764,7 @@ static void sch_create_and_recog_new_device(struct subchannel *sch) static void io_subchannel_register(struct ccw_device *cdev) { struct subchannel *sch; - int ret; + int ret, adjust_init_count = 1; unsigned long flags; sch = to_subchannel(cdev->dev.parent); @@ -793,6 +793,7 @@ static void io_subchannel_register(struct ccw_device *cdev) cdev->private->dev_id.ssid, cdev->private->dev_id.devno); } + adjust_init_count = 0; goto out; } /* @@ -818,7 +819,7 @@ static void io_subchannel_register(struct ccw_device *cdev) cdev->private->flags.recog_done = 1; wake_up(&cdev->private->wait_q); out_err: - if (atomic_dec_and_test(&ccw_device_init_count)) + if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count)) wake_up(&ccw_device_init_wq); } From bd6e8a162ecdec4f1d8895b0f330f75425993567 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 8 Mar 2010 12:25:18 +0100 Subject: [PATCH 103/114] [S390] qdio: add missing bracket Add a missing bracket to only log the outbound handler event in the appropriate case. Signed-off-by: Ursula Braun Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 232ef047ba34..4f8f74311778 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -588,10 +588,11 @@ static void qdio_kick_handler(struct qdio_q *q) if (q->is_input_q) { qperf_inc(q, inbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); - } else + } else { qperf_inc(q, outbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", start, count); + } q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, q->irq_ptr->int_parm); From b1e2ba8da973535e62839915403b6f5450081d8c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 8 Mar 2010 12:25:19 +0100 Subject: [PATCH 104/114] [S390] Cleanup xtime usage This replaces direct xtime usage in the s390 arch with timekeeping accessors, so we can further clean up the timekeeping core. Cc: Thomas Gleixner Signed-off-by: John Stultz Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/time.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index a8f93f1705ad..8b22e7f316bb 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -73,15 +73,15 @@ unsigned long long monotonic_clock(void) } EXPORT_SYMBOL(monotonic_clock); -void tod_to_timeval(__u64 todval, struct timespec *xtime) +void tod_to_timeval(__u64 todval, struct timespec *xt) { unsigned long long sec; sec = todval >> 12; do_div(sec, 1000000); - xtime->tv_sec = sec; + xt->tv_sec = sec; todval -= (sec * 1000000) << 12; - xtime->tv_nsec = ((todval * 1000) >> 12); + xt->tv_nsec = ((todval * 1000) >> 12); } EXPORT_SYMBOL(tod_to_timeval); @@ -216,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, ++vdso_data->tb_update_count; smp_wmb(); vdso_data->xtime_tod_stamp = clock->cycle_last; - vdso_data->xtime_clock_sec = xtime.tv_sec; - vdso_data->xtime_clock_nsec = xtime.tv_nsec; + vdso_data->xtime_clock_sec = wall_time->tv_sec; + vdso_data->xtime_clock_nsec = wall_time->tv_nsec; vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; smp_wmb(); From 584dfddfce1bd81d877f14de2b56d4bc747af821 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 8 Mar 2010 12:25:20 +0100 Subject: [PATCH 105/114] [S390] remove unused qdio flags in zfcp and qeth zfcp and qeth are setting flags for the qdio-layer, but these flags are not used in qdio. Patch removes the flag definitions from qdio and their settings in zfcp and qeth. Cc: Jan Glauber Cc: Christof Schmitt Signed-off-by: Ursula Braun Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/qdio.h | 7 ------- drivers/s390/cio/qdio_debug.c | 1 - drivers/s390/net/qeth_core_main.c | 3 --- drivers/s390/scsi/zfcp_qdio.c | 2 -- 4 files changed, 13 deletions(-) diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index c666bfe5e984..9b04b1102bbc 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -321,11 +321,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 #define QDIO_ERROR_SLSB_STATE 0x80 -/* for qdio_initialize */ -#define QDIO_INBOUND_0COPY_SBALS 0x01 -#define QDIO_OUTBOUND_0COPY_SBALS 0x02 -#define QDIO_USE_OUTBOUND_PCIS 0x04 - /* for qdio_cleanup */ #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 @@ -344,7 +339,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, * @input_handler: handler to be called for input queues * @output_handler: handler to be called for output queues * @int_parm: interruption parameter - * @flags: initialization flags * @input_sbal_addr_array: address of no_input_qs * 128 pointers * @output_sbal_addr_array: address of no_output_qs * 128 pointers */ @@ -361,7 +355,6 @@ struct qdio_initialize { qdio_handler_t *input_handler; qdio_handler_t *output_handler; unsigned long int_parm; - unsigned long flags; void **input_sbal_addr_array; void **output_sbal_addr_array; }; diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index c94eb2a0fa2e..6ce83f56d537 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -33,7 +33,6 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data, DBF_HEX(&init_data->input_handler, sizeof(void *)); DBF_HEX(&init_data->output_handler, sizeof(void *)); DBF_HEX(&init_data->int_parm, sizeof(long)); - DBF_HEX(&init_data->flags, sizeof(long)); DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index fa8a519218ac..7d25bdd443cd 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3805,9 +3805,6 @@ static int qeth_qdio_establish(struct qeth_card *card) init_data.input_handler = card->discipline.input_handler; init_data.output_handler = card->discipline.output_handler; init_data.int_parm = (unsigned long) card; - init_data.flags = QDIO_INBOUND_0COPY_SBALS | - QDIO_OUTBOUND_0COPY_SBALS | - QDIO_USE_OUTBOUND_PCIS; init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 71b97ff77cf0..6479273a3094 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -319,8 +319,6 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, id->input_handler = zfcp_qdio_int_resp; id->output_handler = zfcp_qdio_int_req; id->int_parm = (unsigned long) qdio; - id->flags = QDIO_INBOUND_0COPY_SBALS | - QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS; id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal); id->output_sbal_addr_array = (void **) (qdio->req_q.sbal); From 33b62a30f78536b976183cc764c08038ac011e0a Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Mon, 8 Mar 2010 12:26:24 +0100 Subject: [PATCH 106/114] [S390] dasd: automatic recognition of read-only devices In z/VM it is possible to attach a device as read-only. To prevent unintentional write requests and subsequent I/O errors, we can detect this configuration using the z/VM DIAG 210 interface and set the respective linux block device to read-only as well. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 36 ++++++++++++++++++++++++++++++ drivers/s390/block/dasd_3990_erp.c | 4 ++++ drivers/s390/block/dasd_devmap.c | 13 ++++++----- drivers/s390/block/dasd_diag.c | 6 ++--- drivers/s390/block/dasd_eckd.c | 10 +++++++-- drivers/s390/block/dasd_fba.c | 10 +++++++-- drivers/s390/block/dasd_genhd.c | 3 ++- drivers/s390/block/dasd_int.h | 7 ++++++ drivers/s390/block/dasd_ioctl.c | 6 +++-- 9 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4951aa82e9f5..bbea90baf98f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -26,6 +26,7 @@ #include #include #include +#include /* This is ugly... */ #define PRINTK_HEADER "dasd:" @@ -2212,6 +2213,13 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) goto out; } + if ((mode & FMODE_WRITE) && + (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) || + (base->features & DASD_FEATURE_READONLY))) { + rc = -EROFS; + goto out; + } + return 0; out: @@ -2289,6 +2297,34 @@ dasd_exit(void) * SECTION: common functions for ccw_driver use */ +/* + * Is the device read-only? + * Note that this function does not report the setting of the + * readonly device attribute, but how it is configured in z/VM. + */ +int dasd_device_is_ro(struct dasd_device *device) +{ + struct ccw_dev_id dev_id; + struct diag210 diag_data; + int rc; + + if (!MACHINE_IS_VM) + return 0; + ccw_device_get_id(device->cdev, &dev_id); + memset(&diag_data, 0, sizeof(diag_data)); + diag_data.vrdcdvno = dev_id.devno; + diag_data.vrdclen = sizeof(diag_data); + rc = diag210(&diag_data); + if (rc == 0 || rc == 2) { + return diag_data.vrdcvfla & 0x80; + } else { + DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d", + dev_id.devno, rc); + return 0; + } +} +EXPORT_SYMBOL_GPL(dasd_device_is_ro); + static void dasd_generic_auto_online(void *data, async_cookie_t cookie) { struct ccw_device *cdev = data; diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 44796ba4eb9b..51224f76b980 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1045,6 +1045,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) erp->retries = 5; + } else if (sense[1] & SNS1_WRITE_INHIBITED) { + dev_err(&device->cdev->dev, "An I/O request was rejected" + " because writing is inhibited\n"); + erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); } else { /* fatal error - set status to FAILED internal error 09 - Command Reject */ diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index d49766f3b940..8e23919c8704 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -742,6 +742,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dasd_devmap *devmap; + struct dasd_device *device; int val; char *endp; @@ -758,12 +759,14 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, devmap->features |= DASD_FEATURE_READONLY; else devmap->features &= ~DASD_FEATURE_READONLY; - if (devmap->device) - devmap->device->features = devmap->features; - if (devmap->device && devmap->device->block - && devmap->device->block->gdp) - set_disk_ro(devmap->device->block->gdp, val); + device = devmap->device; + if (device) { + device->features = devmap->features; + val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); + } spin_unlock(&dasd_devmap_lock); + if (device && device->block && device->block->gdp) + set_disk_ro(device->block->gdp, val); return count; } diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 6e14863f5c70..687f323cdc38 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -145,12 +145,10 @@ dasd_diag_erp(struct dasd_device *device) mdsk_term_io(device); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); if (rc == 4) { - if (!(device->features & DASD_FEATURE_READONLY)) { + if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags))) pr_warning("%s: The access mode of a DIAG device " "changed to read-only\n", dev_name(&device->cdev->dev)); - device->features |= DASD_FEATURE_READONLY; - } rc = 0; } if (rc) @@ -449,7 +447,7 @@ dasd_diag_check_device(struct dasd_device *device) rc = -EIO; } else { if (rc == 4) - device->features |= DASD_FEATURE_READONLY; + set_bit(DASD_FLAG_DEVICE_RO, &device->flags); pr_info("%s: New DASD with %ld byte/block, total size %ld " "KB%s\n", dev_name(&device->cdev->dev), (unsigned long) block->bp_block, diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index d7163f904f40..01f4e7a34aa8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1089,6 +1089,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) struct dasd_eckd_private *private; struct dasd_block *block; int is_known, rc; + int readonly; if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, @@ -1182,15 +1183,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device) else private->real_cyl = private->rdc_data.no_cyl; + readonly = dasd_device_is_ro(device); + if (readonly) + set_bit(DASD_FLAG_DEVICE_RO, &device->flags); + dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " - "with %d cylinders, %d heads, %d sectors\n", + "with %d cylinders, %d heads, %d sectors%s\n", private->rdc_data.dev_type, private->rdc_data.dev_model, private->rdc_data.cu_type, private->rdc_data.cu_model.model, private->real_cyl, private->rdc_data.trk_per_cyl, - private->rdc_data.sec_per_trk); + private->rdc_data.sec_per_trk, + readonly ? ", read-only device" : ""); return 0; out_err3: diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 0f152444ac77..37282b90eecc 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -124,6 +124,7 @@ dasd_fba_check_characteristics(struct dasd_device *device) struct dasd_fba_private *private; struct ccw_device *cdev = device->cdev; int rc; + int readonly; private = (struct dasd_fba_private *) device->private; if (!private) { @@ -162,16 +163,21 @@ dasd_fba_check_characteristics(struct dasd_device *device) return rc; } + readonly = dasd_device_is_ro(device); + if (readonly) + set_bit(DASD_FLAG_DEVICE_RO, &device->flags); + dev_info(&device->cdev->dev, "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " - "and %d B/blk\n", + "and %d B/blk%s\n", cdev->id.dev_type, cdev->id.dev_model, cdev->id.cu_type, cdev->id.cu_model, ((private->rdc_data.blk_bdsa * (private->rdc_data.blk_size >> 9)) >> 11), - private->rdc_data.blk_size); + private->rdc_data.blk_size, + readonly ? ", read-only device" : ""); return 0; } diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 94f92a1247f2..30a1ca3d08b7 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -70,7 +70,8 @@ int dasd_gendisk_alloc(struct dasd_block *block) } len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26)); - if (block->base->features & DASD_FEATURE_READONLY) + if (base->features & DASD_FEATURE_READONLY || + test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) set_disk_ro(gdp, 1); gdp->private_data = block; gdp->queue = block->request_queue; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index ed73ce550822..a91d4a97d4f2 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -436,6 +436,10 @@ struct dasd_block { #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ #define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */ #define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */ +#define DASD_FLAG_DEVICE_RO 6 /* The device itself is read-only. Don't + * confuse this with the user specified + * read-only feature. + */ void dasd_put_device_wake(struct dasd_device *); @@ -609,6 +613,9 @@ char *dasd_get_sense(struct irb *); void dasd_device_set_stop_bits(struct dasd_device *, int); void dasd_device_remove_stop_bits(struct dasd_device *, int); +int dasd_device_is_ro(struct dasd_device *); + + /* externals in dasd_devmap.c */ extern int dasd_max_devindex; extern int dasd_probeonly; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 7039d9cf0fb4..3479f8158a1b 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -199,7 +199,8 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) if (!argp) return -EINVAL; - if (block->base->features & DASD_FEATURE_READONLY) + if (block->base->features & DASD_FEATURE_READONLY || + test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) return -EROFS; if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) return -EFAULT; @@ -349,7 +350,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) return -EINVAL; if (get_user(intval, (int __user *)argp)) return -EFAULT; - + if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) + return -EROFS; set_disk_ro(bdev->bd_disk, intval); return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval); } From 09003ed90a2880de7e36b170a9298dd10d53e322 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 8 Mar 2010 12:26:25 +0100 Subject: [PATCH 107/114] [S390] smsgiucv: declare char pointers as "const" Declare the smsgiucv prefix char pointer as "const" and use use const char pointers in callback functions. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- arch/s390/mm/cmm.c | 2 +- drivers/s390/net/smsgiucv.c | 13 +++++++------ drivers/s390/net/smsgiucv.h | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 76a3637b88e0..f16bd04e39e9 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -374,7 +374,7 @@ static struct ctl_table cmm_dir_table[] = { #ifdef CONFIG_CMM_IUCV #define SMSG_PREFIX "CMM" static void -cmm_smsg_target(char *from, char *msg) +cmm_smsg_target(const char *from, char *msg) { long nr, seconds; diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 67f2485d2372..3e666b6e77b4 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -31,9 +31,9 @@ struct smsg_callback { struct list_head list; - char *prefix; + const char *prefix; int len; - void (*callback)(char *from, char *str); + void (*callback)(const char *from, char *str); }; MODULE_AUTHOR @@ -100,8 +100,8 @@ static void smsg_message_pending(struct iucv_path *path, kfree(buffer); } -int smsg_register_callback(char *prefix, - void (*callback)(char *from, char *str)) +int smsg_register_callback(const char *prefix, + void (*callback)(const char *from, char *str)) { struct smsg_callback *cb; @@ -117,8 +117,9 @@ int smsg_register_callback(char *prefix, return 0; } -void smsg_unregister_callback(char *prefix, - void (*callback)(char *from, char *str)) +void smsg_unregister_callback(const char *prefix, + void (*callback)(const char *from, + char *str)) { struct smsg_callback *cb, *tmp; diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h index 67f5d4f8378d..9410b45fde03 100644 --- a/drivers/s390/net/smsgiucv.h +++ b/drivers/s390/net/smsgiucv.h @@ -5,6 +5,8 @@ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) */ -int smsg_register_callback(char *, void (*)(char *, char *)); -void smsg_unregister_callback(char *, void (*)(char *, char *)); +int smsg_register_callback(const char *, + void (*)(const char *, char *)); +void smsg_unregister_callback(const char *, + void (*)(const char *, char *)); From 1ffaa640c6ba135aafc91841204e41846eae6841 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 8 Mar 2010 12:26:26 +0100 Subject: [PATCH 108/114] [S390] smsgiucv_app: deliver z/VM CP special messages (SMSG) as uevents The smsgiucv_app driver registers a callback with the smsgiucv driver to receive z/VM CP special messages (SMSG) starting with "APP". When the callback is called for special messages, the driver creates an uevent for the received message. The uevent consists of additional environment data containing the message prefix ("APP"), message sender, and message content. udev rules can be used to trigger application specific actions through matching the content or sender of the special message. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky --- drivers/s390/net/Kconfig | 10 ++ drivers/s390/net/Makefile | 1 + drivers/s390/net/smsgiucv.c | 2 +- drivers/s390/net/smsgiucv.h | 2 + drivers/s390/net/smsgiucv_app.c | 211 ++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 drivers/s390/net/smsgiucv_app.c diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index cb909a5b5047..977bb4d4ed15 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig @@ -43,6 +43,16 @@ config SMSGIUCV Select this option if you want to be able to receive SMSG messages from other VM guest systems. +config SMSGIUCV_EVENT + tristate "Deliver IUCV special messages as uevents (VM only)" + depends on SMSGIUCV + help + Select this option to deliver CP special messages (SMSGs) as + uevents. The driver handles only those special messages that + start with "APP". + + To compile as a module, choose M. The module name is "smsgiucv_app". + config CLAW tristate "CLAW device support" depends on CCW && NETDEVICES diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 6cab5a62f99e..4dfe8c1092da 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -6,6 +6,7 @@ ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o obj-$(CONFIG_CTCM) += ctcm.o fsm.o obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o +obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o obj-$(CONFIG_LCS) += lcs.o obj-$(CONFIG_CLAW) += claw.o qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 3e666b6e77b4..ecef1edee701 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -177,7 +177,7 @@ static const struct dev_pm_ops smsg_pm_ops = { static struct device_driver smsg_driver = { .owner = THIS_MODULE, - .name = "SMSGIUCV", + .name = SMSGIUCV_DRV_NAME, .bus = &iucv_bus, .pm = &smsg_pm_ops, }; diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h index 9410b45fde03..149a1151608d 100644 --- a/drivers/s390/net/smsgiucv.h +++ b/drivers/s390/net/smsgiucv.h @@ -5,6 +5,8 @@ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) */ +#define SMSGIUCV_DRV_NAME "SMSGIUCV" + int smsg_register_callback(const char *, void (*)(const char *, char *)); void smsg_unregister_callback(const char *, diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c new file mode 100644 index 000000000000..91579dc6a2b0 --- /dev/null +++ b/drivers/s390/net/smsgiucv_app.c @@ -0,0 +1,211 @@ +/* + * Deliver z/VM CP special messages (SMSG) as uevents. + * + * The driver registers for z/VM CP special messages with the + * "APP" prefix. Incoming messages are delivered to user space + * as uevents. + * + * Copyright IBM Corp. 2010 + * Author(s): Hendrik Brueckner + * + */ +#define KMSG_COMPONENT "smsgiucv_app" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smsgiucv.h" + +/* prefix used for SMSG registration */ +#define SMSG_PREFIX "APP" + +/* SMSG related uevent environment variables */ +#define ENV_SENDER_STR "SMSG_SENDER=" +#define ENV_SENDER_LEN (strlen(ENV_SENDER_STR) + 8 + 1) +#define ENV_PREFIX_STR "SMSG_ID=" +#define ENV_PREFIX_LEN (strlen(ENV_PREFIX_STR) + \ + strlen(SMSG_PREFIX) + 1) +#define ENV_TEXT_STR "SMSG_TEXT=" +#define ENV_TEXT_LEN(msg) (strlen(ENV_TEXT_STR) + strlen((msg)) + 1) + +/* z/VM user ID which is permitted to send SMSGs + * If the value is undefined or empty (""), special messages are + * accepted from any z/VM user ID. */ +static char *sender; +module_param(sender, charp, 0400); +MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted"); + +/* SMSG device representation */ +static struct device *smsg_app_dev; + +/* list element for queuing received messages for delivery */ +struct smsg_app_event { + struct list_head list; + char *buf; + char *envp[4]; +}; + +/* queue for outgoing uevents */ +static LIST_HEAD(smsg_event_queue); +static DEFINE_SPINLOCK(smsg_event_queue_lock); + +static void smsg_app_event_free(struct smsg_app_event *ev) +{ + kfree(ev->buf); + kfree(ev); +} + +static struct smsg_app_event *smsg_app_event_alloc(const char *from, + const char *msg) +{ + struct smsg_app_event *ev; + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + return NULL; + + ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN + + ENV_TEXT_LEN(msg), GFP_ATOMIC); + if (!ev->buf) { + kfree(ev); + return NULL; + } + + /* setting up environment pointers into buf */ + ev->envp[0] = ev->buf; + ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN; + ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN; + ev->envp[3] = NULL; + + /* setting up environment: sender, prefix name, and message text */ + snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from); + snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX); + snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg); + + return ev; +} + +static void smsg_event_work_fn(struct work_struct *work) +{ + LIST_HEAD(event_queue); + struct smsg_app_event *p, *n; + struct device *dev; + + dev = get_device(smsg_app_dev); + if (!dev) + return; + + spin_lock_bh(&smsg_event_queue_lock); + list_splice_init(&smsg_event_queue, &event_queue); + spin_unlock_bh(&smsg_event_queue_lock); + + list_for_each_entry_safe(p, n, &event_queue, list) { + list_del(&p->list); + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp); + smsg_app_event_free(p); + } + + put_device(dev); +} +static DECLARE_WORK(smsg_event_work, smsg_event_work_fn); + +static void smsg_app_callback(const char *from, char *msg) +{ + struct smsg_app_event *se; + + /* check if the originating z/VM user ID matches + * the configured sender. */ + if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0) + return; + + /* get start of message text (skip prefix and leading blanks) */ + msg += strlen(SMSG_PREFIX); + while (*msg && isspace(*msg)) + msg++; + if (*msg == '\0') + return; + + /* allocate event list element and its environment */ + se = smsg_app_event_alloc(from, msg); + if (!se) + return; + + /* queue event and schedule work function */ + spin_lock(&smsg_event_queue_lock); + list_add_tail(&se->list, &smsg_event_queue); + spin_unlock(&smsg_event_queue_lock); + + schedule_work(&smsg_event_work); + return; +} + +static int __init smsgiucv_app_init(void) +{ + struct device_driver *smsgiucv_drv; + int rc; + + if (!MACHINE_IS_VM) + return -ENODEV; + + smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL); + if (!smsg_app_dev) + return -ENOMEM; + + smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus); + if (!smsgiucv_drv) { + kfree(smsg_app_dev); + return -ENODEV; + } + + rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); + if (rc) { + kfree(smsg_app_dev); + goto fail_put_driver; + } + smsg_app_dev->bus = &iucv_bus; + smsg_app_dev->parent = iucv_root; + smsg_app_dev->release = (void (*)(struct device *)) kfree; + smsg_app_dev->driver = smsgiucv_drv; + rc = device_register(smsg_app_dev); + if (rc) { + put_device(smsg_app_dev); + goto fail_put_driver; + } + + /* register with the smsgiucv device driver */ + rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); + if (rc) { + device_unregister(smsg_app_dev); + goto fail_put_driver; + } + + rc = 0; +fail_put_driver: + put_driver(smsgiucv_drv); + return rc; +} +module_init(smsgiucv_app_init); + +static void __exit smsgiucv_app_exit(void) +{ + /* unregister callback */ + smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback); + + /* cancel pending work and flush any queued event work */ + cancel_work_sync(&smsg_event_work); + smsg_event_work_fn(&smsg_event_work); + + device_unregister(smsg_app_dev); +} +module_exit(smsgiucv_app_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents"); +MODULE_AUTHOR("Hendrik Brueckner "); From 2786095a58fd55931fa0298ff6e3914331edaaf2 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 8 Mar 2010 13:48:01 +0000 Subject: [PATCH 109/114] [WATCHDOG] i6300esb.c: change platform_driver to pci_driver Since the intel 6300esb platform uses a dedicated PCI ID for it's watchdog timer (00:1d.4), it's better and easier to have this as a pci_driver. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/i6300esb.c | 93 +++++++++++++------------------------ 1 file changed, 33 insertions(+), 60 deletions(-) diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 3e00dc5b5a20..bb9750a03942 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -42,7 +41,7 @@ #include /* Module and version information */ -#define ESB_VERSION "0.04" +#define ESB_VERSION "0.05" #define ESB_MODULE_NAME "i6300ESB timer" #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION #define PFX ESB_MODULE_NAME ": " @@ -82,7 +81,9 @@ static unsigned long timer_alive; static struct pci_dev *esb_pci; static unsigned short triggered; /* The status of the watchdog upon boot */ static char esb_expect_close; -static struct platform_device *esb_platform_device; + +/* We can only use 1 card due to the /dev/watchdog restriction */ +static int cards_found; /* module parameters */ /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ @@ -332,11 +333,6 @@ static struct miscdevice esb_miscdev = { /* * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. */ static struct pci_device_id esb_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, @@ -348,29 +344,19 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); * Init & exit routines */ -static unsigned char __devinit esb_getdevice(void) +static unsigned char __devinit esb_getdevice(struct pci_dev *pdev) { - /* - * Find the PCI device - */ - - esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_ESB_9, NULL); - - if (!esb_pci) - return 0; - - if (pci_enable_device(esb_pci)) { + if (pci_enable_device(pdev)) { printk(KERN_ERR PFX "failed to enable device\n"); goto err_devput; } - if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { + if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) { printk(KERN_ERR PFX "failed to request region\n"); goto err_disable; } - BASEADDR = pci_ioremap_bar(esb_pci, 0); + BASEADDR = pci_ioremap_bar(pdev, 0); if (BASEADDR == NULL) { /* Something's wrong here, BASEADDR has to be set */ printk(KERN_ERR PFX "failed to get BASEADDR\n"); @@ -378,14 +364,14 @@ static unsigned char __devinit esb_getdevice(void) } /* Done */ + esb_pci = pdev; return 1; err_release: - pci_release_region(esb_pci, 0); + pci_release_region(pdev, 0); err_disable: - pci_disable_device(esb_pci); + pci_disable_device(pdev); err_devput: - pci_dev_put(esb_pci); return 0; } @@ -430,12 +416,23 @@ static void __devinit esb_initdevice(void) esb_timer_set_heartbeat(heartbeat); } -static int __devinit esb_probe(struct platform_device *dev) +static int __devinit esb_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { int ret; + cards_found++; + if (cards_found == 1) + printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", + ESB_VERSION); + + if (cards_found > 1) { + printk(KERN_ERR PFX "This driver only supports 1 device\n"); + return -ENODEV; + } + /* Check whether or not the hardware watchdog is there */ - if (!esb_getdevice() || esb_pci == NULL) + if (!esb_getdevice(pdev) || esb_pci == NULL) return -ENODEV; /* Check that the heartbeat value is within it's range; @@ -467,11 +464,11 @@ static int __devinit esb_probe(struct platform_device *dev) iounmap(BASEADDR); pci_release_region(esb_pci, 0); pci_disable_device(esb_pci); - pci_dev_put(esb_pci); + esb_pci = NULL; return ret; } -static int __devexit esb_remove(struct platform_device *dev) +static void __devexit esb_remove(struct pci_dev *pdev) { /* Stop the timer before we leave */ if (!nowayout) @@ -482,54 +479,30 @@ static int __devexit esb_remove(struct platform_device *dev) iounmap(BASEADDR); pci_release_region(esb_pci, 0); pci_disable_device(esb_pci); - pci_dev_put(esb_pci); - return 0; + esb_pci = NULL; } -static void esb_shutdown(struct platform_device *dev) +static void esb_shutdown(struct pci_dev *pdev) { esb_timer_stop(); } -static struct platform_driver esb_platform_driver = { +static struct pci_driver esb_driver = { + .name = ESB_MODULE_NAME, + .id_table = esb_pci_tbl, .probe = esb_probe, .remove = __devexit_p(esb_remove), .shutdown = esb_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = ESB_MODULE_NAME, - }, }; static int __init watchdog_init(void) { - int err; - - printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", - ESB_VERSION); - - err = platform_driver_register(&esb_platform_driver); - if (err) - return err; - - esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME, - -1, NULL, 0); - if (IS_ERR(esb_platform_device)) { - err = PTR_ERR(esb_platform_device); - goto unreg_platform_driver; - } - - return 0; - -unreg_platform_driver: - platform_driver_unregister(&esb_platform_driver); - return err; + return pci_register_driver(&esb_driver); } static void __exit watchdog_cleanup(void) { - platform_device_unregister(esb_platform_device); - platform_driver_unregister(&esb_platform_driver); + pci_unregister_driver(&esb_driver); printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); } From d4014030d2b2508aaf54093a5885f1c8a2275dd7 Mon Sep 17 00:00:00 2001 From: Christian Kujau Date: Mon, 8 Mar 2010 15:03:09 +0000 Subject: [PATCH 110/114] FS-Cache: Remove the EXPERIMENTAL flag Remove the EXPERIMENTAL flag from FS-Cache so that Ubuntu can make use of the facility. Signed-off-by: Christian Kujau Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- fs/fscache/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig index 864dac20a242..cc94bb9563f2 100644 --- a/fs/fscache/Kconfig +++ b/fs/fscache/Kconfig @@ -1,7 +1,6 @@ config FSCACHE tristate "General filesystem local caching manager" - depends on EXPERIMENTAL select SLOW_WORK help This option enables a generic filesystem caching manager that can be From 57d54889cd00db2752994b389ba714138652e60c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 8 Mar 2010 10:45:44 -0800 Subject: [PATCH 111/114] Linux 2.6.34-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1b24895212d8..08ff02da7ce3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 -SUBLEVEL = 33 -EXTRAVERSION = +SUBLEVEL = 34 +EXTRAVERSION = -rc1 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From a636ee7fb35b731ba2b331f6294e809bb6be09c8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 9 Mar 2010 06:57:53 +0000 Subject: [PATCH 112/114] driver core: Early dev_name() support. Presently early platform devices suffer from the fact they are unable to use dev_xxx() calls early on due to dev_name() and others being unavailable at the time ->probe() is called. This implements early init_name construction from the matched name/id pair following the semantics of the late device/driver match. As a result, matched IDs (inclusive of requested ones) are preserved when the handoff from the early platform code happens at kobject initialization time. Since we still require kmalloc slabs to be available at this point, using kstrdup() for establishing the init_name works fine. This subsequently needs to be tested from dev_name() prior to the init_name being cleared by the driver core. We don't kfree() since others will already have a handle on the string long before the kobject initialization takes place. This is also needed to permit drivers to use the clock framework early, without having to manually construct their own device IDs from the match id/name pair locally (needed by the early console and timer code on sh and arm). Signed-off-by: Paul Mundt Acked-by: Greg Kroah-Hartman --- drivers/base/platform.c | 19 +++++++++++++++++++ include/linux/device.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1ba9d617d241..d2d4926c5c4c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1239,6 +1239,25 @@ static int __init early_platform_driver_probe_id(char *class_str, } if (match) { + /* + * Set up a sensible init_name to enable + * dev_name() and others to be used before the + * rest of the driver core is initialized. + */ + if (!match->dev.init_name) { + char buf[32]; + + if (match->id != -1) + snprintf(buf, sizeof(buf), "%s.%d", + match->name, match->id); + else + snprintf(buf, sizeof(buf), "%s", + match->name); + + match->dev.init_name = kstrdup(buf, GFP_KERNEL); + if (!match->dev.init_name) + return -ENOMEM; + } if (epdrv->pdrv->probe(match)) pr_warning("%s: unable to probe %s early.\n", class_str, match->name); diff --git a/include/linux/device.h b/include/linux/device.h index 182192892d45..241b96bcd7ad 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -451,6 +451,10 @@ struct device { static inline const char *dev_name(const struct device *dev) { + /* Use the init name until the kobject becomes available */ + if (dev->init_name) + return dev->init_name; + return kobject_name(&dev->kobj); } From 214a607a4f5bf5a14dab0304ba350cdaf3916795 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Mar 2010 16:26:25 +0900 Subject: [PATCH 113/114] clocksource: Use dev_name() universally across the SH drivers. There is no need to copy in the name from the sh timer config now that dev_name() is available early. We prefer the dev_name() variant for consistent naming. Signed-off-by: Paul Mundt --- drivers/clocksource/sh_cmt.c | 32 ++++++++++++++------------------ drivers/clocksource/sh_mtu2.c | 24 +++++++++++------------- drivers/clocksource/sh_tmu.c | 28 ++++++++++++---------------- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 578595c4425d..a1d381171388 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -149,13 +149,12 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -278,7 +277,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, delay = 1; if (!delay) - pr_warning("sh_cmt: too long delay\n"); + dev_warn(&p->pdev->dev, "too long delay\n"); } while (delay); } @@ -288,7 +287,7 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) unsigned long flags; if (delta > p->max_match_value) - pr_warning("sh_cmt: delta out of range\n"); + dev_warn(&p->pdev->dev, "delta out of range\n"); spin_lock_irqsave(&p->lock, flags); p->next_match_value = delta; @@ -450,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, cs->resume = sh_cmt_clocksource_resume; cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_cmt: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -496,13 +495,11 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_cmt: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_cmt_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_cmt: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_cmt_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_SHUTDOWN: @@ -543,7 +540,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ced->set_next_event = sh_cmt_clock_event_next; ced->set_mode = sh_cmt_clock_event_mode; - pr_info("sh_cmt: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); } @@ -600,12 +597,12 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_cmt: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* request irq using setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; @@ -613,7 +610,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } @@ -628,17 +625,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->clear_bits = ~0xc000; } - ret = sh_cmt_register(p, cfg->name, + ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); if (ret) { - pr_err("sh_cmt: registration failed\n"); + dev_err(&p->pdev->dev, "registration failed\n"); goto err1; } ret = setup_irq(irq, &p->irqaction); if (ret) { - pr_err("sh_cmt: failed to request irq %d\n", irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); goto err1; } @@ -653,11 +650,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) static int __devinit sh_cmt_probe(struct platform_device *pdev) { struct sh_cmt_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 4c8a759e60cd..8ce355572d16 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -118,13 +118,12 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) static int sh_mtu2_enable(struct sh_mtu2_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -193,8 +192,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_mtu2: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_mtu2_enable(p); break; case CLOCK_EVT_MODE_UNUSED: @@ -221,13 +219,13 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, ced->cpumask = cpumask_of(0); ced->set_mode = sh_mtu2_clock_event_mode; - pr_info("sh_mtu2: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_mtu2: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -273,12 +271,12 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_mtu2: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_mtu2_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; @@ -287,12 +285,13 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } - return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); + return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), + cfg->clockevent_rating); err1: iounmap(p->mapbase); err0: @@ -302,11 +301,10 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) static int __devinit sh_mtu2_probe(struct platform_device *pdev) { struct sh_mtu2_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 961f5b5ef6a3..34239453ebaf 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -106,13 +106,12 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) static int sh_tmu_enable(struct sh_tmu_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -228,7 +227,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, cs->disable = sh_tmu_clocksource_disable; cs->mask = CLOCKSOURCE_MASK(32); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_tmu: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -276,13 +275,11 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_tmu: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_tmu_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_tmu: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_tmu_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_UNUSED: @@ -323,13 +320,13 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_next_event = sh_tmu_clock_event_next; ced->set_mode = sh_tmu_clock_event_mode; - pr_info("sh_tmu: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_tmu: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -378,12 +375,12 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_tmu: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_tmu_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; @@ -392,12 +389,12 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } - return sh_tmu_register(p, cfg->name, + return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); err1: @@ -409,11 +406,10 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) static int __devinit sh_tmu_probe(struct platform_device *pdev) { struct sh_tmu_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } From ec0ffe2ee0e0fb9da4409d86bfd72636450f32df Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Mar 2010 16:28:16 +0900 Subject: [PATCH 114/114] sh: Kill off all timer name clobbering. Now that dev_name() can be used early, we no longer require a static string. Kill off all of the superfluous timer names. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2/setup-sh7619.c | 4 ---- arch/sh/kernel/cpu/sh2a/setup-mxg.c | 6 ------ arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 6 ------ arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 8 -------- arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 10 ---------- arch/sh/kernel/cpu/sh3/setup-sh7705.c | 6 ------ arch/sh/kernel/cpu/sh3/setup-sh770x.c | 6 ------ arch/sh/kernel/cpu/sh3/setup-sh7710.c | 6 ------ arch/sh/kernel/cpu/sh3/setup-sh7720.c | 16 ---------------- arch/sh/kernel/cpu/sh4/setup-sh4-202.c | 6 ------ arch/sh/kernel/cpu/sh4/setup-sh7750.c | 10 ---------- arch/sh/kernel/cpu/sh4/setup-sh7760.c | 6 ------ arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 8 -------- arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 8 -------- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 8 -------- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 14 -------------- arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 14 -------------- arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 4 ---- arch/sh/kernel/cpu/sh4a/setup-sh7763.c | 12 ------------ arch/sh/kernel/cpu/sh4a/setup-sh7770.c | 18 ------------------ arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 12 ------------ arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 12 ------------ arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 24 ------------------------ arch/sh/kernel/cpu/sh4a/setup-shx3.c | 12 ------------ arch/sh/kernel/cpu/sh5/setup-sh5.c | 6 ------ 25 files changed, 242 deletions(-) diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 114c7cee7184..9b96457ccc7b 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -128,7 +128,6 @@ static struct platform_device eth_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -138,7 +137,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xf84a0072, .end = 0xf84a0077, .flags = IORESOURCE_MEM, @@ -160,7 +158,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -170,7 +167,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xf84a0078, .end = 0xf84a007d, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c index 8f669dc9b0da..5301450656cc 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c +++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c @@ -115,7 +115,6 @@ static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups, mask_registers, prio_registers, NULL); static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -124,7 +123,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xff801300, .end = 0xff801326, .flags = IORESOURCE_MEM, @@ -146,7 +144,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -155,7 +152,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xff801380, .end = 0xff801390, .flags = IORESOURCE_MEM, @@ -177,7 +173,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -186,7 +181,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xff801000, .end = 0xff80100a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c index 4ccfeb59eb1a..5b07ab57acfd 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c @@ -318,7 +318,6 @@ static struct platform_device rtc_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -327,7 +326,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -349,7 +347,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -358,7 +355,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, @@ -380,7 +376,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -389,7 +384,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xfffe4000, .end = 0xfffe400a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index 3136966cc9b3..433ac5301314 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -234,7 +234,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -244,7 +243,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xfffec002, .end = 0xfffec007, .flags = IORESOURCE_MEM, @@ -266,7 +264,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -276,7 +273,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xfffec008, .end = 0xfffec00d, .flags = IORESOURCE_MEM, @@ -298,7 +294,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -307,7 +302,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -329,7 +323,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -338,7 +331,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 064873585a8b..8caecb41e4e6 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -194,7 +194,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -204,7 +203,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xfffec002, .end = 0xfffec007, .flags = IORESOURCE_MEM, @@ -226,7 +224,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -236,7 +233,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xfffec008, .end = 0xfffec00d, .flags = IORESOURCE_MEM, @@ -258,7 +254,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -267,7 +262,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -289,7 +283,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -298,7 +291,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, @@ -320,7 +312,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -329,7 +320,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xfffe4000, .end = 0xfffe400a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 7b892d60e3a0..5e45fb7338fd 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -124,7 +124,6 @@ static struct platform_device rtc_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -133,7 +132,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfffffe94, .end = 0xfffffe9f, .flags = IORESOURCE_MEM, @@ -155,7 +153,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -164,7 +161,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfffffea0, .end = 0xfffffeab, .flags = IORESOURCE_MEM, @@ -186,7 +182,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -194,7 +189,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xfffffeac, .end = 0xfffffebb, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index bc0c4f68c7c7..9adb853a9184 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -157,7 +157,6 @@ static struct platform_device scif2_device = { #endif static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -166,7 +165,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfffffe94, .end = 0xfffffe9f, .flags = IORESOURCE_MEM, @@ -188,7 +186,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -197,7 +194,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfffffea0, .end = 0xfffffeab, .flags = IORESOURCE_MEM, @@ -219,7 +215,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -227,7 +222,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xfffffeac, .end = 0xfffffebb, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 0845a3ad006d..2e581e30d13d 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -127,7 +127,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -136,7 +135,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xa412fe94, .end = 0xa412fe9f, .flags = IORESOURCE_MEM, @@ -158,7 +156,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -167,7 +164,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xa412fea0, .end = 0xa412feab, .flags = IORESOURCE_MEM, @@ -189,7 +185,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -197,7 +192,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xa412feac, .end = 0xa412feb5, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index a718a6231091..9a006e13b41d 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -130,7 +130,6 @@ static struct platform_device usbf_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x10, .timer_bit = 0, .clk = "peripheral_clk", @@ -140,7 +139,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0x044a0010, .end = 0x044a001b, .flags = IORESOURCE_MEM, @@ -162,7 +160,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x20, .timer_bit = 1, .clk = "peripheral_clk", @@ -170,7 +167,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0x044a0020, .end = 0x044a002b, .flags = IORESOURCE_MEM, @@ -192,7 +188,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config cmt2_platform_data = { - .name = "CMT2", .channel_offset = 0x30, .timer_bit = 2, .clk = "peripheral_clk", @@ -200,7 +195,6 @@ static struct sh_timer_config cmt2_platform_data = { static struct resource cmt2_resources[] = { [0] = { - .name = "CMT2", .start = 0x044a0030, .end = 0x044a003b, .flags = IORESOURCE_MEM, @@ -222,7 +216,6 @@ static struct platform_device cmt2_device = { }; static struct sh_timer_config cmt3_platform_data = { - .name = "CMT3", .channel_offset = 0x40, .timer_bit = 3, .clk = "peripheral_clk", @@ -230,7 +223,6 @@ static struct sh_timer_config cmt3_platform_data = { static struct resource cmt3_resources[] = { [0] = { - .name = "CMT3", .start = 0x044a0040, .end = 0x044a004b, .flags = IORESOURCE_MEM, @@ -252,7 +244,6 @@ static struct platform_device cmt3_device = { }; static struct sh_timer_config cmt4_platform_data = { - .name = "CMT4", .channel_offset = 0x50, .timer_bit = 4, .clk = "peripheral_clk", @@ -260,7 +251,6 @@ static struct sh_timer_config cmt4_platform_data = { static struct resource cmt4_resources[] = { [0] = { - .name = "CMT4", .start = 0x044a0050, .end = 0x044a005b, .flags = IORESOURCE_MEM, @@ -282,7 +272,6 @@ static struct platform_device cmt4_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -291,7 +280,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xa412fe94, .end = 0xa412fe9f, .flags = IORESOURCE_MEM, @@ -313,7 +301,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -322,7 +309,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xa412fea0, .end = 0xa412feab, .flags = IORESOURCE_MEM, @@ -344,7 +330,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -352,7 +337,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xa412feac, .end = 0xa412feb5, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c index b9b7e10ad68f..223d06657775 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c @@ -31,7 +31,6 @@ static struct platform_device scif0_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -40,7 +39,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -62,7 +60,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -71,7 +68,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -93,7 +89,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -101,7 +96,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index ffd79e57254f..2f337b143c8f 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -66,7 +66,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -75,7 +74,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -97,7 +95,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -106,7 +103,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -128,7 +124,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -136,7 +131,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -163,7 +157,6 @@ static struct platform_device tmu2_device = { defined(CONFIG_CPU_SUBTYPE_SH7751R) static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -171,7 +164,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xfe100008, .end = 0xfe100013, .flags = IORESOURCE_MEM, @@ -193,7 +185,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -201,7 +192,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xfe100014, .end = 0xfe10001f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index a16eb3656f4b..fa43da0502bd 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -187,7 +187,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -196,7 +195,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -218,7 +216,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -227,7 +224,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -249,7 +245,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -257,7 +252,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 45eb1bfd42c9..fdbd7d07a69f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -207,7 +207,6 @@ static struct platform_device jpu_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -217,7 +216,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -239,7 +237,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -248,7 +245,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -270,7 +266,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -279,7 +274,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -301,7 +295,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -309,7 +302,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index c494c193e3b6..d90fe0a65c2a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -169,7 +169,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -179,7 +178,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -201,7 +199,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -210,7 +207,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -232,7 +228,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -241,7 +236,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -263,7 +257,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -271,7 +264,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index fd7e3639e845..83ae9ad19874 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -401,7 +401,6 @@ static struct platform_device jpu_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -411,7 +410,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -436,7 +434,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -445,7 +442,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -470,7 +466,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -479,7 +474,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -504,7 +498,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -512,7 +505,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 85c61f624702..68446b3f06af 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -211,7 +211,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -221,7 +220,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -246,7 +244,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -255,7 +252,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -280,7 +276,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -289,7 +284,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -314,7 +308,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -322,7 +315,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, @@ -347,7 +339,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu1", @@ -355,7 +346,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd90008, .end = 0xffd90013, .flags = IORESOURCE_MEM, @@ -380,7 +370,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu1", @@ -388,7 +377,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd90014, .end = 0xffd9001f, .flags = IORESOURCE_MEM, @@ -413,7 +401,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu1", @@ -421,7 +408,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd90020, .end = 0xffd9002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index e7fa2a92fc1f..abc98b0fef91 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -485,7 +485,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -495,7 +494,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -520,7 +518,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -529,7 +526,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -554,7 +550,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -563,7 +558,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -588,7 +582,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -596,7 +589,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, @@ -622,7 +614,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu1", @@ -630,7 +621,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd90008, .end = 0xffd90013, .flags = IORESOURCE_MEM, @@ -655,7 +645,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu1", @@ -663,7 +652,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd90014, .end = 0xffd9001f, .flags = IORESOURCE_MEM, @@ -688,7 +676,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu1", @@ -696,7 +683,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd90020, .end = 0xffd9002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index e75edf58796a..25eddf24f634 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -63,7 +63,6 @@ static struct platform_device scif4_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -72,7 +71,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfe430008, .end = 0xfe430013, .flags = IORESOURCE_MEM, @@ -94,7 +92,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -103,7 +100,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfe430014, .end = 0xfe43001f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index 7f6b0a5f7f82..a91263e0358b 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c @@ -131,7 +131,6 @@ static struct platform_device usbf_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -140,7 +139,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -162,7 +160,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -171,7 +168,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -193,7 +189,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -201,7 +196,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -223,7 +217,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -231,7 +224,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd88008, .end = 0xffd88013, .flags = IORESOURCE_MEM, @@ -253,7 +245,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -261,7 +252,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd88014, .end = 0xffd8801f, .flags = IORESOURCE_MEM, @@ -283,7 +273,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -291,7 +280,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd88020, .end = 0xffd8802b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c index 86d681ecf90e..83a27b0e4ed2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c @@ -165,7 +165,6 @@ static struct platform_device scif9_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -174,7 +173,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -196,7 +194,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -205,7 +202,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -227,7 +223,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -235,7 +230,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -257,7 +251,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -265,7 +258,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd81008, .end = 0xffd81013, .flags = IORESOURCE_MEM, @@ -287,7 +279,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -295,7 +286,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd81014, .end = 0xffd8101f, .flags = IORESOURCE_MEM, @@ -317,7 +307,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -325,7 +314,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd81020, .end = 0xffd8102f, .flags = IORESOURCE_MEM, @@ -347,7 +335,6 @@ static struct platform_device tmu5_device = { }; static struct sh_timer_config tmu6_platform_data = { - .name = "TMU6", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -355,7 +342,6 @@ static struct sh_timer_config tmu6_platform_data = { static struct resource tmu6_resources[] = { [0] = { - .name = "TMU6", .start = 0xffd82008, .end = 0xffd82013, .flags = IORESOURCE_MEM, @@ -377,7 +363,6 @@ static struct platform_device tmu6_device = { }; static struct sh_timer_config tmu7_platform_data = { - .name = "TMU7", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -385,7 +370,6 @@ static struct sh_timer_config tmu7_platform_data = { static struct resource tmu7_resources[] = { [0] = { - .name = "TMU7", .start = 0xffd82014, .end = 0xffd8201f, .flags = IORESOURCE_MEM, @@ -407,7 +391,6 @@ static struct platform_device tmu7_device = { }; static struct sh_timer_config tmu8_platform_data = { - .name = "TMU8", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -415,7 +398,6 @@ static struct sh_timer_config tmu8_platform_data = { static struct resource tmu8_resources[] = { [0] = { - .name = "TMU8", .start = 0xffd82020, .end = 0xffd8202b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 02e792c90de6..f7c48e92b95b 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -49,7 +49,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -58,7 +57,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -80,7 +78,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -89,7 +86,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -111,7 +107,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -119,7 +114,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -141,7 +135,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -149,7 +142,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -171,7 +163,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -179,7 +170,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -201,7 +191,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -209,7 +198,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 1fcd88b1671e..05e9308505cf 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -117,7 +117,6 @@ static struct platform_device scif5_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu012_fck", @@ -126,7 +125,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -148,7 +146,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu012_fck", @@ -157,7 +154,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -179,7 +175,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu012_fck", @@ -187,7 +182,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -209,7 +203,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu345_fck", @@ -217,7 +210,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -239,7 +231,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu345_fck", @@ -247,7 +238,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -269,7 +259,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu345_fck", @@ -277,7 +266,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 7e585320710a..542ced88e50f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -117,7 +117,6 @@ static struct platform_device scif5_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -126,7 +125,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -148,7 +146,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -157,7 +154,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -179,7 +175,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -187,7 +182,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -209,7 +203,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -217,7 +210,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffda0008, .end = 0xffda0013, .flags = IORESOURCE_MEM, @@ -239,7 +231,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -247,7 +238,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffda0014, .end = 0xffda001f, .flags = IORESOURCE_MEM, @@ -269,7 +259,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -277,7 +266,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffda0020, .end = 0xffda002b, .flags = IORESOURCE_MEM, @@ -299,7 +287,6 @@ static struct platform_device tmu5_device = { }; static struct sh_timer_config tmu6_platform_data = { - .name = "TMU6", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -307,7 +294,6 @@ static struct sh_timer_config tmu6_platform_data = { static struct resource tmu6_resources[] = { [0] = { - .name = "TMU6", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -329,7 +315,6 @@ static struct platform_device tmu6_device = { }; static struct sh_timer_config tmu7_platform_data = { - .name = "TMU7", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -337,7 +322,6 @@ static struct sh_timer_config tmu7_platform_data = { static struct resource tmu7_resources[] = { [0] = { - .name = "TMU7", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -359,7 +343,6 @@ static struct platform_device tmu7_device = { }; static struct sh_timer_config tmu8_platform_data = { - .name = "TMU8", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -367,7 +350,6 @@ static struct sh_timer_config tmu8_platform_data = { static struct resource tmu8_resources[] = { [0] = { - .name = "TMU8", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, @@ -389,7 +371,6 @@ static struct platform_device tmu8_device = { }; static struct sh_timer_config tmu9_platform_data = { - .name = "TMU9", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -397,7 +378,6 @@ static struct sh_timer_config tmu9_platform_data = { static struct resource tmu9_resources[] = { [0] = { - .name = "TMU9", .start = 0xffde0008, .end = 0xffde0013, .flags = IORESOURCE_MEM, @@ -419,7 +399,6 @@ static struct platform_device tmu9_device = { }; static struct sh_timer_config tmu10_platform_data = { - .name = "TMU10", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -427,7 +406,6 @@ static struct sh_timer_config tmu10_platform_data = { static struct resource tmu10_resources[] = { [0] = { - .name = "TMU10", .start = 0xffde0014, .end = 0xffde001f, .flags = IORESOURCE_MEM, @@ -449,7 +427,6 @@ static struct platform_device tmu10_device = { }; static struct sh_timer_config tmu11_platform_data = { - .name = "TMU11", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -457,7 +434,6 @@ static struct sh_timer_config tmu11_platform_data = { static struct resource tmu11_resources[] = { [0] = { - .name = "TMU11", .start = 0xffde0020, .end = 0xffde002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index 780ba17a5599..ba545b5ccc15 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c @@ -70,7 +70,6 @@ static struct platform_device scif2_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -79,7 +78,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffc10008, .end = 0xffc10013, .flags = IORESOURCE_MEM, @@ -101,7 +99,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -110,7 +107,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffc10014, .end = 0xffc1001f, .flags = IORESOURCE_MEM, @@ -132,7 +128,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -140,7 +135,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffc10020, .end = 0xffc1002f, .flags = IORESOURCE_MEM, @@ -162,7 +156,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -170,7 +163,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffc20008, .end = 0xffc20013, .flags = IORESOURCE_MEM, @@ -192,7 +184,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -200,7 +191,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffc20014, .end = 0xffc2001f, .flags = IORESOURCE_MEM, @@ -222,7 +212,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -230,7 +219,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffc20020, .end = 0xffc2002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index e7a3c1e4b604..c84ca204240b 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c @@ -68,7 +68,6 @@ static struct platform_device rtc_device = { #define TMU2_BASE (TMU_BASE + 0x8 + (0xc * 0x2)) static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -77,7 +76,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = TMU0_BASE, .end = TMU0_BASE + 0xc - 1, .flags = IORESOURCE_MEM, @@ -99,7 +97,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -108,7 +105,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = TMU1_BASE, .end = TMU1_BASE + 0xc - 1, .flags = IORESOURCE_MEM, @@ -130,7 +126,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -138,7 +133,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = TMU2_BASE, .end = TMU2_BASE + 0xc - 1, .flags = IORESOURCE_MEM,