~ubuntu-branches/ubuntu/lucid/linux-qcm-msm/lucid

« back to all changes in this revision

Viewing changes to drivers/connector/connector.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Andy Whitcroft, Ubuntu: 2.6.31-21.59, Ubuntu: 2.6.31-20.58
  • Date: 2010-03-31 18:43:39 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100331184339-q3ee013jxywlf5ln
Tags: 2.6.31-800.2
[ Andy Whitcroft ]

* getabis -- get the correct source package
* rebase to Ubuntu-2.6.31-21.59

[ Ubuntu: 2.6.31-21.59 ]

* [Config] generic-pae switch to M586TSC
  - LP: #519448
* (pre-stable) drm/i915: Increase fb alignment to 64k
  - LP: #404064
* Input: i8042 - bypass AUX IRQ delivery test on laptops
  - LP: #534448
* SAUCE: Fix volume hotkeys for Dell Studio 1557
  - LP: #465250
* SAUCE: aufs: Fix header files inclusion in debug.h
  - LP: #517151
* [Config] Enable all CGROUP configuration options
  - LP: #480739
* Revert "[Upstream] acerhdf: Limit modalias matching to supported
  boards"
  - LP: #509730
* [Config] ext3 defaults to ordered mode
  - LP: #510067
* [Config] Fix sub-flavours package conflicts
  - LP: #454827
* PCI/cardbus: Add a fixup hook and fix powerpc
  - LP: #455723
* fnctl: f_modown should call write_lock_irqsave/restore
  - LP: #519436
* ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
  - LP: #516325
* tg3: Add 57788, remove 57720
  - LP: #515390
* HID: ignore all recent SoundGraph iMON devices
  - LP: #488443
* Input: ALPS - add interleaved protocol support (Dell E6x00 series)
  - LP: #296610
* acerhdf: limit modalias matching to supported
  - LP: #509730
* ASoC: Do not write to invalid registers on the wm9712.
  - LP: #509730
* cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS
  referrals
  - LP: #509730
* clockevents: Prevent clockevent_devices list corruption on cpu hotplug
  - LP: #509730
* dma: at_hdmac: correct incompatible type for argument 1 of
  'spin_lock_bh'
  - LP: #509730
* drivers/net/usb: Correct code taking the size of a pointer
  - LP: #509730
* Libertas: fix buffer overflow in lbs_get_essid()
  - LP: #509730
* md: Fix unfortunate interaction with evms
  - LP: #509730
* pata_cmd64x: fix overclocking of UDMA0-2 modes
  - LP: #509730
* pata_hpt3x2n: fix clock turnaround
  - LP: #509730
* SCSI: fc class: fix fc_transport_init error handling
  - LP: #509730
* sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer
  - LP: #509730
* USB: emi62: fix crash when trying to load EMI 6|2 firmware
  - LP: #509730
* USB: Fix a bug on appledisplay.c regarding signedness
  - LP: #509730
* USB: musb: gadget_ep0: avoid SetupEnd interrupt
  - LP: #509730
* USB: option: support hi speed for modem Haier CE100
  - LP: #490068, #509730
* x86, cpuid: Add "volatile" to asm in native_cpuid()
  - LP: #509730
* e100: Use pci pool to work around GFP_ATOMIC order 5 memory allocation
  failure
  - LP: #509730
* e100: Fix broken cbs accounting due to missing memset.
  - LP: #509730
* hostap: Revert a toxic part of the conversion to net_device_ops
  - LP: #509730
* hwmon: (fschmd) Fix check on unsigned in watchdog_write()
  - LP: #509730
* hwmon: (sht15) Off-by-one error in array index + incorrect constants
  - LP: #509730
* i2c/tsl2550: Fix lux value in extended mode
  - LP: #509730
* ipv6: reassembly: use seperate reassembly queues for conntrack and
  local delivery
  - LP: #509730
* S390: dasd: support DIAG access for read-only devices
  - LP: #509730
* udf: Try harder when looking for VAT inode
  - LP: #509730
* V4L/DVB (13596): ov511.c typo: lock => unlock
  - LP: #509730
* x86/ptrace: make genregs[32]_get/set more robust
  - LP: #509730
* XFS bug in log recover with quota (bugzilla id 855)
  - LP: #509730
* generic_permission: MAY_OPEN is not write access
  - LP: #509730
* memcg: avoid oom-killing innocent task in case of use_hierarchy
  - LP: #509730
* Input: atkbd - add force relese key quirk for Samsung R59P/R60P/R61P
  - LP: #253874, #509730
* Add unlocked version of inode_add_bytes() function
  - LP: #509730
* ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
  - LP: #509730
* Linux 2.6.31.10
  - LP: #509730
* Linux 2.6.31.11
  - LP: #509730
* quota: decouple fs reserved space from quota reservation
  - LP: #510674
* ext4: Convert to generic reserved quota's space management.
  - LP: #510674
* hwmon: (adt7462) Fix pin 28 monitoring
  - LP: #510674
* netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq()
  - LP: #510674
