diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-03-23 08:14:02 -0400 |
commit | 3372dbdd8ca11f51be8c6a30b2bc79eb04c4a902 (patch) | |
tree | d4499bf5a5665b4820ffaf96bce55bf6b895195e /sound/core | |
parent | bc465aa9d045feb0e13b4a8f32cc33c1943f62d6 (diff) | |
parent | 967b1307b69b8ada8b331e01046ad1ef83742e99 (diff) |
Merge branch 'for-next' into topic/hda-core
Diffstat (limited to 'sound/core')
29 files changed, 553 insertions, 768 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index eeb691d1911f..d677c27746e9 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -192,36 +192,41 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, | |||
192 | EXPORT_SYMBOL(snd_ctl_notify); | 192 | EXPORT_SYMBOL(snd_ctl_notify); |
193 | 193 | ||
194 | /** | 194 | /** |
195 | * snd_ctl_new - create a control instance from the template | 195 | * snd_ctl_new - create a new control instance with some elements |
196 | * @control: the control template | 196 | * @kctl: the pointer to store new control instance |
197 | * @access: the default control access | 197 | * @count: the number of elements in this control |
198 | * @access: the default access flags for elements in this control | ||
199 | * @file: given when locking these elements | ||
198 | * | 200 | * |
199 | * Allocates a new struct snd_kcontrol instance and copies the given template | 201 | * Allocates a memory object for a new control instance. The instance has |
200 | * to the new instance. It does not copy volatile data (access). | 202 | * elements as many as the given number (@count). Each element has given |
203 | * access permissions (@access). Each element is locked when @file is given. | ||
201 | * | 204 | * |
202 | * Return: The pointer of the new instance, or %NULL on failure. | 205 | * Return: 0 on success, error code on failure |
203 | */ | 206 | */ |
204 | static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, | 207 | static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count, |
205 | unsigned int access) | 208 | unsigned int access, struct snd_ctl_file *file) |
206 | { | 209 | { |
207 | struct snd_kcontrol *kctl; | 210 | unsigned int size; |
208 | unsigned int idx; | 211 | unsigned int idx; |
209 | 212 | ||
210 | if (snd_BUG_ON(!control || !control->count)) | 213 | if (count == 0 || count > MAX_CONTROL_COUNT) |
211 | return NULL; | 214 | return -EINVAL; |
212 | 215 | ||
213 | if (control->count > MAX_CONTROL_COUNT) | 216 | size = sizeof(struct snd_kcontrol); |
214 | return NULL; | 217 | size += sizeof(struct snd_kcontrol_volatile) * count; |
215 | 218 | ||
216 | kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); | 219 | *kctl = kzalloc(size, GFP_KERNEL); |
217 | if (kctl == NULL) { | 220 | if (!*kctl) |
218 | pr_err("ALSA: Cannot allocate control instance\n"); | 221 | return -ENOMEM; |
219 | return NULL; | 222 | |
223 | for (idx = 0; idx < count; idx++) { | ||
224 | (*kctl)->vd[idx].access = access; | ||
225 | (*kctl)->vd[idx].owner = file; | ||
220 | } | 226 | } |
221 | *kctl = *control; | 227 | (*kctl)->count = count; |
222 | for (idx = 0; idx < kctl->count; idx++) | 228 | |
223 | kctl->vd[idx].access = access; | 229 | return 0; |
224 | return kctl; | ||
225 | } | 230 | } |
226 | 231 | ||
227 | /** | 232 | /** |
@@ -238,37 +243,53 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, | |||
238 | struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | 243 | struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, |
239 | void *private_data) | 244 | void *private_data) |
240 | { | 245 | { |
241 | struct snd_kcontrol kctl; | 246 | struct snd_kcontrol *kctl; |
247 | unsigned int count; | ||
242 | unsigned int access; | 248 | unsigned int access; |
249 | int err; | ||
243 | 250 | ||
244 | if (snd_BUG_ON(!ncontrol || !ncontrol->info)) | 251 | if (snd_BUG_ON(!ncontrol || !ncontrol->info)) |
245 | return NULL; | 252 | return NULL; |
246 | memset(&kctl, 0, sizeof(kctl)); | 253 | |
247 | kctl.id.iface = ncontrol->iface; | 254 | count = ncontrol->count; |
248 | kctl.id.device = ncontrol->device; | 255 | if (count == 0) |
249 | kctl.id.subdevice = ncontrol->subdevice; | 256 | count = 1; |
257 | |||
258 | access = ncontrol->access; | ||
259 | if (access == 0) | ||
260 | access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
261 | access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
262 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | | ||
263 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | | ||
264 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | | ||
265 | SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND | | ||
266 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); | ||
267 | |||
268 | err = snd_ctl_new(&kctl, count, access, NULL); | ||
269 | if (err < 0) | ||
270 | return NULL; | ||
271 | |||
272 | /* The 'numid' member is decided when calling snd_ctl_add(). */ | ||
273 | kctl->id.iface = ncontrol->iface; | ||
274 | kctl->id.device = ncontrol->device; | ||
275 | kctl->id.subdevice = ncontrol->subdevice; | ||
250 | if (ncontrol->name) { | 276 | if (ncontrol->name) { |
251 | strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name)); | 277 | strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name)); |
252 | if (strcmp(ncontrol->name, kctl.id.name) != 0) | 278 | if (strcmp(ncontrol->name, kctl->id.name) != 0) |
253 | pr_warn("ALSA: Control name '%s' truncated to '%s'\n", | 279 | pr_warn("ALSA: Control name '%s' truncated to '%s'\n", |
254 | ncontrol->name, kctl.id.name); | 280 | ncontrol->name, kctl->id.name); |
255 | } | 281 | } |
256 | kctl.id.index = ncontrol->index; | 282 | kctl->id.index = ncontrol->index; |
257 | kctl.count = ncontrol->count ? ncontrol->count : 1; | 283 | |
258 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 284 | kctl->info = ncontrol->info; |
259 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 285 | kctl->get = ncontrol->get; |
260 | SNDRV_CTL_ELEM_ACCESS_VOLATILE| | 286 | kctl->put = ncontrol->put; |
261 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| | 287 | kctl->tlv.p = ncontrol->tlv.p; |
262 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| | 288 | |
263 | SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| | 289 | kctl->private_value = ncontrol->private_value; |
264 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); | 290 | kctl->private_data = private_data; |
265 | kctl.info = ncontrol->info; | 291 | |
266 | kctl.get = ncontrol->get; | 292 | return kctl; |
267 | kctl.put = ncontrol->put; | ||
268 | kctl.tlv.p = ncontrol->tlv.p; | ||
269 | kctl.private_value = ncontrol->private_value; | ||
270 | kctl.private_data = private_data; | ||
271 | return snd_ctl_new(&kctl, access); | ||
272 | } | 293 | } |
273 | EXPORT_SYMBOL(snd_ctl_new1); | 294 | EXPORT_SYMBOL(snd_ctl_new1); |
274 | 295 | ||
@@ -1161,84 +1182,102 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) | |||
1161 | static int snd_ctl_elem_add(struct snd_ctl_file *file, | 1182 | static int snd_ctl_elem_add(struct snd_ctl_file *file, |
1162 | struct snd_ctl_elem_info *info, int replace) | 1183 | struct snd_ctl_elem_info *info, int replace) |
1163 | { | 1184 | { |
1185 | /* The capacity of struct snd_ctl_elem_value.value.*/ | ||
1186 | static const unsigned int value_sizes[] = { | ||
1187 | [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = sizeof(long), | ||
1188 | [SNDRV_CTL_ELEM_TYPE_INTEGER] = sizeof(long), | ||
1189 | [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int), | ||
1190 | [SNDRV_CTL_ELEM_TYPE_BYTES] = sizeof(unsigned char), | ||
1191 | [SNDRV_CTL_ELEM_TYPE_IEC958] = sizeof(struct snd_aes_iec958), | ||
1192 | [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long), | ||
1193 | }; | ||
1194 | static const unsigned int max_value_counts[] = { | ||
1195 | [SNDRV_CTL_ELEM_TYPE_BOOLEAN] = 128, | ||
1196 | [SNDRV_CTL_ELEM_TYPE_INTEGER] = 128, | ||
1197 | [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128, | ||
1198 | [SNDRV_CTL_ELEM_TYPE_BYTES] = 512, | ||
1199 | [SNDRV_CTL_ELEM_TYPE_IEC958] = 1, | ||
1200 | [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64, | ||
1201 | }; | ||
1164 | struct snd_card *card = file->card; | 1202 | struct snd_card *card = file->card; |
1165 | struct snd_kcontrol kctl, *_kctl; | 1203 | struct snd_kcontrol *kctl; |
1204 | unsigned int count; | ||
1166 | unsigned int access; | 1205 | unsigned int access; |
1167 | long private_size; | 1206 | long private_size; |
1168 | struct user_element *ue; | 1207 | struct user_element *ue; |
1169 | int idx, err; | 1208 | int err; |
1170 | 1209 | ||
1171 | if (info->count < 1) | ||
1172 | return -EINVAL; | ||
1173 | if (!*info->id.name) | 1210 | if (!*info->id.name) |
1174 | return -EINVAL; | 1211 | return -EINVAL; |
1175 | if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name)) | 1212 | if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name)) |
1176 | return -EINVAL; | 1213 | return -EINVAL; |
1177 | access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | ||
1178 | (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | ||
1179 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| | ||
1180 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)); | ||
1181 | info->id.numid = 0; | ||
1182 | memset(&kctl, 0, sizeof(kctl)); | ||
1183 | 1214 | ||
1215 | /* Delete a control to replace them if needed. */ | ||
1184 | if (replace) { | 1216 | if (replace) { |
1217 | info->id.numid = 0; | ||
1185 | err = snd_ctl_remove_user_ctl(file, &info->id); | 1218 | err = snd_ctl_remove_user_ctl(file, &info->id); |
1186 | if (err) | 1219 | if (err) |
1187 | return err; | 1220 | return err; |
1188 | } | 1221 | } |
1189 | 1222 | ||
1190 | if (card->user_ctl_count >= MAX_USER_CONTROLS) | 1223 | /* |
1224 | * The number of userspace controls are counted control by control, | ||
1225 | * not element by element. | ||
1226 | */ | ||
1227 | if (card->user_ctl_count + 1 > MAX_USER_CONTROLS) | ||
1191 | return -ENOMEM; | 1228 | return -ENOMEM; |
1192 | 1229 | ||
1193 | memcpy(&kctl.id, &info->id, sizeof(info->id)); | 1230 | /* Check the number of elements for this userspace control. */ |
1194 | kctl.count = info->owner ? info->owner : 1; | 1231 | count = info->owner; |
1195 | access |= SNDRV_CTL_ELEM_ACCESS_USER; | 1232 | if (count == 0) |
1196 | if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) | 1233 | count = 1; |
1197 | kctl.info = snd_ctl_elem_user_enum_info; | 1234 | |
1198 | else | 1235 | /* Arrange access permissions if needed. */ |
1199 | kctl.info = snd_ctl_elem_user_info; | 1236 | access = info->access; |
1200 | if (access & SNDRV_CTL_ELEM_ACCESS_READ) | 1237 | if (access == 0) |
1201 | kctl.get = snd_ctl_elem_user_get; | 1238 | access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
1202 | if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) | 1239 | access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1203 | kctl.put = snd_ctl_elem_user_put; | 1240 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | |
1204 | if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { | 1241 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE); |
1205 | kctl.tlv.c = snd_ctl_elem_user_tlv; | 1242 | if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) |
1206 | access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | 1243 | access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; |
1207 | } | 1244 | access |= SNDRV_CTL_ELEM_ACCESS_USER; |
1208 | switch (info->type) { | 1245 | |
1209 | case SNDRV_CTL_ELEM_TYPE_BOOLEAN: | 1246 | /* |
1210 | case SNDRV_CTL_ELEM_TYPE_INTEGER: | 1247 | * Check information and calculate the size of data specific to |
1211 | private_size = sizeof(long); | 1248 | * this userspace control. |
1212 | if (info->count > 128) | 1249 | */ |
1213 | return -EINVAL; | 1250 | if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN || |
1214 | break; | 1251 | info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64) |
1215 | case SNDRV_CTL_ELEM_TYPE_INTEGER64: | ||
1216 | private_size = sizeof(long long); | ||
1217 | if (info->count > 64) | ||
1218 | return -EINVAL; | ||
1219 | break; | ||
1220 | case SNDRV_CTL_ELEM_TYPE_ENUMERATED: | ||
1221 | private_size = sizeof(unsigned int); | ||
1222 | if (info->count > 128 || info->value.enumerated.items == 0) | ||
1223 | return -EINVAL; | ||
1224 | break; | ||
1225 | case SNDRV_CTL_ELEM_TYPE_BYTES: | ||
1226 | private_size = sizeof(unsigned char); | ||
1227 | if (info->count > 512) | ||
1228 | return -EINVAL; | ||
1229 | break; | ||
1230 | case SNDRV_CTL_ELEM_TYPE_IEC958: | ||
1231 | private_size = sizeof(struct snd_aes_iec958); | ||
1232 | if (info->count != 1) | ||
1233 | return -EINVAL; | ||
1234 | break; | ||
1235 | default: | ||
1236 | return -EINVAL; | 1252 | return -EINVAL; |
1237 | } | 1253 | if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED && |
1238 | private_size *= info->count; | 1254 | info->value.enumerated.items == 0) |
1239 | ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL); | 1255 | return -EINVAL; |
1240 | if (ue == NULL) | 1256 | if (info->count < 1 || |
1257 | info->count > max_value_counts[info->type]) | ||
1258 | return -EINVAL; | ||
1259 | private_size = value_sizes[info->type] * info->count; | ||
1260 | |||
1261 | /* | ||
1262 | * Keep memory object for this userspace control. After passing this | ||
1263 | * code block, the instance should be freed by snd_ctl_free_one(). | ||
1264 | * | ||
1265 | * Note that these elements in this control are locked. | ||
1266 | */ | ||
1267 | err = snd_ctl_new(&kctl, count, access, file); | ||
1268 | if (err < 0) | ||
1269 | return err; | ||
1270 | memcpy(&kctl->id, &info->id, sizeof(kctl->id)); | ||
1271 | kctl->private_data = kzalloc(sizeof(struct user_element) + private_size, | ||
1272 | GFP_KERNEL); | ||
1273 | if (kctl->private_data == NULL) { | ||
1274 | kfree(kctl); | ||
1241 | return -ENOMEM; | 1275 | return -ENOMEM; |
1276 | } | ||
1277 | kctl->private_free = snd_ctl_elem_user_free; | ||
1278 | |||
1279 | /* Set private data for this userspace control. */ | ||
1280 | ue = (struct user_element *)kctl->private_data; | ||
1242 | ue->card = card; | 1281 | ue->card = card; |
1243 | ue->info = *info; | 1282 | ue->info = *info; |
1244 | ue->info.access = 0; | 1283 | ue->info.access = 0; |
@@ -1247,21 +1286,25 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, | |||
1247 | if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { | 1286 | if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { |
1248 | err = snd_ctl_elem_init_enum_names(ue); | 1287 | err = snd_ctl_elem_init_enum_names(ue); |
1249 | if (err < 0) { | 1288 | if (err < 0) { |
1250 | kfree(ue); | 1289 | snd_ctl_free_one(kctl); |
1251 | return err; | 1290 | return err; |
1252 | } | 1291 | } |
1253 | } | 1292 | } |
1254 | kctl.private_free = snd_ctl_elem_user_free; | 1293 | |
1255 | _kctl = snd_ctl_new(&kctl, access); | 1294 | /* Set callback functions. */ |
1256 | if (_kctl == NULL) { | 1295 | if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) |
1257 | kfree(ue->priv_data); | 1296 | kctl->info = snd_ctl_elem_user_enum_info; |
1258 | kfree(ue); | 1297 | else |
1259 | return -ENOMEM; | 1298 | kctl->info = snd_ctl_elem_user_info; |
1260 | } | 1299 | if (access & SNDRV_CTL_ELEM_ACCESS_READ) |
1261 | _kctl->private_data = ue; | 1300 | kctl->get = snd_ctl_elem_user_get; |
1262 | for (idx = 0; idx < _kctl->count; idx++) | 1301 | if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) |
1263 | _kctl->vd[idx].owner = file; | 1302 | kctl->put = snd_ctl_elem_user_put; |
1264 | err = snd_ctl_add(card, _kctl); | 1303 | if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) |
1304 | kctl->tlv.c = snd_ctl_elem_user_tlv; | ||
1305 | |||
1306 | /* This function manage to free the instance on failure. */ | ||
1307 | err = snd_ctl_add(card, kctl); | ||
1265 | if (err < 0) | 1308 | if (err < 0) |
1266 | return err; | 1309 | return err; |
1267 | 1310 | ||
diff --git a/sound/core/device.c b/sound/core/device.c index 41bec3075ae5..8918838b1999 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -50,10 +50,8 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type, | |||
50 | if (snd_BUG_ON(!card || !device_data || !ops)) | 50 | if (snd_BUG_ON(!card || !device_data || !ops)) |
51 | return -ENXIO; | 51 | return -ENXIO; |
52 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 52 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
53 | if (dev == NULL) { | 53 | if (!dev) |
54 | dev_err(card->dev, "Cannot allocate device, type=%d\n", type); | ||
55 | return -ENOMEM; | 54 | return -ENOMEM; |
56 | } | ||
57 | INIT_LIST_HEAD(&dev->list); | 55 | INIT_LIST_HEAD(&dev->list); |
58 | dev->card = card; | 56 | dev->card = card; |
59 | dev->type = type; | 57 | dev->type = type; |
@@ -73,7 +71,7 @@ int snd_device_new(struct snd_card *card, enum snd_device_type type, | |||
73 | } | 71 | } |
74 | EXPORT_SYMBOL(snd_device_new); | 72 | EXPORT_SYMBOL(snd_device_new); |
75 | 73 | ||
76 | static int __snd_device_disconnect(struct snd_device *dev) | 74 | static void __snd_device_disconnect(struct snd_device *dev) |
77 | { | 75 | { |
78 | if (dev->state == SNDRV_DEV_REGISTERED) { | 76 | if (dev->state == SNDRV_DEV_REGISTERED) { |
79 | if (dev->ops->dev_disconnect && | 77 | if (dev->ops->dev_disconnect && |
@@ -81,7 +79,6 @@ static int __snd_device_disconnect(struct snd_device *dev) | |||
81 | dev_err(dev->card->dev, "device disconnect failure\n"); | 79 | dev_err(dev->card->dev, "device disconnect failure\n"); |
82 | dev->state = SNDRV_DEV_DISCONNECTED; | 80 | dev->state = SNDRV_DEV_DISCONNECTED; |
83 | } | 81 | } |
84 | return 0; | ||
85 | } | 82 | } |
86 | 83 | ||
87 | static void __snd_device_free(struct snd_device *dev) | 84 | static void __snd_device_free(struct snd_device *dev) |
@@ -109,6 +106,34 @@ static struct snd_device *look_for_dev(struct snd_card *card, void *device_data) | |||
109 | } | 106 | } |
110 | 107 | ||
111 | /** | 108 | /** |
109 | * snd_device_disconnect - disconnect the device | ||
110 | * @card: the card instance | ||
111 | * @device_data: the data pointer to disconnect | ||
112 | * | ||
113 | * Turns the device into the disconnection state, invoking | ||
114 | * dev_disconnect callback, if the device was already registered. | ||
115 | * | ||
116 | * Usually called from snd_card_disconnect(). | ||
117 | * | ||
118 | * Return: Zero if successful, or a negative error code on failure or if the | ||
119 | * device not found. | ||
120 | */ | ||
121 | void snd_device_disconnect(struct snd_card *card, void *device_data) | ||
122 | { | ||
123 | struct snd_device *dev; | ||
124 | |||
125 | if (snd_BUG_ON(!card || !device_data)) | ||
126 | return; | ||
127 | dev = look_for_dev(card, device_data); | ||
128 | if (dev) | ||
129 | __snd_device_disconnect(dev); | ||
130 | else | ||
131 | dev_dbg(card->dev, "device disconnect %p (from %pF), not found\n", | ||
132 | device_data, __builtin_return_address(0)); | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(snd_device_disconnect); | ||
135 | |||
136 | /** | ||
112 | * snd_device_free - release the device from the card | 137 | * snd_device_free - release the device from the card |
113 | * @card: the card instance | 138 | * @card: the card instance |
114 | * @device_data: the data pointer to release | 139 | * @device_data: the data pointer to release |
@@ -195,18 +220,14 @@ int snd_device_register_all(struct snd_card *card) | |||
195 | * disconnect all the devices on the card. | 220 | * disconnect all the devices on the card. |
196 | * called from init.c | 221 | * called from init.c |
197 | */ | 222 | */ |
198 | int snd_device_disconnect_all(struct snd_card *card) | 223 | void snd_device_disconnect_all(struct snd_card *card) |
199 | { | 224 | { |
200 | struct snd_device *dev; | 225 | struct snd_device *dev; |
201 | int err = 0; | ||
202 | 226 | ||
203 | if (snd_BUG_ON(!card)) | 227 | if (snd_BUG_ON(!card)) |
204 | return -ENXIO; | 228 | return; |
205 | list_for_each_entry_reverse(dev, &card->devices, list) { | 229 | list_for_each_entry_reverse(dev, &card->devices, list) |
206 | if (__snd_device_disconnect(dev) < 0) | 230 | __snd_device_disconnect(dev); |
207 | err = -ENXIO; | ||
208 | } | ||
209 | return err; | ||
210 | } | 231 | } |
211 | 232 | ||
212 | /* | 233 | /* |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 84244a5143cf..51692c8a39ea 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -378,10 +378,8 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, | |||
378 | if (rhwdep) | 378 | if (rhwdep) |
379 | *rhwdep = NULL; | 379 | *rhwdep = NULL; |
380 | hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); | 380 | hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); |
381 | if (hwdep == NULL) { | 381 | if (!hwdep) |
382 | dev_err(card->dev, "hwdep: cannot allocate\n"); | ||
383 | return -ENOMEM; | 382 | return -ENOMEM; |
384 | } | ||
385 | 383 | ||
386 | init_waitqueue_head(&hwdep->open_wait); | 384 | init_waitqueue_head(&hwdep->open_wait); |
387 | mutex_init(&hwdep->open_mutex); | 385 | mutex_init(&hwdep->open_mutex); |
diff --git a/sound/core/init.c b/sound/core/init.c index 35419054821c..04734e047bfe 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -400,7 +400,6 @@ static const struct file_operations snd_shutdown_f_ops = | |||
400 | int snd_card_disconnect(struct snd_card *card) | 400 | int snd_card_disconnect(struct snd_card *card) |
401 | { | 401 | { |
402 | struct snd_monitor_file *mfile; | 402 | struct snd_monitor_file *mfile; |
403 | int err; | ||
404 | 403 | ||
405 | if (!card) | 404 | if (!card) |
406 | return -EINVAL; | 405 | return -EINVAL; |
@@ -445,9 +444,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
445 | #endif | 444 | #endif |
446 | 445 | ||
447 | /* notify all devices that we are disconnected */ | 446 | /* notify all devices that we are disconnected */ |
448 | err = snd_device_disconnect_all(card); | 447 | snd_device_disconnect_all(card); |
449 | if (err < 0) | ||
450 | dev_err(card->dev, "not all devices for card %i can be disconnected\n", card->number); | ||
451 | 448 | ||
452 | snd_info_card_disconnect(card); | 449 | snd_info_card_disconnect(card); |
453 | if (card->registered) { | 450 | if (card->registered) { |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 5e6349f00ecd..056f8e274851 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1212,10 +1212,8 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, | |||
1212 | /* not changed */ | 1212 | /* not changed */ |
1213 | goto __unlock; | 1213 | goto __unlock; |
1214 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); | 1214 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); |
1215 | if (! tbl) { | 1215 | if (!tbl) |
1216 | pr_err("ALSA: mixer_oss: no memory\n"); | ||
1217 | goto __unlock; | 1216 | goto __unlock; |
1218 | } | ||
1219 | tbl->oss_id = ch; | 1217 | tbl->oss_id = ch; |
1220 | tbl->name = kstrdup(str, GFP_KERNEL); | 1218 | tbl->name = kstrdup(str, GFP_KERNEL); |
1221 | if (! tbl->name) { | 1219 | if (! tbl->name) { |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 80423a4ccab6..58550cc93f28 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -854,7 +854,6 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
854 | params = kmalloc(sizeof(*params), GFP_KERNEL); | 854 | params = kmalloc(sizeof(*params), GFP_KERNEL); |
855 | sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); | 855 | sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); |
856 | if (!sw_params || !params || !sparams) { | 856 | if (!sw_params || !params || !sparams) { |
857 | pcm_dbg(substream->pcm, "No memory\n"); | ||
858 | err = -ENOMEM; | 857 | err = -ENOMEM; |
859 | goto failure; | 858 | goto failure; |
860 | } | 859 | } |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 0345e53a340c..b25bcf5b8644 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) | |||
49 | struct snd_pcm *pcm; | 49 | struct snd_pcm *pcm; |
50 | 50 | ||
51 | list_for_each_entry(pcm, &snd_pcm_devices, list) { | 51 | list_for_each_entry(pcm, &snd_pcm_devices, list) { |
52 | if (pcm->internal) | ||
53 | continue; | ||
54 | if (pcm->card == card && pcm->device == device) | 52 | if (pcm->card == card && pcm->device == device) |
55 | return pcm; | 53 | return pcm; |
56 | } | 54 | } |
@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device) | |||
62 | struct snd_pcm *pcm; | 60 | struct snd_pcm *pcm; |
63 | 61 | ||
64 | list_for_each_entry(pcm, &snd_pcm_devices, list) { | 62 | list_for_each_entry(pcm, &snd_pcm_devices, list) { |
65 | if (pcm->internal) | ||
66 | continue; | ||
67 | if (pcm->card == card && pcm->device > device) | 63 | if (pcm->card == card && pcm->device > device) |
68 | return pcm->device; | 64 | return pcm->device; |
69 | else if (pcm->card->number > card->number) | 65 | else if (pcm->card->number > card->number) |
@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm) | |||
76 | { | 72 | { |
77 | struct snd_pcm *pcm; | 73 | struct snd_pcm *pcm; |
78 | 74 | ||
75 | if (newpcm->internal) | ||
76 | return 0; | ||
77 | |||
79 | list_for_each_entry(pcm, &snd_pcm_devices, list) { | 78 | list_for_each_entry(pcm, &snd_pcm_devices, list) { |
80 | if (pcm->card == newpcm->card && pcm->device == newpcm->device) | 79 | if (pcm->card == newpcm->card && pcm->device == newpcm->device) |
81 | return -EBUSY; | 80 | return -EBUSY; |
@@ -344,11 +343,8 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, | |||
344 | return; | 343 | return; |
345 | 344 | ||
346 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 345 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
347 | if (! info) { | 346 | if (!info) |
348 | pcm_dbg(substream->pcm, | ||
349 | "snd_pcm_proc_info_read: cannot malloc\n"); | ||
350 | return; | 347 | return; |
351 | } | ||
352 | 348 | ||
353 | err = snd_pcm_info(substream, info); | 349 | err = snd_pcm_info(substream, info); |
354 | if (err < 0) { | 350 | if (err < 0) { |
@@ -718,10 +714,8 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
718 | prev = NULL; | 714 | prev = NULL; |
719 | for (idx = 0, prev = NULL; idx < substream_count; idx++) { | 715 | for (idx = 0, prev = NULL; idx < substream_count; idx++) { |
720 | substream = kzalloc(sizeof(*substream), GFP_KERNEL); | 716 | substream = kzalloc(sizeof(*substream), GFP_KERNEL); |
721 | if (substream == NULL) { | 717 | if (!substream) |
722 | pcm_err(pcm, "Cannot allocate PCM substream\n"); | ||
723 | return -ENOMEM; | 718 | return -ENOMEM; |
724 | } | ||
725 | substream->pcm = pcm; | 719 | substream->pcm = pcm; |
726 | substream->pstr = pstr; | 720 | substream->pstr = pstr; |
727 | substream->number = idx; | 721 | substream->number = idx; |
@@ -775,13 +769,14 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, | |||
775 | if (rpcm) | 769 | if (rpcm) |
776 | *rpcm = NULL; | 770 | *rpcm = NULL; |
777 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 771 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
778 | if (pcm == NULL) { | 772 | if (!pcm) |
779 | dev_err(card->dev, "Cannot allocate PCM\n"); | ||
780 | return -ENOMEM; | 773 | return -ENOMEM; |
781 | } | ||
782 | pcm->card = card; | 774 | pcm->card = card; |
783 | pcm->device = device; | 775 | pcm->device = device; |
784 | pcm->internal = internal; | 776 | pcm->internal = internal; |
777 | mutex_init(&pcm->open_mutex); | ||
778 | init_waitqueue_head(&pcm->open_wait); | ||
779 | INIT_LIST_HEAD(&pcm->list); | ||
785 | if (id) | 780 | if (id) |
786 | strlcpy(pcm->id, id, sizeof(pcm->id)); | 781 | strlcpy(pcm->id, id, sizeof(pcm->id)); |
787 | if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { | 782 | if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { |
@@ -792,8 +787,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device, | |||
792 | snd_pcm_free(pcm); | 787 | snd_pcm_free(pcm); |
793 | return err; | 788 | return err; |
794 | } | 789 | } |
795 | mutex_init(&pcm->open_mutex); | ||
796 | init_waitqueue_head(&pcm->open_wait); | ||
797 | if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { | 790 | if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { |
798 | snd_pcm_free(pcm); | 791 | snd_pcm_free(pcm); |
799 | return err; | 792 | return err; |
@@ -888,8 +881,9 @@ static int snd_pcm_free(struct snd_pcm *pcm) | |||
888 | 881 | ||
889 | if (!pcm) | 882 | if (!pcm) |
890 | return 0; | 883 | return 0; |
891 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 884 | if (!pcm->internal) { |
892 | notify->n_unregister(pcm); | 885 | list_for_each_entry(notify, &snd_pcm_notify_list, list) |
886 | notify->n_unregister(pcm); | ||
893 | } | 887 | } |
894 | if (pcm->private_free) | 888 | if (pcm->private_free) |
895 | pcm->private_free(pcm); | 889 | pcm->private_free(pcm); |
@@ -919,6 +913,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
919 | 913 | ||
920 | if (snd_BUG_ON(!pcm || !rsubstream)) | 914 | if (snd_BUG_ON(!pcm || !rsubstream)) |
921 | return -ENXIO; | 915 | return -ENXIO; |
916 | if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK && | ||
917 | stream != SNDRV_PCM_STREAM_CAPTURE)) | ||
918 | return -EINVAL; | ||
922 | *rsubstream = NULL; | 919 | *rsubstream = NULL; |
923 | pstr = &pcm->streams[stream]; | 920 | pstr = &pcm->streams[stream]; |
924 | if (pstr->substream == NULL || pstr->substream_count == 0) | 921 | if (pstr->substream == NULL || pstr->substream_count == 0) |
@@ -927,25 +924,14 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
927 | card = pcm->card; | 924 | card = pcm->card; |
928 | prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); | 925 | prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); |
929 | 926 | ||
930 | switch (stream) { | 927 | if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { |
931 | case SNDRV_PCM_STREAM_PLAYBACK: | 928 | int opposite = !stream; |
932 | if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { | 929 | |
933 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) { | 930 | for (substream = pcm->streams[opposite].substream; substream; |
934 | if (SUBSTREAM_BUSY(substream)) | 931 | substream = substream->next) { |
935 | return -EAGAIN; | 932 | if (SUBSTREAM_BUSY(substream)) |
936 | } | 933 | return -EAGAIN; |
937 | } | ||
938 | break; | ||
939 | case SNDRV_PCM_STREAM_CAPTURE: | ||
940 | if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { | ||
941 | for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) { | ||
942 | if (SUBSTREAM_BUSY(substream)) | ||
943 | return -EAGAIN; | ||
944 | } | ||
945 | } | 934 | } |
946 | break; | ||
947 | default: | ||
948 | return -EINVAL; | ||
949 | } | 935 | } |
950 | 936 | ||
951 | if (file->f_flags & O_APPEND) { | 937 | if (file->f_flags & O_APPEND) { |
@@ -968,15 +954,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
968 | return 0; | 954 | return 0; |
969 | } | 955 | } |
970 | 956 | ||
971 | if (prefer_subdevice >= 0) { | 957 | for (substream = pstr->substream; substream; substream = substream->next) { |
972 | for (substream = pstr->substream; substream; substream = substream->next) | 958 | if (!SUBSTREAM_BUSY(substream) && |
973 | if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) | 959 | (prefer_subdevice == -1 || |
974 | goto __ok; | 960 | substream->number == prefer_subdevice)) |
975 | } | ||
976 | for (substream = pstr->substream; substream; substream = substream->next) | ||
977 | if (!SUBSTREAM_BUSY(substream)) | ||
978 | break; | 961 | break; |
979 | __ok: | 962 | } |
980 | if (substream == NULL) | 963 | if (substream == NULL) |
981 | return -EAGAIN; | 964 | return -EAGAIN; |
982 | 965 | ||
@@ -1086,15 +1069,16 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1086 | if (snd_BUG_ON(!device || !device->device_data)) | 1069 | if (snd_BUG_ON(!device || !device->device_data)) |
1087 | return -ENXIO; | 1070 | return -ENXIO; |
1088 | pcm = device->device_data; | 1071 | pcm = device->device_data; |
1072 | if (pcm->internal) | ||
1073 | return 0; | ||
1074 | |||
1089 | mutex_lock(®ister_mutex); | 1075 | mutex_lock(®ister_mutex); |
1090 | err = snd_pcm_add(pcm); | 1076 | err = snd_pcm_add(pcm); |
1091 | if (err) { | 1077 | if (err) |
1092 | mutex_unlock(®ister_mutex); | 1078 | goto unlock; |
1093 | return err; | ||
1094 | } | ||
1095 | for (cidx = 0; cidx < 2; cidx++) { | 1079 | for (cidx = 0; cidx < 2; cidx++) { |
1096 | int devtype = -1; | 1080 | int devtype = -1; |
1097 | if (pcm->streams[cidx].substream == NULL || pcm->internal) | 1081 | if (pcm->streams[cidx].substream == NULL) |
1098 | continue; | 1082 | continue; |
1099 | switch (cidx) { | 1083 | switch (cidx) { |
1100 | case SNDRV_PCM_STREAM_PLAYBACK: | 1084 | case SNDRV_PCM_STREAM_PLAYBACK: |
@@ -1109,9 +1093,8 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1109 | &snd_pcm_f_ops[cidx], pcm, | 1093 | &snd_pcm_f_ops[cidx], pcm, |
1110 | &pcm->streams[cidx].dev); | 1094 | &pcm->streams[cidx].dev); |
1111 | if (err < 0) { | 1095 | if (err < 0) { |
1112 | list_del(&pcm->list); | 1096 | list_del_init(&pcm->list); |
1113 | mutex_unlock(®ister_mutex); | 1097 | goto unlock; |
1114 | return err; | ||
1115 | } | 1098 | } |
1116 | 1099 | ||
1117 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | 1100 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) |
@@ -1121,8 +1104,9 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1121 | list_for_each_entry(notify, &snd_pcm_notify_list, list) | 1104 | list_for_each_entry(notify, &snd_pcm_notify_list, list) |
1122 | notify->n_register(pcm); | 1105 | notify->n_register(pcm); |
1123 | 1106 | ||
1107 | unlock: | ||
1124 | mutex_unlock(®ister_mutex); | 1108 | mutex_unlock(®ister_mutex); |
1125 | return 0; | 1109 | return err; |
1126 | } | 1110 | } |
1127 | 1111 | ||
1128 | static int snd_pcm_dev_disconnect(struct snd_device *device) | 1112 | static int snd_pcm_dev_disconnect(struct snd_device *device) |
@@ -1133,13 +1117,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1133 | int cidx; | 1117 | int cidx; |
1134 | 1118 | ||
1135 | mutex_lock(®ister_mutex); | 1119 | mutex_lock(®ister_mutex); |
1136 | if (list_empty(&pcm->list)) | ||
1137 | goto unlock; | ||
1138 | |||
1139 | mutex_lock(&pcm->open_mutex); | 1120 | mutex_lock(&pcm->open_mutex); |
1140 | wake_up(&pcm->open_wait); | 1121 | wake_up(&pcm->open_wait); |
1141 | list_del_init(&pcm->list); | 1122 | list_del_init(&pcm->list); |
1142 | for (cidx = 0; cidx < 2; cidx++) | 1123 | for (cidx = 0; cidx < 2; cidx++) { |
1143 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { | 1124 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { |
1144 | snd_pcm_stream_lock_irq(substream); | 1125 | snd_pcm_stream_lock_irq(substream); |
1145 | if (substream->runtime) { | 1126 | if (substream->runtime) { |
@@ -1149,18 +1130,20 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1149 | } | 1130 | } |
1150 | snd_pcm_stream_unlock_irq(substream); | 1131 | snd_pcm_stream_unlock_irq(substream); |
1151 | } | 1132 | } |
1152 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 1133 | } |
1153 | notify->n_disconnect(pcm); | 1134 | if (!pcm->internal) { |
1135 | list_for_each_entry(notify, &snd_pcm_notify_list, list) | ||
1136 | notify->n_disconnect(pcm); | ||
1154 | } | 1137 | } |
1155 | for (cidx = 0; cidx < 2; cidx++) { | 1138 | for (cidx = 0; cidx < 2; cidx++) { |
1156 | snd_unregister_device(&pcm->streams[cidx].dev); | 1139 | if (!pcm->internal) |
1140 | snd_unregister_device(&pcm->streams[cidx].dev); | ||
1157 | if (pcm->streams[cidx].chmap_kctl) { | 1141 | if (pcm->streams[cidx].chmap_kctl) { |
1158 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); | 1142 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); |
1159 | pcm->streams[cidx].chmap_kctl = NULL; | 1143 | pcm->streams[cidx].chmap_kctl = NULL; |
1160 | } | 1144 | } |
1161 | } | 1145 | } |
1162 | mutex_unlock(&pcm->open_mutex); | 1146 | mutex_unlock(&pcm->open_mutex); |
1163 | unlock: | ||
1164 | mutex_unlock(®ister_mutex); | 1147 | mutex_unlock(®ister_mutex); |
1165 | return 0; | 1148 | return 0; |
1166 | } | 1149 | } |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 2d957ba63557..b48b434444ed 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -194,18 +194,30 @@ struct snd_pcm_status32 { | |||
194 | u32 avail_max; | 194 | u32 avail_max; |
195 | u32 overrange; | 195 | u32 overrange; |
196 | s32 suspended_state; | 196 | s32 suspended_state; |
197 | u32 reserved_alignment; | 197 | u32 audio_tstamp_data; |
198 | struct compat_timespec audio_tstamp; | 198 | struct compat_timespec audio_tstamp; |
199 | unsigned char reserved[56-sizeof(struct compat_timespec)]; | 199 | struct compat_timespec driver_tstamp; |
200 | u32 audio_tstamp_accuracy; | ||
201 | unsigned char reserved[52-2*sizeof(struct compat_timespec)]; | ||
200 | } __attribute__((packed)); | 202 | } __attribute__((packed)); |
201 | 203 | ||
202 | 204 | ||
203 | static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, | 205 | static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, |
204 | struct snd_pcm_status32 __user *src) | 206 | struct snd_pcm_status32 __user *src, |
207 | bool ext) | ||
205 | { | 208 | { |
206 | struct snd_pcm_status status; | 209 | struct snd_pcm_status status; |
207 | int err; | 210 | int err; |
208 | 211 | ||
212 | memset(&status, 0, sizeof(status)); | ||
213 | /* | ||
214 | * with extension, parameters are read/write, | ||
215 | * get audio_tstamp_data from user, | ||
216 | * ignore rest of status structure | ||
217 | */ | ||
218 | if (ext && get_user(status.audio_tstamp_data, | ||
219 | (u32 __user *)(&src->audio_tstamp_data))) | ||
220 | return -EFAULT; | ||
209 | err = snd_pcm_status(substream, &status); | 221 | err = snd_pcm_status(substream, &status); |
210 | if (err < 0) | 222 | if (err < 0) |
211 | return err; | 223 | return err; |
@@ -222,7 +234,10 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, | |||
222 | put_user(status.avail_max, &src->avail_max) || | 234 | put_user(status.avail_max, &src->avail_max) || |
223 | put_user(status.overrange, &src->overrange) || | 235 | put_user(status.overrange, &src->overrange) || |
224 | put_user(status.suspended_state, &src->suspended_state) || | 236 | put_user(status.suspended_state, &src->suspended_state) || |
225 | compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp)) | 237 | put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || |
238 | compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) || | ||
239 | compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) || | ||
240 | put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) | ||
226 | return -EFAULT; | 241 | return -EFAULT; |
227 | 242 | ||
228 | return err; | 243 | return err; |
@@ -457,6 +472,7 @@ enum { | |||
457 | SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), | 472 | SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), |
458 | SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), | 473 | SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), |
459 | SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32), | 474 | SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32), |
475 | SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32), | ||
460 | SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), | 476 | SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), |
461 | SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), | 477 | SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), |
462 | SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), | 478 | SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), |
@@ -517,7 +533,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
517 | case SNDRV_PCM_IOCTL_SW_PARAMS32: | 533 | case SNDRV_PCM_IOCTL_SW_PARAMS32: |
518 | return snd_pcm_ioctl_sw_params_compat(substream, argp); | 534 | return snd_pcm_ioctl_sw_params_compat(substream, argp); |
519 | case SNDRV_PCM_IOCTL_STATUS32: | 535 | case SNDRV_PCM_IOCTL_STATUS32: |
520 | return snd_pcm_status_user_compat(substream, argp); | 536 | return snd_pcm_status_user_compat(substream, argp, false); |
537 | case SNDRV_PCM_IOCTL_STATUS_EXT32: | ||
538 | return snd_pcm_status_user_compat(substream, argp, true); | ||
521 | case SNDRV_PCM_IOCTL_SYNC_PTR32: | 539 | case SNDRV_PCM_IOCTL_SYNC_PTR32: |
522 | return snd_pcm_ioctl_sync_ptr_compat(substream, argp); | 540 | return snd_pcm_ioctl_sync_ptr_compat(substream, argp); |
523 | case SNDRV_PCM_IOCTL_CHANNEL_INFO32: | 541 | case SNDRV_PCM_IOCTL_CHANNEL_INFO32: |
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 6542c4083594..fba365a78390 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c | |||
@@ -289,7 +289,7 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); | |||
289 | * | 289 | * |
290 | * The function should usually be called from the pcm open callback. Note that | 290 | * The function should usually be called from the pcm open callback. Note that |
291 | * this function will use private_data field of the substream's runtime. So it | 291 | * this function will use private_data field of the substream's runtime. So it |
292 | * is not availabe to your pcm driver implementation. | 292 | * is not available to your pcm driver implementation. |
293 | */ | 293 | */ |
294 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | 294 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, |
295 | struct dma_chan *chan) | 295 | struct dma_chan *chan) |
@@ -328,7 +328,7 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); | |||
328 | * This function will request a DMA channel using the passed filter function and | 328 | * This function will request a DMA channel using the passed filter function and |
329 | * data. The function should usually be called from the pcm open callback. Note | 329 | * data. The function should usually be called from the pcm open callback. Note |
330 | * that this function will use private_data field of the substream's runtime. So | 330 | * that this function will use private_data field of the substream's runtime. So |
331 | * it is not availabe to your pcm driver implementation. | 331 | * it is not available to your pcm driver implementation. |
332 | */ | 332 | */ |
333 | int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, | 333 | int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, |
334 | dma_filter_fn filter_fn, void *filter_data) | 334 | dma_filter_fn filter_fn, void *filter_data) |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ffd656012ab8..ac6b33f3779c 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -232,6 +232,49 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | static void update_audio_tstamp(struct snd_pcm_substream *substream, | ||
236 | struct timespec *curr_tstamp, | ||
237 | struct timespec *audio_tstamp) | ||
238 | { | ||
239 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
240 | u64 audio_frames, audio_nsecs; | ||
241 | struct timespec driver_tstamp; | ||
242 | |||
243 | if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE) | ||
244 | return; | ||
245 | |||
246 | if (!(substream->ops->get_time_info) || | ||
247 | (runtime->audio_tstamp_report.actual_type == | ||
248 | SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)) { | ||
249 | |||
250 | /* | ||
251 | * provide audio timestamp derived from pointer position | ||
252 | * add delay only if requested | ||
253 | */ | ||
254 | |||
255 | audio_frames = runtime->hw_ptr_wrap + runtime->status->hw_ptr; | ||
256 | |||
257 | if (runtime->audio_tstamp_config.report_delay) { | ||
258 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
259 | audio_frames -= runtime->delay; | ||
260 | else | ||
261 | audio_frames += runtime->delay; | ||
262 | } | ||
263 | audio_nsecs = div_u64(audio_frames * 1000000000LL, | ||
264 | runtime->rate); | ||
265 | *audio_tstamp = ns_to_timespec(audio_nsecs); | ||
266 | } | ||
267 | runtime->status->audio_tstamp = *audio_tstamp; | ||
268 | runtime->status->tstamp = *curr_tstamp; | ||
269 | |||
270 | /* | ||
271 | * re-take a driver timestamp to let apps detect if the reference tstamp | ||
272 | * read by low-level hardware was provided with a delay | ||
273 | */ | ||
274 | snd_pcm_gettime(substream->runtime, (struct timespec *)&driver_tstamp); | ||
275 | runtime->driver_tstamp = driver_tstamp; | ||
276 | } | ||
277 | |||
235 | static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | 278 | static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, |
236 | unsigned int in_interrupt) | 279 | unsigned int in_interrupt) |
237 | { | 280 | { |
@@ -256,11 +299,18 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
256 | pos = substream->ops->pointer(substream); | 299 | pos = substream->ops->pointer(substream); |
257 | curr_jiffies = jiffies; | 300 | curr_jiffies = jiffies; |
258 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { | 301 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { |
259 | snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); | 302 | if ((substream->ops->get_time_info) && |
260 | 303 | (runtime->audio_tstamp_config.type_requested != SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)) { | |
261 | if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) && | 304 | substream->ops->get_time_info(substream, &curr_tstamp, |
262 | (substream->ops->wall_clock)) | 305 | &audio_tstamp, |
263 | substream->ops->wall_clock(substream, &audio_tstamp); | 306 | &runtime->audio_tstamp_config, |
307 | &runtime->audio_tstamp_report); | ||
308 | |||
309 | /* re-test in case tstamp type is not supported in hardware and was demoted to DEFAULT */ | ||
310 | if (runtime->audio_tstamp_report.actual_type == SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT) | ||
311 | snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); | ||
312 | } else | ||
313 | snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); | ||
264 | } | 314 | } |
265 | 315 | ||
266 | if (pos == SNDRV_PCM_POS_XRUN) { | 316 | if (pos == SNDRV_PCM_POS_XRUN) { |
@@ -403,8 +453,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
403 | } | 453 | } |
404 | 454 | ||
405 | no_delta_check: | 455 | no_delta_check: |
406 | if (runtime->status->hw_ptr == new_hw_ptr) | 456 | if (runtime->status->hw_ptr == new_hw_ptr) { |
457 | update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); | ||
407 | return 0; | 458 | return 0; |
459 | } | ||
408 | 460 | ||
409 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 461 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
410 | runtime->silence_size > 0) | 462 | runtime->silence_size > 0) |
@@ -426,30 +478,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
426 | snd_BUG_ON(crossed_boundary != 1); | 478 | snd_BUG_ON(crossed_boundary != 1); |
427 | runtime->hw_ptr_wrap += runtime->boundary; | 479 | runtime->hw_ptr_wrap += runtime->boundary; |
428 | } | 480 | } |
429 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { | ||
430 | runtime->status->tstamp = curr_tstamp; | ||
431 | 481 | ||
432 | if (!(runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)) { | 482 | update_audio_tstamp(substream, &curr_tstamp, &audio_tstamp); |
433 | /* | ||
434 | * no wall clock available, provide audio timestamp | ||
435 | * derived from pointer position+delay | ||
436 | */ | ||
437 | u64 audio_frames, audio_nsecs; | ||
438 | |||
439 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
440 | audio_frames = runtime->hw_ptr_wrap | ||
441 | + runtime->status->hw_ptr | ||
442 | - runtime->delay; | ||
443 | else | ||
444 | audio_frames = runtime->hw_ptr_wrap | ||
445 | + runtime->status->hw_ptr | ||
446 | + runtime->delay; | ||
447 | audio_nsecs = div_u64(audio_frames * 1000000000LL, | ||
448 | runtime->rate); | ||
449 | audio_tstamp = ns_to_timespec(audio_nsecs); | ||
450 | } | ||
451 | runtime->status->audio_tstamp = audio_tstamp; | ||
452 | } | ||
453 | 483 | ||
454 | return snd_pcm_update_state(substream, runtime); | 484 | return snd_pcm_update_state(substream, runtime); |
455 | } | 485 | } |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 279e24f61305..abe1e811e660 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -707,6 +707,23 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
707 | struct snd_pcm_runtime *runtime = substream->runtime; | 707 | struct snd_pcm_runtime *runtime = substream->runtime; |
708 | 708 | ||
709 | snd_pcm_stream_lock_irq(substream); | 709 | snd_pcm_stream_lock_irq(substream); |
710 | |||
711 | snd_pcm_unpack_audio_tstamp_config(status->audio_tstamp_data, | ||
712 | &runtime->audio_tstamp_config); | ||
713 | |||
714 | /* backwards compatible behavior */ | ||
715 | if (runtime->audio_tstamp_config.type_requested == | ||
716 | SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT) { | ||
717 | if (runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) | ||
718 | runtime->audio_tstamp_config.type_requested = | ||
719 | SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; | ||
720 | else | ||
721 | runtime->audio_tstamp_config.type_requested = | ||
722 | SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; | ||
723 | runtime->audio_tstamp_report.valid = 0; | ||
724 | } else | ||
725 | runtime->audio_tstamp_report.valid = 1; | ||
726 | |||
710 | status->state = runtime->status->state; | 727 | status->state = runtime->status->state; |
711 | status->suspended_state = runtime->status->suspended_state; | 728 | status->suspended_state = runtime->status->suspended_state; |
712 | if (status->state == SNDRV_PCM_STATE_OPEN) | 729 | if (status->state == SNDRV_PCM_STATE_OPEN) |
@@ -716,8 +733,15 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
716 | snd_pcm_update_hw_ptr(substream); | 733 | snd_pcm_update_hw_ptr(substream); |
717 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { | 734 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { |
718 | status->tstamp = runtime->status->tstamp; | 735 | status->tstamp = runtime->status->tstamp; |
736 | status->driver_tstamp = runtime->driver_tstamp; | ||
719 | status->audio_tstamp = | 737 | status->audio_tstamp = |
720 | runtime->status->audio_tstamp; | 738 | runtime->status->audio_tstamp; |
739 | if (runtime->audio_tstamp_report.valid == 1) | ||
740 | /* backwards compatibility, no report provided in COMPAT mode */ | ||
741 | snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data, | ||
742 | &status->audio_tstamp_accuracy, | ||
743 | &runtime->audio_tstamp_report); | ||
744 | |||
721 | goto _tstamp_end; | 745 | goto _tstamp_end; |
722 | } | 746 | } |
723 | } else { | 747 | } else { |
@@ -753,12 +777,21 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
753 | } | 777 | } |
754 | 778 | ||
755 | static int snd_pcm_status_user(struct snd_pcm_substream *substream, | 779 | static int snd_pcm_status_user(struct snd_pcm_substream *substream, |
756 | struct snd_pcm_status __user * _status) | 780 | struct snd_pcm_status __user * _status, |
781 | bool ext) | ||
757 | { | 782 | { |
758 | struct snd_pcm_status status; | 783 | struct snd_pcm_status status; |
759 | int res; | 784 | int res; |
760 | 785 | ||
761 | memset(&status, 0, sizeof(status)); | 786 | memset(&status, 0, sizeof(status)); |
787 | /* | ||
788 | * with extension, parameters are read/write, | ||
789 | * get audio_tstamp_data from user, | ||
790 | * ignore rest of status structure | ||
791 | */ | ||
792 | if (ext && get_user(status.audio_tstamp_data, | ||
793 | (u32 __user *)(&_status->audio_tstamp_data))) | ||
794 | return -EFAULT; | ||
762 | res = snd_pcm_status(substream, &status); | 795 | res = snd_pcm_status(substream, &status); |
763 | if (res < 0) | 796 | if (res < 0) |
764 | return res; | 797 | return res; |
@@ -2725,7 +2758,9 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2725 | case SNDRV_PCM_IOCTL_SW_PARAMS: | 2758 | case SNDRV_PCM_IOCTL_SW_PARAMS: |
2726 | return snd_pcm_sw_params_user(substream, arg); | 2759 | return snd_pcm_sw_params_user(substream, arg); |
2727 | case SNDRV_PCM_IOCTL_STATUS: | 2760 | case SNDRV_PCM_IOCTL_STATUS: |
2728 | return snd_pcm_status_user(substream, arg); | 2761 | return snd_pcm_status_user(substream, arg, false); |
2762 | case SNDRV_PCM_IOCTL_STATUS_EXT: | ||
2763 | return snd_pcm_status_user(substream, arg, true); | ||
2729 | case SNDRV_PCM_IOCTL_CHANNEL_INFO: | 2764 | case SNDRV_PCM_IOCTL_CHANNEL_INFO: |
2730 | return snd_pcm_channel_info_user(substream, arg); | 2765 | return snd_pcm_channel_info_user(substream, arg); |
2731 | case SNDRV_PCM_IOCTL_PREPARE: | 2766 | case SNDRV_PCM_IOCTL_PREPARE: |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b5a748596fc4..a7759846fbaa 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -1429,10 +1429,8 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi, | |||
1429 | 1429 | ||
1430 | for (idx = 0; idx < count; idx++) { | 1430 | for (idx = 0; idx < count; idx++) { |
1431 | substream = kzalloc(sizeof(*substream), GFP_KERNEL); | 1431 | substream = kzalloc(sizeof(*substream), GFP_KERNEL); |
1432 | if (substream == NULL) { | 1432 | if (!substream) |
1433 | rmidi_err(rmidi, "rawmidi: cannot allocate substream\n"); | ||
1434 | return -ENOMEM; | 1433 | return -ENOMEM; |
1435 | } | ||
1436 | substream->stream = direction; | 1434 | substream->stream = direction; |
1437 | substream->number = idx; | 1435 | substream->number = idx; |
1438 | substream->rmidi = rmidi; | 1436 | substream->rmidi = rmidi; |
@@ -1479,10 +1477,8 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, | |||
1479 | if (rrawmidi) | 1477 | if (rrawmidi) |
1480 | *rrawmidi = NULL; | 1478 | *rrawmidi = NULL; |
1481 | rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL); | 1479 | rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL); |
1482 | if (rmidi == NULL) { | 1480 | if (!rmidi) |
1483 | dev_err(card->dev, "rawmidi: cannot allocate\n"); | ||
1484 | return -ENOMEM; | 1481 | return -ENOMEM; |
1485 | } | ||
1486 | rmidi->card = card; | 1482 | rmidi->card = card; |
1487 | rmidi->device = device; | 1483 | rmidi->device = device; |
1488 | mutex_init(&rmidi->open_mutex); | 1484 | mutex_init(&rmidi->open_mutex); |
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 16d42679e43f..72873a46afeb 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c | |||
@@ -65,15 +65,20 @@ static unsigned int odev_poll(struct file *file, poll_table * wait); | |||
65 | * module interface | 65 | * module interface |
66 | */ | 66 | */ |
67 | 67 | ||
68 | static struct snd_seq_driver seq_oss_synth_driver = { | ||
69 | .driver = { | ||
70 | .name = KBUILD_MODNAME, | ||
71 | .probe = snd_seq_oss_synth_probe, | ||
72 | .remove = snd_seq_oss_synth_remove, | ||
73 | }, | ||
74 | .id = SNDRV_SEQ_DEV_ID_OSS, | ||
75 | .argsize = sizeof(struct snd_seq_oss_reg), | ||
76 | }; | ||
77 | |||
68 | static int __init alsa_seq_oss_init(void) | 78 | static int __init alsa_seq_oss_init(void) |
69 | { | 79 | { |
70 | int rc; | 80 | int rc; |
71 | static struct snd_seq_dev_ops ops = { | ||
72 | snd_seq_oss_synth_register, | ||
73 | snd_seq_oss_synth_unregister, | ||
74 | }; | ||
75 | 81 | ||
76 | snd_seq_autoload_lock(); | ||
77 | if ((rc = register_device()) < 0) | 82 | if ((rc = register_device()) < 0) |
78 | goto error; | 83 | goto error; |
79 | if ((rc = register_proc()) < 0) { | 84 | if ((rc = register_proc()) < 0) { |
@@ -86,8 +91,8 @@ static int __init alsa_seq_oss_init(void) | |||
86 | goto error; | 91 | goto error; |
87 | } | 92 | } |
88 | 93 | ||
89 | if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops, | 94 | rc = snd_seq_driver_register(&seq_oss_synth_driver); |
90 | sizeof(struct snd_seq_oss_reg))) < 0) { | 95 | if (rc < 0) { |
91 | snd_seq_oss_delete_client(); | 96 | snd_seq_oss_delete_client(); |
92 | unregister_proc(); | 97 | unregister_proc(); |
93 | unregister_device(); | 98 | unregister_device(); |
@@ -98,13 +103,12 @@ static int __init alsa_seq_oss_init(void) | |||
98 | snd_seq_oss_synth_init(); | 103 | snd_seq_oss_synth_init(); |
99 | 104 | ||
100 | error: | 105 | error: |
101 | snd_seq_autoload_unlock(); | ||
102 | return rc; | 106 | return rc; |
103 | } | 107 | } |
104 | 108 | ||
105 | static void __exit alsa_seq_oss_exit(void) | 109 | static void __exit alsa_seq_oss_exit(void) |
106 | { | 110 | { |
107 | snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OSS); | 111 | snd_seq_driver_unregister(&seq_oss_synth_driver); |
108 | snd_seq_oss_delete_client(); | 112 | snd_seq_oss_delete_client(); |
109 | unregister_proc(); | 113 | unregister_proc(); |
110 | unregister_device(); | 114 | unregister_device(); |
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index b0e32e161dd1..2de3feff70d0 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c | |||
@@ -188,10 +188,8 @@ snd_seq_oss_open(struct file *file, int level) | |||
188 | struct seq_oss_devinfo *dp; | 188 | struct seq_oss_devinfo *dp; |
189 | 189 | ||
190 | dp = kzalloc(sizeof(*dp), GFP_KERNEL); | 190 | dp = kzalloc(sizeof(*dp), GFP_KERNEL); |
191 | if (!dp) { | 191 | if (!dp) |
192 | pr_err("ALSA: seq_oss: can't malloc device info\n"); | ||
193 | return -ENOMEM; | 192 | return -ENOMEM; |
194 | } | ||
195 | 193 | ||
196 | dp->cseq = system_client; | 194 | dp->cseq = system_client; |
197 | dp->port = -1; | 195 | dp->port = -1; |
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index e79cc44b1394..96e8395ae586 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c | |||
@@ -173,10 +173,9 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) | |||
173 | /* | 173 | /* |
174 | * allocate midi info record | 174 | * allocate midi info record |
175 | */ | 175 | */ |
176 | if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) { | 176 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
177 | pr_err("ALSA: seq_oss: can't malloc midi info\n"); | 177 | if (!mdev) |
178 | return -ENOMEM; | 178 | return -ENOMEM; |
179 | } | ||
180 | 179 | ||
181 | /* copy the port information */ | 180 | /* copy the port information */ |
182 | mdev->client = pinfo->addr.client; | 181 | mdev->client = pinfo->addr.client; |
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index 654d17a5023c..c080c73cea04 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c | |||
@@ -47,13 +47,12 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen) | |||
47 | { | 47 | { |
48 | struct seq_oss_readq *q; | 48 | struct seq_oss_readq *q; |
49 | 49 | ||
50 | if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) { | 50 | q = kzalloc(sizeof(*q), GFP_KERNEL); |
51 | pr_err("ALSA: seq_oss: can't malloc read queue\n"); | 51 | if (!q) |
52 | return NULL; | 52 | return NULL; |
53 | } | ||
54 | 53 | ||
55 | if ((q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL)) == NULL) { | 54 | q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL); |
56 | pr_err("ALSA: seq_oss: can't malloc read queue buffer\n"); | 55 | if (!q->q) { |
57 | kfree(q); | 56 | kfree(q); |
58 | return NULL; | 57 | return NULL; |
59 | } | 58 | } |
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 701feb71b700..48e4fe1b68ab 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c | |||
@@ -98,17 +98,17 @@ snd_seq_oss_synth_init(void) | |||
98 | * registration of the synth device | 98 | * registration of the synth device |
99 | */ | 99 | */ |
100 | int | 100 | int |
101 | snd_seq_oss_synth_register(struct snd_seq_device *dev) | 101 | snd_seq_oss_synth_probe(struct device *_dev) |
102 | { | 102 | { |
103 | struct snd_seq_device *dev = to_seq_dev(_dev); | ||
103 | int i; | 104 | int i; |
104 | struct seq_oss_synth *rec; | 105 | struct seq_oss_synth *rec; |
105 | struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); | 106 | struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); |
106 | unsigned long flags; | 107 | unsigned long flags; |
107 | 108 | ||
108 | if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) { | 109 | rec = kzalloc(sizeof(*rec), GFP_KERNEL); |
109 | pr_err("ALSA: seq_oss: can't malloc synth info\n"); | 110 | if (!rec) |
110 | return -ENOMEM; | 111 | return -ENOMEM; |
111 | } | ||
112 | rec->seq_device = -1; | 112 | rec->seq_device = -1; |
113 | rec->synth_type = reg->type; | 113 | rec->synth_type = reg->type; |
114 | rec->synth_subtype = reg->subtype; | 114 | rec->synth_subtype = reg->subtype; |
@@ -149,8 +149,9 @@ snd_seq_oss_synth_register(struct snd_seq_device *dev) | |||
149 | 149 | ||
150 | 150 | ||
151 | int | 151 | int |
152 | snd_seq_oss_synth_unregister(struct snd_seq_device *dev) | 152 | snd_seq_oss_synth_remove(struct device *_dev) |
153 | { | 153 | { |
154 | struct snd_seq_device *dev = to_seq_dev(_dev); | ||
154 | int index; | 155 | int index; |
155 | struct seq_oss_synth *rec = dev->driver_data; | 156 | struct seq_oss_synth *rec = dev->driver_data; |
156 | unsigned long flags; | 157 | unsigned long flags; |
@@ -247,7 +248,6 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) | |||
247 | if (info->nr_voices > 0) { | 248 | if (info->nr_voices > 0) { |
248 | info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); | 249 | info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); |
249 | if (!info->ch) { | 250 | if (!info->ch) { |
250 | pr_err("ALSA: seq_oss: Cannot malloc voices\n"); | ||
251 | rec->oper.close(&info->arg); | 251 | rec->oper.close(&info->arg); |
252 | module_put(rec->oper.owner); | 252 | module_put(rec->oper.owner); |
253 | snd_use_lock_free(&rec->use_lock); | 253 | snd_use_lock_free(&rec->use_lock); |
diff --git a/sound/core/seq/oss/seq_oss_synth.h b/sound/core/seq/oss/seq_oss_synth.h index dbdfcbb80eaa..74ac55f166b6 100644 --- a/sound/core/seq/oss/seq_oss_synth.h +++ b/sound/core/seq/oss/seq_oss_synth.h | |||
@@ -28,8 +28,8 @@ | |||
28 | #include <sound/seq_device.h> | 28 | #include <sound/seq_device.h> |
29 | 29 | ||
30 | void snd_seq_oss_synth_init(void); | 30 | void snd_seq_oss_synth_init(void); |
31 | int snd_seq_oss_synth_register(struct snd_seq_device *dev); | 31 | int snd_seq_oss_synth_probe(struct device *dev); |
32 | int snd_seq_oss_synth_unregister(struct snd_seq_device *dev); | 32 | int snd_seq_oss_synth_remove(struct device *dev); |
33 | void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp); | 33 | void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp); |
34 | void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp); | 34 | void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp); |
35 | void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp); | 35 | void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp); |
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 0631bdadd12b..d99f99d61983 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c | |||
@@ -36,6 +36,7 @@ | |||
36 | * | 36 | * |
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <linux/device.h> | ||
39 | #include <linux/init.h> | 40 | #include <linux/init.h> |
40 | #include <linux/module.h> | 41 | #include <linux/module.h> |
41 | #include <sound/core.h> | 42 | #include <sound/core.h> |
@@ -51,140 +52,78 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | |||
51 | MODULE_DESCRIPTION("ALSA sequencer device management"); | 52 | MODULE_DESCRIPTION("ALSA sequencer device management"); |
52 | MODULE_LICENSE("GPL"); | 53 | MODULE_LICENSE("GPL"); |
53 | 54 | ||
54 | /* driver state */ | 55 | /* |
55 | #define DRIVER_EMPTY 0 | 56 | * bus definition |
56 | #define DRIVER_LOADED (1<<0) | 57 | */ |
57 | #define DRIVER_REQUESTED (1<<1) | 58 | static int snd_seq_bus_match(struct device *dev, struct device_driver *drv) |
58 | #define DRIVER_LOCKED (1<<2) | 59 | { |
59 | #define DRIVER_REQUESTING (1<<3) | 60 | struct snd_seq_device *sdev = to_seq_dev(dev); |
60 | 61 | struct snd_seq_driver *sdrv = to_seq_drv(drv); | |
61 | struct ops_list { | ||
62 | char id[ID_LEN]; /* driver id */ | ||
63 | int driver; /* driver state */ | ||
64 | int used; /* reference counter */ | ||
65 | int argsize; /* argument size */ | ||
66 | |||
67 | /* operators */ | ||
68 | struct snd_seq_dev_ops ops; | ||
69 | |||
70 | /* registered devices */ | ||
71 | struct list_head dev_list; /* list of devices */ | ||
72 | int num_devices; /* number of associated devices */ | ||
73 | int num_init_devices; /* number of initialized devices */ | ||
74 | struct mutex reg_mutex; | ||
75 | |||
76 | struct list_head list; /* next driver */ | ||
77 | }; | ||
78 | 62 | ||
63 | return strcmp(sdrv->id, sdev->id) == 0 && | ||
64 | sdrv->argsize == sdev->argsize; | ||
65 | } | ||
79 | 66 | ||
80 | static LIST_HEAD(opslist); | 67 | static struct bus_type snd_seq_bus_type = { |
81 | static int num_ops; | 68 | .name = "snd_seq", |
82 | static DEFINE_MUTEX(ops_mutex); | 69 | .match = snd_seq_bus_match, |
83 | #ifdef CONFIG_PROC_FS | 70 | }; |
84 | static struct snd_info_entry *info_entry; | ||
85 | #endif | ||
86 | 71 | ||
87 | /* | 72 | /* |
88 | * prototypes | 73 | * proc interface -- just for compatibility |
89 | */ | 74 | */ |
90 | static int snd_seq_device_free(struct snd_seq_device *dev); | 75 | #ifdef CONFIG_PROC_FS |
91 | static int snd_seq_device_dev_free(struct snd_device *device); | 76 | static struct snd_info_entry *info_entry; |
92 | static int snd_seq_device_dev_register(struct snd_device *device); | ||
93 | static int snd_seq_device_dev_disconnect(struct snd_device *device); | ||
94 | |||
95 | static int init_device(struct snd_seq_device *dev, struct ops_list *ops); | ||
96 | static int free_device(struct snd_seq_device *dev, struct ops_list *ops); | ||
97 | static struct ops_list *find_driver(char *id, int create_if_empty); | ||
98 | static struct ops_list *create_driver(char *id); | ||
99 | static void unlock_driver(struct ops_list *ops); | ||
100 | static void remove_drivers(void); | ||
101 | 77 | ||
102 | /* | 78 | static int print_dev_info(struct device *dev, void *data) |
103 | * show all drivers and their status | 79 | { |
104 | */ | 80 | struct snd_seq_device *sdev = to_seq_dev(dev); |
81 | struct snd_info_buffer *buffer = data; | ||
82 | |||
83 | snd_iprintf(buffer, "snd-%s,%s,%d\n", sdev->id, | ||
84 | dev->driver ? "loaded" : "empty", | ||
85 | dev->driver ? 1 : 0); | ||
86 | return 0; | ||
87 | } | ||
105 | 88 | ||
106 | #ifdef CONFIG_PROC_FS | ||
107 | static void snd_seq_device_info(struct snd_info_entry *entry, | 89 | static void snd_seq_device_info(struct snd_info_entry *entry, |
108 | struct snd_info_buffer *buffer) | 90 | struct snd_info_buffer *buffer) |
109 | { | 91 | { |
110 | struct ops_list *ops; | 92 | bus_for_each_dev(&snd_seq_bus_type, NULL, buffer, print_dev_info); |
111 | |||
112 | mutex_lock(&ops_mutex); | ||
113 | list_for_each_entry(ops, &opslist, list) { | ||
114 | snd_iprintf(buffer, "snd-%s%s%s%s,%d\n", | ||
115 | ops->id, | ||
116 | ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""), | ||
117 | ops->driver & DRIVER_REQUESTED ? ",requested" : "", | ||
118 | ops->driver & DRIVER_LOCKED ? ",locked" : "", | ||
119 | ops->num_devices); | ||
120 | } | ||
121 | mutex_unlock(&ops_mutex); | ||
122 | } | 93 | } |
123 | #endif | 94 | #endif |
124 | 95 | ||
125 | /* | 96 | /* |
126 | * load all registered drivers (called from seq_clientmgr.c) | 97 | * load all registered drivers (called from seq_clientmgr.c) |
127 | */ | 98 | */ |
128 | 99 | ||
129 | #ifdef CONFIG_MODULES | 100 | #ifdef CONFIG_MODULES |
130 | /* avoid auto-loading during module_init() */ | 101 | /* flag to block auto-loading */ |
131 | static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ | 102 | static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ |
132 | void snd_seq_autoload_lock(void) | ||
133 | { | ||
134 | atomic_inc(&snd_seq_in_init); | ||
135 | } | ||
136 | 103 | ||
137 | void snd_seq_autoload_unlock(void) | 104 | static int request_seq_drv(struct device *dev, void *data) |
138 | { | 105 | { |
139 | atomic_dec(&snd_seq_in_init); | 106 | struct snd_seq_device *sdev = to_seq_dev(dev); |
107 | |||
108 | if (!dev->driver) | ||
109 | request_module("snd-%s", sdev->id); | ||
110 | return 0; | ||
140 | } | 111 | } |
141 | 112 | ||
142 | static void autoload_drivers(void) | 113 | static void autoload_drivers(struct work_struct *work) |
143 | { | 114 | { |
144 | /* avoid reentrance */ | 115 | /* avoid reentrance */ |
145 | if (atomic_inc_return(&snd_seq_in_init) == 1) { | 116 | if (atomic_inc_return(&snd_seq_in_init) == 1) |
146 | struct ops_list *ops; | 117 | bus_for_each_dev(&snd_seq_bus_type, NULL, NULL, |
147 | 118 | request_seq_drv); | |
148 | mutex_lock(&ops_mutex); | ||
149 | list_for_each_entry(ops, &opslist, list) { | ||
150 | if ((ops->driver & DRIVER_REQUESTING) && | ||
151 | !(ops->driver & DRIVER_REQUESTED)) { | ||
152 | ops->used++; | ||
153 | mutex_unlock(&ops_mutex); | ||
154 | ops->driver |= DRIVER_REQUESTED; | ||
155 | request_module("snd-%s", ops->id); | ||
156 | mutex_lock(&ops_mutex); | ||
157 | ops->used--; | ||
158 | } | ||
159 | } | ||
160 | mutex_unlock(&ops_mutex); | ||
161 | } | ||
162 | atomic_dec(&snd_seq_in_init); | 119 | atomic_dec(&snd_seq_in_init); |
163 | } | 120 | } |
164 | 121 | ||
165 | static void call_autoload(struct work_struct *work) | 122 | static DECLARE_WORK(autoload_work, autoload_drivers); |
166 | { | ||
167 | autoload_drivers(); | ||
168 | } | ||
169 | |||
170 | static DECLARE_WORK(autoload_work, call_autoload); | ||
171 | |||
172 | static void try_autoload(struct ops_list *ops) | ||
173 | { | ||
174 | if (!ops->driver) { | ||
175 | ops->driver |= DRIVER_REQUESTING; | ||
176 | schedule_work(&autoload_work); | ||
177 | } | ||
178 | } | ||
179 | 123 | ||
180 | static void queue_autoload_drivers(void) | 124 | static void queue_autoload_drivers(void) |
181 | { | 125 | { |
182 | struct ops_list *ops; | 126 | schedule_work(&autoload_work); |
183 | |||
184 | mutex_lock(&ops_mutex); | ||
185 | list_for_each_entry(ops, &opslist, list) | ||
186 | try_autoload(ops); | ||
187 | mutex_unlock(&ops_mutex); | ||
188 | } | 127 | } |
189 | 128 | ||
190 | void snd_seq_autoload_init(void) | 129 | void snd_seq_autoload_init(void) |
@@ -195,384 +134,143 @@ void snd_seq_autoload_init(void) | |||
195 | queue_autoload_drivers(); | 134 | queue_autoload_drivers(); |
196 | #endif | 135 | #endif |
197 | } | 136 | } |
198 | #else | 137 | EXPORT_SYMBOL(snd_seq_autoload_init); |
199 | #define try_autoload(ops) /* NOP */ | ||
200 | #endif | ||
201 | 138 | ||
202 | void snd_seq_device_load_drivers(void) | 139 | void snd_seq_autoload_exit(void) |
203 | { | 140 | { |
204 | #ifdef CONFIG_MODULES | 141 | atomic_inc(&snd_seq_in_init); |
205 | queue_autoload_drivers(); | ||
206 | flush_work(&autoload_work); | ||
207 | #endif | ||
208 | } | 142 | } |
143 | EXPORT_SYMBOL(snd_seq_autoload_exit); | ||
209 | 144 | ||
210 | /* | 145 | void snd_seq_device_load_drivers(void) |
211 | * register a sequencer device | ||
212 | * card = card info | ||
213 | * device = device number (if any) | ||
214 | * id = id of driver | ||
215 | * result = return pointer (NULL allowed if unnecessary) | ||
216 | */ | ||
217 | int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, | ||
218 | struct snd_seq_device **result) | ||
219 | { | 146 | { |
220 | struct snd_seq_device *dev; | 147 | queue_autoload_drivers(); |
221 | struct ops_list *ops; | 148 | flush_work(&autoload_work); |
222 | int err; | ||
223 | static struct snd_device_ops dops = { | ||
224 | .dev_free = snd_seq_device_dev_free, | ||
225 | .dev_register = snd_seq_device_dev_register, | ||
226 | .dev_disconnect = snd_seq_device_dev_disconnect, | ||
227 | }; | ||
228 | |||
229 | if (result) | ||
230 | *result = NULL; | ||
231 | |||
232 | if (snd_BUG_ON(!id)) | ||
233 | return -EINVAL; | ||
234 | |||
235 | ops = find_driver(id, 1); | ||
236 | if (ops == NULL) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL); | ||
240 | if (dev == NULL) { | ||
241 | unlock_driver(ops); | ||
242 | return -ENOMEM; | ||
243 | } | ||
244 | |||
245 | /* set up device info */ | ||
246 | dev->card = card; | ||
247 | dev->device = device; | ||
248 | strlcpy(dev->id, id, sizeof(dev->id)); | ||
249 | dev->argsize = argsize; | ||
250 | dev->status = SNDRV_SEQ_DEVICE_FREE; | ||
251 | |||
252 | /* add this device to the list */ | ||
253 | mutex_lock(&ops->reg_mutex); | ||
254 | list_add_tail(&dev->list, &ops->dev_list); | ||
255 | ops->num_devices++; | ||
256 | mutex_unlock(&ops->reg_mutex); | ||
257 | |||
258 | if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { | ||
259 | snd_seq_device_free(dev); | ||
260 | return err; | ||
261 | } | ||
262 | |||
263 | try_autoload(ops); | ||
264 | unlock_driver(ops); | ||
265 | |||
266 | if (result) | ||
267 | *result = dev; | ||
268 | |||
269 | return 0; | ||
270 | } | 149 | } |
150 | EXPORT_SYMBOL(snd_seq_device_load_drivers); | ||
151 | #else | ||
152 | #define queue_autoload_drivers() /* NOP */ | ||
153 | #endif | ||
271 | 154 | ||
272 | /* | 155 | /* |
273 | * free the existing device | 156 | * device management |
274 | */ | 157 | */ |
275 | static int snd_seq_device_free(struct snd_seq_device *dev) | ||
276 | { | ||
277 | struct ops_list *ops; | ||
278 | |||
279 | if (snd_BUG_ON(!dev)) | ||
280 | return -EINVAL; | ||
281 | |||
282 | ops = find_driver(dev->id, 0); | ||
283 | if (ops == NULL) | ||
284 | return -ENXIO; | ||
285 | |||
286 | /* remove the device from the list */ | ||
287 | mutex_lock(&ops->reg_mutex); | ||
288 | list_del(&dev->list); | ||
289 | ops->num_devices--; | ||
290 | mutex_unlock(&ops->reg_mutex); | ||
291 | |||
292 | free_device(dev, ops); | ||
293 | if (dev->private_free) | ||
294 | dev->private_free(dev); | ||
295 | kfree(dev); | ||
296 | |||
297 | unlock_driver(ops); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int snd_seq_device_dev_free(struct snd_device *device) | 158 | static int snd_seq_device_dev_free(struct snd_device *device) |
303 | { | 159 | { |
304 | struct snd_seq_device *dev = device->device_data; | 160 | struct snd_seq_device *dev = device->device_data; |
305 | return snd_seq_device_free(dev); | 161 | |
162 | put_device(&dev->dev); | ||
163 | return 0; | ||
306 | } | 164 | } |
307 | 165 | ||
308 | /* | ||
309 | * register the device | ||
310 | */ | ||
311 | static int snd_seq_device_dev_register(struct snd_device *device) | 166 | static int snd_seq_device_dev_register(struct snd_device *device) |
312 | { | 167 | { |
313 | struct snd_seq_device *dev = device->device_data; | 168 | struct snd_seq_device *dev = device->device_data; |
314 | struct ops_list *ops; | 169 | int err; |
315 | |||
316 | ops = find_driver(dev->id, 0); | ||
317 | if (ops == NULL) | ||
318 | return -ENOENT; | ||
319 | |||
320 | /* initialize this device if the corresponding driver was | ||
321 | * already loaded | ||
322 | */ | ||
323 | if (ops->driver & DRIVER_LOADED) | ||
324 | init_device(dev, ops); | ||
325 | 170 | ||
326 | unlock_driver(ops); | 171 | err = device_add(&dev->dev); |
172 | if (err < 0) | ||
173 | return err; | ||
174 | if (!dev->dev.driver) | ||
175 | queue_autoload_drivers(); | ||
327 | return 0; | 176 | return 0; |
328 | } | 177 | } |
329 | 178 | ||
330 | /* | ||
331 | * disconnect the device | ||
332 | */ | ||
333 | static int snd_seq_device_dev_disconnect(struct snd_device *device) | 179 | static int snd_seq_device_dev_disconnect(struct snd_device *device) |
334 | { | 180 | { |
335 | struct snd_seq_device *dev = device->device_data; | 181 | struct snd_seq_device *dev = device->device_data; |
336 | struct ops_list *ops; | ||
337 | |||
338 | ops = find_driver(dev->id, 0); | ||
339 | if (ops == NULL) | ||
340 | return -ENOENT; | ||
341 | |||
342 | free_device(dev, ops); | ||
343 | 182 | ||
344 | unlock_driver(ops); | 183 | device_del(&dev->dev); |
345 | return 0; | 184 | return 0; |
346 | } | 185 | } |
347 | 186 | ||
348 | /* | 187 | static void snd_seq_dev_release(struct device *dev) |
349 | * register device driver | ||
350 | * id = driver id | ||
351 | * entry = driver operators - duplicated to each instance | ||
352 | */ | ||
353 | int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, | ||
354 | int argsize) | ||
355 | { | 188 | { |
356 | struct ops_list *ops; | 189 | struct snd_seq_device *sdev = to_seq_dev(dev); |
357 | struct snd_seq_device *dev; | ||
358 | 190 | ||
359 | if (id == NULL || entry == NULL || | 191 | if (sdev->private_free) |
360 | entry->init_device == NULL || entry->free_device == NULL) | 192 | sdev->private_free(sdev); |
361 | return -EINVAL; | 193 | kfree(sdev); |
362 | |||
363 | ops = find_driver(id, 1); | ||
364 | if (ops == NULL) | ||
365 | return -ENOMEM; | ||
366 | if (ops->driver & DRIVER_LOADED) { | ||
367 | pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id); | ||
368 | unlock_driver(ops); | ||
369 | return -EBUSY; | ||
370 | } | ||
371 | |||
372 | mutex_lock(&ops->reg_mutex); | ||
373 | /* copy driver operators */ | ||
374 | ops->ops = *entry; | ||
375 | ops->driver |= DRIVER_LOADED; | ||
376 | ops->argsize = argsize; | ||
377 | |||
378 | /* initialize existing devices if necessary */ | ||
379 | list_for_each_entry(dev, &ops->dev_list, list) { | ||
380 | init_device(dev, ops); | ||
381 | } | ||
382 | mutex_unlock(&ops->reg_mutex); | ||
383 | |||
384 | unlock_driver(ops); | ||
385 | |||
386 | return 0; | ||
387 | } | 194 | } |
388 | 195 | ||
389 | |||
390 | /* | ||
391 | * create driver record | ||
392 | */ | ||
393 | static struct ops_list * create_driver(char *id) | ||
394 | { | ||
395 | struct ops_list *ops; | ||
396 | |||
397 | ops = kzalloc(sizeof(*ops), GFP_KERNEL); | ||
398 | if (ops == NULL) | ||
399 | return ops; | ||
400 | |||
401 | /* set up driver entry */ | ||
402 | strlcpy(ops->id, id, sizeof(ops->id)); | ||
403 | mutex_init(&ops->reg_mutex); | ||
404 | /* | ||
405 | * The ->reg_mutex locking rules are per-driver, so we create | ||
406 | * separate per-driver lock classes: | ||
407 | */ | ||
408 | lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id); | ||
409 | |||
410 | ops->driver = DRIVER_EMPTY; | ||
411 | INIT_LIST_HEAD(&ops->dev_list); | ||
412 | /* lock this instance */ | ||
413 | ops->used = 1; | ||
414 | |||
415 | /* register driver entry */ | ||
416 | mutex_lock(&ops_mutex); | ||
417 | list_add_tail(&ops->list, &opslist); | ||
418 | num_ops++; | ||
419 | mutex_unlock(&ops_mutex); | ||
420 | |||
421 | return ops; | ||
422 | } | ||
423 | |||
424 | |||
425 | /* | 196 | /* |
426 | * unregister the specified driver | 197 | * register a sequencer device |
198 | * card = card info | ||
199 | * device = device number (if any) | ||
200 | * id = id of driver | ||
201 | * result = return pointer (NULL allowed if unnecessary) | ||
427 | */ | 202 | */ |
428 | int snd_seq_device_unregister_driver(char *id) | 203 | int snd_seq_device_new(struct snd_card *card, int device, const char *id, |
204 | int argsize, struct snd_seq_device **result) | ||
429 | { | 205 | { |
430 | struct ops_list *ops; | ||
431 | struct snd_seq_device *dev; | 206 | struct snd_seq_device *dev; |
207 | int err; | ||
208 | static struct snd_device_ops dops = { | ||
209 | .dev_free = snd_seq_device_dev_free, | ||
210 | .dev_register = snd_seq_device_dev_register, | ||
211 | .dev_disconnect = snd_seq_device_dev_disconnect, | ||
212 | }; | ||
432 | 213 | ||
433 | ops = find_driver(id, 0); | 214 | if (result) |
434 | if (ops == NULL) | 215 | *result = NULL; |
435 | return -ENXIO; | ||
436 | if (! (ops->driver & DRIVER_LOADED) || | ||
437 | (ops->driver & DRIVER_LOCKED)) { | ||
438 | pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n", | ||
439 | id, ops->driver); | ||
440 | unlock_driver(ops); | ||
441 | return -EBUSY; | ||
442 | } | ||
443 | |||
444 | /* close and release all devices associated with this driver */ | ||
445 | mutex_lock(&ops->reg_mutex); | ||
446 | ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */ | ||
447 | list_for_each_entry(dev, &ops->dev_list, list) { | ||
448 | free_device(dev, ops); | ||
449 | } | ||
450 | |||
451 | ops->driver = 0; | ||
452 | if (ops->num_init_devices > 0) | ||
453 | pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n", | ||
454 | ops->num_init_devices); | ||
455 | mutex_unlock(&ops->reg_mutex); | ||
456 | |||
457 | unlock_driver(ops); | ||
458 | 216 | ||
459 | /* remove empty driver entries */ | 217 | if (snd_BUG_ON(!id)) |
460 | remove_drivers(); | 218 | return -EINVAL; |
461 | 219 | ||
462 | return 0; | 220 | dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL); |
463 | } | 221 | if (!dev) |
222 | return -ENOMEM; | ||
464 | 223 | ||
224 | /* set up device info */ | ||
225 | dev->card = card; | ||
226 | dev->device = device; | ||
227 | dev->id = id; | ||
228 | dev->argsize = argsize; | ||
465 | 229 | ||
466 | /* | 230 | device_initialize(&dev->dev); |
467 | * remove empty driver entries | 231 | dev->dev.parent = &card->card_dev; |
468 | */ | 232 | dev->dev.bus = &snd_seq_bus_type; |
469 | static void remove_drivers(void) | 233 | dev->dev.release = snd_seq_dev_release; |
470 | { | 234 | dev_set_name(&dev->dev, "%s-%d-%d", dev->id, card->number, device); |
471 | struct list_head *head; | ||
472 | |||
473 | mutex_lock(&ops_mutex); | ||
474 | head = opslist.next; | ||
475 | while (head != &opslist) { | ||
476 | struct ops_list *ops = list_entry(head, struct ops_list, list); | ||
477 | if (! (ops->driver & DRIVER_LOADED) && | ||
478 | ops->used == 0 && ops->num_devices == 0) { | ||
479 | head = head->next; | ||
480 | list_del(&ops->list); | ||
481 | kfree(ops); | ||
482 | num_ops--; | ||
483 | } else | ||
484 | head = head->next; | ||
485 | } | ||
486 | mutex_unlock(&ops_mutex); | ||
487 | } | ||
488 | 235 | ||
489 | /* | 236 | /* add this device to the list */ |
490 | * initialize the device - call init_device operator | 237 | err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops); |
491 | */ | 238 | if (err < 0) { |
492 | static int init_device(struct snd_seq_device *dev, struct ops_list *ops) | 239 | put_device(&dev->dev); |
493 | { | 240 | return err; |
494 | if (! (ops->driver & DRIVER_LOADED)) | ||
495 | return 0; /* driver is not loaded yet */ | ||
496 | if (dev->status != SNDRV_SEQ_DEVICE_FREE) | ||
497 | return 0; /* already initialized */ | ||
498 | if (ops->argsize != dev->argsize) { | ||
499 | pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", | ||
500 | dev->name, ops->id, ops->argsize, dev->argsize); | ||
501 | return -EINVAL; | ||
502 | } | ||
503 | if (ops->ops.init_device(dev) >= 0) { | ||
504 | dev->status = SNDRV_SEQ_DEVICE_REGISTERED; | ||
505 | ops->num_init_devices++; | ||
506 | } else { | ||
507 | pr_err("ALSA: seq: init_device failed: %s: %s\n", | ||
508 | dev->name, dev->id); | ||
509 | } | 241 | } |
242 | |||
243 | if (result) | ||
244 | *result = dev; | ||
510 | 245 | ||
511 | return 0; | 246 | return 0; |
512 | } | 247 | } |
248 | EXPORT_SYMBOL(snd_seq_device_new); | ||
513 | 249 | ||
514 | /* | 250 | /* |
515 | * release the device - call free_device operator | 251 | * driver registration |
516 | */ | 252 | */ |
517 | static int free_device(struct snd_seq_device *dev, struct ops_list *ops) | 253 | int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod) |
518 | { | 254 | { |
519 | int result; | 255 | if (WARN_ON(!drv->driver.name || !drv->id)) |
520 | |||
521 | if (! (ops->driver & DRIVER_LOADED)) | ||
522 | return 0; /* driver is not loaded yet */ | ||
523 | if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED) | ||
524 | return 0; /* not registered */ | ||
525 | if (ops->argsize != dev->argsize) { | ||
526 | pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", | ||
527 | dev->name, ops->id, ops->argsize, dev->argsize); | ||
528 | return -EINVAL; | 256 | return -EINVAL; |
529 | } | 257 | drv->driver.bus = &snd_seq_bus_type; |
530 | if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) { | 258 | drv->driver.owner = mod; |
531 | dev->status = SNDRV_SEQ_DEVICE_FREE; | 259 | return driver_register(&drv->driver); |
532 | dev->driver_data = NULL; | ||
533 | ops->num_init_devices--; | ||
534 | } else { | ||
535 | pr_err("ALSA: seq: free_device failed: %s: %s\n", | ||
536 | dev->name, dev->id); | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | } | 260 | } |
261 | EXPORT_SYMBOL_GPL(__snd_seq_driver_register); | ||
541 | 262 | ||
542 | /* | 263 | void snd_seq_driver_unregister(struct snd_seq_driver *drv) |
543 | * find the matching driver with given id | ||
544 | */ | ||
545 | static struct ops_list * find_driver(char *id, int create_if_empty) | ||
546 | { | 264 | { |
547 | struct ops_list *ops; | 265 | driver_unregister(&drv->driver); |
548 | |||
549 | mutex_lock(&ops_mutex); | ||
550 | list_for_each_entry(ops, &opslist, list) { | ||
551 | if (strcmp(ops->id, id) == 0) { | ||
552 | ops->used++; | ||
553 | mutex_unlock(&ops_mutex); | ||
554 | return ops; | ||
555 | } | ||
556 | } | ||
557 | mutex_unlock(&ops_mutex); | ||
558 | if (create_if_empty) | ||
559 | return create_driver(id); | ||
560 | return NULL; | ||
561 | } | 266 | } |
562 | 267 | EXPORT_SYMBOL_GPL(snd_seq_driver_unregister); | |
563 | static void unlock_driver(struct ops_list *ops) | ||
564 | { | ||
565 | mutex_lock(&ops_mutex); | ||
566 | ops->used--; | ||
567 | mutex_unlock(&ops_mutex); | ||
568 | } | ||
569 | |||
570 | 268 | ||
571 | /* | 269 | /* |
572 | * module part | 270 | * module part |
573 | */ | 271 | */ |
574 | 272 | ||
575 | static int __init alsa_seq_device_init(void) | 273 | static int __init seq_dev_proc_init(void) |
576 | { | 274 | { |
577 | #ifdef CONFIG_PROC_FS | 275 | #ifdef CONFIG_PROC_FS |
578 | info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", | 276 | info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", |
@@ -589,28 +287,29 @@ static int __init alsa_seq_device_init(void) | |||
589 | return 0; | 287 | return 0; |
590 | } | 288 | } |
591 | 289 | ||
290 | static int __init alsa_seq_device_init(void) | ||
291 | { | ||
292 | int err; | ||
293 | |||
294 | err = bus_register(&snd_seq_bus_type); | ||
295 | if (err < 0) | ||
296 | return err; | ||
297 | err = seq_dev_proc_init(); | ||
298 | if (err < 0) | ||
299 | bus_unregister(&snd_seq_bus_type); | ||
300 | return err; | ||
301 | } | ||
302 | |||
592 | static void __exit alsa_seq_device_exit(void) | 303 | static void __exit alsa_seq_device_exit(void) |
593 | { | 304 | { |
594 | #ifdef CONFIG_MODULES | 305 | #ifdef CONFIG_MODULES |
595 | cancel_work_sync(&autoload_work); | 306 | cancel_work_sync(&autoload_work); |
596 | #endif | 307 | #endif |
597 | remove_drivers(); | ||
598 | #ifdef CONFIG_PROC_FS | 308 | #ifdef CONFIG_PROC_FS |
599 | snd_info_free_entry(info_entry); | 309 | snd_info_free_entry(info_entry); |
600 | #endif | 310 | #endif |
601 | if (num_ops) | 311 | bus_unregister(&snd_seq_bus_type); |
602 | pr_err("ALSA: seq: drivers not released (%d)\n", num_ops); | ||
603 | } | 312 | } |
604 | 313 | ||
605 | module_init(alsa_seq_device_init) | 314 | subsys_initcall(alsa_seq_device_init) |
606 | module_exit(alsa_seq_device_exit) | 315 | module_exit(alsa_seq_device_exit) |
607 | |||
608 | EXPORT_SYMBOL(snd_seq_device_load_drivers); | ||
609 | EXPORT_SYMBOL(snd_seq_device_new); | ||
610 | EXPORT_SYMBOL(snd_seq_device_register_driver); | ||
611 | EXPORT_SYMBOL(snd_seq_device_unregister_driver); | ||
612 | #ifdef CONFIG_MODULES | ||
613 | EXPORT_SYMBOL(snd_seq_autoload_init); | ||
614 | EXPORT_SYMBOL(snd_seq_autoload_lock); | ||
615 | EXPORT_SYMBOL(snd_seq_autoload_unlock); | ||
616 | #endif | ||
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 5d905d90d504..d3a2ec4f0561 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c | |||
@@ -214,11 +214,7 @@ delete_client(void) | |||
214 | 214 | ||
215 | static int __init alsa_seq_dummy_init(void) | 215 | static int __init alsa_seq_dummy_init(void) |
216 | { | 216 | { |
217 | int err; | 217 | return register_client(); |
218 | snd_seq_autoload_lock(); | ||
219 | err = register_client(); | ||
220 | snd_seq_autoload_unlock(); | ||
221 | return err; | ||
222 | } | 218 | } |
223 | 219 | ||
224 | static void __exit alsa_seq_dummy_exit(void) | 220 | static void __exit alsa_seq_dummy_exit(void) |
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 53a403e17c5b..1d5acbe0c08b 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c | |||
@@ -33,10 +33,8 @@ struct snd_seq_fifo *snd_seq_fifo_new(int poolsize) | |||
33 | struct snd_seq_fifo *f; | 33 | struct snd_seq_fifo *f; |
34 | 34 | ||
35 | f = kzalloc(sizeof(*f), GFP_KERNEL); | 35 | f = kzalloc(sizeof(*f), GFP_KERNEL); |
36 | if (f == NULL) { | 36 | if (!f) |
37 | pr_debug("ALSA: seq: malloc failed for snd_seq_fifo_new() \n"); | ||
38 | return NULL; | 37 | return NULL; |
39 | } | ||
40 | 38 | ||
41 | f->pool = snd_seq_pool_new(poolsize); | 39 | f->pool = snd_seq_pool_new(poolsize); |
42 | if (f->pool == NULL) { | 40 | if (f->pool == NULL) { |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index ba8e4a64e13e..801076687bb1 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -387,10 +387,8 @@ int snd_seq_pool_init(struct snd_seq_pool *pool) | |||
387 | return 0; | 387 | return 0; |
388 | 388 | ||
389 | pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); | 389 | pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); |
390 | if (pool->ptr == NULL) { | 390 | if (!pool->ptr) |
391 | pr_debug("ALSA: seq: malloc for sequencer events failed\n"); | ||
392 | return -ENOMEM; | 391 | return -ENOMEM; |
393 | } | ||
394 | 392 | ||
395 | /* add new cells to the free cell list */ | 393 | /* add new cells to the free cell list */ |
396 | spin_lock_irqsave(&pool->lock, flags); | 394 | spin_lock_irqsave(&pool->lock, flags); |
@@ -463,10 +461,8 @@ struct snd_seq_pool *snd_seq_pool_new(int poolsize) | |||
463 | 461 | ||
464 | /* create pool block */ | 462 | /* create pool block */ |
465 | pool = kzalloc(sizeof(*pool), GFP_KERNEL); | 463 | pool = kzalloc(sizeof(*pool), GFP_KERNEL); |
466 | if (pool == NULL) { | 464 | if (!pool) |
467 | pr_debug("ALSA: seq: malloc failed for pool\n"); | ||
468 | return NULL; | 465 | return NULL; |
469 | } | ||
470 | spin_lock_init(&pool->lock); | 466 | spin_lock_init(&pool->lock); |
471 | pool->ptr = NULL; | 467 | pool->ptr = NULL; |
472 | pool->free = NULL; | 468 | pool->free = NULL; |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 68fec776da26..5dd0ee258359 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -273,8 +273,9 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth) | |||
273 | 273 | ||
274 | /* register new midi synth port */ | 274 | /* register new midi synth port */ |
275 | static int | 275 | static int |
276 | snd_seq_midisynth_register_port(struct snd_seq_device *dev) | 276 | snd_seq_midisynth_probe(struct device *_dev) |
277 | { | 277 | { |
278 | struct snd_seq_device *dev = to_seq_dev(_dev); | ||
278 | struct seq_midisynth_client *client; | 279 | struct seq_midisynth_client *client; |
279 | struct seq_midisynth *msynth, *ms; | 280 | struct seq_midisynth *msynth, *ms; |
280 | struct snd_seq_port_info *port; | 281 | struct snd_seq_port_info *port; |
@@ -427,8 +428,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
427 | 428 | ||
428 | /* release midi synth port */ | 429 | /* release midi synth port */ |
429 | static int | 430 | static int |
430 | snd_seq_midisynth_unregister_port(struct snd_seq_device *dev) | 431 | snd_seq_midisynth_remove(struct device *_dev) |
431 | { | 432 | { |
433 | struct snd_seq_device *dev = to_seq_dev(_dev); | ||
432 | struct seq_midisynth_client *client; | 434 | struct seq_midisynth_client *client; |
433 | struct seq_midisynth *msynth; | 435 | struct seq_midisynth *msynth; |
434 | struct snd_card *card = dev->card; | 436 | struct snd_card *card = dev->card; |
@@ -457,24 +459,14 @@ snd_seq_midisynth_unregister_port(struct snd_seq_device *dev) | |||
457 | return 0; | 459 | return 0; |
458 | } | 460 | } |
459 | 461 | ||
462 | static struct snd_seq_driver seq_midisynth_driver = { | ||
463 | .driver = { | ||
464 | .name = KBUILD_MODNAME, | ||
465 | .probe = snd_seq_midisynth_probe, | ||
466 | .remove = snd_seq_midisynth_remove, | ||
467 | }, | ||
468 | .id = SNDRV_SEQ_DEV_ID_MIDISYNTH, | ||
469 | .argsize = 0, | ||
470 | }; | ||
460 | 471 | ||
461 | static int __init alsa_seq_midi_init(void) | 472 | module_snd_seq_driver(seq_midisynth_driver); |
462 | { | ||
463 | static struct snd_seq_dev_ops ops = { | ||
464 | snd_seq_midisynth_register_port, | ||
465 | snd_seq_midisynth_unregister_port, | ||
466 | }; | ||
467 | memset(&synths, 0, sizeof(synths)); | ||
468 | snd_seq_autoload_lock(); | ||
469 | snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0); | ||
470 | snd_seq_autoload_unlock(); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static void __exit alsa_seq_midi_exit(void) | ||
475 | { | ||
476 | snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH); | ||
477 | } | ||
478 | |||
479 | module_init(alsa_seq_midi_init) | ||
480 | module_exit(alsa_seq_midi_exit) | ||
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 46ff593f618d..55170a20ae72 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -141,10 +141,8 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
141 | 141 | ||
142 | /* create a new port */ | 142 | /* create a new port */ |
143 | new_port = kzalloc(sizeof(*new_port), GFP_KERNEL); | 143 | new_port = kzalloc(sizeof(*new_port), GFP_KERNEL); |
144 | if (! new_port) { | 144 | if (!new_port) |
145 | pr_debug("ALSA: seq: malloc failed for registering client port\n"); | ||
146 | return NULL; /* failure, out of memory */ | 145 | return NULL; /* failure, out of memory */ |
147 | } | ||
148 | /* init port data */ | 146 | /* init port data */ |
149 | new_port->addr.client = client->number; | 147 | new_port->addr.client = client->number; |
150 | new_port->addr.port = -1; | 148 | new_port->addr.port = -1; |
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 021b02bc9330..bc1c8488fc2a 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c | |||
@@ -59,10 +59,8 @@ struct snd_seq_prioq *snd_seq_prioq_new(void) | |||
59 | struct snd_seq_prioq *f; | 59 | struct snd_seq_prioq *f; |
60 | 60 | ||
61 | f = kzalloc(sizeof(*f), GFP_KERNEL); | 61 | f = kzalloc(sizeof(*f), GFP_KERNEL); |
62 | if (f == NULL) { | 62 | if (!f) |
63 | pr_debug("ALSA: seq: malloc failed for snd_seq_prioq_new()\n"); | ||
64 | return NULL; | 63 | return NULL; |
65 | } | ||
66 | 64 | ||
67 | spin_lock_init(&f->lock); | 65 | spin_lock_init(&f->lock); |
68 | f->head = NULL; | 66 | f->head = NULL; |
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index aad4878cee55..a0cda38205b9 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c | |||
@@ -111,10 +111,8 @@ static struct snd_seq_queue *queue_new(int owner, int locked) | |||
111 | struct snd_seq_queue *q; | 111 | struct snd_seq_queue *q; |
112 | 112 | ||
113 | q = kzalloc(sizeof(*q), GFP_KERNEL); | 113 | q = kzalloc(sizeof(*q), GFP_KERNEL); |
114 | if (q == NULL) { | 114 | if (!q) |
115 | pr_debug("ALSA: seq: malloc failed for snd_seq_queue_new()\n"); | ||
116 | return NULL; | 115 | return NULL; |
117 | } | ||
118 | 116 | ||
119 | spin_lock_init(&q->owner_lock); | 117 | spin_lock_init(&q->owner_lock); |
120 | spin_lock_init(&q->check_lock); | 118 | spin_lock_init(&q->check_lock); |
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index e73605393eee..186f1611103c 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -56,10 +56,8 @@ struct snd_seq_timer *snd_seq_timer_new(void) | |||
56 | struct snd_seq_timer *tmr; | 56 | struct snd_seq_timer *tmr; |
57 | 57 | ||
58 | tmr = kzalloc(sizeof(*tmr), GFP_KERNEL); | 58 | tmr = kzalloc(sizeof(*tmr), GFP_KERNEL); |
59 | if (tmr == NULL) { | 59 | if (!tmr) |
60 | pr_debug("ALSA: seq: malloc failed for snd_seq_timer_new() \n"); | ||
61 | return NULL; | 60 | return NULL; |
62 | } | ||
63 | spin_lock_init(&tmr->lock); | 61 | spin_lock_init(&tmr->lock); |
64 | 62 | ||
65 | /* reset setup to defaults */ | 63 | /* reset setup to defaults */ |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 185cec01ee25..5fc93d00572a 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -186,7 +186,7 @@ static const struct file_operations snd_fops = | |||
186 | }; | 186 | }; |
187 | 187 | ||
188 | #ifdef CONFIG_SND_DYNAMIC_MINORS | 188 | #ifdef CONFIG_SND_DYNAMIC_MINORS |
189 | static int snd_find_free_minor(int type) | 189 | static int snd_find_free_minor(int type, struct snd_card *card, int dev) |
190 | { | 190 | { |
191 | int minor; | 191 | int minor; |
192 | 192 | ||
@@ -209,7 +209,7 @@ static int snd_find_free_minor(int type) | |||
209 | return -EBUSY; | 209 | return -EBUSY; |
210 | } | 210 | } |
211 | #else | 211 | #else |
212 | static int snd_kernel_minor(int type, struct snd_card *card, int dev) | 212 | static int snd_find_free_minor(int type, struct snd_card *card, int dev) |
213 | { | 213 | { |
214 | int minor; | 214 | int minor; |
215 | 215 | ||
@@ -237,6 +237,8 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) | |||
237 | } | 237 | } |
238 | if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS)) | 238 | if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS)) |
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | if (snd_minors[minor]) | ||
241 | return -EBUSY; | ||
240 | return minor; | 242 | return minor; |
241 | } | 243 | } |
242 | #endif | 244 | #endif |
@@ -276,13 +278,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, | |||
276 | preg->private_data = private_data; | 278 | preg->private_data = private_data; |
277 | preg->card_ptr = card; | 279 | preg->card_ptr = card; |
278 | mutex_lock(&sound_mutex); | 280 | mutex_lock(&sound_mutex); |
279 | #ifdef CONFIG_SND_DYNAMIC_MINORS | 281 | minor = snd_find_free_minor(type, card, dev); |
280 | minor = snd_find_free_minor(type); | ||
281 | #else | ||
282 | minor = snd_kernel_minor(type, card, dev); | ||
283 | if (minor >= 0 && snd_minors[minor]) | ||
284 | minor = -EBUSY; | ||
285 | #endif | ||
286 | if (minor < 0) { | 282 | if (minor < 0) { |
287 | err = minor; | 283 | err = minor; |
288 | goto error; | 284 | goto error; |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 490b489d713d..a9a1a047c521 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -774,10 +774,8 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, | |||
774 | if (rtimer) | 774 | if (rtimer) |
775 | *rtimer = NULL; | 775 | *rtimer = NULL; |
776 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | 776 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); |
777 | if (timer == NULL) { | 777 | if (!timer) |
778 | pr_err("ALSA: timer: cannot allocate\n"); | ||
779 | return -ENOMEM; | 778 | return -ENOMEM; |
780 | } | ||
781 | timer->tmr_class = tid->dev_class; | 779 | timer->tmr_class = tid->dev_class; |
782 | timer->card = card; | 780 | timer->card = card; |
783 | timer->tmr_device = tid->device; | 781 | timer->tmr_device = tid->device; |