* quota: Fix dquot_transfer for filesystems different from ext4
  - LP: #510674
* fix braindamage in audit_tree.c untag_chunk()
  - LP: #510674
* fix more leaks in audit_tree.c tag_chunk()
  - LP: #510674
* ACPI: sleep: another HP DMI entry for init_set_sci_en_on_resume
  - LP: #453963, #510674
* ACPI: add DMI entry for SCI_EN resume quirk on HP dv4
  - LP: #453963, #510674
* ACPI: sleep: another HP/Compaq DMI entries for
  init_set_sci_en_on_resume
  - LP: #453963, #510674
* ACPI: DMI init_set_sci_en_on_resume for HP-Compaq C700
  - LP: #453963, #510674
* Linux 2.6.31.12
  - LP: #510674

[ Ubuntu: 2.6.31-20.58 ]

* Revert "[Upstream] e1000: enhance frame fragment detection"
  - CVE-2009-4536
* Revert "[Upstream] e1000e: enhance frame fragment detection"
  - CVE-2009-4538
* e1000: enhance frame fragment detection
  - CVE-2009-4536
* e1000/e1000e: don't use small hardware rx buffers
  - CVE-2009-4536
* e1000e: enhance frame fragment detection
  - CVE-2009-4538
* KVM: PIT: control word is write-only
  - CVE-2010-0309
* connector: Delete buggy notification code.
  - CVE-2010-0410
* Fix potential crash with sys_move_pages
  - CVE-2010-0415
* futex: Handle user space corruption gracefully
  - CVE-2010-0622
* futex_lock_pi() key refcnt fix
  - CVE-2010-0623
* Split 'flush_old_exec' into two functions
  - CVE-2010-0307
* Fix 'flush_old_exec()/setup_new_exec()' split
  - CVE-2010-0307
* x86: get rid of the insane TIF_ABI_PENDING bit
  - CVE-2010-0307
* powerpc: TIF_ABI_PENDING bit removal
  - CVE-2010-0307
* sparc: TIF_ABI_PENDING bit removal
  - CVE-2010-0307
* x86: set_personality_ia32() misses force_personality32
  - CVE-2010-0307

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
37
37
MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
38
38
 
39
 
static u32 cn_idx = CN_IDX_CONNECTOR;
40
 
static u32 cn_val = CN_VAL_CONNECTOR;
41
 
 
42
 
module_param(cn_idx, uint, 0);
43
 
module_param(cn_val, uint, 0);
44
 
MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
45
 
MODULE_PARM_DESC(cn_val, "Connector's main device val.");
46
 
 
47
 
static DEFINE_MUTEX(notify_lock);
48
 
static LIST_HEAD(notify_list);
49
 
 
50
39
static struct cn_dev cdev;
51
40
 
52
41
static int cn_already_initialized;
210
199
}
211
200
 
212
201
/*
213
 
 * Notification routing.
214
 
 *
215
 
 * Gets id and checks if there are notification request for it's idx
216
 
 * and val.  If there are such requests notify the listeners with the
217
 
 * given notify event.
218
 
 *
219
 
 */
220
 
static void cn_notify(struct cb_id *id, u32 notify_event)
221
 
{
222
 
        struct cn_ctl_entry *ent;
223
 
 
224
 
        mutex_lock(&notify_lock);
225
 
        list_for_each_entry(ent, &notify_list, notify_entry) {
226
 
                int i;
227
 
                struct cn_notify_req *req;
228
 
                struct cn_ctl_msg *ctl = ent->msg;
229
 
                int idx_found, val_found;
230
 
 
231
 
                idx_found = val_found = 0;
232
 
 
233
 
                req = (struct cn_notify_req *)ctl->data;
234
 
                for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
235
 
                        if (id->idx >= req->first &&
236
 
                                        id->idx < req->first + req->range) {
237
 
                                idx_found = 1;
238
 
                                break;
239
 
                        }
240
 
                }
241
 
 
242
 
                for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
243
 
                        if (id->val >= req->first &&
244
 
                                        id->val < req->first + req->range) {
245
 
                                val_found = 1;
246
 
                                break;
247
 
                        }
248
 
                }
249
 
 
250
 
                if (idx_found && val_found) {
251
 
                        struct cn_msg m = { .ack = notify_event, };
252
 
 
253
 
                        memcpy(&m.id, id, sizeof(m.id));
254
 
                        cn_netlink_send(&m, ctl->group, GFP_KERNEL);
255
 
                }
256
 
        }
257
 
        mutex_unlock(&notify_lock);
258
 
}
259
 
 
260
 
/*
261
202
 * Callback add routing - adds callback with given ID and name.
262
203
 * If there is registered callback with the same ID it will not be added.
263
204
 *
276
217
        if (err)
277
218
                return err;
278
219
 
279
 
        cn_notify(id, 0);
280
 
 
281
220
        return 0;
282
221
}
283
222
EXPORT_SYMBOL_GPL(cn_add_callback);
295
234
        struct cn_dev *dev = &cdev;
296
235
 
297
236
        cn_queue_del_callback(dev->cbdev, id);
298
 
        cn_notify(id, 1);
299
237
}
300
238
EXPORT_SYMBOL_GPL(cn_del_callback);
301
239
 
302
 
/*
303
 
 * Checks two connector's control messages to be the same.
304
 
 * Returns 1 if they are the same or if the first one is corrupted.
305
 
 */
306
 
static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
307
 
{
308
 
        int i;
309
 
        struct cn_notify_req *req1, *req2;
310
 
 
311
 
        if (m1->idx_notify_num != m2->idx_notify_num)
312
 
                return 0;
313
 
 
314
 
        if (m1->val_notify_num != m2->val_notify_num)
315
 
                return 0;
316
 
 
317
 
        if (m1->len != m2->len)
318
 
                return 0;
319
 
 
320
 
        if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
321
 
            m1->len)
322
 
                return 1;
323
 
 
324
 
        req1 = (struct cn_notify_req *)m1->data;
325
 
        req2 = (struct cn_notify_req *)m2->data;
326
 
 
327
 
        for (i = 0; i < m1->idx_notify_num; ++i) {
328
 
                if (req1->first != req2->first || req1->range != req2->range)
329
 
                        return 0;
330
 
                req1++;
331
 
                req2++;
332
 
        }
333
 
 
334
 
        for (i = 0; i < m1->val_notify_num; ++i) {
335
 
                if (req1->first != req2->first || req1->range != req2->range)
336
 
                        return 0;
337
 
                req1++;
338
 
                req2++;
339
 
        }
340
 
 
341
 
        return 1;
342
 
}
343
 
 
344
 
/*
345
 
 * Main connector device's callback.
346
 
 *
347
 
 * Used for notification of a request's processing.
348
 
 */
349
 
static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
350
 
{
351
 
        struct cn_ctl_msg *ctl;
352
 
        struct cn_ctl_entry *ent;
353
 
        u32 size;
354
 
 
355
 
        if (msg->len < sizeof(*ctl))
356
 
                return;
357
 
 
358
 
        ctl = (struct cn_ctl_msg *)msg->data;
359
 
 
360
 
        size = (sizeof(*ctl) + ((ctl->idx_notify_num +
361
 
                                 ctl->val_notify_num) *
362
 
                                sizeof(struct cn_notify_req)));
363
 
 
364
 
        if (msg->len != size)
365
 
                return;
366
 
 
367
 
        if (ctl->len + sizeof(*ctl) != msg->len)
368
 
                return;
369
 
 
370
 
        /*
371
 
         * Remove notification.
372
 
         */
373
 
        if (ctl->group == 0) {
374
 
                struct cn_ctl_entry *n;
375
 
 
376
 
                mutex_lock(&notify_lock);
377
 
                list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
378
 
                        if (cn_ctl_msg_equals(ent->msg, ctl)) {
379
 
                                list_del(&ent->notify_entry);
380
 
                                kfree(ent);
381
 
                        }
382
 
                }
383
 
                mutex_unlock(&notify_lock);
384
 
 
385
 
                return;
386
 
        }
387
 
 
388
 
        size += sizeof(*ent);
389
 
 
390
 
        ent = kzalloc(size, GFP_KERNEL);
391
 
        if (!ent)
392
 
                return;
393
 
 
394
 
        ent->msg = (struct cn_ctl_msg *)(ent + 1);
395
 
 
396
 
        memcpy(ent->msg, ctl, size - sizeof(*ent));
397
 
 
398
 
        mutex_lock(&notify_lock);
399
 
        list_add(&ent->notify_entry, &notify_list);
400
 
        mutex_unlock(&notify_lock);
401
 
}
402
 
 
403
240
static int cn_proc_show(struct seq_file *m, void *v)
404
241
{
405
242
        struct cn_queue_dev *dev = cdev.cbdev;
437
274
static int __devinit cn_init(void)
438
275
{
439
276
        struct cn_dev *dev = &cdev;
440
 
        int err;
441
277
 
442
278
        dev->input = cn_rx_skb;
443
 
        dev->id.idx = cn_idx;
444
 
        dev->id.val = cn_val;
445
279
 
446
280
        dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
447
281
                                         CN_NETLINK_USERS + 0xf,
457
291
 
458
292
        cn_already_initialized = 1;
459
293
 
460
 
        err = cn_add_callback(&dev->id, "connector", &cn_callback);
461
 
        if (err) {
462
 
                cn_already_initialized = 0;
463
 
                cn_queue_free_dev(dev->cbdev);
464
 
                netlink_kernel_release(dev->nls);
465
 
                return -EINVAL;
466
 
        }
467
 
 
468
294
        proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
469
295
 
470
296
        return 0;
478
304
 
479
305
        proc_net_remove(&init_net, "connector");
480
306
 
481
 
        cn_del_callback(&dev->id);
482
307
        cn_queue_free_dev(dev->cbdev);
483
308
        netlink_kernel_release(dev->nls);
484
309
}