From 76f16f83ee520d6c10356b0f6ff592441a6f08bd Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 30 Jul 2012 15:42:36 +0800 Subject: crypto: hifn_795x - fix 64bit division and undefined __divdi3 on 32bit archs Commit feb7b7ab928afa97a79a9c424e4e0691f49d63be changed NSEC_PER_SEC to 64-bit constant, which causes "DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq)" to generate __divdi3 call on 32-bit archs. Fix this by changing DIV_ROUND_UP to DIV_ROUND_UP_ULL. Signed-off-by: Jussi Kivilinna Acked-by: Randy Dunlap Signed-off-by: Herbert Xu --- drivers/crypto/hifn_795x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index c9c4befb5a8d..df14358d7fa1 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -821,8 +821,8 @@ static int hifn_register_rng(struct hifn_device *dev) /* * We must wait at least 256 Pk_clk cycles between two reads of the rng. */ - dev->rng_wait_time = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) * - 256; + dev->rng_wait_time = DIV_ROUND_UP_ULL(NSEC_PER_SEC, + dev->pk_clk_freq) * 256; dev->rng.name = dev->name; dev->rng.data_present = hifn_rng_data_present, -- cgit v1.2.3 From 1b8652142334a8c0729c5c4536a22cfc6fc49297 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 9 Aug 2012 12:38:21 +0530 Subject: cpufreq: OMAP: Handle missing frequency table on SMP systems On OMAP4, if the first CPU fails to get a valid frequency table (this could happen if the platform does not register any OPP table), the subsequent CPU instances end up dealing with a NULL freq_table and crash. Check for an already existing freq_table, before trying to create one, and increment the freq_table_users only if the table is sucessfully created. Signed-off-by: Rajendra Nayak Signed-off-by: Santosh Shilimkar Cc: Signed-off-by: Kevin Hilman --- drivers/cpufreq/omap-cpufreq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 17fa04d08be9..b47034e650a5 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -218,7 +218,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); - if (atomic_inc_return(&freq_table_users) == 1) + if (!freq_table) result = opp_init_cpufreq_table(mpu_dev, &freq_table); if (result) { @@ -227,6 +227,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) goto fail_ck; } + atomic_inc_return(&freq_table_users); + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (result) goto fail_table; -- cgit v1.2.3 From bc21fde2d549d1cb1ebef04016eb7affa43bb5c1 Mon Sep 17 00:00:00 2001 From: Yevgeniy Melnichuk Date: Tue, 7 Aug 2012 19:48:10 +0530 Subject: Bluetooth: Add support for Sony Vaio T-Series Add Sony Vaio T-Series Bluetooth Module( 0x489:0xE036) to the blacklist of btusb module and add it to the ath3k module. output of cat /sys/kernel/debug/usb/devices T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e036 Rev= 0.02 S: Manufacturer=Atheros Communications S: Product=Bluetooth USB Host Controller S: SerialNumber=Alaska Day 2006 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Yevgeniy Melnichuk Signed-off-by: Mohammed Shafi Shajakhan Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 11f36e502136..fc2de5528dcc 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C) }, + { USB_DEVICE(0x0489, 0xE036) }, { } /* Terminating entry */ }; @@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cef3bac1a543..2fe7776dc49c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -141,6 +141,7 @@ static struct usb_device_id blacklist_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, -- cgit v1.2.3 From 227f052f4711caf432b9a7dbcfe1a2857d3c0def Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 31 Jul 2012 09:31:11 +0200 Subject: drbd: fix drbd wire compatibility for empty flushes DRBD has a concept of request epochs or reorder-domains, which are separated on the wire by P_BARRIER packets. Older DRBD is not able to handle zero-sized requests at all, so we need to map empty flushes to these drbd barriers. These are the equivalent of empty flushes, and by default trigger flushes on the receiving side anyways (unless not supported or explicitly disabled), so there is no need to handle this differently in newer drbd either. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_req.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 910335c30927..0bb1e41f136f 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -834,7 +834,15 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns req->private_bio = NULL; } if (rw == WRITE) { - remote = 1; + /* Need to replicate writes. Unless it is an empty flush, + * which is better mapped to a DRBD P_BARRIER packet, + * also for drbd wire protocol compatibility reasons. */ + if (unlikely(size == 0)) { + /* The only size==0 bios we expect are empty flushes. */ + D_ASSERT(bio->bi_rw & REQ_FLUSH); + remote = 0; + } else + remote = 1; } else { /* READ || READA */ if (local) { @@ -870,8 +878,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns * extent. This waits for any resync activity in the corresponding * resync extent to finish, and, if necessary, pulls in the target * extent into the activity log, which involves further disk io because - * of transactional on-disk meta data updates. */ - if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) { + * of transactional on-disk meta data updates. + * Empty flushes don't need to go into the activity log, they can only + * flush data for pending writes which are already in there. */ + if (rw == WRITE && local && size + && !test_bit(AL_SUSPENDED, &mdev->flags)) { req->rq_state |= RQ_IN_ACT_LOG; drbd_al_begin_io(mdev, sector); } @@ -994,7 +1005,10 @@ allocate_barrier: if (rw == WRITE && _req_conflicts(req)) goto fail_conflicting; - list_add_tail(&req->tl_requests, &mdev->newest_tle->requests); + /* no point in adding empty flushes to the transfer log, + * they are mapped to drbd barriers already. */ + if (likely(size!=0)) + list_add_tail(&req->tl_requests, &mdev->newest_tle->requests); /* NOTE remote first: to get the concurrent write detection right, * we must register the request before start of local IO. */ @@ -1014,6 +1028,14 @@ allocate_barrier: mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) maybe_pull_ahead(mdev); + /* If this was a flush, queue a drbd barrier/start a new epoch. + * Unless the current epoch was empty anyways, or we are not currently + * replicating, in which case there is no point. */ + if (unlikely(bio->bi_rw & REQ_FLUSH) + && mdev->newest_tle->n_writes + && drbd_should_do_remote(mdev->state)) + queue_barrier(mdev); + spin_unlock_irq(&mdev->req_lock); kfree(b); /* if someone else has beaten us to it... */ -- cgit v1.2.3 From 509fc019e534bdf5f3969d78c53184db4cf7ff48 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 31 Jul 2012 11:22:58 +0200 Subject: drbd: Finish requests that completed while IO was frozen Requests of an acked epoch are stored on the barrier_acked_requests list. In case the private bio of such a request completes while IO on the drbd device is suspended [req_mod(completed_ok)] then the request stays there. When thawing IO because the fence_peer handler returned, then we use tl_clear() to apply the connection_lost_while_pending event to all requests on the transfer-log and the barrier_acked_requests list. Up to now the connection_lost_while_pending event was not applied on requests on the barrier_acked_requests list. Fixed that. I.e. now the connection_lost_while_pending and resend events are applied to requests on the barrier_acked_requests list. For that it is necessary that the resend event finishes (local only) READS correctly. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 28 ++++++++++++---------------- drivers/block/drbd/drbd_req.c | 6 ++++++ 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 2e0e7fc1dbba..136db95b212d 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -79,6 +79,7 @@ static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused); static void md_sync_timer_fn(unsigned long data); static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused); static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused); +static void _tl_clear(struct drbd_conf *mdev); MODULE_AUTHOR("Philipp Reisner , " "Lars Ellenberg "); @@ -432,19 +433,10 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) /* Actions operating on the disk state, also want to work on requests that got barrier acked. */ - switch (what) { - case fail_frozen_disk_io: - case restart_frozen_disk_io: - list_for_each_safe(le, tle, &mdev->barrier_acked_requests) { - req = list_entry(le, struct drbd_request, tl_requests); - _req_mod(req, what); - } - case connection_lost_while_pending: - case resend: - break; - default: - dev_err(DEV, "what = %d in _tl_restart()\n", what); + list_for_each_safe(le, tle, &mdev->barrier_acked_requests) { + req = list_entry(le, struct drbd_request, tl_requests); + _req_mod(req, what); } } @@ -458,12 +450,17 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) * receiver thread and the worker thread. */ void tl_clear(struct drbd_conf *mdev) +{ + spin_lock_irq(&mdev->req_lock); + _tl_clear(mdev); + spin_unlock_irq(&mdev->req_lock); +} + +static void _tl_clear(struct drbd_conf *mdev) { struct list_head *le, *tle; struct drbd_request *r; - spin_lock_irq(&mdev->req_lock); - _tl_restart(mdev, connection_lost_while_pending); /* we expect this list to be empty. */ @@ -482,7 +479,6 @@ void tl_clear(struct drbd_conf *mdev) memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *)); - spin_unlock_irq(&mdev->req_lock); } void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) @@ -1476,12 +1472,12 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, if (ns.susp_fen) { /* case1: The outdate peer handler is successful: */ if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) { - tl_clear(mdev); if (test_bit(NEW_CUR_UUID, &mdev->flags)) { drbd_uuid_new_current(mdev); clear_bit(NEW_CUR_UUID, &mdev->flags); } spin_lock_irq(&mdev->req_lock); + _tl_clear(mdev); _drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL); spin_unlock_irq(&mdev->req_lock); } diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 0bb1e41f136f..01b2ac641c7b 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -695,6 +695,12 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, break; case resend: + /* Simply complete (local only) READs. */ + if (!(req->rq_state & RQ_WRITE) && !req->w.cb) { + _req_may_be_done(req, m); + break; + } + /* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK before the connection loss (B&C only); only P_BARRIER_ACK was missing. Trowing them out of the TL here by pretending we got a BARRIER_ACK -- cgit v1.2.3 From d1aa4d04da8de5c89d73859e077d89c4c71d8ed1 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Wed, 8 Aug 2012 21:19:09 +0200 Subject: drbd: Write all pages of the bitmap after an online resize We need to write the whole bitmap after we moved the meta data due to an online resize operation. With the support for one peta byte devices bitmap IO was optimized to only write out touched pages. This optimization must be turned off when writing the bitmap after an online resize. This issue was introduced with drbd-8.3.10. The impact of this bug is that after an online resize, the next resync could become larger than expected. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_bitmap.c | 15 ++++++++++++++- drivers/block/drbd/drbd_int.h | 1 + drivers/block/drbd/drbd_nl.c | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index ba91b408abad..d84566496746 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -889,6 +889,7 @@ struct bm_aio_ctx { unsigned int done; unsigned flags; #define BM_AIO_COPY_PAGES 1 +#define BM_WRITE_ALL_PAGES 2 int error; struct kref kref; }; @@ -1059,7 +1060,8 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) break; if (rw & WRITE) { - if (bm_test_page_unchanged(b->bm_pages[i])) { + if (!(flags & BM_WRITE_ALL_PAGES) && + bm_test_page_unchanged(b->bm_pages[i])) { dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i); continue; } @@ -1140,6 +1142,17 @@ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) return bm_rw(mdev, WRITE, 0, 0); } +/** + * drbd_bm_write_all() - Write the whole bitmap to its on disk location. + * @mdev: DRBD device. + * + * Will write all pages. + */ +int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local) +{ + return bm_rw(mdev, WRITE, BM_WRITE_ALL_PAGES, 0); +} + /** * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed. * @mdev: DRBD device. diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index b2ca143d0053..b953cc7c9c00 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1469,6 +1469,7 @@ extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr); extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); +extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local); extern int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local); extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index fb9dce8daa24..edb490aad8b4 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -674,8 +674,8 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds la_size_changed && md_moved ? "size changed and md moved" : la_size_changed ? "size changed" : "md moved"); /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */ - err = drbd_bitmap_io(mdev, &drbd_bm_write, - "size changed", BM_LOCKED_MASK); + err = drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write, + "size changed", BM_LOCKED_MASK); if (err) { rv = dev_size_error; goto out; -- cgit v1.2.3 From ca08649eb5dd30f11a5a8fe8659b48899b7ea6a1 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 16 Aug 2012 11:31:27 -0400 Subject: Revert "xen PVonHVM: move shared_info to MMIO before kexec" This reverts commit 00e37bdb0113a98408de42db85be002f21dbffd3. During shutdown of PVHVM guests with more than 2VCPUs on certain machines we can hit the race where the replaced shared_info is not replaced fast enough and the PV time clock retries reading the same area over and over without any any success and is stuck in an infinite loop. Acked-by: Olaf Hering Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 118 +++++---------------------------------------- arch/x86/xen/suspend.c | 2 +- arch/x86/xen/xen-ops.h | 2 +- drivers/xen/platform-pci.c | 15 ------ include/xen/events.h | 2 - 5 files changed, 13 insertions(+), 126 deletions(-) (limited to 'drivers') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a6f8acbdfc9a..f1814fc2cb77 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -1472,130 +1471,38 @@ asmlinkage void __init xen_start_kernel(void) #endif } -#ifdef CONFIG_XEN_PVHVM -/* - * The pfn containing the shared_info is located somewhere in RAM. This - * will cause trouble if the current kernel is doing a kexec boot into a - * new kernel. The new kernel (and its startup code) can not know where - * the pfn is, so it can not reserve the page. The hypervisor will - * continue to update the pfn, and as a result memory corruption occours - * in the new kernel. - * - * One way to work around this issue is to allocate a page in the - * xen-platform pci device's BAR memory range. But pci init is done very - * late and the shared_info page is already in use very early to read - * the pvclock. So moving the pfn from RAM to MMIO is racy because some - * code paths on other vcpus could access the pfn during the small - * window when the old pfn is moved to the new pfn. There is even a - * small window were the old pfn is not backed by a mfn, and during that - * time all reads return -1. - * - * Because it is not known upfront where the MMIO region is located it - * can not be used right from the start in xen_hvm_init_shared_info. - * - * To minimise trouble the move of the pfn is done shortly before kexec. - * This does not eliminate the race because all vcpus are still online - * when the syscore_ops will be called. But hopefully there is no work - * pending at this point in time. Also the syscore_op is run last which - * reduces the risk further. - */ - -static struct shared_info *xen_hvm_shared_info; - -static void xen_hvm_connect_shared_info(unsigned long pfn) +void __ref xen_hvm_init_shared_info(void) { + int cpu; struct xen_add_to_physmap xatp; + static struct shared_info *shared_info_page = 0; + if (!shared_info_page) + shared_info_page = (struct shared_info *) + extend_brk(PAGE_SIZE, PAGE_SIZE); xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; - xatp.gpfn = pfn; + xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) BUG(); -} -static void xen_hvm_set_shared_info(struct shared_info *sip) -{ - int cpu; - - HYPERVISOR_shared_info = sip; + HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info * page, we use it in the event channel upcall and in some pvclock * related functions. We don't need the vcpu_info placement * optimizations because we don't use any pv_mmu or pv_irq op on * HVM. - * When xen_hvm_set_shared_info is run at boot time only vcpu 0 is - * online but xen_hvm_set_shared_info is run at resume time too and + * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is + * online but xen_hvm_init_shared_info is run at resume time too and * in that case multiple vcpus might be online. */ for_each_online_cpu(cpu) { per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; } } -/* Reconnect the shared_info pfn to a mfn */ -void xen_hvm_resume_shared_info(void) -{ - xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT); -} - -#ifdef CONFIG_KEXEC -static struct shared_info *xen_hvm_shared_info_kexec; -static unsigned long xen_hvm_shared_info_pfn_kexec; - -/* Remember a pfn in MMIO space for kexec reboot */ -void __devinit xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn) -{ - xen_hvm_shared_info_kexec = sip; - xen_hvm_shared_info_pfn_kexec = pfn; -} - -static void xen_hvm_syscore_shutdown(void) -{ - struct xen_memory_reservation reservation = { - .domid = DOMID_SELF, - .nr_extents = 1, - }; - unsigned long prev_pfn; - int rc; - - if (!xen_hvm_shared_info_kexec) - return; - - prev_pfn = __pa(xen_hvm_shared_info) >> PAGE_SHIFT; - set_xen_guest_handle(reservation.extent_start, &prev_pfn); - - /* Move pfn to MMIO, disconnects previous pfn from mfn */ - xen_hvm_connect_shared_info(xen_hvm_shared_info_pfn_kexec); - - /* Update pointers, following hypercall is also a memory barrier */ - xen_hvm_set_shared_info(xen_hvm_shared_info_kexec); - - /* Allocate new mfn for previous pfn */ - do { - rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); - if (rc == 0) - msleep(123); - } while (rc == 0); - - /* Make sure the previous pfn is really connected to a (new) mfn */ - BUG_ON(rc != 1); -} - -static struct syscore_ops xen_hvm_syscore_ops = { - .shutdown = xen_hvm_syscore_shutdown, -}; -#endif - -/* Use a pfn in RAM, may move to MMIO before kexec. */ -static void __init xen_hvm_init_shared_info(void) -{ - /* Remember pointer for resume */ - xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE); - xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT); - xen_hvm_set_shared_info(xen_hvm_shared_info); -} - +#ifdef CONFIG_XEN_PVHVM static void __init init_hvm_pv_info(void) { int major, minor; @@ -1646,9 +1553,6 @@ static void __init xen_hvm_guest_init(void) init_hvm_pv_info(); xen_hvm_init_shared_info(); -#ifdef CONFIG_KEXEC - register_syscore_ops(&xen_hvm_syscore_ops); -#endif if (xen_feature(XENFEAT_hvm_callback_vector)) xen_have_vector_callback = 1; diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index ae8a00c39de4..45329c8c226e 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled) { #ifdef CONFIG_XEN_PVHVM int cpu; - xen_hvm_resume_shared_info(); + xen_hvm_init_shared_info(); xen_callback_vector(); xen_unplug_emulated_devices(); if (xen_feature(XENFEAT_hvm_safe_pvclock)) { diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 1e4329e04e0f..202d4c150154 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -41,7 +41,7 @@ void xen_enable_syscall(void); void xen_vcpu_restore(void); void xen_callback_vector(void); -void xen_hvm_resume_shared_info(void); +void xen_hvm_init_shared_info(void); void xen_unplug_emulated_devices(void); void __init xen_build_dynamic_phys_to_machine(void); diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index d4c50d63acbc..97ca359ae2bd 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c @@ -101,19 +101,6 @@ static int platform_pci_resume(struct pci_dev *pdev) return 0; } -static void __devinit prepare_shared_info(void) -{ -#ifdef CONFIG_KEXEC - unsigned long addr; - struct shared_info *hvm_shared_info; - - addr = alloc_xen_mmio(PAGE_SIZE); - hvm_shared_info = ioremap(addr, PAGE_SIZE); - memset(hvm_shared_info, 0, PAGE_SIZE); - xen_hvm_prepare_kexec(hvm_shared_info, addr >> PAGE_SHIFT); -#endif -} - static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -151,8 +138,6 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, platform_mmio = mmio_addr; platform_mmiolen = mmio_len; - prepare_shared_info(); - if (!xen_have_vector_callback) { ret = xen_allocate_irq(pdev); if (ret) { diff --git a/include/xen/events.h b/include/xen/events.h index 9c641deb65d2..04399b28e821 100644 --- a/include/xen/events.h +++ b/include/xen/events.h @@ -58,8 +58,6 @@ void notify_remote_via_irq(int irq); void xen_irq_resume(void); -void xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn); - /* Clear an irq's pending state, in preparation for polling on it */ void xen_clear_irq_pending(int irq); void xen_set_irq_pending(int irq); -- cgit v1.2.3 From c61307a7cc1be87b6785dad0885492b6ca7998db Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 9 Aug 2012 08:38:43 +0200 Subject: gpio: Fix debug message in of_get_named_gpio_flags() This was probably missed in the conversion done in commit 3d0f7cf ("gpio: Adjust of_xlate API to support multiple GPIO chips"). Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a18c4aa68b1e..f1a45997aea8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -82,7 +82,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); of_node_put(gg_data.gpiospec.np); - pr_debug("%s exited with status %d\n", __func__, ret); + pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio); return gg_data.out_gpio; } EXPORT_SYMBOL(of_get_named_gpio_flags); -- cgit v1.2.3 From 5a6704454a68ab6e27e4fc5b82818a8c5733bf29 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 18 Jun 2012 12:07:51 +0200 Subject: MIPS: BCM63xx: Fix SPI message control register handling for BCM6338/6348. BCM6338 and BCM6348 have a message control register width of 8 bits, instead of 16-bits like what the SPI driver assumes right now. Also the SPI message type shift value of 14 is actually 6 for these SoCs. This resulted in transmit FIFO corruption because we were writing 16-bits to an 8-bits wide register, thus spanning on the first byte of the transmit FIFO, which had already been filed in bcm63xx_spi_fill_txrx_fifo(). Fix this by passing the message control register width and message type shift through platform data back to the SPI driver so that it can use it properly. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: grant.likely@secretlab.ca Cc: spi-devel-general@lists.sourceforge.net Cc: jonas.gorski@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/3983/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/dev-spi.c | 4 +++ .../include/asm/mach-bcm63xx/bcm63xx_dev_spi.h | 2 ++ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 13 ++++++--- drivers/spi/spi-bcm63xx.c | 31 ++++++++++++++++++---- 4 files changed, 42 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c index e39f73048d4f..f1c9c3e2f678 100644 --- a/arch/mips/bcm63xx/dev-spi.c +++ b/arch/mips/bcm63xx/dev-spi.c @@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void) if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; + spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT; + spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH; } if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; + spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; + spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH; } bcm63xx_spi_regs_init(); diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h index 7d98dbe5d4b5..c9bae1362606 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h @@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void); struct bcm63xx_spi_pdata { unsigned int fifo_size; + unsigned int msg_type_shift; + unsigned int msg_ctl_width; int bus_num; int num_chipselect; u32 speed_hz; diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 4ccc2a748aff..61f2a2a5099d 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -1054,7 +1054,8 @@ #define SPI_6338_FILL_BYTE 0x07 #define SPI_6338_MSG_TAIL 0x09 #define SPI_6338_RX_TAIL 0x0b -#define SPI_6338_MSG_CTL 0x40 +#define SPI_6338_MSG_CTL 0x40 /* 8-bits register */ +#define SPI_6338_MSG_CTL_WIDTH 8 #define SPI_6338_MSG_DATA 0x41 #define SPI_6338_MSG_DATA_SIZE 0x3f #define SPI_6338_RX_DATA 0x80 @@ -1070,7 +1071,8 @@ #define SPI_6348_FILL_BYTE 0x07 #define SPI_6348_MSG_TAIL 0x09 #define SPI_6348_RX_TAIL 0x0b -#define SPI_6348_MSG_CTL 0x40 +#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */ +#define SPI_6348_MSG_CTL_WIDTH 8 #define SPI_6348_MSG_DATA 0x41 #define SPI_6348_MSG_DATA_SIZE 0x3f #define SPI_6348_RX_DATA 0x80 @@ -1078,6 +1080,7 @@ /* BCM 6358 SPI core */ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ +#define SPI_6358_MSG_CTL_WIDTH 16 #define SPI_6358_MSG_DATA 0x02 #define SPI_6358_MSG_DATA_SIZE 0x21e #define SPI_6358_RX_DATA 0x400 @@ -1094,6 +1097,7 @@ /* BCM 6358 SPI core */ #define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ +#define SPI_6368_MSG_CTL_WIDTH 16 #define SPI_6368_MSG_DATA 0x02 #define SPI_6368_MSG_DATA_SIZE 0x21e #define SPI_6368_RX_DATA 0x400 @@ -1115,7 +1119,10 @@ #define SPI_HD_W 0x01 #define SPI_HD_R 0x02 #define SPI_BYTE_CNT_SHIFT 0 -#define SPI_MSG_TYPE_SHIFT 14 +#define SPI_6338_MSG_TYPE_SHIFT 6 +#define SPI_6348_MSG_TYPE_SHIFT 6 +#define SPI_6358_MSG_TYPE_SHIFT 14 +#define SPI_6368_MSG_TYPE_SHIFT 14 /* Command */ #define SPI_CMD_NOOP 0x00 diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 6e25ef1bce91..b7d61e7b8737 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -47,6 +47,8 @@ struct bcm63xx_spi { /* Platform data */ u32 speed_hz; unsigned fifo_size; + unsigned int msg_type_shift; + unsigned int msg_ctl_width; /* Data buffers */ const unsigned char *tx_ptr; @@ -221,13 +223,20 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); if (t->rx_buf && t->tx_buf) - msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); + msg_ctl |= (SPI_FD_RW << bs->msg_type_shift); else if (t->rx_buf) - msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); + msg_ctl |= (SPI_HD_R << bs->msg_type_shift); else if (t->tx_buf) - msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); - - bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); + msg_ctl |= (SPI_HD_W << bs->msg_type_shift); + + switch (bs->msg_ctl_width) { + case 8: + bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL); + break; + case 16: + bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); + break; + } /* Issue the transfer */ cmd = SPI_CMD_START_IMMEDIATE; @@ -406,9 +415,21 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev) master->transfer_one_message = bcm63xx_spi_transfer_one; master->mode_bits = MODEBITS; bs->speed_hz = pdata->speed_hz; + bs->msg_type_shift = pdata->msg_type_shift; + bs->msg_ctl_width = pdata->msg_ctl_width; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); + switch (bs->msg_ctl_width) { + case 8: + case 16: + break; + default: + dev_err(dev, "unsupported MSG_CTL width: %d\n", + bs->msg_ctl_width); + goto out_clk_disable; + } + /* Initialize hardware */ clk_enable(bs->clk); bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); -- cgit v1.2.3 From 127c6e731106a2071ee4a6c5a34c471cd3e719f0 Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Tue, 7 Aug 2012 09:59:40 +0800 Subject: booke/wdt: some ioctls do not return values properly Fix some booke wdt ioctls return value error. Signed-off-by: Tiejun Chen Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- drivers/watchdog/booke_wdt.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 3fe82d0e8caa..5b06d31ab6a9 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -166,18 +166,17 @@ static long booke_wdt_ioctl(struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((void *)arg, &ident, sizeof(ident))) - return -EFAULT; + return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: return put_user(0, p); case WDIOC_GETBOOTSTATUS: /* XXX: something is clearing TSR */ tmp = mfspr(SPRN_TSR) & TSR_WRS(3); /* returns CARDRESET if last reset was caused by the WDT */ - return (tmp ? WDIOF_CARDRESET : 0); + return put_user((tmp ? WDIOF_CARDRESET : 0), p); case WDIOC_SETOPTIONS: if (get_user(tmp, p)) - return -EINVAL; + return -EFAULT; if (tmp == WDIOS_ENABLECARD) { booke_wdt_ping(); break; -- cgit v1.2.3 From bbb4ab43f82adf02c8b4d0d7e7b7e79d24204b05 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 17 Aug 2012 09:51:50 -0500 Subject: ahci: un-staticize ahci_dev_classify Make ahci_dev_classify available to the ahci platform driver for custom hard reset function. Signed-off-by: Rob Herring Signed-off-by: Jeff Garzik --- drivers/ata/ahci.h | 1 + drivers/ata/libahci.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index c2594ddf25b0..57eb1c212a4c 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -320,6 +320,7 @@ extern struct device_attribute *ahci_sdev_attrs[]; extern struct ata_port_operations ahci_ops; extern struct ata_port_operations ahci_pmp_retry_srst_ops; +unsigned int ahci_dev_classify(struct ata_port *ap); void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts); void ahci_save_initial_config(struct device *dev, diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index f9eaa82311a9..555c07afa05b 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1139,7 +1139,7 @@ static void ahci_dev_config(struct ata_device *dev) } } -static unsigned int ahci_dev_classify(struct ata_port *ap) +unsigned int ahci_dev_classify(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); struct ata_taskfile tf; @@ -1153,6 +1153,7 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) return ata_dev_classify(&tf); } +EXPORT_SYMBOL_GPL(ahci_dev_classify); void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts) -- cgit v1.2.3 From 1117c811a64d948c9f88ee80a0c7f35e9fea1d69 Mon Sep 17 00:00:00 2001 From: Arnd Hannemann Date: Fri, 17 Aug 2012 10:11:15 +0200 Subject: pata_atiixp: override cable detection on MSI E350DM-E33 The mainboard MSI E350DM-E33 is advertised with 6 SATA ports. As it turns out, two of them seem to be driven by on-board SATA<->PATA converters. If a disk drive is connected to one of them kernel uses UDMA/33 mode due to cable detection: [ 34.550823] scsi4 : pata_atiixp [ 34.555517] scsi5 : pata_atiixp [ 34.555942] ata5: PATA max UDMA/100 cmd 0x1f0 ctl 0x3f6 bmdma 0xf100 irq 14 [ 34.555948] ata6: PATA max UDMA/100 cmd 0x170 ctl 0x376 bmdma 0xf108 irq 15 ... [ 35.040799] ata5.00: ATA-8: WDC WD20EADS-00R6B0, 01.00A01, max UDMA/133 [ 35.040806] ata5.00: 3907029168 sectors, multi 16: LBA48 NCQ (depth 0/32) [ 35.040817] ata5.00: limited to UDMA/33 due to 40-wire cable [ 35.049166] ata5.00: configured for UDMA/33 [ 35.049402] scsi 4:0:0:0: Direct-Access ATA WDC WD20EADS-00R 01.0 PQ: 0 ANSI: 5 This patch forces "short cable" mode on this board, as it seems clear that the on-board SATA<->PATA "cable" is short. With this patch the disk is configured for UDMA/100: [ 5.976756] ata5.00: ATA-8: WDC WD20EADS-00R6B0, 01.00A01, max UDMA/133 [ 5.996434] ata5.00: 3907029168 sectors, multi 16: LBA48 NCQ (depth 0/32) [ 6.024787] ata5.00: configured for UDMA/100 Testing revealed no transfer issues. Signed-off-by: Arnd Hannemann Signed-off-by: Jeff Garzik --- drivers/ata/pata_atiixp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 361c75cea57b..24e51056ac26 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -20,6 +20,7 @@ #include #include #include +#include #define DRV_NAME "pata_atiixp" #define DRV_VERSION "0.4.6" @@ -33,11 +34,26 @@ enum { ATIIXP_IDE_UDMA_MODE = 0x56 }; +static const struct dmi_system_id attixp_cable_override_dmi_table[] = { + { + /* Board has onboard PATA<->SATA converters */ + .ident = "MSI E350DM-E33", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), + DMI_MATCH(DMI_BOARD_NAME, "E350DM-E33(MS-7720)"), + }, + }, + { } +}; + static int atiixp_cable_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 udma; + if (dmi_check_system(attixp_cable_override_dmi_table)) + return ATA_CBL_PATA40_SHORT; + /* Hack from drivers/ide/pci. Really we want to know how to do the raw detection not play follow the bios mode guess */ pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma); -- cgit v1.2.3 From 77b12bc9cf7b10c7c1a04ca45272fbb4287902d0 Mon Sep 17 00:00:00 2001 From: James Ralston Date: Thu, 9 Aug 2012 09:02:31 -0700 Subject: ahci: Add Device IDs for Intel Lynx Point-LP PCH This patch adds the AHCI-mode SATA Device IDs for the Intel Lynx Point-LP PCH Signed-off-by: James Ralston Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 062e6a1a248f..50d5dea0ff59 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -256,6 +256,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ + { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From 389cd784969e9148fedcde0608f15bd74d6b769e Mon Sep 17 00:00:00 2001 From: James Ralston Date: Thu, 9 Aug 2012 09:34:20 -0700 Subject: ata_piix: Add Device IDs for Intel Lynx Point-LP PCH This patch adds the IDE-mode SATA Device IDs for the Intel Lynx Point-LP PCH Signed-off-by: James Ralston Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 3c809bfbccf5..ef773e12af79 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -329,6 +329,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (DH89xxCC) */ { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ -- cgit v1.2.3 From 834009170986f295c5eca37c76c59f1b28670d69 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 15 Aug 2012 17:08:12 +0800 Subject: [libata] acpi: call ata_acpi_gtm during ata port init time Commit 30dcf76acc695cbd2fa919e294670fe9552e16e7 mistakenly dropped the code to get an initial gtm for the IDE channel. This caused the following problem for Sergei: http://marc.info/?l=linux-kernel&m=134484963618457&w=2 Fix this by adding the call back in ata_acpi_bind_host, and due to this, the ata_ap_acpi_handle is modified accordingly. Tested-by: Sergei Trofimovich Signed-off-by: Aaron Lu Signed-off-by: Jeff Garzik --- drivers/ata/libata-acpi.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 902b5a457170..fd9ecf74e631 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -60,17 +60,7 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap) if (ap->flags & ATA_FLAG_ACPI_SATA) return NULL; - /* - * If acpi bind operation has already happened, we can get the handle - * for the port by checking the corresponding scsi_host device's - * firmware node, otherwise we will need to find out the handle from - * its parent's acpi node. - */ - if (ap->scsi_host) - return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev); - else - return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), - ap->port_no); + return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no); } EXPORT_SYMBOL(ata_ap_acpi_handle); @@ -1101,6 +1091,9 @@ static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle) if (!*handle) return -ENODEV; + if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) + ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; + return 0; } -- cgit v1.2.3 From ebd600281566ab40fb2e3004af7eacb3375626d1 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Sun, 12 Aug 2012 23:43:42 +0200 Subject: [libata] Kconfig: Elaborate that SFF is meant for legacy and PATA stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building Linux for an ASUS Eee PC 701 4G with ata2.00: CFA: SILICONMOTION SM223AC, , max UDMA/66 ata2.00: 7815024 sectors, multi 0: LBA ata2.00: configured for UDMA/66 scsi 1:0:0:0: Direct-Access ATA SILICONMOTION SM n/a PQ: 0 ANSI: 5 sd 1:0:0:0: [sda] 7815024 512-byte logical blocks: (4.00 GB/3.72 GiB) sd 1:0:0:0: [sda] Write Protect is off sd 1:0:0:0: [sda] Mode Sense: 00 3a 00 00 sd 1:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA sda: sda1 sd 1:0:0:0: [sda] Attached SCSI disk sd 1:0:0:0: Attached scsi generic sg0 type 0 I followed the advice to not use the deprecated old PATA subsystem ATA/ATAPI/MFM/RLL support (DEPRECATED) ---> and use the ATA subsystem instead. Serial ATA and Parallel ATA drivers ---> Unfortunately I needed several tries to find out, that I needed the SFF menu I had not selected before because I had never heard that term before. I think it would have helped me, to have PATA or legacy IDE in that item’s name. Signed-off-by: Paul Menzel Signed-off-by: Jeff Garzik --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 2be8ef1d3093..27cecd313e75 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -115,7 +115,7 @@ config SATA_SIL24 If unsure, say N. config ATA_SFF - bool "ATA SFF support" + bool "ATA SFF support (for legacy IDE and PATA)" default y help This option adds support for ATA controllers with SFF -- cgit v1.2.3 From 04d0f1b84927169cdaa4e3a24da768a9fd9aca6f Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 17 Aug 2012 13:36:59 -0400 Subject: [libata] new quirk, lift bridge limits for Buffalo DriveStation Quattro Michael Eitelwein writes: I have an external SATA drive that was slowed down by bridge limits. I found a solution in a thread on this list posted in 2008: It introduces whitelist entries in libata-core.c for devices with well working bridges (e.g. email on Fri, 31 Oct 2008 01:45:27 -0400). I added my device to this whitelist in a custom built kernel and it works fine for weeks now. How can I have this device added on the whitelist within the official kernel? Is this whitelist mechanism still supported or is there a smarter way to achieve whitelisting? I added the following whitelist entry for my Buffalo DriveStation Quattro "BUFFALO HD-QSU2/R5": /* Devices that do not need bridging limits applied */ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, { "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK, }, Reported-by: Michael Eitelwein Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fadd5866d40f..5eee1c1537d2 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4128,6 +4128,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices that do not need bridging limits applied */ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, + { "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK, }, /* Devices which aren't very happy with higher link speeds */ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, -- cgit v1.2.3 From ce026cb9cbf1d529652394ea91fb8a459072be91 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Fri, 13 Jul 2012 18:04:23 -0500 Subject: crypto: caam - fix possible deadlock condition commit "crypto: caam - use non-irq versions of spinlocks for job rings" made two bad assumptions: (a) The caam_jr_enqueue lock isn't used in softirq context. Not true: jr_enqueue can be interrupted by an incoming net interrupt and the received packet may be sent for encryption, via caam_jr_enqueue in softirq context, thereby inducing a deadlock. This is evidenced when running netperf over an IPSec tunnel between two P4080's, with spinlock debugging turned on: [ 892.092569] BUG: spinlock lockup on CPU#7, netperf/10634, e8bf5f70 [ 892.098747] Call Trace: [ 892.101197] [eff9fc10] [c00084c0] show_stack+0x48/0x15c (unreliable) [ 892.107563] [eff9fc50] [c0239c2c] do_raw_spin_lock+0x16c/0x174 [ 892.113399] [eff9fc80] [c0596494] _raw_spin_lock+0x3c/0x50 [ 892.118889] [eff9fc90] [c0445e74] caam_jr_enqueue+0xf8/0x250 [ 892.124550] [eff9fcd0] [c044a644] aead_decrypt+0x6c/0xc8 [ 892.129625] BUG: spinlock lockup on CPU#5, swapper/5/0, e8bf5f70 [ 892.129629] Call Trace: [ 892.129637] [effa7c10] [c00084c0] show_stack+0x48/0x15c (unreliable) [ 892.129645] [effa7c50] [c0239c2c] do_raw_spin_lock+0x16c/0x174 [ 892.129652] [effa7c80] [c0596494] _raw_spin_lock+0x3c/0x50 [ 892.129660] [effa7c90] [c0445e74] caam_jr_enqueue+0xf8/0x250 [ 892.129666] [effa7cd0] [c044a644] aead_decrypt+0x6c/0xc8 [ 892.129674] [effa7d00] [c0509724] esp_input+0x178/0x334 [ 892.129681] [effa7d50] [c0519778] xfrm_input+0x77c/0x818 [ 892.129688] [effa7da0] [c050e344] xfrm4_rcv_encap+0x20/0x30 [ 892.129697] [effa7db0] [c04b90c8] ip_local_deliver+0x190/0x408 [ 892.129703] [effa7de0] [c04b966c] ip_rcv+0x32c/0x898 [ 892.129709] [effa7e10] [c048b998] __netif_receive_skb+0x27c/0x4e8 [ 892.129715] [effa7e80] [c048d744] netif_receive_skb+0x4c/0x13c [ 892.129726] [effa7eb0] [c03c28ac] _dpa_rx+0x1a8/0x354 [ 892.129732] [effa7ef0] [c03c2ac4] ingress_rx_default_dqrr+0x6c/0x108 [ 892.129742] [effa7f10] [c0467ae0] qman_poll_dqrr+0x170/0x1d4 [ 892.129748] [effa7f40] [c03c153c] dpaa_eth_poll+0x20/0x94 [ 892.129754] [effa7f60] [c048dbd0] net_rx_action+0x13c/0x1f4 [ 892.129763] [effa7fa0] [c003d1b8] __do_softirq+0x108/0x1b0 [ 892.129769] [effa7ff0] [c000df58] call_do_softirq+0x14/0x24 [ 892.129775] [ebacfe70] [c0004868] do_softirq+0xd8/0x104 [ 892.129780] [ebacfe90] [c003d5a4] irq_exit+0xb8/0xd8 [ 892.129786] [ebacfea0] [c0004498] do_IRQ+0xa4/0x1b0 [ 892.129792] [ebacfed0] [c000fad8] ret_from_except+0x0/0x18 [ 892.129798] [ebacff90] [c0009010] cpu_idle+0x94/0xf0 [ 892.129804] [ebacffb0] [c059ff88] start_secondary+0x42c/0x430 [ 892.129809] [ebacfff0] [c0001e28] __secondary_start+0x30/0x84 [ 892.281474] [ 892.282959] [eff9fd00] [c0509724] esp_input+0x178/0x334 [ 892.288186] [eff9fd50] [c0519778] xfrm_input+0x77c/0x818 [ 892.293499] [eff9fda0] [c050e344] xfrm4_rcv_encap+0x20/0x30 [ 892.299074] [eff9fdb0] [c04b90c8] ip_local_deliver+0x190/0x408 [ 892.304907] [eff9fde0] [c04b966c] ip_rcv+0x32c/0x898 [ 892.309872] [eff9fe10] [c048b998] __netif_receive_skb+0x27c/0x4e8 [ 892.315966] [eff9fe80] [c048d744] netif_receive_skb+0x4c/0x13c [ 892.321803] [eff9feb0] [c03c28ac] _dpa_rx+0x1a8/0x354 [ 892.326855] [eff9fef0] [c03c2ac4] ingress_rx_default_dqrr+0x6c/0x108 [ 892.333212] [eff9ff10] [c0467ae0] qman_poll_dqrr+0x170/0x1d4 [ 892.338872] [eff9ff40] [c03c153c] dpaa_eth_poll+0x20/0x94 [ 892.344271] [eff9ff60] [c048dbd0] net_rx_action+0x13c/0x1f4 [ 892.349846] [eff9ffa0] [c003d1b8] __do_softirq+0x108/0x1b0 [ 892.355338] [eff9fff0] [c000df58] call_do_softirq+0x14/0x24 [ 892.360910] [e7169950] [c0004868] do_softirq+0xd8/0x104 [ 892.366135] [e7169970] [c003d5a4] irq_exit+0xb8/0xd8 [ 892.371101] [e7169980] [c0004498] do_IRQ+0xa4/0x1b0 [ 892.375979] [e71699b0] [c000fad8] ret_from_except+0x0/0x18 [ 892.381466] [e7169a70] [c0445e74] caam_jr_enqueue+0xf8/0x250 [ 892.387127] [e7169ab0] [c044ad4c] aead_givencrypt+0x6ac/0xa70 [ 892.392873] [e7169b20] [c050a0b8] esp_output+0x2b4/0x570 [ 892.398186] [e7169b80] [c0519b9c] xfrm_output_resume+0x248/0x7c0 [ 892.404194] [e7169bb0] [c050e89c] xfrm4_output_finish+0x18/0x28 [ 892.410113] [e7169bc0] [c050e8f4] xfrm4_output+0x48/0x98 [ 892.415427] [e7169bd0] [c04beac0] ip_local_out+0x48/0x98 [ 892.420740] [e7169be0] [c04bec7c] ip_queue_xmit+0x16c/0x490 [ 892.426314] [e7169c10] [c04d6128] tcp_transmit_skb+0x35c/0x9a4 [ 892.432147] [e7169c70] [c04d6f98] tcp_write_xmit+0x200/0xa04 [ 892.437808] [e7169cc0] [c04c8ccc] tcp_sendmsg+0x994/0xcec [ 892.443213] [e7169d40] [c04eebfc] inet_sendmsg+0xd0/0x164 [ 892.448617] [e7169d70] [c04792f8] sock_sendmsg+0x8c/0xbc [ 892.453931] [e7169e40] [c047aecc] sys_sendto+0xc0/0xfc [ 892.459069] [e7169f10] [c047b934] sys_socketcall+0x110/0x25c [ 892.464729] [e7169f40] [c000f480] ret_from_syscall+0x0/0x3c (b) since the caam_jr_dequeue lock is only used in bh context, then semantically it should use _bh spin_lock types. spin_lock_bh semantics are to disable back-halves, and used when a lock is shared between softirq (bh) context and process and/or h/w IRQ context. Since the lock is only used within softirq context, and this tasklet is atomic, there is no need to do the additional work to disable back halves. This patch adds back-half disabling protection to caam_jr_enqueue spin_locks to fix (a), and drops it from caam_jr_dequeue to fix (b). Signed-off-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/jr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 53c8c51d5881..93d14070141a 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -63,7 +63,7 @@ static void caam_jr_dequeue(unsigned long devarg) head = ACCESS_ONCE(jrp->head); - spin_lock_bh(&jrp->outlock); + spin_lock(&jrp->outlock); sw_idx = tail = jrp->tail; hw_idx = jrp->out_ring_read_index; @@ -115,7 +115,7 @@ static void caam_jr_dequeue(unsigned long devarg) jrp->tail = tail; } - spin_unlock_bh(&jrp->outlock); + spin_unlock(&jrp->outlock); /* Finally, execute user's callback */ usercall(dev, userdesc, userstatus, userarg); @@ -236,14 +236,14 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, return -EIO; } - spin_lock(&jrp->inplock); + spin_lock_bh(&jrp->inplock); head = jrp->head; tail = ACCESS_ONCE(jrp->tail); if (!rd_reg32(&jrp->rregs->inpring_avail) || CIRC_SPACE(head, tail, JOBR_DEPTH) <= 0) { - spin_unlock(&jrp->inplock); + spin_unlock_bh(&jrp->inplock); dma_unmap_single(dev, desc_dma, desc_size, DMA_TO_DEVICE); return -EBUSY; } @@ -265,7 +265,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, wr_reg32(&jrp->rregs->inpring_jobadd, 1); - spin_unlock(&jrp->inplock); + spin_unlock_bh(&jrp->inplock); return 0; } -- cgit v1.2.3 From 92c385f46b30f4954e9dd2d2005c12d233b479ea Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 6 Aug 2012 15:36:49 -0300 Subject: Bluetooth: Use USB_VENDOR_AND_INTERFACE() for Broadcom devices Many Broadcom devices has a vendor specific devices class, with this rule we match all existent and future controllers with this behavior. We also remove old rules to that matches product id for Broadcom devices. Tested-by: John Hommel Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2fe7776dc49c..e791b20beaf5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -94,16 +94,14 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0489, 0xe042) }, - { USB_DEVICE(0x0a5c, 0x21e3) }, - { USB_DEVICE(0x0a5c, 0x21e6) }, - { USB_DEVICE(0x0a5c, 0x21e8) }, - { USB_DEVICE(0x0a5c, 0x21f3) }, - { USB_DEVICE(0x0a5c, 0x21f4) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ { USB_DEVICE(0x0489, 0xe033) }, + /*Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + { } /* Terminating entry */ }; -- cgit v1.2.3 From 3a245cbef6a9e4398456bd733b0b4b7cb3f11994 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Wed, 15 Aug 2012 22:48:35 +0200 Subject: ath5k: fix wrong max power per rate eeprom reads for 802.11a This patch reduces the per rate target power eeprom reads for AR5K_EEPROM_MODE_11A from 10 to 8, as there are only 8 valid power curve entries on the eeprom. The former 10 reads lead to equal max power limits per rate and this causes an increasing distortion for all rates above 24 MBit and leads to a needless poor performance in 802.11a mode. Signed-off-by: Thomas Huehn Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 2 +- drivers/net/wireless/ath/ath5k/eeprom.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 4026c906cc7b..b7e0258887e7 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1482,7 +1482,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) case AR5K_EEPROM_MODE_11A: offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); rate_pcal_info = ee->ee_rate_tpwr_a; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; + ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_RATE_CHAN; break; case AR5K_EEPROM_MODE_11B: offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index dc2bcfeadeb4..94a9bbea6874 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -182,6 +182,7 @@ #define AR5K_EEPROM_EEP_DELTA 10 #define AR5K_EEPROM_N_MODES 3 #define AR5K_EEPROM_N_5GHZ_CHAN 10 +#define AR5K_EEPROM_N_5GHZ_RATE_CHAN 8 #define AR5K_EEPROM_N_2GHZ_CHAN 3 #define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 #define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 -- cgit v1.2.3 From 7b4e6cfbae304177b8edc0c12341b4896cab3f2d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 19 Aug 2012 11:49:58 +0200 Subject: drivers/net/wireless/ipw2x00/ipw2100.c: introduce missing initialization The result of one call to a function is tested, and then at the second call to the same function, the previous result, and not the current result, is tested again. Also changed &bssid to bssid, at the suggestion of Stanislav Yakovlev. The semantic match that finds the first problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression ret; identifier f; statement S1,S2; @@ *ret = f(...); if (\(ret != 0\|ret < 0\|ret == NULL\)) S1 ... when any *f(...); if (\(ret != 0\|ret < 0\|ret == NULL\)) S2 // Signed-off-by: Julia Lawall Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 95aa8e1683ec..83324b321652 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2042,7 +2042,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) return; } len = ETH_ALEN; - ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); + ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, bssid, + &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", __LINE__); -- cgit v1.2.3 From 94543a8d4fb302817014981489f15cb3b92ec3c2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Aug 2012 18:57:10 +0200 Subject: iwlwifi: fix flow handler debug code iwl_dbgfs_fh_reg_read() can cause crashes and/or BUG_ON in slub because the ifdefs are wrong, the code in iwl_dump_fh() should use DEBUGFS, not DEBUG to protect the buffer writing code. Also, while at it, clean up the arguments to the function, some code and make it generally safer. Cc: stable@vger.kernel.org Reported-by: Benjamin Herrenschmidt Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/pcie/internal.h | 2 +- drivers/net/wireless/iwlwifi/pcie/rx.c | 2 +- drivers/net/wireless/iwlwifi/pcie/trans.c | 30 +++++++++++++++------------- 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index d9694c58208c..4ffc18dc3a57 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -350,7 +350,7 @@ int iwl_queue_space(const struct iwl_queue *q); /***************************************************** * Error handling ******************************************************/ -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); +int iwl_dump_fh(struct iwl_trans *trans, char **buf); void iwl_dump_csr(struct iwl_trans *trans); /***************************************************** diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 39a6ca1f009c..d1a61ba6247a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -555,7 +555,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) } iwl_dump_csr(trans); - iwl_dump_fh(trans, NULL, false); + iwl_dump_fh(trans, NULL); iwl_op_mode_nic_error(trans->op_mode); } diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 939c2f78df58..1e86ea2266d4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1649,13 +1649,9 @@ static const char *get_fh_string(int cmd) #undef IWL_CMD } -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) +int iwl_dump_fh(struct iwl_trans *trans, char **buf) { int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif static const u32 fh_tbl[] = { FH_RSCSR_CHNL0_STTS_WPTR_REG, FH_RSCSR_CHNL0_RBDCB_BASE_REG, @@ -1667,29 +1663,35 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_ERROR_REG }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (buf) { + int pos = 0; + size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) pos += scnprintf(*buf + pos, bufsz - pos, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - } + return pos; } #endif + IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) IWL_ERR(trans, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), iwl_read_direct32(trans, fh_tbl[i])); - } + return 0; } @@ -1982,11 +1984,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, size_t count, loff_t *ppos) { struct iwl_trans *trans = file->private_data; - char *buf; + char *buf = NULL; int pos = 0; ssize_t ret = -EFAULT; - ret = pos = iwl_dump_fh(trans, &buf, true); + ret = pos = iwl_dump_fh(trans, &buf); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- cgit v1.2.3 From 4fc79db178f0a0ede479b4713e00df2d106028b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Aug 2012 18:57:11 +0200 Subject: iwlwifi: protect SRAM debugfs If the device is not started, we can't read its SRAM and attempting to do so will cause issues. Protect the debugfs read. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/dvm/debugfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 46782f1102ac..a47b306b522c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -124,6 +124,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, const struct fw_img *img; size_t bufsz; + if (!iwl_is_ready_rf(priv)) + return -EAGAIN; + /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { priv->dbgfs_sram_offset = 0x800000; -- cgit v1.2.3 From 9974e43d900af7979e0a571b8e0c9674c7399b79 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 21 Aug 2012 17:20:30 +0200 Subject: ide: fix generic_ide_suspend/resume Oops This patch fixes a regresion introduced by commit 0998d063 (device-core: Ensure drvdata = NULL when no driver is bound). Suspend oopses in generic_ide_suspend() because dev_get_drvdata() returns NULL (dev->p->driver_data == NULL) and this function is not prepared for this. Fix is based on Alan Stern's suggestion. Signed-off-by: Miklos Szeredi Acked-by: Rafael J. Wysocki Signed-off-by: David S. Miller --- drivers/ide/ide-pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 92406097efeb..8d1e32d7cd97 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -4,7 +4,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) { - ide_drive_t *drive = dev_get_drvdata(dev); + ide_drive_t *drive = to_ide_device(dev); ide_drive_t *pair = ide_get_pair_dev(drive); ide_hwif_t *hwif = drive->hwif; struct request *rq; @@ -40,7 +40,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) int generic_ide_resume(struct device *dev) { - ide_drive_t *drive = dev_get_drvdata(dev); + ide_drive_t *drive = to_ide_device(dev); ide_drive_t *pair = ide_get_pair_dev(drive); ide_hwif_t *hwif = drive->hwif; struct request *rq; -- cgit v1.2.3 From 4f9c1397e2e80e52b17ec4e39760caa807bd15c7 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 8 Aug 2012 09:07:38 +0800 Subject: PCI/PM: Enable D3/D3cold by default for most devices This patch fixes the following bug: http://marc.info/?l=linux-usb&m=134318961120825&w=2 Originally, device lower power states include D1, D2, D3. After that, D3 is further divided into D3hot and D3cold. To support both scenario safely, original D3 is mapped to D3cold. When adding D3cold support, because worry about some device may have broken D3cold support, D3cold is disabled by default. This disable D3 on original platform too. But some original platform may only have working D3, but no working D1, D2. The root cause of the above bug is it too. To deal with this, this patch enables D3/D3cold by default for most devices. This restores the original behavior. For some devices that suspected to have broken D3cold support, such as PCIe port, D3cold is disabled by default. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci.c | 1 + drivers/pci/pcie/portdrv_pci.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f3ea977a5b1b..ab4bf5a4c2f1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev) dev->pm_cap = pm; dev->d3_delay = PCI_PM_D3_WAIT; dev->d3cold_delay = PCI_PM_D3COLD_WAIT; + dev->d3cold_allowed = true; dev->d1_support = false; dev->d2_support = false; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3a7eefcb270a..62f5a76c8f80 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -200,6 +200,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, return status; pci_save_state(dev); + /* + * D3cold may not work properly on some PCIe port, so disable + * it by default. + */ + dev->d3cold_allowed = false; if (!pci_match_id(port_runtime_pm_black_list, dev)) pm_runtime_put_noidle(&dev->dev); -- cgit v1.2.3 From ea8c88f13d9fb1d6b39a05bfa07ae076ca1c6803 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 8 Aug 2012 09:07:39 +0800 Subject: PCI/PM: Keep parent bridge active when probing device This patch fixes the following bug: http://marc.info/?l=linux-pci&m=134329923124234&w=2 The root cause of the bug is as follow. If a device is not bound with the corresponding driver, the device runtime PM will be disabled and the device will be put into suspended state. So that, the bridge/PCIe port connected to it may be put into suspended and low power state. When do probing for the device later, because the bridge/PCIe port connected to it is in low power state, the IO access to device may fail. To solve the issue, the bridge/PCIe port connected to the device is put into active state before probing. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci-driver.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 5270f1a99328..d6fd6b6d9d4b 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi) { struct drv_dev_and_id *ddi = _ddi; struct device *dev = &ddi->dev->dev; + struct device *parent = dev->parent; int rc; + /* The parent bridge must be in active state when probing */ + if (parent) + pm_runtime_get_sync(parent); /* Unbound PCI devices are always set to disabled and suspended. * During probe, the device is set to enabled and active and the * usage count is incremented. If the driver supports runtime PM, @@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi) pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); } + if (parent) + pm_runtime_put(parent); return rc; } -- cgit v1.2.3 From 3d8387efe1ad9eb5bfe8a2e58cdbd1b88b247eef Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 15 Aug 2012 09:43:03 +0800 Subject: PCI/PM: Fix config reg access for D3cold and bridge suspending This patch fixes the following bug: http://marc.info/?l=linux-pci&m=134338059022620&w=2 Where lspci does not work properly if a device and the corresponding parent bridge (such as PCIe port) is suspended. This is because the device configuration space registers will be not accessible if the corresponding parent bridge is suspended or the device is put into D3cold state. To solve the issue, the bridge/PCIe port connected to the device is put into active state before read/write configuration space registers. If the device is in D3cold state, it will be put into active state too. To avoid resume/suspend PCIe port for each configuration register read/write, a small delay is added before the PCIe port to go suspended. Reported-by: Bjorn Mork Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- drivers/pci/pci-sysfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pcie/portdrv_pci.c | 9 +++++++++ 2 files changed, 51 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6869009c7393..02d107b15281 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); +static void +pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +static void +pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, size = count; } + pci_config_pm_runtime_get(dev); + if ((off & 1) && size) { u8 val; pci_user_read_config_byte(dev, off, &val); @@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj, --size; } + pci_config_pm_runtime_put(dev); + return count; } @@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, count = size; } + pci_config_pm_runtime_get(dev); + if ((off & 1) && size) { pci_user_write_config_byte(dev, off, data[off - init_off]); off++; @@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj, --size; } + pci_config_pm_runtime_put(dev); + return count; } diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 62f5a76c8f80..e76b44777dbf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev) { return 0; } + +static int pcie_port_runtime_idle(struct device *dev) +{ + /* Delay for a short while to prevent too frequent suspend/resume */ + pm_schedule_suspend(dev, 10); + return -EBUSY; +} #else #define pcie_port_runtime_suspend NULL #define pcie_port_runtime_resume NULL +#define pcie_port_runtime_idle NULL #endif static const struct dev_pm_ops pcie_portdrv_pm_ops = { @@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { .resume_noirq = pcie_port_resume_noirq, .runtime_suspend = pcie_port_runtime_suspend, .runtime_resume = pcie_port_runtime_resume, + .runtime_idle = pcie_port_runtime_idle, }; #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) -- cgit v1.2.3 From a1d0fa776870aeda5eb91b131d0f1aede6d94ef1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 21 Aug 2012 22:01:45 -0700 Subject: Input: edt-ft5x06 - fix build error when compiling wthout CONFIG_DEBUG_FS This fixes the following breakage: edt-ft5x06.c: In function edt_ft5x06_ts_remove: edt-ft5x06.c:846:14: error: struct edt_ft5x06_ts_data has no member named raw_buffer Signed-off-by: Guenter Roeck Acked-by: Simon Budig Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 9afc777a40a7..b06a5e3a665e 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -602,6 +602,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { if (tsdata->debug_dir) debugfs_remove_recursive(tsdata->debug_dir); + kfree(tsdata->raw_buffer); } #else @@ -843,7 +844,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) if (gpio_is_valid(pdata->reset_pin)) gpio_free(pdata->reset_pin); - kfree(tsdata->raw_buffer); kfree(tsdata); return 0; -- cgit v1.2.3 From f35dd69ba341bda3790713b9e964483934b995e1 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 21 Aug 2012 21:57:15 -0700 Subject: Input: imx_keypad - reset the hardware before enabling Ensure the hardware is correctly initialized before requesting the interrupt, otherwise if a key was already touched since power-on the kernel enters an interrupt loop. To fix this issue we clear pending interrupt sources. We also have to make sure clk is enabled while changing the keypad registers. Signed-off-by: Michael Grzeschik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_keypad.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index ff4c0a87a25f..ce68e361558c 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad) /* Inhibit KDI and KRI interrupts. */ reg_val = readw(keypad->mmio_base + KPSR); reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); + reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD; writew(reg_val, keypad->mmio_base + KPSR); /* Colums as open drain and disable all rows */ @@ -515,7 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) input_set_drvdata(input_dev, keypad); /* Ensure that the keypad will stay dormant until opened */ + clk_enable(keypad->clk); imx_keypad_inhibit(keypad); + clk_disable(keypad->clk); error = request_irq(irq, imx_keypad_irq_handler, 0, pdev->name, keypad); -- cgit v1.2.3 From 7b125b94ca16b7e618c6241cb02c4c8060cea5e3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 21 Aug 2012 21:57:15 -0700 Subject: Input: i8042 - add Gigabyte T1005 series netbooks to noloop table They all define their chassis type as "Other" and therefore are not categorized as "laptops" by the driver, which tries to perform AUX IRQ delivery test which fails and causes touchpad not working. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42620 Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ec774d6c82b..6918773ce024 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), }, }, + { + /* Gigabyte T1005 - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), + }, + }, + { + /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -- cgit v1.2.3 From 6f4d0382e2a6d27045e223d8c452659477826650 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 21 Aug 2012 22:11:59 -0700 Subject: Input: wacom - add support for EMR on Cintiq 24HD touch Adds support for the EMR digitizer on the Cintiq 24HD touch. The EMR digitizer should work identically to that found on the Cintiq 24HD. The touch digitizer is a separate USB device similar to how we split apart some other devices. Signed-off-by: Jason Gerecke Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 002041975de9..532d067a9e07 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1848,7 +1848,10 @@ static const struct wacom_features wacom_features_0x2A = { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xF8 = + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, @@ -2091,6 +2094,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_WACOM(0xF8) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } -- cgit v1.2.3 From 338b131a3269881c7431234855c93c219b0979b6 Mon Sep 17 00:00:00 2001 From: "sreekanth.reddy@lsi.com" Date: Tue, 17 Jul 2012 15:57:05 +0530 Subject: [SCSI] mpt2sas: Fix for Driver oops, when loading driver with max_queue_depth command line option to a very small value If the specified max_queue_depth setting is less than the expected number of internal commands, then driver will calculate the queue depth size to a negitive number. This negitive number is actually a very large number because variable is unsigned 16bit integer. So, the driver will ask for a very large amount of memory for message frames and resulting into oops as memory allocation routines will not able to handle such a large request. So, in order to limit this kind of oops, The driver need to set the max_queue_depth to a scsi mid layer's can_queue value. Then the overall message frames required for IO is minimum of either (max_queue_depth plus internal commands) or the IOC global credits. Signed-off-by: Sreekanth Reddy Cc: Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 9d46fcbe7755..b25757d1e91b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -2424,10 +2424,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) - max_request_credit = (max_queue_depth < facts->RequestCredit) - ? max_queue_depth : facts->RequestCredit; - else + if (max_queue_depth != -1 && max_queue_depth != 0) { + max_request_credit = min_t(u16, max_queue_depth + + ioc->hi_priority_depth + ioc->internal_depth, + facts->RequestCredit); + if (max_request_credit > MAX_HBA_QUEUE_DEPTH) + max_request_credit = MAX_HBA_QUEUE_DEPTH; + } else max_request_credit = min_t(u16, facts->RequestCredit, MAX_HBA_QUEUE_DEPTH); @@ -2502,7 +2505,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* set the scsi host can_queue depth * with some internal commands that could be outstanding */ - ioc->shost->can_queue = ioc->scsiio_depth - (2); + ioc->shost->can_queue = ioc->scsiio_depth; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); -- cgit v1.2.3 From bd8d6dd43a77bfd2b8fef5b094b9d6095e169dee Mon Sep 17 00:00:00 2001 From: Kashyap Desai Date: Tue, 17 Jul 2012 18:20:44 -0700 Subject: [SCSI] megaraid_sas: Move poll_aen_lock initializer The following patch moves the poll_aen_lock initializer from megasas_probe_one() to megasas_init(). This prevents a crash when a user loads the driver and tries to issue a poll() system call on the ioctl interface with no adapters present. Signed-off-by: Kashyap Desai Signed-off-by: Adam Radford Cc: Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index dc27598785e5..ed38454228c6 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); - spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); @@ -5392,6 +5391,8 @@ static int __init megasas_init(void) printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, MEGASAS_EXT_VERSION); + spin_lock_init(&poll_aen_lock); + support_poll_for_event = 2; support_device_change = 1; -- cgit v1.2.3 From 27c419739b67decced4650440829b8d51bef954b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 31 May 2012 15:05:33 -0400 Subject: [SCSI] scsi_lib: fix scsi_io_completion's SG_IO error propagation The following v3.4-rc1 commit unmasked an existing bug in scsi_io_completion's SG_IO error handling: 47ac56d [SCSI] scsi_error: classify some ILLEGAL_REQUEST sense as a permanent TARGET_ERROR Given that certain ILLEGAL_REQUEST are now properly categorized as TARGET_ERROR the host_byte is being set (before host_byte wasn't ever set for these ILLEGAL_REQUEST). In scsi_io_completion, initialize req->errors with cmd->result _after_ the SG_IO block that calls __scsi_error_from_host_byte (which may modify the host_byte). Before this fix: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0x10, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: sense buffer empty After: cdb to send: 12 01 01 00 00 00 ioctl(3, SG_IO, {'S', SG_DXFER_NONE, cmd[6]=[12, 01, 01, 00, 00, 00], mx_sb_len=32, iovec_count=0, dxfer_len=0, timeout=20000, flags=0, status=02, masked_status=01, sb[19]=[70, 00, 05, 00, 00, 00, 00, 0b, 00, 00, 00, 00, 24, 00, 00, 00, 00, 00, 00], host_status=0, driver_status=0x8, resid=0, duration=0, info=0x1}) = 0 SCSI Status: Check Condition Sense Information: Fixed format, current; Sense key: Illegal Request Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 05 00 00 00 00 0b 00 00 00 00 24 00 00 00 00 00 00 Reported-by: Paolo Bonzini Tested-by: Paolo Bonzini Signed-off-by: Mike Snitzer Reviewed-by: Babu Moger Cc: stable@vger.kernel.org # 3.4 Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ffd77739ae3e..faa790fba134 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -776,7 +776,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ - req->errors = result; if (result) { if (sense_valid && req->sense) { /* @@ -792,6 +791,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (!sense_deferred) error = __scsi_error_from_host_byte(cmd, result); } + /* + * __scsi_error_from_host_byte may have reset the host_byte + */ + req->errors = cmd->result; req->resid_len = scsi_get_resid(cmd); -- cgit v1.2.3 From 14216561e164671ce147458653b1fea06a4ada1e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 25 Jul 2012 23:55:55 +0400 Subject: [SCSI] Fix 'Device not ready' issue on mpt2sas This is a particularly nasty SCSI ATA Translation Layer (SATL) problem. SAT-2 says (section 8.12.2) if the device is in the stopped state as the result of processing a START STOP UNIT command (see 9.11), then the SATL shall terminate the TEST UNIT READY command with CHECK CONDITION status with the sense key set to NOT READY and the additional sense code of LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED; mpt2sas internal SATL seems to implement this. The result is very confusing standby behaviour (using hdparm -y). If you suspend a drive and then send another command, usually it wakes up. However, if the next command is a TEST UNIT READY, the SATL sees that the drive is suspended and proceeds to follow the SATL rules for this, returning NOT READY to all subsequent commands. This means that the ordering of TEST UNIT READY is crucial: if you send TUR and then a command, you get a NOT READY to both back. If you send a command and then a TUR, you get GOOD status because the preceeding command woke the drive. This bit us badly because commit 85ef06d1d252f6a2e73b678591ab71caad4667bb Author: Tejun Heo Date: Fri Jul 1 16:17:47 2011 +0200 block: flush MEDIA_CHANGE from drivers on close(2) Changed our ordering on TEST UNIT READY commands meaning that SATA drives connected to an mpt2sas now suspend and refuse to wake (because the mpt2sas SATL sees the suspend *before* the drives get awoken by the next ATA command) resulting in lots of failed commands. The standard is completely nuts forcing this inconsistent behaviour, but we have to work around it. The fix for this is twofold: 1. Set the allow_restart flag so we wake the drive when we see it has been suspended 2. Return all TEST UNIT READY status directly to the mid layer without any further error handling which prevents us causing error handling which may offline the device just because of a media check TUR. Reported-by: Matthias Prager Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 10 ++++++++++ drivers/scsi/scsi_scan.c | 10 ++++++++++ 2 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4a6381c87253..de2337f255a7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -42,6 +42,8 @@ #include +static void scsi_eh_done(struct scsi_cmnd *scmd); + #define SENSE_TIMEOUT (10*HZ) /* @@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (! scsi_command_normalize_sense(scmd, &sshdr)) return FAILED; /* no valid sense data */ + if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) + /* + * nasty: for mid-layer issued TURs, we need to return the + * actual sense data without any recovery attempt. For eh + * issued ones, we need to try to recover and interpret + */ + return SUCCESS; + if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 56a93794c470..d947ffc20ceb 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -764,6 +764,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); + if (strncmp(sdev->vendor, "ATA ", 8) == 0) { + /* + * sata emulation layer device. This is a hack to work around + * the SATL power management specifications which state that + * when the SATL detects the device has gone into standby + * mode, it shall respond with NOT READY. + */ + sdev->allow_restart = 1; + } + if (*bflags & BLIST_ISROM) { sdev->type = TYPE_ROM; sdev->removable = 1; -- cgit v1.2.3 From 1922b0f2758badc0b971d1ebbd300bc6635a6aef Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Mon, 13 Aug 2012 20:36:05 +0530 Subject: mfd: Move tps65217 regulator plat data handling to regulator Regulator platform data handling was mistakenly added to MFD driver. So we will see build errors if we compile MFD drivers without CONFIG_REGULATOR. This patch moves regulator platform data handling from TPS65217 MFD driver to regulator driver. This makes MFD driver independent of REGULATOR framework so build error is fixed if CONFIG_REGULATOR is not set. drivers/built-in.o: In function `tps65217_probe': tps65217.c:(.devinit.text+0x13e37): undefined reference to `of_regulator_match' This patch also fix allocation size of tps65217 platform data. Current implementation allocates a struct tps65217_board for each regulator specified in the device tree. But the structure itself provides array of regulators so one instance of it is sufficient. Signed-off-by: AnilKumar Ch --- drivers/mfd/tps65217.c | 130 +++++++++++---------------------- drivers/regulator/tps65217-regulator.c | 124 +++++++++++++++++++++++++++---- include/linux/mfd/tps65217.h | 12 ++- 3 files changed, 161 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 61c097a98f5d..3bc274409b58 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -24,11 +24,18 @@ #include #include #include -#include +#include +#include #include #include +static struct mfd_cell tps65217s[] = { + { + .name = "tps65217-pmic", + }, +}; + /** * tps65217_reg_read: Read a single tps65217 register. * @@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, } EXPORT_SYMBOL_GPL(tps65217_clear_bits); -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { - { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, - { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, - { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, - { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, - { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, - { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, - { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ - struct device_node *node = client->dev.of_node; - struct tps65217_board *pdata; - struct device_node *regs; - int count = ARRAY_SIZE(reg_matches); - int ret, i; - - regs = of_find_node_by_name(node, "regulators"); - if (!regs) - return NULL; - - ret = of_regulator_match(&client->dev, regs, reg_matches, count); - of_node_put(regs); - if ((ret < 0) || (ret > count)) - return NULL; - - count = ret; - pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!reg_matches[i].init_data || !reg_matches[i].of_node) - continue; - - pdata->tps65217_init_data[i] = reg_matches[i].init_data; - pdata->of_node[i] = reg_matches[i].of_node; - } - - return pdata; -} - -static struct of_device_id tps65217_of_match[] = { - { .compatible = "ti,tps65217", }, - { }, -}; -#else -static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) -{ - return NULL; -} -#endif - static struct regmap_config tps65217_regmap_config = { .reg_bits = 8, .val_bits = 8, }; +static const struct of_device_id tps65217_of_match[] = { + { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, + { /* sentinel */ }, +}; + static int __devinit tps65217_probe(struct i2c_client *client, const struct i2c_device_id *ids) { struct tps65217 *tps; - struct regulator_init_data *reg_data; - struct tps65217_board *pdata = client->dev.platform_data; - int i, ret; unsigned int version; + unsigned int chip_id = ids->driver_data; + const struct of_device_id *match; + int ret; - if (!pdata && client->dev.of_node) - pdata = tps65217_parse_dt(client); + if (client->dev.of_node) { + match = of_match_device(tps65217_of_match, &client->dev); + if (!match) { + dev_err(&client->dev, + "Failed to find matching dt id\n"); + return -EINVAL; + } + chip_id = (unsigned int)match->data; + } + + if (!chip_id) { + dev_err(&client->dev, "id is null.\n"); + return -ENODEV; + } tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; - tps->pdata = pdata; + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; + tps->id = chip_id; + tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); if (IS_ERR(tps->regmap)) { ret = PTR_ERR(tps->regmap); @@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client, return ret; } - i2c_set_clientdata(client, tps); - tps->dev = &client->dev; + ret = mfd_add_devices(tps->dev, -1, tps65217s, + ARRAY_SIZE(tps65217s), NULL, 0); + if (ret < 0) { + dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); + return ret; + } ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); if (ret < 0) { @@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client, (version & TPS65217_CHIPID_CHIP_MASK) >> 4, version & TPS65217_CHIPID_REV_MASK); - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { - struct platform_device *pdev; - - pdev = platform_device_alloc("tps65217-pmic", i); - if (!pdev) { - dev_err(tps->dev, "Cannot create regulator %d\n", i); - continue; - } - - pdev->dev.parent = tps->dev; - pdev->dev.of_node = pdata->of_node[i]; - reg_data = pdata->tps65217_init_data[i]; - platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); - tps->regulator_pdev[i] = pdev; - - platform_device_add(pdev); - } - return 0; } static int __devexit tps65217_remove(struct i2c_client *client) { struct tps65217 *tps = i2c_get_clientdata(client); - int i; - for (i = 0; i < TPS65217_NUM_REGULATOR; i++) - platform_device_unregister(tps->regulator_pdev[i]); + mfd_remove_devices(tps->dev); return 0; } static const struct i2c_device_id tps65217_id_table[] = { - {"tps65217", 0xF0}, - {/* end of list */} + {"tps65217", TPS65217}, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, tps65217_id_table); diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 6caa222af77a..ab00cab905b7 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = { NULL), }; +#ifdef CONFIG_OF +static struct of_regulator_match reg_matches[] = { + { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, + { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, + { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, + { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, + { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, + { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, + { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, +}; + +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ + struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); + struct device_node *node = tps->dev->of_node; + struct tps65217_board *pdata; + struct device_node *regs; + int i, count; + + regs = of_find_node_by_name(node, "regulators"); + if (!regs) + return NULL; + + count = of_regulator_match(pdev->dev.parent, regs, + reg_matches, TPS65217_NUM_REGULATOR); + of_node_put(regs); + if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) + return NULL; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + for (i = 0; i < count; i++) { + if (!reg_matches[i].init_data || !reg_matches[i].of_node) + continue; + + pdata->tps65217_init_data[i] = reg_matches[i].init_data; + pdata->of_node[i] = reg_matches[i].of_node; + } + + return pdata; +} +#else +static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) +{ + return NULL; +} +#endif + static int __devinit tps65217_regulator_probe(struct platform_device *pdev) { + struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65217_board *pdata = dev_get_platdata(tps->dev); + struct regulator_init_data *reg_data; struct regulator_dev *rdev; - struct tps65217 *tps; - struct tps_info *info = &tps65217_pmic_regs[pdev->id]; struct regulator_config config = { }; + int i, ret; - /* Already set by core driver */ - tps = dev_to_tps65217(pdev->dev.parent); - tps->info[pdev->id] = info; + if (tps->dev->of_node) + pdata = tps65217_parse_dt(pdev); - config.dev = &pdev->dev; - config.of_node = pdev->dev.of_node; - config.init_data = pdev->dev.platform_data; - config.driver_data = tps; + if (!pdata) { + dev_err(&pdev->dev, "Platform data not found\n"); + return -EINVAL; + } - rdev = regulator_register(®ulators[pdev->id], &config); - if (IS_ERR(rdev)) - return PTR_ERR(rdev); + if (tps65217_chip_id(tps) != TPS65217) { + dev_err(&pdev->dev, "Invalid tps chip version\n"); + return -ENODEV; + } - platform_set_drvdata(pdev, rdev); + platform_set_drvdata(pdev, tps); + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { + + reg_data = pdata->tps65217_init_data[i]; + + /* + * Regulator API handles empty constraints but not NULL + * constraints + */ + if (!reg_data) + continue; + + /* Register the regulators */ + tps->info[i] = &tps65217_pmic_regs[i]; + + config.dev = tps->dev; + config.init_data = reg_data; + config.driver_data = tps; + config.regmap = tps->regmap; + if (tps->dev->of_node) + config.of_node = pdata->of_node[i]; + + rdev = regulator_register(®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "failed to register %s regulator\n", + pdev->name); + ret = PTR_ERR(rdev); + goto err_unregister_regulator; + } + + /* Save regulator for cleanup */ + tps->rdev[i] = rdev; + } return 0; + +err_unregister_regulator: + while (--i >= 0) + regulator_unregister(tps->rdev[i]); + + return ret; } static int __devexit tps65217_regulator_remove(struct platform_device *pdev) { - struct regulator_dev *rdev = platform_get_drvdata(pdev); + struct tps65217 *tps = platform_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < TPS65217_NUM_REGULATOR; i++) + regulator_unregister(tps->rdev[i]); platform_set_drvdata(pdev, NULL); - regulator_unregister(rdev); return 0; } diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 12c06870829a..7cd83d826ed8 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -22,6 +22,9 @@ #include #include +/* TPS chip id list */ +#define TPS65217 0xF0 + /* I2C ID for TPS65217 part */ #define TPS65217_I2C_ID 0x24 @@ -248,13 +251,11 @@ struct tps_info { struct tps65217 { struct device *dev; struct tps65217_board *pdata; + unsigned int id; struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; struct tps_info *info[TPS65217_NUM_REGULATOR]; struct regmap *regmap; - - /* Client devices */ - struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; }; static inline struct tps65217 *dev_to_tps65217(struct device *dev) @@ -262,6 +263,11 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) return dev_get_drvdata(dev); } +static inline int tps65217_chip_id(struct tps65217 *tps65217) +{ + return tps65217->id; +} + int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, unsigned int *val); int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, -- cgit v1.2.3 From 53c84983549230495156d7da666cd1acdb9c9015 Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Wed, 22 Aug 2012 11:17:17 +0100 Subject: HID: Remove QUANTA from special drivers list This QUANTA device is driven by the generic hid-multitouch.ko driver, and therefore shouldn't be in the special drivers list. This has been an oversight in 4fa3a58 ("HID: hid-multitouch: Switch to device groups"). Signed-off-by: Simon Farnsworth Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 500844f04f93..78f0ee74b853 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1624,7 +1624,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, -- cgit v1.2.3 From ea2d218308e5710c70d76eb3c2876988c88119cc Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sun, 5 Aug 2012 00:29:07 +0300 Subject: brcm80211: smac: set interface down on reset This change marks interface as down on reset, otherwise the driver can't reinitialize itself properly. Without the change a transient problem turns out to be critical and leads to inavailability to reset the driver without brcmsmac module unload/load cycle: ieee80211 phy0: wl0: PSM microcode watchdog fired at 5993 (seconds). Resetting. brcms_c_dpc : PSM Watchdog, chipid 0xa8d9, chiprev 0x1 ieee80211 phy0: wl0: fatal error, reinitializing ieee80211 phy0: Hardware restart was requested ieee80211 phy0: brcms_ops_start: brcms_up() returned -19 Signed-off-by: Vladimir Zapolskiy Cc: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 192ad5c1fcc8..a5edebeb0b4f 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1233,6 +1233,9 @@ uint brcms_reset(struct brcms_info *wl) /* dpc will not be rescheduled */ wl->resched = false; + /* inform publicly that interface is down */ + wl->pub->up = false; + return 0; } -- cgit v1.2.3 From 5f42f7bc9638a0bc69dcb8b8b6da542b72113fc2 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 22 Aug 2012 00:26:15 +0000 Subject: stmmac: fix GMAC syn ID Erroneously the DWMAC_CORE_3_40 was set to 34 instead of 0x34. This can generate problems when run on old chips because the driver assumes that there are the extra 16 regs available for perfect filtering. Signed-off-by: Giuseppe Cavallaro Cc: Gianni Antoniazzi Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index f90fcb5f9573..b4c44a587f02 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -229,6 +229,6 @@ enum rtc_control { #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 /* Synopsys Core versions */ -#define DWMAC_CORE_3_40 34 +#define DWMAC_CORE_3_40 0x34 extern const struct stmmac_dma_ops dwmac1000_dma_ops; -- cgit v1.2.3 From a6b9650108003e994770209fb8efedf6e214dcf7 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 22 Aug 2012 00:26:16 +0000 Subject: stmmac: fix a typo in the macro used to mask the mmc irq This patch fixes the name of the macro used to mask the mmc interrupt: erroneously it was used: MMC_DEFAUL_MASK. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index c07cfe989f6e..0c74a702d461 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -33,7 +33,7 @@ #define MMC_TX_INTR 0x00000108 /* MMC TX Interrupt */ #define MMC_RX_INTR_MASK 0x0000010c /* MMC Interrupt Mask */ #define MMC_TX_INTR_MASK 0x00000110 /* MMC Interrupt Mask */ -#define MMC_DEFAUL_MASK 0xffffffff +#define MMC_DEFAULT_MASK 0xffffffff /* MMC TX counter registers */ @@ -147,8 +147,8 @@ void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode) /* To mask all all interrupts.*/ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) { - writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK); - writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK); + writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK); + writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK); } /* This reads the MAC core counters (if actaully supported). -- cgit v1.2.3 From 43ca6cb28c871f2fbad10117b0648e5ae3b0f638 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Tue, 21 Aug 2012 17:36:28 +0200 Subject: hwmon: (asus_atk0110) Add quirk for Asus M5A78L MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old interface is bugged and reads the wrong sensor when retrieving the reading for the chassis fan (it reads the CPU sensor); the new interface works fine. Reported-by: Göran Uddeborg Cc: stable@vger.kernel.org Tested-by: Göran Uddeborg Signed-off-by: Luca Tettamanti Signed-off-by: Guenter Roeck --- drivers/hwmon/asus_atk0110.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 351d1f4593e7..4ee578948723 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -34,6 +34,12 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") } + }, { + /* Old interface reads the same sensor for fan0 and fan1 */ + .ident = "Asus M5A78L", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "M5A78L") + } }, { } }; -- cgit v1.2.3 From b70ad586162609141f0aa9eb34790f31a8954f89 Mon Sep 17 00:00:00 2001 From: "Xu, Anhua" Date: Mon, 13 Aug 2012 03:08:33 +0000 Subject: drm/i915: fix wrong order of parameters in port checking functions Wrong order of parameters passed-in when calling hdmi/adpa /lvds_pipe_enabled(), 2nd and 3rd parameters are reversed. This bug was indroduced by commit 1519b9956eb4b4180fa3f47c73341463cdcfaa37 Author: Keith Packard Date: Sat Aug 6 10:35:34 2011 -0700 drm/i915: Fix PCH port pipe select in CPT disable paths The reachable tag for this commit is v3.1-rc1-3-g1519b99 Signed-off-by: Anhua Xu Reviewed-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44876 Tested-by: Daniel Schroeder Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a69a3d0d3acf..2dfa6cf4886b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1384,7 +1384,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, val, pipe), + WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); @@ -1404,13 +1404,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, val, pipe), + WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, val, pipe), + WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1872,7 +1872,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - if (hdmi_pipe_enabled(dev_priv, val, pipe)) { + if (hdmi_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", reg, pipe); I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1894,12 +1894,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - if (adpa_pipe_enabled(dev_priv, val, pipe)) + if (adpa_pipe_enabled(dev_priv, pipe, val)) I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); reg = PCH_LVDS; val = I915_READ(reg); - if (lvds_pipe_enabled(dev_priv, val, pipe)) { + if (lvds_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val); I915_WRITE(reg, val & ~LVDS_PORT_EN); POSTING_READ(reg); -- cgit v1.2.3 From 5ee369138d28c17305e1cdc662a62a2fc83d80d7 Mon Sep 17 00:00:00 2001 From: Vijay Purushothaman Date: Thu, 23 Aug 2012 12:08:57 +0530 Subject: drm/i915: fix color order for BGR formats on IVB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already fixed for ILK and SNB in the below commit but somehow IVB is missed. commit ab2f9df10dd955f1fc0a8650e377588c98f1c029 Author: Jesse Barnes Date: Mon Feb 27 12:40:10 2012 -0800 drm/i915: fix color order for BGR formats on SNB Had the wrong bits and field definitions. Signed-off-by: Vijay Purushothaman Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sprite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index cc8df4de2d92..7644f31a3778 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -60,11 +60,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, switch (fb->pixel_format) { case DRM_FORMAT_XBGR8888: - sprctl |= SPRITE_FORMAT_RGBX888; + sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; pixel_size = 4; break; case DRM_FORMAT_XRGB8888: - sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; + sprctl |= SPRITE_FORMAT_RGBX888; pixel_size = 4; break; case DRM_FORMAT_YUYV: -- cgit v1.2.3 From e432964a3c5ce517fd93101ae3875172ee958b65 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 24 Jul 2012 03:00:24 +0200 Subject: fbcon: prevent possible buffer overflow. Signed-off-by: Paul Cercueil Signed-off-by: Florian Tobias Schandinat --- drivers/video/console/fbcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 88e92041d8f0..fdefa8fd72c4 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -449,7 +449,7 @@ static int __init fb_console_setup(char *this_opt) while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) - strcpy(fontname, options + 5); + strlcpy(fontname, options + 5, sizeof(fontname)); if (!strncmp(options, "scrollback:", 11)) { options += 11; -- cgit v1.2.3 From 72caa5fb948ef818fe1332848e9c61b10687ce7a Mon Sep 17 00:00:00 2001 From: Bruno Prémont Date: Mon, 30 Jul 2012 21:09:49 +0200 Subject: fbcon: Fix bit_putcs() call to kmalloc(s, GFP_KERNEL) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to kmalloc(,GFP_ATOMIC) in bit_putcs to fix below trace: [ 9.771812] BUG: sleeping function called from invalid context at /usr/src/linux-git/mm/slub.c:943 [ 9.771814] in_atomic(): 1, irqs_disabled(): 1, pid: 1063, name: mount [ 9.771818] Pid: 1063, comm: mount Not tainted 3.5.0-jupiter-00003-g8d858b1-dirty #2 [ 9.771819] Call Trace: [ 9.771838] [] __might_sleep+0xcb/0xe0 [ 9.771844] [] __kmalloc+0xb4/0x1c0 [ 9.771851] [] ? queue_work+0x1a/0x30 [ 9.771854] [] ? queue_delayed_work+0xf/0x30 [ 9.771862] [] ? bit_putcs+0xf2/0x3e0 [ 9.771865] [] ? schedule_delayed_work+0x11/0x20 [ 9.771868] [] bit_putcs+0xf2/0x3e0 [ 9.771875] [] ? get_color.clone.14+0x28/0x100 [ 9.771878] [] fbcon_putcs+0x11f/0x130 [ 9.771882] [] ? bit_clear+0xe0/0xe0 [ 9.771885] [] fbcon_redraw.clone.21+0x11d/0x160 [ 9.771889] [] fbcon_scroll+0x79d/0xe10 [ 9.771892] [] ? get_color.clone.14+0x28/0x100 [ 9.771897] [] scrup+0x64/0xd0 [ 9.771900] [] lf+0x2b/0x60 [ 9.771903] [] vt_console_print+0x1d5/0x2f0 [ 9.771907] [] ? register_vt_notifier+0x20/0x20 [ 9.771913] [] call_console_drivers.clone.5+0xa5/0xc0 [ 9.771916] [] console_unlock+0x2fe/0x3c0 [ 9.771920] [] vprintk_emit+0x2e6/0x300 [ 9.771924] [] printk+0x38/0x3a [ 9.771931] [] reiserfs_remount+0x2ae/0x3e0 [ 9.771934] [] ? reiserfs_fill_super+0xb00/0xb00 [ 9.771939] [] do_remount_sb+0xab/0x150 [ 9.771943] [] ? ns_capable+0x46/0x70 [ 9.771948] [] do_mount+0x20c/0x6b0 [ 9.771955] [] ? strndup_user+0x34/0x50 [ 9.771958] [] sys_mount+0x6c/0xa0 [ 9.771964] [] sysenter_do_call+0x12/0x26 According to comment in bit_putcs() that kammloc() call only happens when fbcon is drawing to a monochrome framebuffer (which is my case with hid-picolcd). Signed-off-by: Bruno Prémont Signed-off-by: Florian Tobias Schandinat --- drivers/video/console/bitblit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 28b1a834906b..61b182bf32a2 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, image.depth = 1; if (attribute) { - buf = kmalloc(cellsize, GFP_KERNEL); + buf = kmalloc(cellsize, GFP_ATOMIC); if (!buf) return; } -- cgit v1.2.3 From 01817d194a5c078696ac4a31b5d8b99a6a9e40c7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 4 Aug 2012 14:00:30 +0200 Subject: drivers/video/auo_k190x.c: drop kfree of devm_kzalloc's data Using kfree to free data allocated with devm_kzalloc causes double frees. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; @@ x = devm_kzalloc(...) ... ?-kfree(x); // Signed-off-by: Julia Lawall Signed-off-by: Florian Tobias Schandinat --- drivers/video/auo_k190x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c index 77da6a2f43dc..c03ecdd31e4c 100644 --- a/drivers/video/auo_k190x.c +++ b/drivers/video/auo_k190x.c @@ -987,7 +987,6 @@ err_regfb: fb_dealloc_cmap(&info->cmap); err_cmap: fb_deferred_io_cleanup(info); - kfree(info->fbdefio); err_defio: vfree((void *)info->screen_base); err_irq: @@ -1022,7 +1021,6 @@ int __devexit auok190x_common_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); fb_deferred_io_cleanup(info); - kfree(info->fbdefio); vfree((void *)info->screen_base); -- cgit v1.2.3 From 25682362564fa0c950d9afe798def2ec9c3676a2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 18 Aug 2012 18:55:41 +0300 Subject: video: mb862xxfb: prevent divide by zero bug Do a sanity check on these before using them as divisors. Signed-off-by: Dan Carpenter Acked-by: Anatolij Gustschin Signed-off-by: Florian Tobias Schandinat --- drivers/video/mb862xx/mb862xxfbdrv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 00ce1f34b496..57d940be5f3d 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c @@ -328,6 +328,8 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, case MB862XX_L1_SET_CFG: if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) return -EFAULT; + if (l1_cfg->dh == 0 || l1_cfg->dw == 0) + return -EINVAL; if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { /* downscaling */ outreg(cap, GC_CAP_CSC, -- cgit v1.2.3 From 35d678664873041026171b4b5e1cec49299e33a0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 21 Aug 2012 09:09:47 +0300 Subject: OMAPDSS: Fix SDI PLL locking Commit f476ae9dab3234532d41d36beb4ba7be838fa786 (OMAPDSS: APPLY: Remove DISPC writes to manager's lcd parameters in interface) broke the SDI output, as it causes the SDI PLL locking to fail. LCLK and PCLK divisors are located in shadow registers, and we normally write them to DISPC registers when enabling the output. However, SDI uses pck-free as source clock for its PLL, and pck-free is affected by the divisors. And as we need the PLL before enabling the output, we need to write the divisors early. It seems just writing to the DISPC register is enough, and we don't need to care about the shadow register mechanism for pck-free. The exact reason for this is unknown. Signed-off-by: Tomi Valkeinen Reported-by: Aaro Koskinen Signed-off-by: Florian Tobias Schandinat --- drivers/video/omap2/dss/sdi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 5d31699fbd3c..f43bfe17b3b6 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -105,6 +105,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) sdi_config_lcd_manager(dssdev); + /* + * LCLK and PCLK divisors are located in shadow registers, and we + * normally write them to DISPC registers when enabling the output. + * However, SDI uses pck-free as source clock for its PLL, and pck-free + * is affected by the divisors. And as we need the PLL before enabling + * the output, we need to write the divisors early. + * + * It seems just writing to the DISPC register is enough, and we don't + * need to care about the shadow register mechanism for pck-free. The + * exact reason for this is unknown. + */ + dispc_mgr_set_clock_div(dssdev->manager->id, + &sdi.mgr_config.clock_info); + dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) -- cgit v1.2.3 From c1c52848cef52e157468b8879fc3cae23b6f3a99 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Tue, 21 Aug 2012 09:09:48 +0300 Subject: OMAPFB: fix framebuffer console colors omapfb does not currently set pseudo palette correctly for color depths above 16bpp, making red text invisible, command like echo -e '\e[0;31mRED' > /dev/tty1 will display nothing on framebuffer console in 24bpp mode. This is because temporary variable is declared incorrectly, fix it. Signed-off-by: Grazvydas Ignotas Cc: stable@vger.kernel.org # v3.x Signed-off-by: Tomi Valkeinen Signed-off-by: Florian Tobias Schandinat --- drivers/video/omap2/omapfb/omapfb-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 08ec1a7103f2..fc671d3d8004 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, break; if (regno < 16) { - u16 pal; + u32 pal; pal = ((red >> (16 - var->red.length)) << var->red.offset) | ((green >> (16 - var->green.length)) << -- cgit v1.2.3 From e402af6caa02f12ad213af2e22aa8a32970f99b0 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 14 Aug 2012 11:19:22 +0200 Subject: ARM: at91: fix rtc-at91sam9 irq issue due to sparse irq support AT91_ID_SYS as virq is incorrect because of spare irq support which introduces NR_IRQS_LEGACY offset. It modifies rtc-at91sam9 driver in order to get irq from resources. Signed-off-by: Ludovic Desroches Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/at91sam9260_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9261_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9263_devices.c | 10 ++++++++-- arch/arm/mach-at91/at91sam9g45_devices.c | 6 +++++- arch/arm/mach-at91/at91sam9rl_devices.c | 6 +++++- drivers/rtc/rtc-at91sam9.c | 22 +++++++++++++++------- 6 files changed, 43 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 7b9c2ba396ed..bce572a530ef 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -726,6 +726,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, }, }; @@ -744,10 +746,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9260_rtt_device.num_resources = 2; + at91sam9260_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9260_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 8df5c1bdff92..bc2590d712d0 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -609,6 +609,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -626,10 +628,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9261_rtt_device.num_resources = 2; + at91sam9261_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9261_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index eb6bbf86fb9f..9b6ca734f1a9 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -990,6 +990,8 @@ static struct resource rtt0_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1006,6 +1008,8 @@ static struct resource rtt1_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1027,14 +1031,14 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed only for the chosen RTT: * GPBR will serve as the storage for RTC time offset */ - at91sam9263_rtt0_device.num_resources = 2; + at91sam9263_rtt0_device.num_resources = 3; at91sam9263_rtt1_device.num_resources = 1; pdev = &at91sam9263_rtt0_device; r = rtt0_resources; break; case 1: at91sam9263_rtt0_device.num_resources = 1; - at91sam9263_rtt1_device.num_resources = 2; + at91sam9263_rtt1_device.num_resources = 3; pdev = &at91sam9263_rtt1_device; r = rtt1_resources; break; @@ -1047,6 +1051,8 @@ static void __init at91_add_device_rtt_rtc(void) pdev->name = "rtc-at91sam9"; r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; r[1].end = r[1].start + 3; + r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 06073996a382..1b47319ca00b 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1293,6 +1293,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -1310,10 +1312,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9g45_rtt_device.num_resources = 2; + at91sam9g45_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9G45_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index f09fff932172..b3d365dadef5 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -688,6 +688,8 @@ static struct resource rtt_resources[] = { .flags = IORESOURCE_MEM, }, { .flags = IORESOURCE_MEM, + }, { + .flags = IORESOURCE_IRQ, } }; @@ -705,10 +707,12 @@ static void __init at91_add_device_rtt_rtc(void) * The second resource is needed: * GPBR will serve as the storage for RTC time offset */ - at91sam9rl_rtt_device.num_resources = 2; + at91sam9rl_rtt_device.num_resources = 3; rtt_resources[1].start = AT91SAM9RL_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR; rtt_resources[1].end = rtt_resources[1].start + 3; + rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS; + rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS; } #else static void __init at91_add_device_rtt_rtc(void) diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 831868904e02..1dd61f402b04 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -58,6 +58,7 @@ struct sam9_rtc { struct rtc_device *rtcdev; u32 imr; void __iomem *gpbr; + int irq; }; #define rtt_readl(rtc, field) \ @@ -292,7 +293,7 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) { struct resource *r, *r_gpbr; struct sam9_rtc *rtc; - int ret; + int ret, irq; u32 mr; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -302,10 +303,18 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) return -ENODEV; } + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get interrupt resource\n"); + return irq; + } + rtc = kzalloc(sizeof *rtc, GFP_KERNEL); if (!rtc) return -ENOMEM; + rtc->irq = irq; + /* platform setup code should have handled this; sigh */ if (!device_can_wakeup(&pdev->dev)) device_init_wakeup(&pdev->dev, 1); @@ -345,11 +354,10 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev) } /* register irq handler after we know what name we'll use */ - ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_SHARED, + ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED, dev_name(&rtc->rtcdev->dev), rtc); if (ret) { - dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); + dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq); rtc_device_unregister(rtc->rtcdev); goto fail_register; } @@ -386,7 +394,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev) /* disable all interrupts */ rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); - free_irq(AT91_ID_SYS, rtc); + free_irq(rtc->irq, rtc); rtc_device_unregister(rtc->rtcdev); @@ -423,7 +431,7 @@ static int at91_rtc_suspend(struct platform_device *pdev, rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); if (rtc->imr) { if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { - enable_irq_wake(AT91_ID_SYS); + enable_irq_wake(rtc->irq); /* don't let RTTINC cause wakeups */ if (mr & AT91_RTT_RTTINCIEN) rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); @@ -441,7 +449,7 @@ static int at91_rtc_resume(struct platform_device *pdev) if (rtc->imr) { if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(AT91_ID_SYS); + disable_irq_wake(rtc->irq); mr = rtt_readl(rtc, MR); rtt_writel(rtc, MR, mr | rtc->imr); } -- cgit v1.2.3 From a0e35322910555e20e9eced3f050a76c7b3a1f92 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 16 Aug 2012 15:50:10 +0800 Subject: mfd: lpc_ich: Fix a 3.5 kernel regression for iTCO_wdt driver There are many reports (including 2 of my machines) that iTCO_wdt watchdog driver fails to be initialized in 3.5 kernel with error message like: [ 5.265175] ACPI Warning: 0x00001060-0x0000107f SystemIO conflicts with Region \_SB_.PCI0.LPCB.TCOI 1 (20120320/utaddress-251) [ 5.265192] ACPI: If an ACPI driver is available for this device, you should use it instead of the native driver [ 5.265206] lpc_ich: Resource conflict(s) found affecting iTCO_wdt The root cause the iTCO_wdt driver in 3.4 probes the HW IO resource from LPC's PCI config space, while in 3.5 kernel it relies on lpc_ich driver for the probe, which adds a new acpi_check_resource_conflict() check, and give up the probe if there is any conflict with ACPI. Fix it by removing all the checks for iTCO_wdt to keep the same behavior as 3.4 kernel. https://bugzilla.kernel.org/show_bug.cgi?id=44991 Actually the same check could be removed for the gpio-ich in lpc_ich.c, but I'm not sure if it will cause problems. Signed-off-by: Feng Tang Cc: Aaron Sierra Cc: Wim Van Sebroeck Cc: Len Brown Cc: Bob Moore Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 027cc8f86132..a05fdfc2ebcf 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -765,7 +765,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, u32 base_addr_cfg; u32 base_addr; int ret; - bool acpi_conflict = false; struct resource *res; /* Setup power management base register */ @@ -780,20 +779,11 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_io_res(ICH_RES_IO_TCO); res->start = base_addr + ACPIBASE_TCO_OFF; res->end = base_addr + ACPIBASE_TCO_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } res = wdt_io_res(ICH_RES_IO_SMI); res->start = base_addr + ACPIBASE_SMI_OFF; res->end = base_addr + ACPIBASE_SMI_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } + lpc_ich_enable_acpi_space(dev); /* @@ -813,11 +803,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, res = wdt_mem_res(ICH_RES_MEM_GCS); res->start = base_addr + ACPIBASE_GCS_OFF; res->end = base_addr + ACPIBASE_GCS_END; - ret = acpi_check_resource_conflict(res); - if (ret) { - acpi_conflict = true; - goto wdt_done; - } } lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); @@ -825,9 +810,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, 1, NULL, 0); wdt_done: - if (acpi_conflict) - pr_warn("Resource conflict(s) found affecting %s\n", - lpc_ich_cells[LPC_WDT].name); return ret; } -- cgit v1.2.3 From 0ff9514b579b4f2f3e6038cd961ce64c224c3c73 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 23 Aug 2012 10:53:08 -0600 Subject: PCI: Don't print anything while decoding is disabled If we try to print to the console device while its decoding is disabled, the system will hang. Reported-and-tested-by: Olof Johansson Signed-off-by: Bjorn Helgaas Acked-by: Olof Johansson --- drivers/pci/probe.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6c143b4497ca..9f8a6b79a8ec 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) case PCI_BASE_ADDRESS_MEM_TYPE_32: break; case PCI_BASE_ADDRESS_MEM_TYPE_1M: - dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); + /* 1M mem BAR treated as 32-bit BAR */ break; case PCI_BASE_ADDRESS_MEM_TYPE_64: flags |= IORESOURCE_MEM_64; break; default: - dev_warn(&dev->dev, - "mem unknown type %x treated as 32-bit BAR\n", - mem_type); + /* mem unknown type treated as 32-bit BAR */ break; } return flags; @@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u32 l, sz, mask; u16 orig_cmd; struct pci_bus_region region; + bool bar_too_big = false, bar_disabled = false; mask = type ? PCI_ROM_ADDRESS_MASK : ~0; + /* No printks while decoding is disabled! */ if (!dev->mmio_always_on) { pci_read_config_word(dev, PCI_COMMAND, &orig_cmd); pci_write_config_word(dev, PCI_COMMAND, @@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto fail; if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { - dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", - pos); + bar_too_big = true; goto fail; } @@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = 0; region.end = sz64; pcibios_bus_to_resource(dev, res, ®ion); + bar_disabled = true; } else { region.start = l64; region.end = l64 + sz64; pcibios_bus_to_resource(dev, res, ®ion); - dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", - pos, res); } } else { sz = pci_size(l, sz, mask); @@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, region.start = l; region.end = l + sz; pcibios_bus_to_resource(dev, res, ®ion); - - dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); } - out: + goto out; + + +fail: + res->flags = 0; +out: if (!dev->mmio_always_on) pci_write_config_word(dev, PCI_COMMAND, orig_cmd); + if (bar_too_big) + dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos); + if (res->flags && !bar_disabled) + dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); + return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; - fail: - res->flags = 0; - goto out; } static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) -- cgit v1.2.3 From 4c054ba63ad47ef244cfcfa1cea38134620a5bae Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 16 Aug 2012 15:33:10 -0700 Subject: target: Fix ->data_length re-assignment bug with SCSI overflow This patch fixes a long-standing bug with SCSI overflow handling where se_cmd->data_length was incorrectly being re-assigned to the larger CDB extracted allocation length, resulting in a number of fabric level errors that would end up causing a session reset in most cases. So instead now: - Only re-assign se_cmd->data_length durining UNDERFLOW (to use the smaller value) - Use existing se_cmd->data_length for OVERFLOW (to use the smaller value) This fix has been tested with the following CDB to generate an SCSI overflow: sg_raw -r512 /dev/sdc 28 0 0 0 0 0 0 0 9 0 Tested using iscsi-target, tcm_qla2xxx, loopback and tcm_vhost fabric ports. Here is a bit more detail on each case: - iscsi-target: Bug with open-iscsi with overflow, sg_raw returns -3584 bytes of data. - tcm_qla2xxx: Working as expected, returnins 512 bytes of data - loopback: sg_raw returns CHECK_CONDITION, from overflow rejection in transport_generic_map_mem_to_cmd() - tcm_vhost: Same as loopback Reported-by: Roland Dreier Cc: Roland Dreier Cc: Christoph Hellwig Cc: Boaz Harrosh Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4de3186dc44e..3425098ef728 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1181,15 +1181,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - + /* + * For the overflow case keep the existing fabric provided + * ->data_length. Otherwise for the underflow case, reset + * ->data_length to the smaller SCSI expected data transfer + * length. + */ if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); + cmd->data_length = size; } - cmd->data_length = size; } return 0; -- cgit v1.2.3 From 7c4eaca4162d0b5ad4fb39f974d7ffd71b9daa09 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 16 Aug 2012 08:29:03 +0000 Subject: drm: Check for invalid cursor flags Signed-off-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 2 +- include/drm/drm_mode.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 08a7aa722d6b..6fbfc244748f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags) + if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) return -EINVAL; mutex_lock(&dev->mode_config.mutex); diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 5581980b14f6..3d6301b6ec16 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -359,8 +359,9 @@ struct drm_mode_mode_cmd { struct drm_mode_modeinfo mode; }; -#define DRM_MODE_CURSOR_BO (1<<0) -#define DRM_MODE_CURSOR_MOVE (1<<1) +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 /* * depending on the value in flags different members are used. -- cgit v1.2.3 From ac70b2e9a13423b5efa0178e081936ce6979aea5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 15 Aug 2012 18:09:15 +0100 Subject: sfc: Fix reporting of IPv4 full filters through ethtool ETHTOOL_GRXCLSRULE returns filters for a TCP/IPv4 or UDP/IPv4 4-tuple with source and destination swapped. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 8cba2df82b18..5faedd855b77 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -863,8 +863,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &ip_entry->ip4dst, &ip_entry->pdst); if (rc != 0) { rc = efx_filter_get_ipv4_full( - &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc, - &ip_entry->ip4dst, &ip_entry->pdst); + &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, + &ip_entry->ip4src, &ip_entry->psrc); EFX_WARN_ON_PARANOID(rc); ip_mask->ip4src = ~0; ip_mask->psrc = ~0; -- cgit v1.2.3 From ef813c412c0cf254ddce7d922289e2d6a69960f0 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 19:15:01 +0400 Subject: can: softing: Fix potential memory leak in softing_load_fw() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Marc Kleine-Budde --- drivers/net/can/softing/softing_fw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c index 310596175676..b595d3422b9f 100644 --- a/drivers/net/can/softing/softing_fw.c +++ b/drivers/net/can/softing/softing_fw.c @@ -150,7 +150,7 @@ int softing_load_fw(const char *file, struct softing *card, const uint8_t *mem, *end, *dat; uint16_t type, len; uint32_t addr; - uint8_t *buf = NULL; + uint8_t *buf = NULL, *new_buf; int buflen = 0; int8_t type_end = 0; @@ -199,11 +199,12 @@ int softing_load_fw(const char *file, struct softing *card, if (len > buflen) { /* align buflen */ buflen = (len + (1024-1)) & ~(1024-1); - buf = krealloc(buf, buflen, GFP_KERNEL); - if (!buf) { + new_buf = krealloc(buf, buflen, GFP_KERNEL); + if (!new_buf) { ret = -ENOMEM; goto failed; } + buf = new_buf; } /* verify record data */ memcpy_fromio(buf, &dpram[addr + offset], len); -- cgit v1.2.3 From da3d50ef308d53f216f1f92f4971f245c13e9f65 Mon Sep 17 00:00:00 2001 From: Sven Schmitt Date: Thu, 9 Aug 2012 14:46:34 +0200 Subject: can: sja1000_platform: fix wrong flag IRQF_SHARED for interrupt sharing The sja1000 platform driver wrongly assumes that a shared IRQ is indicated with the IRQF_SHARED flag in irq resource flags. This patch changes the driver to handle the correct flag IORESOURCE_IRQ_SHAREABLE instead. There are no mainline users of the platform driver which wrongly make use of IRQF_SHARED. Signed-off-by: Sven Schmitt Acked-by: Yegor Yefremov Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/sja1000_platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 4f50145f6483..662c5f7eb0c5 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -109,7 +109,9 @@ static int sp_probe(struct platform_device *pdev) priv = netdev_priv(dev); dev->irq = res_irq->start; - priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED); + priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; + if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE) + priv->irq_flags |= IRQF_SHARED; priv->reg_base = addr; /* The CAN clock frequency is half the oscillator clock frequency */ priv->can.clock.freq = pdata->osc_freq / 2; -- cgit v1.2.3 From 9a0f938bde74bf9e50bd75c8de9e38c1787398cd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 24 Aug 2012 09:12:22 +0100 Subject: drm/i915: Use the correct size of the GTT for placing the per-process entries The current layout is to place the per-process tables at the end of the GTT. However, this is currently using a hardcoded maximum size for the GTT and not taking in account limitations imposed by the BIOS. Use the value for the total number of entries allocated in the table as provided by the configuration registers. Reported-by: Matthew Garrett Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ben Widawsky Cc: Matthew Garret Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index d9a5372ec56f..60815b861ec2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 * entries. For aliasing ppgtt support we just steal them at the end for * now. */ - first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES; + first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); if (!ppgtt) -- cgit v1.2.3 From a51d4ed01e5bb39d2cf36a12f9976ab08872c192 Mon Sep 17 00:00:00 2001 From: Calvin Walton Date: Fri, 24 Aug 2012 07:56:31 -0400 Subject: i915: Quirk no_lvds on Gigabyte GA-D525TUD ITX motherboard This board is incorrectly detected as having an LVDS connector, resulting in the VGA output (the only available output on the board) showing the console only in the top-left 1024x768 pixels, and an extra LVDS connector appearing in X. It's a desktop Mini-ITX board using an Atom D525 CPU with an NM10 chipset. I've had this board for about a year, but this is the first time I noticed the issue because I've been running it headless for most of its life. Signed-off-by: Calvin Walton --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e05c0d3e3440..e9a6f6aaed85 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -780,6 +780,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), + }, + }, { } /* terminating entry */ }; -- cgit v1.2.3 From bd4242dfe85470b9caecbd049310518f9b9e3f14 Mon Sep 17 00:00:00 2001 From: Rayagond Kokatanur Date: Wed, 22 Aug 2012 21:28:18 +0000 Subject: stmmac: add header inclusion protection This patch adds "#ifndef __
_H" for protecting header from double inclusion. Signed-off-by: Rayagond Kokatanur Hacked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/descs.h | 6 ++++++ drivers/net/ethernet/stmicro/stmmac/descs_com.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/dwmac100.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 3 +++ drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/mmc.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 5 +++++ drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h | 4 ++++ 9 files changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index e2d083228f3a..719be3912aa9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __COMMON_H__ +#define __COMMON_H__ + #include #include #include @@ -366,3 +369,5 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable); extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr); extern const struct stmmac_ring_mode_ops ring_mode_ops; + +#endif /* __COMMON_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h index 9820ec842cc0..223adf95fd03 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs.h @@ -20,6 +20,10 @@ Author: Giuseppe Cavallaro *******************************************************************************/ + +#ifndef __DESCS_H__ +#define __DESCS_H__ + struct dma_desc { /* Receive descriptor */ union { @@ -166,3 +170,5 @@ enum tdes_csum_insertion { * is not calculated */ cic_full = 3, /* IP header and pseudoheader */ }; + +#endif /* __DESCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h index dd8d6e19dff6..7ee9499a6e38 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -27,6 +27,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DESC_COM_H__ +#define __DESC_COM_H__ + #if defined(CONFIG_STMMAC_RING) static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end) { @@ -124,3 +127,5 @@ static inline void norm_set_tx_desc_len(struct dma_desc *p, int len) p->des01.tx.buffer1_size = len; } #endif + +#endif /* __DESC_COM_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h index 7c6d857a9cc7..2ec6aeae349e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC100_H__ +#define __DWMAC100_H__ + #include #include "common.h" @@ -119,3 +122,5 @@ enum ttc_control { #define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ extern const struct stmmac_dma_ops dwmac100_dma_ops; + +#endif /* __DWMAC100_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index b4c44a587f02..0e4cacedc1f0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -19,6 +19,8 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC1000_H__ +#define __DWMAC1000_H__ #include #include "common.h" @@ -232,3 +234,4 @@ enum rtc_control { #define DWMAC_CORE_3_40 0x34 extern const struct stmmac_dma_ops dwmac1000_dma_ops; +#endif /* __DWMAC1000_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index e678ce39d014..e49c9a0fd6ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __DWMAC_DMA_H__ +#define __DWMAC_DMA_H__ + /* DMA CRS Control and Status Register Mapping */ #define DMA_BUS_MODE 0x00001000 /* Bus Mode */ #define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */ @@ -109,3 +112,5 @@ extern void dwmac_dma_start_rx(void __iomem *ioaddr); extern void dwmac_dma_stop_rx(void __iomem *ioaddr); extern int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); + +#endif /* __DWMAC_DMA_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h index a38352024cb8..67995ef25251 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -22,6 +22,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __MMC_H__ +#define __MMC_H__ + /* MMC control register */ /* When set, all counter are reset */ #define MMC_CNTRL_COUNTER_RESET 0x1 @@ -129,3 +132,5 @@ struct stmmac_counters { extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode); extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr); extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc); + +#endif /* __MMC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index f2d3665430ad..e872e1da3137 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -20,6 +20,9 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __STMMAC_H__ +#define __STMMAC_H__ + #define STMMAC_RESOURCE_NAME "stmmaceth" #define DRV_MODULE_VERSION "March_2012" @@ -166,3 +169,5 @@ static inline void stmmac_unregister_pci(void) { } #endif /* CONFIG_STMMAC_PCI */ + +#endif /* __STMMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h index 6863590d184b..aea9b14cdfbe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h @@ -21,6 +21,8 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#ifndef __STMMAC_TIMER_H__ +#define __STMMAC_TIMER_H__ struct stmmac_timer { void (*timer_start) (unsigned int new_freq); @@ -40,3 +42,5 @@ void stmmac_schedule(struct net_device *dev); extern int tmu2_register_user(void *fnt, void *data); extern void tmu2_unregister_user(void); #endif + +#endif /* __STMMAC_TIMER_H__ */ -- cgit v1.2.3 From d17d794c63e2dc0a5b1ffc8367c9475880427fc7 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 23 Aug 2012 15:11:52 -0400 Subject: libata: Add a space to " 2GB ATA Flash Disk" DMA blacklist entry commit d70e551c8e1ecb6f20422f8db6bfe6a0049edcb8, Add " 2GB ATA Flash Disk"/"ADMA428M" to DMA blacklist, should have added a space before 2GB. Signed-off-by: Prarit Bhargava Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5eee1c1537d2..8e1039c8e159 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4062,7 +4062,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA }, { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, - { "2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, + { " 2GB ATA Flash Disk", "ADMA428M", ATA_HORKAGE_NODMA }, /* Odd clown on sil3726/4726 PMPs */ { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, -- cgit v1.2.3 From 13b5533a38b1eec9d61a07711dc075f03ae47a36 Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Sun, 26 Aug 2012 18:04:10 +0800 Subject: target: Check idr_get_new return value in iscsi_login_zero_tsih_s1 This patch updates iscsi_login_zero_tsih_s1() usage for generating iscsi_session->session_index to properly check the return value from idr_get_new(), and reject the iSCSI login attempt with exception status ISCSI_LOGIN_STATUS_NO_RESOURCES in the event of a failure. Signed-off-by: Benjamin Wang Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 0694d9b1bce6..6aba4395e8d8 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1( { struct iscsi_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; + int ret; sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); if (!sess) { @@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1( return -ENOMEM; } spin_lock(&sess_idr_lock); - idr_get_new(&sess_idr, NULL, &sess->session_index); + ret = idr_get_new(&sess_idr, NULL, &sess->session_index); spin_unlock(&sess_idr_lock); + if (ret < 0) { + pr_err("idr_get_new() for sess_idr failed\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_NO_RESOURCES); + kfree(sess); + return -ENOMEM; + } + sess->creation_time = get_jiffies_64(); spin_lock_init(&sess->session_stats_lock); /* -- cgit v1.2.3 From 1fa6535faf055cd71311ab887e94fc234f04ee18 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 25 Aug 2012 19:28:06 +0200 Subject: Bluetooth: Add support for Apple vendor-specific devices As pointed out by Gustavo and Marcel, all Apple-specific Broadcom devices seen so far have the same interface class, subclass and protocol numbers. This patch adds an entry which matches all of them, using the new USB_VENDOR_AND_INTERFACE_INFO() macro. In particular, this patch adds support for the MacBook Pro Retina (05ac:8286), which is not in the present list. Signed-off-by: Henrik Rydberg Tested-by: Shea Levy Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e791b20beaf5..654e248763ef 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple-specific (Broadcom) devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, -- cgit v1.2.3 From 67ddbb3e6568fb1820b2cc45b00c50702b114801 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Aug 2012 10:51:55 -0400 Subject: HID: add NOGET quirk for Eaton Ellipse MAX UPS This patch (as1603) adds a NOGET quirk for the Eaton Ellipse MAX UPS device. (The USB IDs were already present in hid-ids.h, apparently under a different name.) Signed-off-by: Alan Stern Reported-by: Laurent Bigonville CC: Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 903eef3d3e10..991e85c7325c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v1.2.3 From 50d4b3062d6d4f165c76854a7644b1502836f9b9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 18 Aug 2012 09:48:00 +0100 Subject: staging:iio: prevent divide by zero bugs "val" is used as a divisor later, so we should check for zero here to avoid a division by zero. Signed-off-by: Dan Carpenter Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 ++ drivers/staging/iio/gyro/adis16260_core.c | 2 ++ drivers/staging/iio/imu/adis16400_core.c | 2 ++ drivers/staging/iio/meter/ade7753.c | 2 ++ drivers/staging/iio/meter/ade7754.c | 2 ++ drivers/staging/iio/meter/ade7759.c | 2 ++ 6 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 095837285f4f..19a064d649e3 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -647,6 +647,8 @@ static ssize_t ad7192_write_frequency(struct device *dev, ret = strict_strtoul(buf, 10, &lval); if (ret) return ret; + if (lval == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 93aa431287ac..eb8e9d69efd3 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -195,6 +195,8 @@ static ssize_t adis16260_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); if (spi_get_device_id(st->us)) { diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 1f4c17779b5a..a618327e06ed 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -234,6 +234,8 @@ static ssize_t adis16400_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index f04ece7fbc2f..3ccff189f258 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -425,6 +425,8 @@ static ssize_t ade7753_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 6cee28a5e877..abb1e9c8d094 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -445,6 +445,8 @@ static ssize_t ade7754_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index b3f7e0fa9612..eb0a2a98f388 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -385,6 +385,8 @@ static ssize_t ade7759_write_frequency(struct device *dev, ret = strict_strtol(buf, 10, &val); if (ret) return ret; + if (val == 0) + return -EINVAL; mutex_lock(&indio_dev->mlock); -- cgit v1.2.3 From d1dc9c1276a4d988b29372fe67796430d5cbc756 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 22 Aug 2012 20:37:00 +0100 Subject: staging iio: fix potential memory leak in lis3l02dq_ring.c Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq_ring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 18d108fd967a..f3da59063ed2 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -121,8 +121,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, if (rx_array == NULL) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); - if (ret < 0) + if (ret < 0) { + kfree(rx_array); return ret; + } for (i = 0; i < scan_count; i++) data[i] = combine_8_to_16(rx_array[i*4+1], rx_array[i*4+3]); -- cgit v1.2.3 From f755bbbf1f9f180aa61eb730d638b62e225bfc10 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 25 Aug 2012 21:57:09 +0200 Subject: drivers/iio/adc/at91_adc.c: adjust inconsistent IS_ERR and PTR_ERR Change the call to PTR_ERR to access the value just tested by IS_ERR. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ ( if (IS_ERR(e)) { ... PTR_ERR(e) ... } | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | *if (IS_ERR(e)) { ... * PTR_ERR(e1) ... } ) // Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f61780a02374..3bd5540238a7 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -617,7 +617,7 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) st->adc_clk = clk_get(&pdev->dev, "adc_op_clk"); if (IS_ERR(st->adc_clk)) { dev_err(&pdev->dev, "Failed to get the ADC clock.\n"); - ret = PTR_ERR(st->clk); + ret = PTR_ERR(st->adc_clk); goto error_disable_clk; } -- cgit v1.2.3 From 6b79d14e7a9f5d31b78bcd01a122f0c692e94a19 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 27 Aug 2012 10:59:42 +0200 Subject: s390/dasd: fix ioctl return value For unimplemented ioctls the dasd driver should return -ENOTTY. Reported-by: Wanlong Gao Acked-by: Stefan Weinhuber Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 2 +- drivers/s390/block/dasd_ioctl.c | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 40a826a7295f..2fb2b9ea97ec 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -3804,7 +3804,7 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp) case BIODASDSYMMIO: return dasd_symm_io(device, argp); default: - return -ENOIOCTLCMD; + return -ENOTTY; } } diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index cceae70279f6..654c6921a6d4 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -498,12 +498,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, break; default: /* if the discipline has an ioctl method try it. */ - if (base->discipline->ioctl) { + rc = -ENOTTY; + if (base->discipline->ioctl) rc = base->discipline->ioctl(block, cmd, argp); - if (rc == -ENOIOCTLCMD) - rc = -EINVAL; - } else - rc = -EINVAL; } dasd_put_device(base); return rc; -- cgit v1.2.3 From 7ce9bf1f4785dab0598a19a7fcb0733a18193e4e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 27 Aug 2012 20:27:19 +0200 Subject: mm: cma: fix alignment requirements for contiguous regions Contiguous Memory Allocator requires each of its regions to be aligned in such a way that it is possible to change migration type for all pageblocks holding it and then isolate page of largest possible order from the buddy allocator (which is MAX_ORDER-1). This patch relaxes alignment requirements by one order, because MAX_ORDER alignment is not really needed. Signed-off-by: Marek Szyprowski CC: Michal Nazarewicz Acked-by: Michal Nazarewicz --- drivers/base/dma-contiguous.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 78efb0306a44..34d94c762a1e 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, return -EINVAL; /* Sanitise input arguments */ - alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order); + alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); base = ALIGN(base, alignment); size = ALIGN(size, alignment); limit &= ~(alignment - 1); -- cgit v1.2.3 From 14f0458a41e033dee31ba605137419385c03fc78 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 27 Aug 2012 16:22:49 +1000 Subject: drm/nvc0/copy: check PUNITS to determine which copy engines are disabled On some Fermi chipsets (NVCE particularly) PCOPY1 doesn't exist. And if what I've seen on Kepler is true of Fermi too, chipsets of the same type can have different PCOPY units available. This should fix a v3.5 regression reported by a number of people effecting suspend/resume on NVC8/NVCE chipsets. Cc: stable@vger.kernel.org [3.5] Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1866dbb49979..c61014442aa9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -736,9 +736,11 @@ nouveau_card_init(struct drm_device *dev) } break; case NV_C0: - nvc0_copy_create(dev, 1); + if (!(nv_rd32(dev, 0x022500) & 0x00000200)) + nvc0_copy_create(dev, 1); case NV_D0: - nvc0_copy_create(dev, 0); + if (!(nv_rd32(dev, 0x022500) & 0x00000100)) + nvc0_copy_create(dev, 0); break; default: break; -- cgit v1.2.3 From 3e5531caffcc07b67452c4a8170ffb4c2bd1c9b7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 7 Aug 2012 15:14:12 +0530 Subject: watchdog: da9052: Remove duplicate inclusion of delay.h delay.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/da9052_wdt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c index 3f75129eb0a9..f7abbaeebcaf 100644 --- a/drivers/watchdog/da9052_wdt.c +++ b/drivers/watchdog/da9052_wdt.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 305a3d204aae15eddf1988e50e33aee4119b710d Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Wed, 22 Aug 2012 17:02:42 +0200 Subject: drm/radeon: fix reading CB_COLORn_MASK from the CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ab74e6b149e7..7799e283811f 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1416,7 +1416,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028118_CB_COLOR6_MASK: case R_02811C_CB_COLOR7_MASK: tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; - track->cb_color_mask[tmp] = ib[idx]; + track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { track->cb_dirty = true; } -- cgit v1.2.3 From 3b5ef597ec40603c368f65d3eb6d9818ed6a7bae Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Wed, 22 Aug 2012 17:02:43 +0200 Subject: drm/radeon: initialize tracked CS state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should help catch uninitialized registers and reject commands because of that. Signed-off-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 7799e283811f..8866937bd0b4 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -315,7 +315,14 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->cb_color_bo[i] = NULL; track->cb_color_bo_offset[i] = 0xFFFFFFFF; track->cb_color_bo_mc[i] = 0xFFFFFFFF; - } + track->cb_color_frag_bo[i] = NULL; + track->cb_color_frag_offset[i] = 0xFFFFFFFF; + track->cb_color_tile_bo[i] = NULL; + track->cb_color_tile_offset[i] = 0xFFFFFFFF; + track->cb_color_mask[i] = 0xFFFFFFFF; + } + track->nsamples = 16; + track->log_nsamples = 4; track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; -- cgit v1.2.3 From 523885dec109188b6bed53ec67362072f13b0d43 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Fri, 24 Aug 2012 14:27:36 +0200 Subject: drm/radeon: add proper checking of RESOLVE_BOX command for r600-r700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checking of the second colorbuffer was skipped on r700, because CB_TARGET_MASK was 0xf. With r600, CB_TARGET_MASK is changed to 0xff, so we must set the number of samples of the second colorbuffer to 1 in order to pass the CS checker. The DRM version is bumped, because RESOLVE_BOX is always rejected without this fix on r600. Signed-off-by: Marek Olšák Reviewed-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 19 +++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 8 ++++++++ drivers/gpu/drm/radeon/radeon_drv.c | 3 ++- drivers/gpu/drm/radeon/reg_srcs/r600 | 1 - 4 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 8866937bd0b4..f37676d7f217 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -63,6 +63,7 @@ struct r600_cs_track { u32 cb_color_size_idx[8]; /* unused */ u32 cb_target_mask; u32 cb_shader_mask; /* unused */ + bool is_resolve; u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; @@ -321,6 +322,7 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->cb_color_tile_offset[i] = 0xFFFFFFFF; track->cb_color_mask[i] = 0xFFFFFFFF; } + track->is_resolve = false; track->nsamples = 16; track->log_nsamples = 4; track->cb_target_mask = 0xFFFFFFFF; @@ -359,6 +361,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) volatile u32 *ib = p->ib.ptr; unsigned array_mode; u32 format; + /* When resolve is used, the second colorbuffer has always 1 sample. */ + unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples; size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; format = G_0280A0_FORMAT(track->cb_color_info[i]); @@ -382,7 +386,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) array_check.group_size = track->group_size; array_check.nbanks = track->nbanks; array_check.npipes = track->npipes; - array_check.nsamples = track->nsamples; + array_check.nsamples = nsamples; array_check.blocksize = r600_fmt_get_blocksize(format); if (r600_get_array_mode_alignment(&array_check, &pitch_align, &height_align, &depth_align, &base_align)) { @@ -428,7 +432,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) /* check offset */ tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * - r600_fmt_get_blocksize(format) * track->nsamples; + r600_fmt_get_blocksize(format) * nsamples; switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -799,6 +803,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) */ if (track->cb_dirty) { tmp = track->cb_target_mask; + + /* We must check both colorbuffers for RESOLVE. */ + if (track->is_resolve) { + tmp |= 0xff; + } + for (i = 0; i < 8; i++) { if ((tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ @@ -1288,6 +1298,11 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) track->nsamples = 1 << tmp; track->cb_dirty = true; break; + case R_028808_CB_COLOR_CONTROL: + tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx)); + track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX; + track->cb_dirty = true; + break; case R_0280A0_CB_COLOR0_INFO: case R_0280A4_CB_COLOR1_INFO: case R_0280A8_CB_COLOR2_INFO: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index bdb69a63062f..fa6f37099ba9 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -66,6 +66,14 @@ #define CC_RB_BACKEND_DISABLE 0x98F4 #define BACKEND_DISABLE(x) ((x) << 16) +#define R_028808_CB_COLOR_CONTROL 0x28808 +#define S_028808_SPECIAL_OP(x) (((x) & 0x7) << 4) +#define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) +#define C_028808_SPECIAL_OP 0xFFFFFF8F +#define V_028808_SPECIAL_NORMAL 0x00 +#define V_028808_SPECIAL_DISABLE 0x01 +#define V_028808_SPECIAL_RESOLVE_BOX 0x07 + #define CB_COLOR0_BASE 0x28040 #define CB_COLOR1_BASE 0x28044 #define CB_COLOR2_BASE 0x28048 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 27d22d709c90..8c593ea82c41 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -63,9 +63,10 @@ * 2.19.0 - r600-eg: MSAA textures * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query * 2.21.0 - r600-r700: FMASK and CMASK + * 2.22.0 - r600 only: RESOLVE_BOX allowed */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 21 +#define KMS_DRIVER_MINOR 22 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index f93e45d869f4..20bfbda7b3f1 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,7 +744,6 @@ r600 0x9400 0x00028C38 CB_CLRCMP_DST 0x00028C3C CB_CLRCMP_MSK 0x00028C34 CB_CLRCMP_SRC -0x00028808 CB_COLOR_CONTROL 0x0002842C CB_FOG_BLUE 0x00028428 CB_FOG_GREEN 0x00028424 CB_FOG_RED -- cgit v1.2.3 From 4e58591c8961b3e31709313f75819f2eec06e322 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 21 Aug 2012 19:06:21 -0400 Subject: drm/radeon: don't disable plls that are in use by other crtcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some plls are shared for DP. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Reviewed-by: Michel Dänzer --- drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f4d4505fe831..961d366f00eb 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1682,9 +1682,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; + int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != radeon_crtc->crtc_id && + radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: case ATOM_PPLL2: @@ -1701,6 +1714,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) default: break; } +done: radeon_crtc->pll_id = -1; } -- cgit v1.2.3 From 8d1af57ae3c4458ed0de93ef97f388dd1b3239c7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Aug 2012 09:54:56 -0400 Subject: drm/radeon/atom: rework DIG modesetting on DCE3+ The ordering is important and the current drm code wasn't cutting it for modern DIG encoders. We need to have information about crtc before setting up the encoders so I've shifted the ordering a bit. Probably we'll need a full rework akin to danvet's recent intel patchs. This patch fixes numerous issues with DP bridge chips and makes link training much more reliable. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_encoders.c | 109 +++++++++++++---------------- 1 file changed, 47 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index f9bc27fe269a..4a7f95e5550d 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - if (ASIC_IS_DCE6(rdev)) { - /* It seems we need to call ATOM_ENCODER_CMD_SETUP again - * before reenabling encoder on DPMS ON, otherwise we never - * get picture - */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); } atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { + } else if (ASIC_IS_DCE4(rdev)) { + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + /* enable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } else { + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1848,10 +1877,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); radeon_encoder->pixel_clock = adjusted_mode->clock; + /* need to call this here rather than in prepare() since we need some crtc info */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1870,38 +1901,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - - if (!connector) - dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - else - dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - dig->panel_mode); - } else if (ASIC_IS_DCE4(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - - /* enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - - /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1922,14 +1922,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } - if (ext_encoder) { - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); - else - atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); - } - atombios_apply_encoder_quirks(encoder, adjusted_mode); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2116,7 +2108,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) } radeon_atom_output_lock(encoder, true); - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2137,6 +2128,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) static void radeon_atom_encoder_commit(struct drm_encoder *encoder) { + /* need to call this here as we need the crtc set up */ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); radeon_atom_output_lock(encoder, false); } @@ -2177,14 +2169,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE4(rdev)) - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: -- cgit v1.2.3 From c205b232a64fed6d26edd7e40985b396de99a27f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Aug 2012 18:21:21 -0400 Subject: drm/radeon/atom: powergating fixes for DCE6 Power gating is per crtc pair, but the powergating registers should be called individually. The hw handles power up/down properly. The pair is powered up if either crtc in the pair is powered up and the pair is not powered down until both crtcs in the pair are powered down. This simplifies programming and should save additional power as the previous code never actually power gated the crtc pair. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 961d366f00eb..2817101fb167 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,7 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - /* disable crtc pair power gating before programming */ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { - struct drm_crtc *other_crtc; - struct radeon_crtc *other_radeon_crtc; - list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { - other_radeon_crtc = to_radeon_crtc(other_crtc); - if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || - ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || - ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || - ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || - ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || - ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { - /* if both crtcs in the pair are off, enable power gating */ - if (other_radeon_crtc->enabled == false) - atombios_powergate_crtc(crtc, ATOM_ENABLE); - break; - } - } - } + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; -- cgit v1.2.3 From 0ceb996c9e729b056977a0f07692b38bbd57bc77 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Aug 2012 17:48:18 -0400 Subject: drm/radeon: rework panel mode setup Adjust the panel mode setup to match the behavior of the vbios. Rather than checking for specific bridge chip ids, just check the eDP configuration register. This saves extra aux transactions and works across DP bridge chips without requiring additional per chip id checking. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_dp.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 7712cf5ab33b..3623b98ed3fe 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -577,30 +577,25 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); + u8 tmp; if (!ASIC_IS_DCE4(rdev)) return panel_mode; - if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_NUTMEG) - panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; - else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_TRAVIS) { - u8 id[6]; - int i; - for (i = 0; i < 6; i++) - id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); - if (id[0] == 0x73 && - id[1] == 0x69 && - id[2] == 0x76 && - id[3] == 0x61 && - id[4] == 0x72 && - id[5] == 0x54) + if (dp_bridge != ENCODER_OBJECT_ID_NONE) { + /* DP bridge chips */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + if (tmp & 1) + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || + (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; else - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); + /* eDP */ + tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } -- cgit v1.2.3 From 4a2b6662c3632176b4fdf012243dd3751367bf1f Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 28 Aug 2012 16:50:22 -0400 Subject: drm/radeon: force dma32 to fix regression rs4xx,rs6xx,rs740 It seems some of those IGP dislike non dma32 page despite what documentation says. Fix regression since we allowed non dma32 pages. It seems it only affect some revision of those IGP chips as we don't know which one just force dma32 for all of them. https://bugzilla.redhat.com/show_bug.cgi?id=785375 Signed-off-by: Jerome Glisse Cc: Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index d2e243867ac6..33da8bff8942 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1051,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family < CHIP_RS400)) + (rdev->family <= CHIP_RS740)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; -- cgit v1.2.3 From f54b350d89bf16d31593b935bafccf510ff4a708 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 29 Aug 2012 13:24:15 +0200 Subject: drm/radeon: fix double free in radeon_gpu_reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit radeon_ring_restore is freeing the memory for the saved ring data. We need to remember that, otherwise we try to restore the ring data again on the next try. Additional to that it shouldn't try the reset infinitely if we have saved ring data. Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 33da8bff8942..7a3daebd732d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1346,12 +1346,15 @@ retry: for (i = 0; i < RADEON_NUM_RINGS; ++i) { radeon_ring_restore(rdev, &rdev->ring[i], ring_sizes[i], ring_data[i]); + ring_sizes[i] = 0; + ring_data[i] = NULL; } r = radeon_ib_ring_tests(rdev); if (r) { dev_err(rdev->dev, "ib ring test failed (%d).\n", r); if (saved) { + saved = false; radeon_suspend(rdev); goto retry; } -- cgit v1.2.3 From 072a9c48600409d72aeb0d5b29fbb75861a06631 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Fri, 24 Aug 2012 21:41:11 +0000 Subject: netpoll: revert 6bdb7fe3104 and fix be_poll() instead Against -net. In the patch "netpoll: re-enable irq in poll_napi()", I tried to fix the following warning: [100718.051041] ------------[ cut here ]------------ [100718.051048] WARNING: at kernel/softirq.c:159 local_bh_enable_ip+0x7d/0xb0() (Not tainted) [100718.051049] Hardware name: ProLiant BL460c G7 ... [100718.051068] Call Trace: [100718.051073] [] ? warn_slowpath_common+0x87/0xc0 [100718.051075] [] ? warn_slowpath_null+0x1a/0x20 [100718.051077] [] ? local_bh_enable_ip+0x7d/0xb0 [100718.051080] [] ? _spin_unlock_bh+0x1b/0x20 [100718.051085] [] ? be_process_mcc+0x74/0x230 [be2net] [100718.051088] [] ? be_poll_tx_mcc+0x16c/0x290 [be2net] [100718.051090] [] ? netpoll_poll_dev+0xd6/0x490 [100718.051095] [] ? bond_poll_controller+0x75/0x80 [bonding] [100718.051097] [] ? netpoll_poll_dev+0x45/0x490 [100718.051100] [] ? ksize+0x19/0x80 [100718.051102] [] ? netpoll_send_skb_on_dev+0x157/0x240 by reenabling IRQ before calling ->poll, but it seems more problems are introduced after that patch: http://ozlabs.org/~akpm/stuff/IMG_20120824_122054.jpg http://marc.info/?l=linux-netdev&m=134563282530588&w=2 So it is safe to fix be2net driver code directly. This patch reverts the offending commit and fixes be_poll() by avoid disabling BH there, this is okay because be_poll() can be called either by poll_napi() which already disables IRQ, or by net_rx_action() which already disables BH. Reported-by: Andrew Morton Reported-by: Sylvain Munaut Cc: Sylvain Munaut Cc: Andrew Morton Cc: David Miller Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Ajit Khaparde Signed-off-by: Cong Wang Tested-by: Sylvain Munaut Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 6 ++++-- drivers/net/ethernet/emulex/benet/be_main.c | 2 ++ net/core/netpoll.c | 10 +--------- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 7fac97b4bb59..8c63d06ab12b 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -259,7 +259,7 @@ int be_process_mcc(struct be_adapter *adapter) int num = 0, status = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; - spin_lock_bh(&adapter->mcc_cq_lock); + spin_lock(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ @@ -280,7 +280,7 @@ int be_process_mcc(struct be_adapter *adapter) if (num) be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); - spin_unlock_bh(&adapter->mcc_cq_lock); + spin_unlock(&adapter->mcc_cq_lock); return status; } @@ -295,7 +295,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) if (be_error(adapter)) return -EIO; + local_bh_disable(); status = be_process_mcc(adapter); + local_bh_enable(); if (atomic_read(&mcc_obj->q.used) == 0) break; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 90a903d83d87..78b8aa8069f0 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3763,7 +3763,9 @@ static void be_worker(struct work_struct *work) /* when interrupts are not yet enabled, just reap any pending * mcc completions */ if (!netif_running(adapter->netdev)) { + local_bh_disable(); be_process_mcc(adapter); + local_bh_enable(); goto reschedule; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 346b1eb83a1f..e4ba3e70c174 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -168,24 +168,16 @@ static void poll_napi(struct net_device *dev) struct napi_struct *napi; int budget = 16; - WARN_ON_ONCE(!irqs_disabled()); - list_for_each_entry(napi, &dev->napi_list, dev_list) { - local_irq_enable(); if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - rcu_read_lock_bh(); budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), napi, budget); - rcu_read_unlock_bh(); spin_unlock(&napi->poll_lock); - if (!budget) { - local_irq_disable(); + if (!budget) break; - } } - local_irq_disable(); } } -- cgit v1.2.3 From 41fa54377057ab38bc3e08ebb46168a7daf2e63b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Aug 2012 19:48:26 -0400 Subject: drm/radeon: fix dig encoder selection on DCE61 Was using the DCE41 code which was wrong. Fixes blank displays on a number of Trinity systems. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_encoders.c | 31 +++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 4a7f95e5550d..6e8803a1170c 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1769,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *test_encoder; - struct radeon_encoder_atom_dig *dig; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t dig_enc_in_use = 0; - /* DCE4/5 */ - if (ASIC_IS_DCE4(rdev)) { - dig = radeon_encoder->enc_priv; - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* DCE6 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { /* ontario follows DCE4 */ if (rdev->family == CHIP_PALM) { if (dig->linkb) -- cgit v1.2.3 From 4a68a74ba04e7ccf798d45988f4f2d2131fb5063 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 13 Aug 2012 16:31:24 +0000 Subject: gma500: Consider CRTC initially active. [this one ideally should make 3.6 - it fixes the very annoying mode setting bug] This causes the pipe to be forced off prior to initial mode set, which roughly mirrors the behavior of the i915 driver. It fixes initial mode setting on my Intel DN2800MT (Cedarview) board. Without it, mode setting triggers an out-of-range error from the monitor for most modes, but only on initial configuration (i.e. they can be configured successfully from userspace after that). Signed-off-by: Forest Bond Signed-off-by: Alan Cox Cc: stable Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_intel_display.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 30dc22a7156c..8033526bb53b 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1362,6 +1362,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, (struct drm_connector **) (psb_intel_crtc + 1); psb_intel_crtc->mode_set.num_connectors = 0; psb_intel_cursor_init(dev, psb_intel_crtc); + + /* Set to true so that the pipe is forced off on initial config. */ + psb_intel_crtc->active = true; } int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, -- cgit v1.2.3 From 6f33814bd4d9cfe76033a31b1c0c76c960cd8e4b Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 8 Aug 2012 23:12:19 +0200 Subject: drm: Add EDID_QUIRK_FORCE_REDUCED_BLANKING for ASUS VW222S Connecting an ASUS VW222S [1] over VGA a garbled screen is shown with vertical stripes in the top half. In commit bc42aabc [2] commit bc42aabc6a01b92b0f961d65671564e0e1cd7592 Author: Adam Jackson Date: Wed May 23 16:26:54 2012 -0400 drm/edid/quirks: ViewSonic VA2026w Adam Jackson added the quirk `EDID_QUIRK_FORCE_REDUCED_BLANKING` which is also needed for this ASUS monitor. All log files and output from `xrandr` is included in the referenced Bugzilla report #17629. Please note that this monitor only has a VGA (D-Sub) connector [1]. [1] http://www.asus.com/Display/LCD_Monitors/VW222S/ [2] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=bc42aabc6a01b92b0f961d65671564e0e1cd7592 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17629 Signed-off-by: Paul Menzel Cc: Cc: Adam Jackson Cc: Ian Pilcher Cc: Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a8743c399e83..b7ee230572b7 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -87,6 +87,9 @@ static struct edid_quirk { int product_id; u32 quirks; } edid_quirk_list[] = { + /* ASUS VW222S */ + { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, + /* Acer AL1706 */ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, /* Acer F51 */ -- cgit v1.2.3 From 3683243b2c551e58082b179fd153c7d43ddc503b Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 22 Aug 2012 00:26:47 +0000 Subject: xen-netfront: use __pskb_pull_tail to ensure linear area is big enough on RX I'm slightly concerned by the "only in exceptional circumstances" comment on __pskb_pull_tail but the structure of an skb just created by netfront shouldn't hit any of the especially slow cases. This approach still does slightly more work than the old way, since if we pull up the entire first frag we now have to shuffle everything down where before we just received into the right place in the first place. Signed-off-by: Ian Campbell Cc: Konrad Rzeszutek Wilk Cc: Jeremy Fitzhardinge Cc: Mel Gorman Cc: xen-devel@lists.xensource.com Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Tested-by: Konrad Rzeszutek Wilk Acked-by: Konrad Rzeszutek Wilk Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 30899901aef5..650f79a1f2bd 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -57,8 +57,7 @@ static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { - struct page *page; - unsigned offset; + int pull_to; }; #define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb)) @@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev, struct sk_buff *skb; while ((skb = __skb_dequeue(rxq)) != NULL) { - struct page *page = NETFRONT_SKB_CB(skb)->page; - void *vaddr = page_address(page); - unsigned offset = NETFRONT_SKB_CB(skb)->offset; - - memcpy(skb->data, vaddr + offset, - skb_headlen(skb)); + int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - if (page != skb_frag_page(&skb_shinfo(skb)->frags[0])) - __free_page(page); + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); @@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget) struct sk_buff_head errq; struct sk_buff_head tmpq; unsigned long flags; - unsigned int len; int err; spin_lock(&np->rx_lock); @@ -955,24 +947,13 @@ err: } } - NETFRONT_SKB_CB(skb)->page = - skb_frag_page(&skb_shinfo(skb)->frags[0]); - NETFRONT_SKB_CB(skb)->offset = rx->offset; - - len = rx->status; - if (len > RX_COPY_THRESHOLD) - len = RX_COPY_THRESHOLD; - skb_put(skb, len); + NETFRONT_SKB_CB(skb)->pull_to = rx->status; + if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD) + NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD; - if (rx->status > len) { - skb_shinfo(skb)->frags[0].page_offset = - rx->offset + len; - skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len); - skb->data_len = rx->status - len; - } else { - __skb_fill_page_desc(skb, 0, NULL, 0, 0); - skb_shinfo(skb)->nr_frags = 0; - } + skb_shinfo(skb)->frags[0].page_offset = rx->offset; + skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); + skb->data_len = rx->status; i = xennet_fill_frags(np, skb, &tmpq); @@ -999,7 +980,7 @@ err: * receive throughout using the standard receive * buffer size was cut by 25%(!!!). */ - skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len); + skb->truesize += skb->data_len - RX_COPY_THRESHOLD; skb->len += skb->data_len; if (rx->flags & XEN_NETRXF_csum_blank) -- cgit v1.2.3 From e2c53be223aca36cf93eb6a0f6bafa079e78f52b Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Thu, 23 Aug 2012 21:46:25 +0000 Subject: gianfar: fix default tx vlan offload feature flag Commit - "b852b72 gianfar: fix bug caused by 87c288c6e9aa31720b72e2bc2d665e24e1653c3e" disables by default (on mac init) the hw vlan tag insertion. The "features" flags were not updated to reflect this, and "ethtool -K" shows tx-vlan-offload to be "on" by default. Cc: Sebastian Poehn Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 4605f7246687..d3233f59a82e 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1041,7 +1041,7 @@ static int gfar_probe(struct platform_device *ofdev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= NETIF_F_HW_VLAN_RX; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { -- cgit v1.2.3 From d821a4c4d11ad160925dab2bb009b8444beff484 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 24 Aug 2012 20:38:11 +0000 Subject: e1000e: DoS while TSO enabled caused by link partner with small MSS With a low enough MSS on the link partner and TSO enabled locally, the networking stack can periodically send a very large (e.g. 64KB) TCP message for which the driver will attempt to use more Tx descriptors than are available by default in the Tx ring. This is due to a workaround in the code that imposes a limit of only 4 MSS-sized segments per descriptor which appears to be a carry-over from the older e1000 driver and may be applicable only to some older PCI or PCIx parts which are not supported in e1000e. When the driver gets a message that is too large to fit across the configured number of Tx descriptors, it stops the upper stack from queueing any more and gets stuck in this state. After a timeout, the upper stack assumes the adapter is hung and calls the driver to reset it. Remove the unnecessary limitation of using up to only 4 MSS-sized segments per Tx descriptor, and put in a hard failure test to catch when attempting to check for message sizes larger than would fit in the whole Tx ring. Refactor the remaining logic that limits the size of data per Tx descriptor from a seemingly arbitrary 8KB to a limit based on the dynamic size of the Tx packet buffer as described in the hardware specification. Also, fix the logic in the check for space in the Tx ring for the next largest possible packet after the current one has been successfully queued for transmit, and use the appropriate defines for default ring sizes in e1000_probe instead of magic values. This issue goes back to the introduction of e1000e in 2.6.24 when it was split off from e1000. Reported-by: Ben Hutchings Signed-off-by: Bruce Allan Cc: Stable [2.6.24+] Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000e/e1000.h | 1 + drivers/net/ethernet/intel/e1000e/netdev.c | 48 ++++++++++++++---------------- 2 files changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index cd153326c3cf..cb3356c9af80 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -310,6 +310,7 @@ struct e1000_adapter { */ struct e1000_ring *tx_ring /* One per active queue */ ____cacheline_aligned_in_smp; + u32 tx_fifo_limit; struct napi_struct napi; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 46c3b1f9ff89..d01a099475a1 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -3516,6 +3516,15 @@ void e1000e_reset(struct e1000_adapter *adapter) break; } + /* + * Alignment of Tx data is on an arbitrary byte boundary with the + * maximum size per Tx descriptor limited only to the transmit + * allocation of the packet buffer minus 96 bytes with an upper + * limit of 24KB due to receive synchronization limitations. + */ + adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, + 24 << 10); + /* * Disable Adaptive Interrupt Moderation if 2 full packets cannot * fit in receive buffer. @@ -4785,12 +4794,9 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) return 1; } -#define E1000_MAX_PER_TXD 8192 -#define E1000_MAX_TXD_PWR 12 - static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, unsigned int first, unsigned int max_per_txd, - unsigned int nr_frags, unsigned int mss) + unsigned int nr_frags) { struct e1000_adapter *adapter = tx_ring->adapter; struct pci_dev *pdev = adapter->pdev; @@ -5023,20 +5029,19 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) { + BUG_ON(size > tx_ring->count); + if (e1000_desc_unused(tx_ring) >= size) return 0; return __e1000_maybe_stop_tx(tx_ring, size); } -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1) static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_ring *tx_ring = adapter->tx_ring; unsigned int first; - unsigned int max_per_txd = E1000_MAX_PER_TXD; - unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb_headlen(skb); unsigned int nr_frags; @@ -5056,18 +5061,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, } mss = skb_shinfo(skb)->gso_size; - /* - * The controller does a simple calculation to - * make sure there is enough room in the FIFO before - * initiating the DMA for each buffer. The calc is: - * 4 = ceil(buffer len/mss). To make sure we don't - * overrun the FIFO, adjust the max buffer len if mss - * drops. - */ if (mss) { u8 hdr_len; - max_per_txd = min(mss << 2, max_per_txd); - max_txd_pwr = fls(max_per_txd) - 1; /* * TSO Workaround for 82571/2/3 Controllers -- if skb->data @@ -5097,12 +5092,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, count++; count++; - count += TXD_USE_COUNT(len, max_txd_pwr); + count += DIV_ROUND_UP(len, adapter->tx_fifo_limit); nr_frags = skb_shinfo(skb)->nr_frags; for (f = 0; f < nr_frags; f++) - count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]), - max_txd_pwr); + count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]), + adapter->tx_fifo_limit); if (adapter->hw.mac.tx_pkt_filtering) e1000_transfer_dhcp_info(adapter, skb); @@ -5144,15 +5139,18 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, tx_flags |= E1000_TX_FLAGS_NO_FCS; /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss); + count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, + nr_frags); if (count) { skb_tx_timestamp(skb); netdev_sent_queue(netdev, skb->len); e1000_tx_queue(tx_ring, tx_flags, count); /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2); - + e1000_maybe_stop_tx(tx_ring, + (MAX_SKB_FRAGS * + DIV_ROUND_UP(PAGE_SIZE, + adapter->tx_fifo_limit) + 2)); } else { dev_kfree_skb_any(skb); tx_ring->buffer_info[first].time_stamp = 0; @@ -6327,8 +6325,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.autoneg_advertised = 0x2f; /* ring size defaults */ - adapter->rx_ring->count = 256; - adapter->tx_ring->count = 256; + adapter->rx_ring->count = E1000_DEFAULT_RXD; + adapter->tx_ring->count = E1000_DEFAULT_TXD; /* * Initial Wake on LAN setting - If APM wake is enabled in -- cgit v1.2.3 From 26614ba5445fe31a69068a5e94266fa08b4ee345 Mon Sep 17 00:00:00 2001 From: Merav Sicron Date: Mon, 27 Aug 2012 03:26:19 +0000 Subject: bnx2x: Move netif_napi_add to the open call Move netif_napi_add for all queues from the probe call to the open call, to avoid the case that napi objects are added for queues that may eventually not be initialized and activated. With the former behavior, the driver could crash when netpoll was calling ndo_poll_controller. Signed-off-by: Merav Sicron Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 3 --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 4 ++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 4 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 -- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 10 ++++------ 5 files changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 463b9ec57d80..6d1a24acb77e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1708,9 +1708,6 @@ struct bnx2x_func_init_params { continue; \ else -#define for_each_napi_rx_queue(bp, var) \ - for ((var) = 0; (var) < bp->num_napi_queues; (var)++) - /* Skip OOO FP */ #define for_each_tx_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index e879e19eb0d6..af20c6ee2cd9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2046,6 +2046,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) */ bnx2x_setup_tc(bp->dev, bp->max_cos); + /* Add all NAPI objects */ + bnx2x_add_all_napi(bp); bnx2x_napi_enable(bp); /* set pf load just before approaching the MCP */ @@ -2408,6 +2410,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index dfa757e74296..21b553229ea4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -792,7 +792,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp) bp->num_napi_queues = bp->num_queues; /* Add NAPI objects */ - for_each_napi_rx_queue(bp, i) + for_each_rx_queue(bp, i) netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, BNX2X_NAPI_WEIGHT); } @@ -801,7 +801,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp) { int i; - for_each_napi_rx_queue(bp, i) + for_each_rx_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index fc4e0e3885b0..c37a68d68090 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -2888,11 +2888,9 @@ static void bnx2x_get_channels(struct net_device *dev, */ static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss) { - bnx2x_del_all_napi(bp); bnx2x_disable_msi(bp); BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE; bnx2x_set_int_mode(bp); - bnx2x_add_all_napi(bp); } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 02b5a343b195..5b42275ed033 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8427,6 +8427,8 @@ unload_error: /* Disable HW interrupts, NAPI */ bnx2x_netif_stop(bp, 1); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); /* Release IRQs */ bnx2x_free_irq(bp); @@ -11899,9 +11901,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, */ bnx2x_set_int_mode(bp); - /* Add all NAPI objects */ - bnx2x_add_all_napi(bp); - rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -11976,9 +11975,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) unregister_netdev(dev); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); - /* Power on: we can't let PCI layer write to us while we are in D3 */ bnx2x_set_power_state(bp, PCI_D0); @@ -12025,6 +12021,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_tx_disable(bp); bnx2x_netif_stop(bp, 0); + /* Delete all NAPI objects */ + bnx2x_del_all_napi(bp); del_timer_sync(&bp->timer); -- cgit v1.2.3 From 14a15d618743ebc4936fe03073bf0c75024d3a07 Mon Sep 17 00:00:00 2001 From: Merav Sicron Date: Mon, 27 Aug 2012 03:26:20 +0000 Subject: bnx2x: Correct the ndo_poll_controller call This patch correct poll_bnx2x (ndo_poll_controller call) which was not functioning well with MSI-X. Signed-off-by: Merav Sicron Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 5b42275ed033..21054987257a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11231,10 +11231,12 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void poll_bnx2x(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + int i; - disable_irq(bp->pdev->irq); - bnx2x_interrupt(bp->pdev->irq, dev); - enable_irq(bp->pdev->irq); + for_each_eth_queue(bp, i) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + napi_schedule(&bnx2x_fp(bp, fp->index, napi)); + } } #endif -- cgit v1.2.3 From a348cd5fd85dbca7260ef865c5def85929932861 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 31 Aug 2012 09:56:25 +1000 Subject: drm/nvd0/disp: hopefully fix selection of 6/8bpc mode on DP outputs I have a very limited number of traces available for DP on NVD9+, but, these values produce the same as the binary driver on a confirmed 18-bit eDP panel and a confirmed 24-bit eDP panel (Retina MBP). It's interesting that the bitfield values also match the MODE_CTRL values that control the same thing on nv50:nvd9. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvd0_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index dac525b2994e..8a2fc89b7763 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, case OUTPUT_DP: if (nv_connector->base.display_info.bpc == 6) { nv_encoder->dp.datarate = mode->clock * 18 / 8; - syncs |= 0x00000140; + syncs |= 0x00000002 << 6; } else { nv_encoder->dp.datarate = mode->clock * 24 / 8; - syncs |= 0x00000180; + syncs |= 0x00000005 << 6; } if (nv_encoder->dcb->sorconf.link & 1) -- cgit v1.2.3 From 991083ba60f89e717e3a4175be96d48a810e9eae Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 31 Aug 2012 10:51:20 +1000 Subject: drm/nv50-/gpio: initialise to vbios defaults during init This is required to fix an issue on the Retina MBP where the eDP panel's AUX channel isn't wired up to the HPD pin for the panel, causing our aux code to bail out early. From looking at various traces of the binary driver, it appears NVIDIA do something very similar on at least all nv50+ chipsets during their initialisation sequence. So, hopefully this is safe. Issue and fix initially tracked down by Ryan Bourgeois on fdo#51971. Backported fix from reworked nouveau kernel module. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_gpio.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index f429e6a8ca7a..f03490534893 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -115,6 +115,9 @@ nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + /* initialise gpios and routing to vbios defaults */ + nouveau_gpio_reset(dev); + /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); nv_wr32(dev, 0xe054, 0xffffffff); -- cgit v1.2.3 From b72c200975a4ed579dbf3353019e19528745a29a Mon Sep 17 00:00:00 2001 From: Jaccon Bastiaansen Date: Mon, 27 Aug 2012 11:53:51 +0000 Subject: cs89x0 : packet reception not working The RxCFG register of the CS89x0 could be configured incorrectly (because of misplaced parentheses), resulting in the disabling of packet reception. Signed-off-by: Jaccon Bastiaansen Signed-off-by: David S. Miller --- drivers/net/ethernet/cirrus/cs89x0.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index 845b2020f291..138446957786 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -1243,6 +1243,7 @@ static void set_multicast_list(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); unsigned long flags; + u16 cfg; spin_lock_irqsave(&lp->lock, flags); if (dev->flags & IFF_PROMISC) @@ -1260,11 +1261,10 @@ static void set_multicast_list(struct net_device *dev) /* in promiscuous mode, we accept errored packets, * so we have to enable interrupts on them also */ - writereg(dev, PP_RxCFG, - (lp->curr_rx_cfg | - (lp->rx_mode == RX_ALL_ACCEPT) - ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL) - : 0)); + cfg = lp->curr_rx_cfg; + if (lp->rx_mode == RX_ALL_ACCEPT) + cfg |= RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL; + writereg(dev, PP_RxCFG, cfg); spin_unlock_irqrestore(&lp->lock, flags); } -- cgit v1.2.3 From ab6f148de28261682d300662e87b9477f7efc95b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 26 Aug 2012 20:41:38 +0000 Subject: usbnet: fix deadlock in resume A usbnet device can share a multifunction device with a storage device. If the storage device is autoresumed the usbnet devices also needs to be autoresumed. Allocating memory with GFP_KERNEL can deadlock in this case. This should go back into all kernels that have commit 65841fd5132c3941cdf5df09e70df3ed28323212 That is 3.5 Signed-off-by: Oliver Neukum CC: stable@kernel.org Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8531c1caac28..fd4b26d46fd5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1573,7 +1573,7 @@ int usbnet_resume (struct usb_interface *intf) netif_device_present(dev->net) && !timer_pending(&dev->delay) && !test_bit(EVENT_RX_HALT, &dev->flags)) - rx_alloc_submit(dev, GFP_KERNEL); + rx_alloc_submit(dev, GFP_NOIO); if (!(dev->txq.qlen >= TX_QLEN(dev))) netif_tx_wake_all_queues(dev->net); -- cgit v1.2.3 From fa026e223df2514b271b20f839ab05d7f21181b9 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Tue, 28 Aug 2012 02:30:32 +0000 Subject: net: qmi_wwan: new device: Foxconn/Novatel E396 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foxconn-branded Novatel E396, Gobi3k modem. Cc: Dan Williams Cc: Bjørn Mork Cc: Ben Chan Signed-off-by: Aleksander Morgado Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 328397c66730..189e52d2eee6 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -441,6 +441,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ { } /* END */ }; -- cgit v1.2.3 From b27393aecf66199f5ddad37c302d3e0cfadbe6c0 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Thu, 30 Aug 2012 06:37:32 +0000 Subject: net: ethernet: fix kernel OOPS when remove davinci_mdio module davinci mdio device is not unregistered from mdiobus when removing the module, which causes BUG_ON() when free the device from mdiobus. Calling mdiobus_unregister() before mdiobus_free() fixes the issue. Signed-off-by: Bin Liu Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_mdio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index cd7ee204e94a..a9ca4a03d31b 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -394,8 +394,10 @@ static int __devexit davinci_mdio_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct davinci_mdio_data *data = dev_get_drvdata(dev); - if (data->bus) + if (data->bus) { + mdiobus_unregister(data->bus); mdiobus_free(data->bus); + } if (data->clk) clk_put(data->clk); -- cgit v1.2.3 From 4c30aa33d4b4ce9a0ee5b32d058a40f4eca2ab63 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 29 Aug 2012 09:35:24 +0800 Subject: gpio: mc9s08dz60: Fix build error if I2C=m Make GPIO_MC9S08DZ60 depend on I2C=y, this fixes below build error: LD init/built-in.o drivers/built-in.o: In function `mc9s08dz60_get_value': clk-fixed-factor.c:(.text+0x7214): undefined reference to `i2c_smbus_read_byte_data' drivers/built-in.o: In function `mc9s08dz60_set': clk-fixed-factor.c:(.text+0x727c): undefined reference to `i2c_smbus_read_byte_data' clk-fixed-factor.c:(.text+0x72bc): undefined reference to `i2c_smbus_write_byte_data' drivers/built-in.o: In function `mc9s08dz60_i2c_driver_init': clk-fixed-factor.c:(.init.text+0x290): undefined reference to `i2c_register_driver' drivers/built-in.o: In function `mc9s08dz60_i2c_driver_exit': clk-fixed-factor.c:(.exit.text+0x2c): undefined reference to `i2c_del_driver' make: *** [vmlinux] Error 1 Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b16c8a72a2e2..ba7926f5c099 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -294,7 +294,7 @@ config GPIO_MAX732X_IRQ config GPIO_MC9S08DZ60 bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" - depends on I2C && MACH_MX35_3DS + depends on I2C=y && MACH_MX35_3DS help Select this to enable the MC9S08DZ60 GPIO driver -- cgit v1.2.3 From dd2914972e5f6d9c1a687158c0f65b81d239fe37 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 28 Aug 2012 19:30:44 +0800 Subject: gpio: em: Fix checking return value of irq_alloc_descs irq_alloc_descs() returns negative error code on failure. Signed-off-by: Axel Lin Acked-by: Magnus Damm Signed-off-by: Linus Walleij --- drivers/gpio/gpio-em.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index ae37181798b3..ec48ed512628 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -247,9 +247,9 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) p->irq_base = irq_alloc_descs(pdata->irq_base, 0, pdata->number_of_pins, numa_node_id()); - if (IS_ERR_VALUE(p->irq_base)) { + if (p->irq_base < 0) { dev_err(&pdev->dev, "cannot get irq_desc\n"); - return -ENXIO; + return p->irq_base; } pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", pdata->gpio_base, pdata->number_of_pins, p->irq_base); -- cgit v1.2.3 From 1146f8822ae6601e24f9072d6cd74f76506142cd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 1 Sep 2012 14:11:22 +0800 Subject: gpio: rdc321x: Prevent removal of modules exporting active GPIOs This driver can be built as a module, set the missing owner field of struct gpio_chip to prevent removal of modules exporting active GPIOs. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rdc321x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index e97016af6443..b62d443e9a59 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -170,6 +170,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; + rdc321x_gpio_dev->chip.owner = THIS_MODULE; rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; -- cgit v1.2.3 From e1b2aa7f3051e268973b6126fdca602ac4af6bc4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Sep 2012 09:57:40 +0000 Subject: fddi: 64 bit bug in smt_add_para() The intent was to set 4 bytes of data so that's why the sp_len is set to 4 on the next line. The cast to u_long pointer clears 8 bytes on 64 bit arches. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/pmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fddi/skfp/pmf.c b/drivers/net/fddi/skfp/pmf.c index 24d8566cfd8b..441b4dc79450 100644 --- a/drivers/net/fddi/skfp/pmf.c +++ b/drivers/net/fddi/skfp/pmf.c @@ -673,7 +673,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, sm_pm_get_ls(smc,port_to_mib(smc,port))) ; break ; case SMT_P_REASON : - * (u_long *) to = 0 ; + *(u32 *)to = 0 ; sp_len = 4 ; goto sp_done ; case SMT_P1033 : /* time stamp */ -- cgit v1.2.3 From 5002200599429e83fc13e0d9a2d4788b79515b0c Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Sat, 1 Sep 2012 03:47:26 +0000 Subject: net: qmi_wwan: add several new Gobi devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gobi devices are composite, needing both the qcserial and qmi_wwan drivers to support all functions. Re-syncing the list of supported devices with qcserial. Cc: Aleksander Morgado Cc: Thomas Tuttle Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 189e52d2eee6..adfab3fc5478 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -413,7 +413,9 @@ static const struct usb_device_id products[] = { /* 5. Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ + {QMI_GOBI_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ @@ -441,6 +443,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ { } /* END */ -- cgit v1.2.3 From 9bfc8da00b1e74f55a52cc06a0d364f1f7f61ed8 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 1 Sep 2012 21:47:11 +0200 Subject: HID: Only dump input if someone is listening Going through the motions of printing the debug message information takes a long time; using the keyboard can lead to a 160 us irqsoff latency. This patch skips hid_dump_input() when there are no open handles, which brings latency down to 100 us. Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8bf8a64e5115..b8485a0106c9 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_driver *hdrv = hid->driver; int ret; - hid_dump_input(hid, usage, value); + if (!list_empty(&hid->debug_list)) + hid_dump_input(hid, usage, value); if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { ret = hdrv->event(hid, field, usage, value); -- cgit v1.2.3 From 0273de08c455031335dbea2630208f66106b0c14 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Sep 2012 07:22:16 +1000 Subject: drm/ast: drop debug level on error printk This was never an error, drop to a debug print. Reported-by: Keven Lachance Signed-off-by: Dave Airlie --- drivers/gpu/drm/ast/ast_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7282c081fb53..a712cafcfa1d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev) ast->cursor_cache = obj; ast->cursor_cache_gpu_addr = gpu_addr; - DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); + DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); return 0; fail: return ret; -- cgit v1.2.3 From c1f05264d834e9fb9a4ebfd36dbd86172ac7107a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 30 Aug 2012 11:06:18 +1000 Subject: drm/i915/edp: get the panel delay before powering up In order to setup the i2c channel, we power up the panel via ironlake_edp_panel_vdd_on, however it requires intel_dp->panel_power_up_delay to be initialised, which hasn't been setup yet. So move things around so we set the panel power up values first then init the i2c stuff. This is one step to fixing the eDP panel in the MBP from uninitialised state. Signed-off-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a6c426afaa7a..ace757af9133 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; } - intel_dp_i2c_init(intel_dp, intel_connector, name); - /* Cache some DPCD data in the eDP case */ if (is_edp(intel_dp)) { - bool ret; struct edp_power_seq cur, vbt; u32 pp_on, pp_off, pp_div; - struct edid *edid; pp_on = I915_READ(PCH_PP_ON_DELAYS); pp_off = I915_READ(PCH_PP_OFF_DELAYS); @@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + } + + intel_dp_i2c_init(intel_dp, intel_connector, name); + + if (is_edp(intel_dp)) { + bool ret; + struct edid *edid; ironlake_edp_panel_vdd_on(intel_dp); ret = intel_dp_get_dpcd(intel_dp); -- cgit v1.2.3 From fcbc50da7753b210b4442ca9abc4efbd4e481f6e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Aug 2012 14:08:42 +0300 Subject: drm/i915: only enable sdvo hotplug irq if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid constant wakeups caused by noisy irq lines when we don't even care about the irq. This should be particularly useful for i945g/gm where the hotplug has been disabled: commit 768b107e4b3be0acf6f58e914afe4f337c00932b Author: Daniel Vetter Date: Fri May 4 11:29:56 2012 +0200 drm/i915: disable sdvo hotplug on i945g/gm v2: While at it, remove the bogus hotplug_active read, and do not mask hotplug_active[0] before checking whether the irq is needed, per discussion with Daniel on IRC. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=38442 Tested-by: Dominik Köppl Signed-off-by: Jani Nikula Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d81bb0bf2885..123afd357611 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2573,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) hotplug_mask = intel_sdvo->is_sdvob ? SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; } - dev_priv->hotplug_supported_mask |= hotplug_mask; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2581,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; - /* Set up hotplug command - note paranoia about contents of reply. - * We assume that the hardware is in a sane state, and only touch - * the bits we think we understand. - */ - intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, - &intel_sdvo->hotplug_active, 2); - intel_sdvo->hotplug_active[0] &= ~0x3; - if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", @@ -2596,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) goto err; } + /* Only enable the hotplug irq if we need it, to work around noisy + * hotplug lines. + */ + if (intel_sdvo->hotplug_active[0]) + dev_priv->hotplug_supported_mask |= hotplug_mask; + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); /* Set the input timing to the screen. Assume always input 0. */ -- cgit v1.2.3 From 85e87870fa18ec9f5df98e2d3b48f3699560a570 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Sun, 2 Sep 2012 22:26:18 +0000 Subject: net: usbnet: fix softirq storm on suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suspending an open usbnet device results in constant rescheduling of usbnet_bh. commit 65841fd5 "usbnet: handle remote wakeup asap" refactored the usbnet_bh code to allow sharing the urb allocate and submit code with usbnet_resume. In this process, a test for, and immediate return on, ENOLINK from rx_submit was unintentionally dropped. The rx queue will not grow if rx_submit fails, making usbnet_bh reschedule itself. This results in a softirq storm if the error is persistent. rx_submit translates the usb_submit_urb error EHOSTUNREACH into ENOLINK, so this is an expected and persistent error for a suspended device. The old code tested for this condition and avoided rescheduling. Putting this test back. Cc: # v3.5 Cc: Ming Lei Cc: Oliver Neukum Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fd4b26d46fd5..fc9f578a1e25 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1201,19 +1201,26 @@ deferred: } EXPORT_SYMBOL_GPL(usbnet_start_xmit); -static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) +static int rx_alloc_submit(struct usbnet *dev, gfp_t flags) { struct urb *urb; int i; + int ret = 0; /* don't refill the queue all at once */ for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) { urb = usb_alloc_urb(0, flags); if (urb != NULL) { - if (rx_submit(dev, urb, flags) == -ENOLINK) - return; + ret = rx_submit(dev, urb, flags); + if (ret) + goto err; + } else { + ret = -ENOMEM; + goto err; } } +err: + return ret; } /*-------------------------------------------------------------------------*/ @@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param) int temp = dev->rxq.qlen; if (temp < RX_QLEN(dev)) { - rx_alloc_submit(dev, GFP_ATOMIC); + if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK) + return; if (temp != dev->rxq.qlen) netif_dbg(dev, link, dev->net, "rxqlen %d --> %d\n", -- cgit v1.2.3 From cab32f39dcc5b35db96497dc0a026b5dea76e4e7 Mon Sep 17 00:00:00 2001 From: Benoît Locher Date: Mon, 27 Aug 2012 15:02:45 +0200 Subject: can: mcp251x: avoid repeated frame bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MCP2515 has a silicon bug causing repeated frame transmission, see section 5 of MCP2515 Rev. B Silicon Errata Revision G (March 2007). Basically, setting TXBnCTRL.TXREQ in either SPI mode (00 or 11) will eventually cause the bug. The workaround proposed by Microchip is to use mode 00 and send a RTS command on the SPI bus to initiate the transmission. Cc: Signed-off-by: Benoît Locher Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index a580db29e503..26e7129332ab 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + /* MPC251x registers */ #define CANSTAT 0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, -- cgit v1.2.3 From 28dcc2d60cb570d9f549c329b2f51400553412a1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 3 Sep 2012 16:25:12 +0300 Subject: drm/i915: do not expose a dysfunctional backlight interface to userspace Previously intel_panel_setup_backlight() would create a sysfs backlight interface with max brightness of 1 if it was unable to figure out the max backlight brightness. This rendered the backlight interface useless. Do not create a dysfunctional backlight interface to begin with. Signed-off-by: Jani Nikula Tested-by: David Woodhouse Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3df4f5fa892a..e019b2369861 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) return val; } -u32 intel_panel_get_max_backlight(struct drm_device *dev) +static u32 _intel_panel_get_max_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 max; max = i915_read_blc_pwm_ctl(dev_priv); - if (max == 0) { - /* XXX add code here to query mode clock or hardware clock - * and program max PWM appropriately. - */ - pr_warn_once("fixme: max PWM is zero\n"); - return 1; - } if (HAS_PCH_SPLIT(dev)) { max >>= 16; @@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) max *= 0xff; } + return max; +} + +u32 intel_panel_get_max_backlight(struct drm_device *dev) +{ + u32 max; + + max = _intel_panel_get_max_backlight(dev); + if (max == 0) { + /* XXX add code here to query mode clock or hardware clock + * and program max PWM appropriately. + */ + pr_warn_once("fixme: max PWM is zero\n"); + return 1; + } + DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); return max; } @@ -424,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; - props.max_brightness = intel_panel_get_max_backlight(dev); + props.max_brightness = _intel_panel_get_max_backlight(dev); + if (props.max_brightness == 0) { + DRM_ERROR("Failed to get maximum backlight value\n"); + return -ENODEV; + } dev_priv->backlight = backlight_device_register("intel_backlight", &connector->kdev, dev, -- cgit v1.2.3 From 9fef76857feed8e94ca3a5ee37db644f04a9488b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 3 Sep 2012 15:31:00 +0800 Subject: mISDN: fix possible memory leak in hfcmulti_init() hc has been allocated in this function and missing free it before leaving from some error handling cases. spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 5e402cf2e795..f02794203bb1 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -5059,6 +5059,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, printk(KERN_INFO "HFC-E1 #%d has overlapping B-channels on fragment #%d\n", E1_cnt + 1, pt); + kfree(hc); return -EINVAL; } maskcheck |= hc->bmask[pt]; @@ -5086,6 +5087,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev, if ((poll >> 1) > sizeof(hc->silence_data)) { printk(KERN_ERR "HFCMULTI error: silence_data too small, " "please fix\n"); + kfree(hc); return -EINVAL; } for (i = 0; i < (poll >> 1); i++) -- cgit v1.2.3 From 78b495c39add820ab66ab897af9bd77a5f2e91f6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 3 Sep 2012 17:12:29 +0300 Subject: UBI: fix a horrible memory deallocation bug UBI was mistakingly using 'kfree()' instead of 'kmem_cache_free()' when freeing "attach eraseblock" structures in vtbl.c. Thankfully, this happened only when we were doing auto-format, so many systems were unaffected. However, there are still many users affected. It is strange, but the system did not crash and nothing bad happened when the SLUB memory allocator was used. However, in case of SLOB we observed an crash right away. This problem was introduced in 2.6.39 by commit "6c1e875 UBI: add slab cache for ubi_scan_leb objects" A note for stable trees: Because variable were renamed, this won't cleanly apply to older kernels. Changing names like this should help: 1. ai -> si 2. aeb_slab_cache -> seb_slab_cache 3. new_aeb -> new_seb Reported-by: Richard Genoud Tested-by: Richard Genoud Tested-by: Artem Bityutskiy Cc: stable@vger.kernel.org [v2.6.39+] Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vtbl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 437bc193e170..568307cc7caf 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -340,7 +340,7 @@ retry: * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'. */ err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); - kfree(new_aeb); + kmem_cache_free(ai->aeb_slab_cache, new_aeb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -353,7 +353,7 @@ write_error: list_add(&new_aeb->u.list, &ai->erase); goto retry; } - kfree(new_aeb); + kmem_cache_free(ai->aeb_slab_cache, new_aeb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; -- cgit v1.2.3 From 660d9a9c4f623eeec80cec3705ae872bd5cb556d Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 30 Jul 2012 15:03:02 +0800 Subject: mmc: bfin_sdh: fix dma_desc_array build error Descriptor array structure has been moved into blackfin dma.h head file. This patch fix below error: drivers/mmc/host/bfin_sdh.c:52:8: error: redefinition of 'struct dma_desc_array' make[4]: *** [drivers/mmc/host/bfin_sdh.o] Error 1 Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Chris Ball --- drivers/mmc/host/bfin_sdh.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 03666174ca48..a17dd7363ceb 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -49,13 +49,6 @@ #define bfin_write_SDH_CFG bfin_write_RSI_CFG #endif -struct dma_desc_array { - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; -} __packed; - struct sdh_host { struct mmc_host *mmc; spinlock_t lock; -- cgit v1.2.3 From 1af36b2a993dddfa3d6860ec4879c9e8abc9b976 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Tue, 17 Jul 2012 17:16:09 +0300 Subject: mmc: mxs-mmc: fix deadlock in SDIO IRQ case Release the lock before mmc_signal_sdio_irq is called by mxs_mmc_irq_handler. Backtrace: [ 79.660000] ============================================= [ 79.660000] [ INFO: possible recursive locking detected ] [ 79.660000] 3.4.0-00009-g3e96082-dirty #11 Not tainted [ 79.660000] --------------------------------------------- [ 79.660000] swapper/0 is trying to acquire lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xd4 [ 79.660000] [ 79.660000] but task is already holding lock: [ 79.660000] (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] other info that might help us debug this: [ 79.660000] Possible unsafe locking scenario: [ 79.660000] [ 79.660000] CPU0 [ 79.660000] ---- [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] lock(&(&host->lock)->rlock#2); [ 79.660000] [ 79.660000] *** DEADLOCK *** [ 79.660000] [ 79.660000] May be due to missing lock nesting notation [ 79.660000] [ 79.660000] 1 lock held by swapper/0: [ 79.660000] #0: (&(&host->lock)->rlock#2){-.....}, at: [] mxs_mmc_irq_handler+0x1c/0xe8 [ 79.660000] [ 79.660000] stack backtrace: [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (__lock_acquire+0x1948/0x1d48) [ 79.660000] [] (__lock_acquire+0x1948/0x1d48) from [] (lock_acquire+0xe0/0xf8) [ 79.660000] [] (lock_acquire+0xe0/0xf8) from [] (_raw_spin_lock_irqsave+0x44/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x44/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) [ 79.660000] BUG: spinlock lockup on CPU#0, swapper/0 [ 79.660000] lock: c398cb2c, .magic: dead4ead, .owner: swapper/0, .owner_cpu: 0 [ 79.660000] [] (unwind_backtrace+0x0/0xf4) from [] (do_raw_spin_lock+0xf0/0x144) [ 79.660000] [] (do_raw_spin_lock+0xf0/0x144) from [] (_raw_spin_lock_irqsave+0x4c/0x58) [ 79.660000] [] (_raw_spin_lock_irqsave+0x4c/0x58) from [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) [ 79.660000] [] (mxs_mmc_enable_sdio_irq+0x18/0xd4) from [] (mxs_mmc_irq_handler+0xd4/0xe8) [ 79.660000] [] (mxs_mmc_irq_handler+0xd4/0xe8) from [] (handle_irq_event_percpu+0x70/0x254) [ 79.660000] [] (handle_irq_event_percpu+0x70/0x254) from [] (handle_irq_event+0x3c/0x5c) [ 79.660000] [] (handle_irq_event+0x3c/0x5c) from [] (handle_level_irq+0x90/0x110) [ 79.660000] [] (handle_level_irq+0x90/0x110) from [] (generic_handle_irq+0x38/0x50) [ 79.660000] [] (generic_handle_irq+0x38/0x50) from [] (handle_IRQ+0x30/0x84) [ 79.660000] [] (handle_IRQ+0x30/0x84) from [] (__irq_svc+0x38/0x60) [ 79.660000] [] (__irq_svc+0x38/0x60) from [] (default_idle+0x2c/0x40) [ 79.660000] [] (default_idle+0x2c/0x40) from [] (cpu_idle+0x64/0xcc) [ 79.660000] [] (cpu_idle+0x64/0xcc) from [] (start_kernel+0x244/0x2c8) Signed-off-by: Lauri Hintsala Acked-by: Shawn Guo Cc: stable Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index a51f9309ffbb..e62e58e5053d 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) writel(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); + spin_unlock(&host->lock); + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); - spin_unlock(&host->lock); - if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) cmd->error = -ETIMEDOUT; else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) -- cgit v1.2.3 From fc108d24d3a6da63576a460e122fa1df0cbdea20 Mon Sep 17 00:00:00 2001 From: Lauri Hintsala Date: Tue, 17 Jul 2012 17:16:10 +0300 Subject: mmc: mxs-mmc: fix deadlock caused by recursion loop Release the lock before mmc_signal_sdio_irq is called by mxs_mmc_enable_sdio_irq. Backtrace: [ 65.470000] ============================================= [ 65.470000] [ INFO: possible recursive locking detected ] [ 65.470000] 3.5.0-rc5 #2 Not tainted [ 65.470000] --------------------------------------------- [ 65.470000] ksdioirqd/mmc0/73 is trying to acquire lock: [ 65.470000] (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] but task is already holding lock: [ 65.470000] (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] other info that might help us debug this: [ 65.470000] Possible unsafe locking scenario: [ 65.470000] [ 65.470000] CPU0 [ 65.470000] ---- [ 65.470000] lock(&(&host->lock)->rlock#2); [ 65.470000] lock(&(&host->lock)->rlock#2); [ 65.470000] [ 65.470000] *** DEADLOCK *** [ 65.470000] [ 65.470000] May be due to missing lock nesting notation [ 65.470000] [ 65.470000] 1 lock held by ksdioirqd/mmc0/73: [ 65.470000] #0: (&(&host->lock)->rlock#2){-.-...}, at: [] mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc] [ 65.470000] [ 65.470000] stack backtrace: [ 65.470000] [] (unwind_backtrace+0x0/0xf4) from [] (__lock_acquire+0x14f8/0x1b98) [ 65.470000] [] (__lock_acquire+0x14f8/0x1b98) from [] (lock_acquire+0xa0/0x108) [ 65.470000] [] (lock_acquire+0xa0/0x108) from [] (_raw_spin_lock_irqsave+0x48/0x5c) [ 65.470000] [] (_raw_spin_lock_irqsave+0x48/0x5c) from [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) from [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) from [] (sdio_irq_thread+0x1bc/0x274) [ 65.470000] [] (sdio_irq_thread+0x1bc/0x274) from [] (kthread+0x8c/0x98) [ 65.470000] [] (kthread+0x8c/0x98) from [] (kernel_thread_exit+0x0/0x8) [ 65.470000] BUG: spinlock lockup suspected on CPU#0, ksdioirqd/mmc0/73 [ 65.470000] lock: 0xc3358724, .magic: dead4ead, .owner: ksdioirqd/mmc0/73, .owner_cpu: 0 [ 65.470000] [] (unwind_backtrace+0x0/0xf4) from [] (do_raw_spin_lock+0x100/0x144) [ 65.470000] [] (do_raw_spin_lock+0x100/0x144) from [] (_raw_spin_lock_irqsave+0x50/0x5c) [ 65.470000] [] (_raw_spin_lock_irqsave+0x50/0x5c) from [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0x18/0xdc [mxs_mmc]) from [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) [ 65.470000] [] (mxs_mmc_enable_sdio_irq+0xc8/0xdc [mxs_mmc]) from [] (sdio_irq_thread+0x1bc/0x274) [ 65.470000] [] (sdio_irq_thread+0x1bc/0x274) from [] (kthread+0x8c/0x98) [ 65.470000] [] (kthread+0x8c/0x98) from [] (kernel_thread_exit+0x0/0x8) Reported-by: Attila Kinali Signed-off-by: Lauri Hintsala Acked-by: Shawn Guo Cc: stable Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e62e58e5053d..ad3fcea1269e 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); - - if (readl(host->base + HW_SSP_STATUS(host)) & - BM_SSP_STATUS_SDIO_IRQ) - mmc_signal_sdio_irq(host->mmc); - } else { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); @@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } spin_unlock_irqrestore(&host->lock, flags); + + if (enable && readl(host->base + HW_SSP_STATUS(host)) & + BM_SSP_STATUS_SDIO_IRQ) + mmc_signal_sdio_irq(host->mmc); + } static const struct mmc_host_ops mxs_mmc_ops = { -- cgit v1.2.3 From 74f330bceaa7b88d06062e1cac3d519a3dfc041e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 22 Aug 2012 23:10:01 +0800 Subject: mmc: sdhci-esdhc: break out early if clock is 0 Since commit 30832ab56 ("mmc: sdhci: Always pass clock request value zero to set_clock host op") was merged, esdhc_set_clock starts hitting "if (clock == 0)" where ESDHC_SYSTEM_CONTROL has been operated. This causes SDHCI card-detection function being broken. Fix the regression by moving "if (clock == 0)" above ESDHC_SYSTEM_CONTROL operation. Signed-off-by: Shawn Guo Cc: Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index b97b2f5dafdb..d25f9ab9a54d 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int div = 1; u32 temp; + if (clock == 0) + goto out; + temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (clock == 0) - goto out; - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; -- cgit v1.2.3 From 077d40731edc90ee9dedf63249034c8cd5f694ce Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Tue, 24 Jul 2012 11:42:04 +0200 Subject: mmc: atmel-mci: not busy flag has also to be used for read operations Even if the datasheet says that the not busy flag has to be used only for write operations, it's false except for version lesser than v2xx. Not waiting on the not busy flag for read operations can cause the controller to hang-up during the initialization of some SD cards with DMA after the first CMD6 -- the next command is sent too early. Signed-off-by: Ludovic Desroches Cc: stable [3.5, 3.6] Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 322412cec4ee..a53c7c478e05 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -81,6 +81,7 @@ struct atmel_mci_caps { bool has_bad_data_ordering; bool need_reset_after_xfer; bool need_blksz_mul_4; + bool need_notbusy_for_read_ops; }; struct atmel_mci_dma { @@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv) __func__); atmci_set_completed(host, EVENT_XFER_COMPLETE); - if (host->data->flags & MMC_DATA_WRITE) { + if (host->caps.need_notbusy_for_read_ops || + (host->data->flags & MMC_DATA_WRITE)) { atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); state = STATE_WAITING_NOTBUSY; } else if (host->mrq->stop) { @@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) host->caps.has_bad_data_ordering = 1; host->caps.need_reset_after_xfer = 1; host->caps.need_blksz_mul_4 = 1; + host->caps.need_notbusy_for_read_ops = 0; /* keep only major version number */ switch (version & 0xf00) { @@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) case 0x200: host->caps.has_rwproof = 1; host->caps.need_blksz_mul_4 = 0; + host->caps.need_notbusy_for_read_ops = 1; case 0x100: host->caps.has_bad_data_ordering = 0; host->caps.need_reset_after_xfer = 0; -- cgit v1.2.3 From 182c90815993452f1902837cc342ac2c05ef13f5 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:30 +0900 Subject: mmc: dw_mmc: amend using error interrupt status RINTSTS status includes masked interrupts as well as unmasked. data_status and cmd_status are set by value of RINTSTS in interrupt handler and tasklet finally uses it to decide whether error is happened or not. In addition, MINTSTS status is used for setting data_status in PIO. Masked error interrupt will not be handled and that status can be considered non-error case. Signed-off-by: Seungwon Jeon Reviewed By: Girish K S Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 72dc3cde646d..7baed457dc3b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1547,12 +1547,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; - u32 status, pending; + u32 pending; unsigned int pass_count = 0; int i; do { - status = mci_readl(host, RINTSTS); pending = mci_readl(host, MINTSTS); /* read-only mask reg */ /* @@ -1570,7 +1569,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_CMD_ERROR_FLAGS) { mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); - host->cmd_status = status; + host->cmd_status = pending; smp_wmb(); set_bit(EVENT_CMD_COMPLETE, &host->pending_events); } @@ -1578,7 +1577,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & DW_MCI_DATA_ERROR_FLAGS) { /* if there is an error report DATA_ERROR */ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); - host->data_status = status; + host->data_status = pending; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | @@ -1589,7 +1588,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_DATA_OVER) { mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); if (!host->data_status) - host->data_status = status; + host->data_status = pending; smp_wmb(); if (host->dir_status == DW_MCI_RECV_STATUS) { if (host->sg != NULL) @@ -1613,7 +1612,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_CMD_DONE) { mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); - dw_mci_cmd_interrupt(host, status); + dw_mci_cmd_interrupt(host, pending); } if (pending & SDMMC_INT_CD) { -- cgit v1.2.3 From 9b2026a12511439d906a5d8d302ae285ebe7378a Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:40 +0900 Subject: mmc: dw_mmc: correct mishandling error interrupt Datasheet of SYNOPSYS mentions that DTO(Data Transfer Over) interrupt will be raised even if some error interrupts, however it is actually found that DTO does not occur. SYNOPSYS has confirmed this issue. Current implementation defers the call of tasklet_schedule until DTO when the error interrupts is happened. This patch fixes error handling. Signed-off-by: Seungwon Jeon Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7baed457dc3b..1a5db20133ee 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1580,9 +1580,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) host->data_status = pending; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); - if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | - SDMMC_INT_SBE | SDMMC_INT_EBE))) - tasklet_schedule(&host->tasklet); + tasklet_schedule(&host->tasklet); } if (pending & SDMMC_INT_DATA_OVER) { -- cgit v1.2.3 From e74f3a9c993a088f0a067e13941075e4acb7300a Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 1 Aug 2012 09:30:46 +0900 Subject: mmc: dw_mmc: fix error handling in PIO mode Data transfer will be continued until all the bytes are transmitted, even if data crc error occurs during a multiple-block data transfer. This means RXDR/TXDR interrupts will occurs until data transfer is terminated. Early setting of host->sg to NULL prevents going into xxx_data_pio functions, hence permanent unhandled RXDR/TXDR interrupts occurs. And checking error interrupt status in the xxx_data_pio functions is no need because dw_mci_interrupt does do the same. This patch also removes it. Signed-off-by: Seungwon Jeon Acked-by: Jaehoon Chung Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1a5db20133ee..cf8511b80782 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1429,22 +1429,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + sg_miter->consumed = offset; status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_RXDR); - if (status & DW_MCI_DATA_ERROR_FLAGS) { - host->data_status = status; - data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; - smp_wmb(); - - set_bit(EVENT_DATA_ERROR, &host->pending_events); - - tasklet_schedule(&host->tasklet); - return; - } } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ data->bytes_xfered += nbytes; @@ -1497,23 +1485,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host) nbytes += len; remain -= len; } while (remain); - sg_miter->consumed = offset; + sg_miter->consumed = offset; status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_TXDR); - if (status & DW_MCI_DATA_ERROR_FLAGS) { - host->data_status = status; - data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; - - smp_wmb(); - - set_bit(EVENT_DATA_ERROR, &host->pending_events); - - tasklet_schedule(&host->tasklet); - return; - } } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ data->bytes_xfered += nbytes; -- cgit v1.2.3 From 9623b5b9192b349bcadb31cce159072a78ac6972 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Wed, 25 Jul 2012 08:33:17 -0700 Subject: mmc: dw_mmc: Disable low power mode if SDIO interrupts are used The documentation for the dw_mmc part says that the low power mode should normally only be set for MMC and SD memory and should be turned off for SDIO cards that need interrupts detected. The best place I could find to do this is when the SDIO interrupt was first enabled. I rely on the fact that dw_mci_setup_bus() will be called when it's time to reenable. Signed-off-by: Doug Anderson Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cf8511b80782..af40d227bece 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) { struct dw_mci *host = slot->host; u32 div; + u32 clk_en_a; if (slot->clock != host->current_speed) { div = host->bus_hz / slot->clock; @@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); - /* enable clock */ - mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | - SDMMC_CLKEN_LOW_PWR) << slot->id)); + /* enable clock; only low power if no SDIO */ + clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; + if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) + clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; + mci_writel(host, CLKENA, clk_en_a); /* inform CIU */ mci_send_cmd(slot, @@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) return present; } +/* + * Disable lower power mode. + * + * Low power mode will stop the card clock when idle. According to the + * description of the CLKENA register we should disable low power mode + * for SDIO cards if we need SDIO interrupts to work. + * + * This function is fast if low power mode is already disabled. + */ +static void dw_mci_disable_low_power(struct dw_mci_slot *slot) +{ + struct dw_mci *host = slot->host; + u32 clk_en_a; + const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; + + clk_en_a = mci_readl(host, CLKENA); + + if (clk_en_a & clken_low_pwr) { + mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); + } +} + static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) { struct dw_mci_slot *slot = mmc_priv(mmc); @@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) /* Enable/disable Slot Specific SDIO interrupt */ int_mask = mci_readl(host, INTMASK); if (enb) { + /* + * Turn off low power mode if it was enabled. This is a bit of + * a heavy operation and we disable / enable IRQs a lot, so + * we'll leave low power mode disabled and it will get + * re-enabled again in dw_mci_setup_bus(). + */ + dw_mci_disable_low_power(slot); + mci_writel(host, INTMASK, (int_mask | SDMMC_INT_SDIO(slot->id))); } else { -- cgit v1.2.3 From 3550ccdb9d8d350e526b809bf3dd92b550a74fe1 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 29 Aug 2012 15:05:36 +0900 Subject: mmc: card: Skip secure erase on MoviNAND; causes unrecoverable corruption. For several MoviNAND eMMC parts, there are known issues with secure erase and secure trim. For these specific MoviNAND devices, we skip these operations. Specifically, there is a bug in the eMMC firmware that causes unrecoverable corruption when the MMC is erased with MMC_CAP_ERASE enabled. References: http://forum.xda-developers.com/showthread.php?t=1644364 https://plus.google.com/111398485184813224730/posts/21pTYfTsCkB#111398485184813224730/posts/21pTYfTsCkB Signed-off-by: Ian Chen Reviewed-by: Namjae Jeon Acked-by: Jaehoon Chung Reviewed-by: Linus Walleij Cc: stable [3.0+] Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 26 +++++++++++++++++++++++++- include/linux/mmc/card.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index f1c84decb192..172a768036d8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE) + if (req->cmd_flags & REQ_SECURE && + !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); @@ -1716,6 +1717,7 @@ force_ro_fail: #define CID_MANFID_SANDISK 0x2 #define CID_MANFID_TOSHIBA 0x11 #define CID_MANFID_MICRON 0x13 +#define CID_MANFID_SAMSUNG 0x15 static const struct mmc_fixup blk_fixups[] = { @@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, MMC_QUIRK_LONG_READ_TIME), + /* + * On these Samsung MoviNAND parts, performing secure erase or + * secure trim can result in unrecoverable corruption due to a + * firmware bug. + */ + MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + END_FIXUP }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 111aca5e97f3..4b27f9f503e4 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -239,6 +239,7 @@ struct mmc_card { #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ +#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 -- cgit v1.2.3 From 75b53aee2f4fe6375c6007226bf68d75b5c4a929 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 24 Aug 2012 06:00:18 +0000 Subject: mmc: omap: fix broken PIO mode After commit 26b88520b80695a6fa5fd95b5d97c03f4daf87e0 ("mmc: omap_hsmmc: remove private DMA API implementation"), the Nokia N800 here stopped booting: [ 2.086181] Waiting for root device /dev/mmcblk0p1... [ 2.324066] Unhandled fault: imprecise external abort (0x406) at 0x00000000 [ 2.331451] Internal error: : 406 [#1] ARM [ 2.335784] Modules linked in: [ 2.339050] CPU: 0 Not tainted (3.6.0-rc3 #60) [ 2.344146] PC is at default_idle+0x28/0x30 [ 2.348602] LR is at trace_hardirqs_on_caller+0x15c/0x1b0 ... This turned out to be due to memory corruption caused by long-broken PIO code in drivers/mmc/host/omap.c. (Previously, this driver had been using DMA; but the above commit caused the MMC driver to fall back to PIO mode with an unmodified Kconfig.) The PIO code, added with the rest of the driver in commit 730c9b7e6630f786fcec026fb11d2e6f2c90fdcb ("[MMC] Add OMAP MMC host driver"), confused bytes with 16-bit words. This bug caused memory located after the PIO transfer buffer to be corrupted with transfers larger than 32 bytes. The driver also did not increment the buffer pointer after the transfer occurred. This bug resulted in data corruption during any transfer larger than 64 bytes. Signed-off-by: Paul Walmsley Reviewed-by: Felipe Balbi Tested-by: Tony Lindgren Signed-off-by: Chris Ball --- drivers/mmc/host/omap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 50e08f03aa65..a5999a74496a 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data) static void mmc_omap_xfer_data(struct mmc_omap_host *host, int write) { - int n; + int n, nwords; if (host->buffer_bytes_left == 0) { host->sg_idx++; @@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) n = 64; if (n > host->buffer_bytes_left) n = host->buffer_bytes_left; + + nwords = n / 2; + nwords += n & 1; /* handle odd number of bytes to transfer */ + host->buffer_bytes_left -= n; host->total_bytes_left -= n; host->data->bytes_xfered += n; if (write) { - __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); + __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), + host->buffer, nwords); } else { - __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); + __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), + host->buffer, nwords); } + + host->buffer += nwords; } static inline void mmc_omap_report_irq(u16 status) -- cgit v1.2.3 From cadf84bfeb80e216fde328d357fe856160157d2c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:38 +0100 Subject: staging: comedi: amplc_pci224: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pci224_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pci224_find_pci_dev()`). It is decremented when the `detach` hook (`pci224_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pci224_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pci224_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Cc: stable # 3.5.x Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci224.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 4e17f13e57f6..8bf109e7bb05 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1503,6 +1503,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev) DRIVER_NAME ": BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pci224_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pci224_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pci224_attach_common(dev, pci_dev, NULL); } -- cgit v1.2.3 From 1a6671d208bb8f558dc12b6a7d2f55e80cf5828d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:39 +0100 Subject: staging: comedi: amplc_dio200: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`dio200_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `dio200_find_pci_dev()`). It is decremented when the `detach` hook (`dio200_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`dio200_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `dio200_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_dio200.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 6c81e377262c..cc8931fde839 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1412,6 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in dio200_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via dio200_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return dio200_pci_common_attach(dev, pci_dev); } -- cgit v1.2.3 From 3abcfe0eeda850481143d05bdd206dd2b170d07d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:40 +0100 Subject: staging: comedi: amplc_pc236: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pc236_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pc236_find_pci_dev()`). It is decremented when the `detach` hook (`pc236_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pc236_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pc236_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc236.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index aabba9886b7d..f50287903038 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -565,6 +565,13 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pc236_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pc236_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pc236_pci_common_attach(dev, pci_dev); } -- cgit v1.2.3 From a0234ade63ce2c14841d9d6e802ed735b4ed2829 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:41 +0100 Subject: staging: comedi: amplc_pc263: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pc263_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pc263_find_pci_dev()`). It is decremented when the `detach` hook (`pc263_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pc263_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pc263_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pc263.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 40ec1ffebba6..8191c4e28e0a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -298,6 +298,13 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev, dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pc263_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pc263_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pc263_pci_common_attach(dev, pci_dev); } -- cgit v1.2.3 From 4375e61ed21d629fe922b3e5591ad6588f715137 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:42 +0100 Subject: staging: comedi: amplc_pci230: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`pci230_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `pci230_find_pci_dev()`). It is decremented when the `detach` hook (`pci230_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`pci230_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `pci230_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/amplc_pci230.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 1b67d0c61fa7..66e74bd12267 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2925,6 +2925,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev, "amplc_pci230: BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in pci230_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via pci230_attach() + * has been removed. + */ + pci_dev_get(pci_dev); return pci230_attach_common(dev, pci_dev); } -- cgit v1.2.3 From 4a7a4f95a5e15648f24a971b36b82adc36d2cb6b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 3 Sep 2012 16:39:43 +0100 Subject: staging: comedi: das08: Fix PCI ref count When attaching a PCI device manually via the comedi driver `attach` hook (`das08_attach()`) (called by the comedi core for the `COMEDI_DEVCONFIG` ioctl), its reference count is incremented in the `for_each_pci_dev` loop (in `das08_find_pci()`). It is decremented when the `detach` hook (`das08_detach()`) is called to detach the device. However, when the PCI device is attached automatically via the `attach_pci` hook (`das08_attach_pci()`, called at probe time via `comedi_pci_auto_config()`) it's reference count is not incremented so there will be an unmatched decrement when detaching the device. Increment the PCI device reference count in `das08_attach_pci()` to correct the mismatch. Once support for manual configuration has been removed from this driver, the calls to `pci_dev_get()` and `pci_dev_put()` can be removed. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 874e02e47668..c5676e267518 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -922,6 +922,13 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev) dev_err(dev->class_dev, "BUG! cannot determine board type!\n"); return -EINVAL; } + /* + * Need to 'get' the PCI device to match the 'put' in das08_detach(). + * TODO: Remove the pci_dev_get() and matching pci_dev_put() once + * support for manual attachment of PCI devices via das08_attach() + * has been removed. + */ + pci_dev_get(pdev); return das08_pci_attach_common(dev, pdev); } -- cgit v1.2.3 From e6391a182865efc896cb2a8d79e07b7ac2f45b48 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 31 Aug 2012 20:41:29 +0100 Subject: staging: comedi: das08: Correct AI encoding for das08jr-16-ao The element of `das08_boards[]` for the 'das08jr-16-ao' board has the `ai_encoding` member set to `das08_encode12`. It should be set to `das08_encode16` same as the 'das08jr/16' board. After all, this board has 16-bit AI resolution. The description of the A/D LSB register at offset 0 seems incorrect in the user manual "cio-das08jr-16-ao.pdf" as it implies that the AI resolution is only 12 bits. The diagrams of the A/D LSB and MSB registers show 15 data bits and a sign bit, which matches what the software expects for the `das08_encode16` AI encoding method. Cc: stable Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c5676e267518..e5eb3b9ba17f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -623,7 +623,7 @@ static const struct das08_board_struct das08_boards[] = { .ai = das08_ai_rinsn, .ai_nbits = 16, .ai_pg = das08_pg_none, - .ai_encoding = das08_encode12, + .ai_encoding = das08_encode16, .ao = das08jr_ao_winsn, .ao_nbits = 16, .di = das08jr_di_rbits, -- cgit v1.2.3 From 61ed59ed09e6ad2b8395178ea5ad5f653bba08e3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 31 Aug 2012 20:41:30 +0100 Subject: staging: comedi: das08: Correct AO output for das08jr-16-ao Don't zero out bits 15..12 of the data value in `das08jr_ao_winsn()` as that knobbles the upper three-quarters of the output range for the 'das08jr-16-ao' board. Cc: stable Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index e5eb3b9ba17f..67a914a10b55 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -378,7 +378,7 @@ das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, int chan; lsb = data[0] & 0xff; - msb = (data[0] >> 8) & 0xf; + msb = (data[0] >> 8) & 0xff; chan = CR_CHAN(insn->chanspec); -- cgit v1.2.3 From b320e97240de0f98b81f866d59f47af41780eab0 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sat, 1 Sep 2012 21:25:46 +0000 Subject: i825xx: fix paging fault on znet_probe() In znet_probe(), strncmp() may access beyond 0x100000 and trigger the below oops in kvm. Fix it by limiting the loop under 0x100000-8. I suspect the limit could be further decreased to 0x100000-sizeof(struct netidblk), however no datasheet at hand.. [ 3.744312] BUG: unable to handle kernel paging request at 80100000 [ 3.746145] IP: [<8119d12a>] strncmp+0xc/0x20 [ 3.747446] *pde = 01d10067 *pte = 00100160 [ 3.747493] Oops: 0000 [#1] DEBUG_PAGEALLOC [ 3.747493] Pid: 1, comm: swapper Not tainted 3.6.0-rc1-00018-g57bfc0a #73 Bochs Bochs [ 3.747493] EIP: 0060:[<8119d12a>] EFLAGS: 00010206 CPU: 0 [ 3.747493] EIP is at strncmp+0xc/0x20 [ 3.747493] EAX: 800fff4e EBX: 00000006 ECX: 00000006 EDX: 814d2bb9 [ 3.747493] ESI: 80100000 EDI: 814d2bba EBP: 8e03dfa0 ESP: 8e03df98 [ 3.747493] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 [ 3.747493] CR0: 8005003b CR2: 80100000 CR3: 016f7000 CR4: 00000690 [ 3.747493] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 3.747493] DR6: ffff0ff0 DR7: 00000400 [ 3.747493] Process swapper (pid: 1, ti=8e03c000 task=8e040000 task.ti=8e03c000) [ 3.747493] Stack: [ 3.747493] 800fffff 00000000 8e03dfb4 816a1376 00000006 816a134a 00000000 8e03dfd0 [ 3.747493] 816819b5 816ed1c0 8e03dfe4 00000006 00000123 816ed604 8e03dfe4 81681b29 [ 3.747493] 00000000 81681a5b 00000000 00000000 8134e542 00000000 00000000 00000000 [ 3.747493] Call Trace: [ 3.747493] [<816a1376>] znet_probe+0x2c/0x26b [ 3.747493] [<816a134a>] ? dnet_driver_init+0xf/0xf [ 3.747493] [<816819b5>] do_one_initcall+0x6a/0x110 [ 3.747493] [<81681b29>] kernel_init+0xce/0x14b Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/i825xx/znet.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c index bd1f1ef91e19..ba4e0cea3506 100644 --- a/drivers/net/ethernet/i825xx/znet.c +++ b/drivers/net/ethernet/i825xx/znet.c @@ -139,8 +139,11 @@ struct znet_private { /* Only one can be built-in;-> */ static struct net_device *znet_dev; +#define NETIDBLK_MAGIC "NETIDBLK" +#define NETIDBLK_MAGIC_SIZE 8 + struct netidblk { - char magic[8]; /* The magic number (string) "NETIDBLK" */ + char magic[NETIDBLK_MAGIC_SIZE]; /* The magic number (string) "NETIDBLK" */ unsigned char netid[8]; /* The physical station address */ char nettype, globalopt; char vendor[8]; /* The machine vendor and product name. */ @@ -373,14 +376,16 @@ static int __init znet_probe (void) struct znet_private *znet; struct net_device *dev; char *p; + char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE); int err = -ENOMEM; /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ - for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++) - if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0) + for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) + if (*p == 'N' && + strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0) break; - if (p >= (char *)phys_to_virt(0x100000)) { + if (p > plast) { if (znet_debug > 1) printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); return -ENODEV; -- cgit v1.2.3 From 01f8a27e3c9109c0187f473e593fa7b45cdb65e8 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Fri, 17 Aug 2012 19:31:04 +0200 Subject: staging: wlan-ng: Fix problem with wrong arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function pointer scan in struct cfg80211_ops is not supposed to be assigned a function with a struct net_device pointer as an argument. Instead access the net_device struct in the following way: struct net_device *dev = request->wdev->netdev; sparse gives these warnings: drivers/staging/wlan-ng/cfg80211.c:726:17: warning: incorrect type in initializer (incompatible argument 2 (different base types)) expected int ( *scan )( ... ) got int ( extern [toplevel] * )( ... ) drivers/staging/wlan-ng/cfg80211.c:726:2: warning: initialization from incompatible pointer type [enabled by default] drivers/staging/wlan-ng/cfg80211.c:726:2: warning: (near initialization for ‘prism2_usb_cfg_ops.scan’) [enabled by default] Signed-off-by: Emil Goode Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index fabff4d650ef..0970127344e6 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -327,9 +327,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, return result; } -int prism2_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) +int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { + struct net_device *dev = request->wdev->netdev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_dot11req_scan msg1; -- cgit v1.2.3 From 07732be2efa7d4ade66d224ea84d2c30740d0b77 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 19 Aug 2012 19:36:37 +0300 Subject: staging: ozwpan: fix memcmp() test in oz_set_active_pd() "addr" is a pointer so it's either 4 or 8 bytes, but actually we want to compare 6 bytes (ETH_ALEN). As network stack already provides helper function is_zero_ether_addr() we use that instead of memcmp Signed-off-by: Tomas Winkler Acked-by: Dan Carpenter Acked-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index d98321945802..758ce0a8d82e 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "ozconfig.h" @@ -213,7 +214,7 @@ static int oz_set_active_pd(u8 *addr) if (old_pd) oz_pd_put(old_pd); } else { - if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) { + if (is_zero_ether_addr(addr)) { spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; g_cdev.active_pd = 0; -- cgit v1.2.3 From aa209eef3ce8419ff2926c2fa944dfbfb5afbacb Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 29 Aug 2012 23:08:21 +0100 Subject: staging: vt6656: [BUG] - Failed connection, incorrect endian. Hi, This patch fixes a bug with driver failing to negotiate a connection. The bug was traced to commit 203e4615ee9d9fa8d3506b9d0ef30095e4d5bc90 staging: vt6656: removed custom definitions of Ethernet packet types In that patch, definitions in include/linux/if_ether.h replaced ones in tether.h which had both big and little endian definitions. include/linux/if_ether.h only refers to big endian values, cpu_to_be16 should be used for the correct endian architectures. Signed-off-by: Malcolm Priestley Cc: stable # 2.6.37+ Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 2 +- drivers/staging/vt6656/rxtx.c | 38 +++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index e4bdf2a2b582..3aa895ec6507 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); - if ((*pwType == cpu_to_le16(ETH_P_IPX)) || + if ((*pwType == cpu_to_be16(ETH_P_IPX)) || (*pwType == cpu_to_le16(0xF380))) { cbHeaderSize -= 8; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index bb464527fc1b..b6e04e7b629b 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb( // 802.1H if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { - if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || + if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), abySNAP_Bridgetunnel, 6); @@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) Packet_Type = skb->data[ETH_HLEN+1]; Descriptor_type = skb->data[ETH_HLEN+1+1+2]; Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - /* 802.1x OR eapol-key challenge frame transfer */ - if (((Protocol_Version == 1) || (Protocol_Version == 2)) && - (Packet_Type == 3)) { + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key @@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } } - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - if (pDevice->byBBType != BB_TYPE_11A) { - pDevice->wCurrentRate = RATE_1M; - pDevice->byACKRate = RATE_1M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } else { - pDevice->wCurrentRate = RATE_6M; - pDevice->byACKRate = RATE_6M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } - } + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); - if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { + if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { -- cgit v1.2.3 From 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 Mon Sep 17 00:00:00 2001 From: "Dae S. Kim" Date: Fri, 31 Aug 2012 02:00:51 +0200 Subject: Staging: Android alarm: IOCTL command encoding fix Fixed a bug. Data was being written to user space using an IOCTL command encoded with _IOC_WRITE access mode. Signed-off-by: Dae S. Kim Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/android_alarm.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index d0cafd637199..f2ffd963f1c3 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,10 +51,12 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) +#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) + /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) -- cgit v1.2.3 From 29d214576f936db627ff62afb9ef438eea18bcd2 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Wed, 22 Aug 2012 11:53:18 -0500 Subject: xhci: Recognize USB 3.0 devices as superspeed at powerup On Intel Panther Point chipset USB 3.0 devices show up as high-speed devices on powerup, but after an s3 cycle they are correctly recognized as SuperSpeed. At powerup switch the port to xHCI so that USB 3.0 devices are correctly recognized. BugLink: http://bugs.launchpad.net/bugs/1000424 This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Manoj Iyer Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index c5e9e4a76f14..486e8122f0d8 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -870,9 +870,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) /* Disable any BIOS SMIs and clear all SMI events*/ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +hc_init: if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); -hc_init: + op_reg_base = base + XHCI_HC_LENGTH(readl(base)); /* Wait for the host controller to be ready before writing any -- cgit v1.2.3 From a96874a2a92feaef607ddd3137277a788cb927a6 Mon Sep 17 00:00:00 2001 From: Keng-Yu Lin Date: Fri, 10 Aug 2012 01:39:23 +0800 Subject: Intel xhci: Only switch the switchable ports With a previous patch to enable the EHCI/XHCI port switching, it switches all the available ports. The assumption is not correct because the BIOS may expect some ports not switchable by the OS. There are two more registers that contains the information of the switchable and non-switchable ports. This patch adds the checking code for the two register so that only the switchable ports are altered. This patch should be backported to kernels as old as 3.0, that contain commit ID 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Keng-Yu Lin Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 486e8122f0d8..20b9f45f931c 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -75,7 +75,9 @@ #define NB_PIF0_PWRDOWN_1 0x01100013 #define USB_INTEL_XUSB2PR 0xD0 +#define USB_INTEL_USB2PRM 0xD4 #define USB_INTEL_USB3_PSSEN 0xD8 +#define USB_INTEL_USB3PRM 0xDC static struct amd_chipset_info { struct pci_dev *nb_dev; @@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) return; } - ports_available = 0xffffffff; + /* Read USB3PRM, the USB 3.0 Port Routing Mask Register + * Indicate the ports that can be changed from OS. + */ + pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", + ports_available); + /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for all - * available ports. + * Register, to turn on SuperSpeed terminations for the + * switchable ports. */ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, cpu_to_le32(ports_available)); @@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " "under xHCI: 0x%x\n", ports_available); - ports_available = 0xffffffff; + /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register + * Indicate the USB 2.0 ports to be controlled by the xHCI host. + */ + + pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", + ports_available); + /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to * switch the USB 2.0 power and data lines over to the xHCI * host. -- cgit v1.2.3 From b5031ed1be0aa419250557123633453753181643 Mon Sep 17 00:00:00 2001 From: Ronny Hegewald Date: Fri, 31 Aug 2012 09:57:52 +0000 Subject: xen: Use correct masking in xen_swiotlb_alloc_coherent. When running 32-bit pvops-dom0 and a driver tries to allocate a coherent DMA-memory the xen swiotlb-implementation returned memory beyond 4GB. The underlaying reason is that if the supplied driver passes in a DMA_BIT_MASK(64) ( hwdev->coherent_dma_mask is set to 0xffffffffffffffff) our dma_mask will be u64 set to 0xffffffffffffffff even if we set it to DMA_BIT_MASK(32) previously. Meaning we do not reset the upper bits. By using the dma_alloc_coherent_mask function - it does the proper casting and we get 0xfffffffff. This caused not working sound on a system with 4 GB and a 64-bit compatible sound-card with sets the DMA-mask to 64bit. On bare-metal and the forward-ported xen-dom0 patches from OpenSuse a coherent DMA-memory is always allocated inside the 32-bit address-range by calling dma_alloc_coherent_mask. This patch adds the same functionality to xen swiotlb and is a rebase of the original patch from Ronny Hegewald which never got upstream b/c the underlaying reason was not understood until now. The original email with the original patch is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-02/msg00038.html the original thread from where the discussion started is in: http://old-list-archives.xen.org/archives/html/xen-devel/2010-01/msg00928.html Signed-off-by: Ronny Hegewald Signed-off-by: Stefano Panella Acked-By: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk CC: stable@vger.kernel.org --- drivers/xen/swiotlb-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b4..4d519488d304 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, return ret; if (hwdev && hwdev->coherent_dma_mask) - dma_mask = hwdev->coherent_dma_mask; + dma_mask = dma_alloc_coherent_mask(hwdev, flags); phys = virt_to_phys(ret); dev_addr = xen_phys_to_bus(phys); -- cgit v1.2.3 From da25186fc605af8ad636073621fa326fbc23a130 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Wed, 22 Aug 2012 20:26:31 -0700 Subject: mwifiex: fix skb length issue when send a command to firmware When we send a command to firmware, we assumed that cmd_size will be always less than or equal to the structure size of host_cmd_ds_command. However, this is no longer true after we added AP support. There are some AP commands that Custom IE TLVs are included in command buffer, hence the cmd_size gets enlarged by the TLV data. We need to increase the skb length for the extra data. Signed-off-by: Stone Piao Signed-off-by: Avinash Patil Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cmdevt.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8b..565527aee0ea 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_code = le16_to_cpu(host_cmd->command); cmd_size = le16_to_cpu(host_cmd->size); - skb_trim(cmd_node->cmd_skb, cmd_size); + /* Adjust skb length */ + if (cmd_node->cmd_skb->len > cmd_size) + /* + * cmd_size is less than sizeof(struct host_cmd_ds_command). + * Trim off the unused portion. + */ + skb_trim(cmd_node->cmd_skb, cmd_size); + else if (cmd_node->cmd_skb->len < cmd_size) + /* + * cmd_size is larger than sizeof(struct host_cmd_ds_command) + * because we have appended custom IE TLV. Increase skb length + * accordingly. + */ + skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); do_gettimeofday(&tstamp); dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," -- cgit v1.2.3 From d0f21fe6585dda550b279ceccd2609111d7f1baa Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 27 Aug 2012 00:26:37 +0200 Subject: rt2x00: fix voltage setting for RT3572/RT3592 According to the vendor driver v2.6.0.1, during the rf register init the SRAM voltage should be increased to 1.35V and after 1ms decreased back to 1.2V. This patch adds the field setting of LDO_CFG0_LDO_CORE_VLEVEL accordingly. Cc: Gertjan van Wingerde Signed-off-by: Marc Kleine-Budde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e4..b93516d832fb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, LDO_CFG0, reg); msleep(1); rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); rt2800_register_write(rt2x00dev, LDO_CFG0, reg); } -- cgit v1.2.3 From 280b9a9de19b0819dcf1ab38c88e37bb82dbea0c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:03 +0200 Subject: ath9k_hw: do not enable the MIB interrupt in the interrupt mask register The interrupt is no longer handling it. While it shouldn't fire (wraparound is highly unlikely), the consequences would be fatal (interrupt storm). Disable the interrupt to prevent that from happening. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60b6a9daff7e..d95474ecb6c9 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -978,9 +978,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, else imr_reg |= AR_IMR_TXOK; - if (opmode == NL80211_IFTYPE_AP) - imr_reg |= AR_IMR_MIB; - ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_IMR, imr_reg); -- cgit v1.2.3 From 26228959938b25bd41311a3f133a695b9da60e72 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:04 +0200 Subject: ath9k_hw: clear the AM2PM predistortion mask on AR933x That predistortion type is not supported Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4cc..2173bd75dd21 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) }; int training_power; int i, val; + u32 am2pm_mask = ah->paprd_ratemask; if (IS_CHAN_2GHZ(ah->curchan)) training_power = ar9003_get_training_power_2g(ah); @@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah) } ah->paprd_training_power = training_power; + if (AR_SREV_9330(ah)) + am2pm_mask = 0; + REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, ah->paprd_ratemask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, - ah->paprd_ratemask); + am2pm_mask); REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ah->paprd_ratemask_ht40); -- cgit v1.2.3 From 381c726c09bb43aea8088ede5ce24eaa158289dc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:05 +0200 Subject: ath9k_hw: calibrate PA input for PA predistortion Re-train if the calibrated PA linearization curve is out of bounds (affects AR933x and AR9485). Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 99 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/ar9003_phy.h | 4 ++ drivers/net/wireless/ath/ath9k/link.c | 9 ++- 3 files changed, 111 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2173bd75dd21..0ed3846f9cbb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -786,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) } EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, + struct ath9k_hw_cal_data *caldata, + int chain) +{ + u32 *pa_in = caldata->pa_table[chain]; + int capdiv_offset, quick_drop_offset; + int capdiv2g, quick_drop; + int count = 0; + int i; + + if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) + return false; + + capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); + + quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); + + if (quick_drop) + quick_drop -= 0x40; + + for (i = 0; i < NUM_BIN + 1; i++) { + if (pa_in[i] == 1400) + count++; + } + + if (AR_SREV_9485(ah)) { + if (pa_in[23] < 800) { + capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); + capdiv2g += capdiv_offset; + if (capdiv2g > 7) { + capdiv2g = 7; + if (pa_in[23] < 600) { + quick_drop++; + if (quick_drop > 0) + quick_drop = 0; + } + } + } else if (pa_in[23] == 1400) { + quick_drop_offset = min_t(int, count / 3, 2); + quick_drop += quick_drop_offset; + capdiv2g += quick_drop_offset / 2; + + if (capdiv2g > 7) + capdiv2g = 7; + + if (quick_drop > 0) { + quick_drop = 0; + capdiv2g -= quick_drop_offset; + if (capdiv2g < 0) + capdiv2g = 0; + } + } else { + return false; + } + } else if (AR_SREV_9330(ah)) { + if (pa_in[23] < 1000) { + capdiv_offset = (1000 - pa_in[23]) / 100; + capdiv2g += capdiv_offset; + if (capdiv_offset > 3) { + capdiv_offset = 1; + quick_drop--; + } + + capdiv2g += capdiv_offset; + if (capdiv2g > 6) + capdiv2g = 6; + if (quick_drop < -4) + quick_drop = -4; + } else if (pa_in[23] == 1400) { + if (count > 3) { + quick_drop++; + capdiv2g -= count / 4; + if (quick_drop > -2) + quick_drop = -2; + } else { + capdiv2g--; + } + + if (capdiv2g < 0) + capdiv2g = 0; + } else { + return false; + } + } + + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, + quick_drop); + + return true; +} + int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_hw_cal_data *caldata, int chain) { @@ -821,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah, if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) status = -2; + if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) + status = -EINPROGRESS; + REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7bfbaf065a43..84d3d4956861 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,6 +625,10 @@ #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) +#define AR_PHY_65NM_CH0_TXRF3 0x16048 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1 + #define AR_PHY_65NM_CH0_SYNTH4 0x1608c #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002) #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d4549e9aac5c..1c241921f95e 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -254,6 +254,7 @@ void ath_paprd_calibrate(struct work_struct *work) int chain_ok = 0; int chain; int len = 1800; + int ret; if (!caldata) return; @@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_struct *work) break; } - if (ar9003_paprd_create_curve(ah, caldata, chain)) { + ret = ar9003_paprd_create_curve(ah, caldata, chain); + if (ret == -EINPROGRESS) { + ath_dbg(common, CALIBRATE, + "PAPRD curve on chain %d needs to be re-trained\n", + chain); + break; + } else if (ret) { ath_dbg(common, CALIBRATE, "PAPRD create curve failed on chain %d\n", chain); -- cgit v1.2.3 From 1630d25fd00f195f0923d4b895e0529fdbba83c3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:06 +0200 Subject: ath9k_hw: disable PA linearization for AR9462 Support for it is incomplete Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d95474ecb6c9..64a00d2f18f2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2499,7 +2499,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); if (!ah->config.paprd_disable && - ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && + !AR_SREV_9462(ah)) pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); -- cgit v1.2.3 From 51dea9be7e01d7e825ed1882246693f09c21374c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:07 +0200 Subject: ath9k: fix PA linearization calibration related crash Before PAPRD training can run, the card needs to have sent a packet for thermal calibration. Sending a dummy packet with the PAPRD training flag set causes a crash under some circumstance. Fix the code by replacing the dummy tx with a delay that waits for a real packet tx to have occurred. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/link.c | 9 +-------- drivers/net/wireless/ath/ath9k/xmit.c | 3 +++ 4 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 64a00d2f18f2..e4b9f35343e5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1775,6 +1775,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); + } else if (caldata) { + caldata->paprd_packet_sent = false; } ah->noise = ath9k_hw_getchan_noise(ah, chan); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce7332c64efb..6599a75f01fe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -405,6 +405,7 @@ struct ath9k_hw_cal_data { int8_t iCoff; int8_t qCoff; bool rtt_done; + bool paprd_packet_sent; bool paprd_done; bool nfcal_pending; bool nfcal_interference; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 1c241921f95e..825a29cc9313 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -256,7 +256,7 @@ void ath_paprd_calibrate(struct work_struct *work) int len = 1800; int ret; - if (!caldata) + if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) return; ath9k_ps_wakeup(sc); @@ -283,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work) continue; chain_ok = 0; - - ath_dbg(common, CALIBRATE, - "Sending PAPRD frame for thermal measurement on chain %d\n", - chain); - if (!ath_paprd_send_frame(sc, skb, chain)) - goto fail_paprd; - ar9003_paprd_setup_gain_table(ah, chain); ath_dbg(common, CALIBRATE, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb1..0d4155aec48d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); + if (sc->sc_ah->caldata) + sc->sc_ah->caldata->paprd_packet_sent = true; + if (!(tx_flags & ATH_TX_ERROR)) /* Frame was ACKed */ tx_info->flags |= IEEE80211_TX_STAT_ACK; -- cgit v1.2.3 From b3ccc1a56280119fe1fbf9929a76b4034358bfef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Aug 2012 17:00:08 +0200 Subject: ath9k_hw: enable PA linearization This feature had been disabled in ath9k because the code to support it was incomplete, but now the code is in sync with the internal QCA codebase, so it's time to enable it. On many newer devices, the calibration is assumed to be done with PA linearization enabled. Tests with a particular AR933x device showed that the signal emitted at full power was highly distorted and unreliable with PA linearization disabled. With this patch, the signal becomes clear and stability is improved. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e4b9f35343e5..48af40151d23 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - /* PAPRD needs some more work to be enabled */ - ah->config.paprd_disable = 1; - ah->config.rx_intr_mitigation = true; ah->config.pcieSerDesWrite = true; -- cgit v1.2.3 From 5d9b6f263995d7f43202d76cf2e23d43f9240a90 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 28 Aug 2012 12:14:48 +0530 Subject: ath9k: Fix a crash in 2 WIRE btcoex chipsets Generic timers for BTCOEX functionality is applicable only for 3 WIRE BTCOEX (and MCI) chipsets. Hence btcoex->no_stomp_timer is allocated only 3 WIRE btcoex chipsets and in all the other cases its NULL. Make sure we stop the generic timer only if 'btcoex->hw_timer_enabled' is true(only if its up and running) Fixes the following crash [68757.020454] BUG: unable to handle kernel NULL pointer dereference at 0000000c [68757.020916] IP: [] ath9k_hw_gen_timer_stop+0x13/0x80 [ath9k_hw] [68757.021251] *pde = 00000000 [68757.024384] EIP: 0060:[] EFLAGS: 00010082 CPU: 0 [68757.024384] EIP is at ath9k_hw_gen_timer_stop+0x13/0x80 [ath9k_hw] [68757.024384] EAX: d32d0000 EBX: d32d0000 ECX: 00000000 EDX: 00000000 [68757.024384] ESI: e67c24c0 EDI: 00000296 EBP: e137be2c ESP: e137be20 [68757.024384] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [68757.024384] CR0: 8005003b CR2: 0000000c CR3: 00b99000 CR4: 000407d0 [68757.024384] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [68757.024384] DR6: ffff0ff0 DR7: 00000400 [68757.024384] Process kworker/u:2 (pid: 8917, ti=e137a000 task=ea7a6860 task.ti=e137a000) [68757.024384] Stack: [68757.024384] c06c4676 d32d0000 e67c24c0 e137be38 f81c9590 e67c1ca0 e137be40 f81c95d9 [68757.024384] e137be64 f81cd1c5 00000246 00000002 d32d0000 e67c05e0 e67c1ca0 e67c05e0 [68757.024384] 00000000 e137beac f81cdfa0 e137be84 00000246 00000246 e67c1ca0 e67c1ca0 [68757.024384] Call Trace: [68757.024384] [] ? _raw_spin_lock_irqsave+0x86/0xa0 [68757.024384] [] ath9k_gen_timer_stop+0x10/0x40 [ath9k] [68757.024384] [] ath9k_btcoex_stop_gen_timer+0x19/0x20 [ath9k] [68757.024384] [] ath9k_ps_restore+0x85/0x110 [ath9k] [68757.024384] [] ath9k_config+0x220/0x520 [ath9k] [68757.024384] [] ? ath9k_flush+0x15d/0x1b0 [ath9k] [68757.024384] [] ieee80211_hw_config+0x135/0x2c0 [mac80211] [68757.024384] [] ieee80211_dynamic_ps_enable_work+0x198/0x5f0 [mac80211] Cc: Rajkumar Manoharan Cc: Bala Shanmugam Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef4..9f83f71742a5 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; - ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); } u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) -- cgit v1.2.3 From 01e3331b30b48fe96d016435707af050700c8421 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 30 Aug 2012 10:05:34 +0200 Subject: brcmfmac: fix use of dev_kfree_skb() in irq context The USB part of the brcmfmac did a dev_kfree_skb() that resulted in a warning in net/core/skbuff.c: Jul 11 04:53:33 lb-bun-10 kernel: [53282.667745] WARNING: at net/core/skbuff.c:490 skb_release_head_state+0xcc/0xe0() The brcmutil modules provides brcmu_pkt_buf_free_skb() which takes the context into account. This patch makes use of this function instead of dev_kfree_skb(). Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a299d42da8e7..f72dfb70ba0b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb) else devinfo->bus_pub.bus->dstats.tx_errors++; - dev_kfree_skb(req->skb); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) devinfo->bus_pub.bus->dstats.rx_packets++; } else { devinfo->bus_pub.bus->dstats.rx_errors++; - dev_kfree_skb(skb); + brcmu_pkt_buf_free_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); return; } @@ -556,7 +556,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) brcmf_usb_rx_refill(devinfo, req); } } else { - dev_kfree_skb(skb); + brcmu_pkt_buf_free_skb(skb); } return; @@ -588,7 +588,7 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, if (ret == 0) { brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); } else { - dev_kfree_skb(req->skb); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); } -- cgit v1.2.3 From 474ab7cea4001f07ec8599a680fd19d8761fa7d8 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:35 +0200 Subject: brcmfmac: dont use ZERO flag for usb IN URB_ZERO_PACKET should only be set or bulk OUT and this condition is checked with a WARN_ON in usb_submit_urb(). This patch fixes brcmfmac to get rid of this warning filling the logs. Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index f72dfb70ba0b..8ea2db7326b8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -581,7 +581,6 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, req); - req->urb->transfer_flags |= URB_ZERO_PACKET; req->devinfo = devinfo; ret = usb_submit_urb(req->urb, GFP_ATOMIC); -- cgit v1.2.3 From 2e875acd399fcc6e301063e5ead371ad089d5920 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:36 +0200 Subject: brcmfmac: fix race condition for rx and tx data. On both rx and tx there is was a race condition on the queueing of usb requests. When for example frame gets submitted it is possible that complete function gets called even before usb_submit_urb() returns. As a result it is possible that usb requests get losts, which was noticed on OMAP4 pandaboard platform. This patch fixes the race condition. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 8ea2db7326b8..58f89fa9c9f8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -550,6 +550,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { brcmf_dbg(ERROR, "rx protocol error\n"); brcmu_pkt_buf_free_skb(skb); + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); devinfo->bus_pub.bus->dstats.rx_errors++; } else { brcmf_rx_packet(devinfo->dev, ifidx, skb); @@ -557,6 +558,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) } } else { brcmu_pkt_buf_free_skb(skb); + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); } return; @@ -582,11 +584,11 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, req); req->devinfo = devinfo; + brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (ret == 0) { - brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); - } else { + if (ret) { + brcmf_usb_del_fromq(devinfo, req); brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); @@ -682,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); if (!req) { + brcmu_pkt_buf_free_skb(skb); brcmf_dbg(ERROR, "no req to send\n"); return -ENOMEM; } - if (!req->urb) { - brcmf_dbg(ERROR, "no urb for req %p\n", req); - return -ENOBUFS; - } req->skb = skb; req->devinfo = devinfo; usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, skb->data, skb->len, brcmf_usb_tx_complete, req); req->urb->transfer_flags |= URB_ZERO_PACKET; + brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (!ret) { - brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); - } else { + if (ret) { + brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); + brcmf_usb_del_fromq(devinfo, req); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); } -- cgit v1.2.3 From 7f6c562dfa52425a28933982df7d21edba7e3d71 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 30 Aug 2012 10:05:37 +0200 Subject: brcmfmac: fix get rssi by clearing getvar struct. The function brcmf_cfg80211_get_station requests the RSSI from the device. The complete structure used needs to be cleared before sending the request to firmware. Otherwise the request fails filling the logs with "Could not get rssi (-2)" messages. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 28c5fbb4af26..c36e92312443 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1876,16 +1876,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, } if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { - scb_val.val = cpu_to_le32(0); + memset(&scb_val, 0, sizeof(scb_val)); err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, sizeof(struct brcmf_scb_val_le)); - if (err) + if (err) { WL_ERR("Could not get rssi (%d)\n", err); - - rssi = le32_to_cpu(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_CONN("RSSI %d dBm\n", rssi); + } else { + rssi = le32_to_cpu(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_CONN("RSSI %d dBm\n", rssi); + } } done: -- cgit v1.2.3 From 177ef8360fabdc49ff08d2598c06e7f7a36b53e3 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:09 +0200 Subject: rt2x00: Identify ASUS USB-N53 device. This is an RT3572 based device. Signed-off-by: Maximilian Engelhardt Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e25..6681bfc03201 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1157,6 +1157,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1222,7 +1224,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, -- cgit v1.2.3 From 6ced58a5dbb94dbfbea1b33ca3c56d1e929cd548 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:10 +0200 Subject: rt2x00: Fix word size of rt2500usb MAC_CSR19 register. The register is 16 bits wide, not 32. Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9e..b3a1d732f3d1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7eed..192531db0b65 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,14 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_BIT0 FIELD16(0x0001) +#define MAC_CSR19_BIT1 FIELD16(0x0002) +#define MAC_CSR19_BIT2 FIELD16(0x0004) +#define MAC_CSR19_BIT3 FIELD16(0x0008) +#define MAC_CSR19_BIT4 FIELD16(0x0010) +#define MAC_CSR19_BIT5 FIELD16(0x0020) +#define MAC_CSR19_BIT6 FIELD16(0x0040) +#define MAC_CSR19_BIT7 FIELD16(0x0080) /* * MAC_CSR20: LED control register. -- cgit v1.2.3 From a396e10019eaf3809b0219c966865aaafec12630 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 31 Aug 2012 19:22:11 +0200 Subject: rt2x00: Fix rfkill polling prior to interface start. We need to program the rfkill switch GPIO pin direction to input at device initialization time, not only when the interface is brought up. Doing this only when the interface is brought up could lead to rfkill detecting the switch is turned on erroneously and inability to create the interface and bringing it up. Reported-and-tested-by: Andreas Messer Signed-off-by: Gertjan van Wingerde Cc: Acked-by: Ivo Van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2400pci.h | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 9 +++++++++ drivers/net/wireless/rt2x00/rt73usb.h | 3 +++ 11 files changed, 69 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a252..64328af496f5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_BIT8, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc439..7564ae992b73 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b5..3de0406735f6 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b3a1d732f3d1..89fee311d8fd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 192531db0b65..196bd5103e4f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -197,6 +197,7 @@ #define MAC_CSR19_BIT5 FIELD16(0x0020) #define MAC_CSR19_BIT6 FIELD16(0x0040) #define MAC_CSR19_BIT7 FIELD16(0x0080) +#define MAC_CSR19_BIT8 FIELD16(0x0100) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a3564..4765bbd654cd 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -995,6 +996,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6681bfc03201..52a32b5baea0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -736,6 +736,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -748,6 +749,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9a..b8ec96163922 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0e..8f3da5a56766 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859d..248436c13ce0 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d3..df1cc116b83b 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) +#define MAC_CSR13_BIT14 FIELD32(0x00004000) +#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. -- cgit v1.2.3 From efd5d6b03bd9c9e0df646c56fb5f4f3e25e5c1ac Mon Sep 17 00:00:00 2001 From: Sergei Poselenov Date: Sun, 2 Sep 2012 13:14:32 +0400 Subject: rt2800usb: Added rx packet length validity check On our system (ARM Cortex-M3 SOC running linux-2.6.33) frequent crashes were observed in the rt2800usb module because of the invalid length of the received packet (3392, 46920...). This patch adds the sanity check on the packet legth. Also, changed WARNING to ERROR in rt2x00lib_rxdone() so that the bad packet condition would be noticed. The fix was tested on the latest compat-wireless-3.5.1-1-snpc. Cc: stable@vger.kernel.org Signed-off-by: Sergei Poselenov Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 52a32b5baea0..6b4226b71618 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * FIXME: we need to check for rx_pkt_len validity + * Check for rx_pkt_len validity. Return if invalid, leaving + * rxdesc->size zeroed out by the upper level. */ + if (unlikely(rx_pkt_len == 0 || + rx_pkt_len > entry->queue->data_size)) { + ERROR(entry->queue->rt2x00dev, + "Bad frame size %d, forcing to 0\n", rx_pkt_len); + return; + } + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a5..3f07e36f462b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; -- cgit v1.2.3 From f10723841e624c0726c70356b31d91befed01dd6 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 3 Sep 2012 15:49:09 -0400 Subject: libertas sdio: fix suspend when interface is down When the interface is down, the hardware is powered off. However, the suspend handler currently tries to send host sleep commands (when wakeup params are set) in this configuration, causing a system hang when going into suspend (the commands will never complete). Avoid this by detecting this situation and simply returning from the suspend handler without doing anything special. Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_sdio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e970897f6ab5..4cb234349fbf 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev) mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); + /* If we're powered off anyway, just let the mmc layer remove the + * card. */ + if (!lbs_iface_active(card->priv)) + return -ENOSYS; + dev_info(dev, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), flags); -- cgit v1.2.3 From 6d7d9798ad5c97ee4e911dd070dc12dc5ae55bd0 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 29 Aug 2012 16:58:45 -0500 Subject: staging: zcache: fix cleancache race condition with shrinker This patch fixes a race condition that results in memory corruption when using cleancache. The race exists between the zcache shrinker handler, shrink_zcache_memory() and cleancache_get_page(). In most cases, the shrinker will both evict a zbpg from its buddy list and flush it from tmem before a cleancache_get_page() occurs on that page. A subsequent cleancache_get_page() will fail in the tmem layer. In the rare case that two occur together and the cleancache_get_page() path gets through the tmem layer before the shrinker path can flush tmem, zbud_decompress() does a check to see if the zbpg is a "zombie", i.e. not on a buddy list, which means the shrinker is in the process of reclaiming it. If the zbpg is a zombie, zbud_decompress() returns -EINVAL. However, this return code is being ignored by the caller, zcache_pampd_get_data_and_free(), which results in the caller of cleancache_get_page() thinking that the page has been properly retrieved when it has not. This patch modifies zcache_pampd_get_data_and_free() to convey the failure up the stack so that the caller of cleancache_get_page() knows the page retrieval failed. This needs to be applied to stable trees as well. zcache-main.c was named zcache.c before v3.1, so I'm not sure how you want to handle trees earlier than that. Signed-off-by: Seth Jennings Cc: stable Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Minchan Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index c214977b4ab4..52b43b7b83d7 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1251,13 +1251,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { - int ret = 0; - BUG_ON(!is_ephemeral(pool)); - zbud_decompress((struct page *)(data), pampd); + if (zbud_decompress((struct page *)(data), pampd) < 0) + return -EINVAL; zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); - return ret; + return 0; } /* -- cgit v1.2.3 From 052c7f9ffb0e95843e75448d02664459253f9ff8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 13 Aug 2012 19:57:03 +0300 Subject: xhci: Fix a logical vs bitwise AND bug The intent was to test whether the flag was set. This patch should be backported to stable kernels as old as 3.0, since it fixes a bug in commit e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.", which was marked for stable. Signed-off-by: Dan Carpenter Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c59d5b5b6c7d..617b0a77b2b4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -659,7 +659,7 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - if (xhci->quirks && XHCI_SPURIOUS_REBOOT) + if (xhci->quirks & XHCI_SPURIOUS_REBOOT) usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); spin_lock_irq(&xhci->lock); -- cgit v1.2.3 From e955a1cd086de4d165ae0f4c7be7289d84b63bdc Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 14 Aug 2012 16:44:49 -0400 Subject: xhci: Make handover code more robust My test platform (Intel DX79SI) boots reliably under BIOS, but frequently crashes when booting via UEFI. I finally tracked this down to the xhci handoff code. It seems that reads from the device occasionally just return 0xff, resulting in xhci_find_next_cap_offset generating a value that's larger than the resource region. We then oops when attempting to read the value. Sanity checking that value lets us avoid the crash. I've no idea what's causing the underlying problem, and xhci still doesn't actually *work* even with this, but the machine at least boots which will probably make further debugging easier. This should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Matthew Garrett Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 20b9f45f931c..966d1484ee79 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -841,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) void __iomem *op_reg_base; u32 val; int timeout; + int len = pci_resource_len(pdev, 0); if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + base = ioremap_nocache(pci_resource_start(pdev, 0), len); if (base == NULL) return; @@ -856,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) */ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); do { + if ((ext_cap_offset + sizeof(val)) > len) { + /* We're reading garbage from the controller */ + dev_warn(&pdev->dev, + "xHCI controller failing to respond"); + return; + } + if (!ext_cap_offset) /* We've reached the end of the extended capabilities */ goto hc_init; + val = readl(base + ext_cap_offset); if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) break; -- cgit v1.2.3 From 71c731a296f1b08a3724bd1b514b64f1bda87a23 Mon Sep 17 00:00:00 2001 From: "Alexis R. Cortes" Date: Fri, 3 Aug 2012 14:00:27 -0500 Subject: usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware This patch is intended to work around a known issue on the SN65LVPE502CP USB3.0 re-driver that can delay the negotiation between a device and the host past the usual handshake timeout. If that happens on the first insertion, the host controller port will enter in Compliance Mode and NO port status event will be generated (as per xHCI Spec) making impossible to detect this event by software. The port will remain in compliance mode until a warm reset is applied to it. As a result of this, the port will seem "dead" to the user and no device connections or disconnections will be detected. For solving this, the patch creates a timer which polls every 2 seconds the link state of each host controller's port (this by reading the PORTSC register) and recovers the port by issuing a Warm reset every time Compliance mode is detected. If a xHC USB3.0 port has previously entered to U0, the compliance mode issue will NOT occur only until system resumes from sleep/hibernate, therefore, the compliance mode timer is stopped when all xHC USB 3.0 ports have entered U0. The timer is initialized again after each system resume. Since the issue is being caused by a piece of hardware, the timer will be enabled ONLY on those systems that have the SN65LVPE502CP installed (this patch uses DMI strings for detecting those systems) therefore making this patch to act as a quirk (XHCI_COMP_MODE_QUIRK has been added to the xhci stack). This patch applies for these systems: Vendor: Hewlett-Packard. System Models: Z420, Z620 and Z820. This patch should be backported to kernels as old as 3.2, as that was the first kernel to support warm reset. The kernels will need to contain both commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When hot reset for USB3 fails, try warm reset" and commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 "usb: Add support for root hub port status CAS". The first patch add warm reset support, and the second patch modifies the USB core to issue a warm reset when the port is in compliance mode. Signed-off-by: Alexis R. Cortes Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-hub.c | 42 +++++++++++++++ drivers/usb/host/xhci.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 6 +++ 3 files changed, 169 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 74bfc868b7ad..d5eb357aa5c4 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) * when this bit is set. */ pls |= USB_PORT_STAT_CONNECTION; + } else { + /* + * If CAS bit isn't set but the Port is already at + * Compliance Mode, fake a connection so the USB core + * notices the Compliance state and resets the port. + * This resolves an issue generated by the SN65LVPE502CP + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ + if (pls == USB_SS_PORT_LS_COMP_MOD) + pls |= USB_PORT_STAT_CONNECTION; } + /* update status field */ *status |= pls; } +/* + * Function for Compliance Mode Quirk. + * + * This Function verifies if all xhc USB3 ports have entered U0, if so, + * the compliance mode timer is deleted. A port won't enter + * compliance mode if it has previously entered U0. + */ +void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) +{ + u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); + bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); + + if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) + return; + + if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { + xhci->port_status_u0 |= 1 << wIndex; + if (xhci->port_status_u0 == all_ports_seen_u0) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); + } + } +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { xhci_hub_report_link_state(&status, temp); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. + */ + xhci_del_comp_mod_timer(xhci, temp, wIndex); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 617b0a77b2b4..6ece0ed288d4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "xhci.h" @@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) #endif +static void compliance_mode_recovery(unsigned long arg) +{ + struct xhci_hcd *xhci; + struct usb_hcd *hcd; + u32 temp; + int i; + + xhci = (struct xhci_hcd *)arg; + + for (i = 0; i < xhci->num_usb3_ports; i++) { + temp = xhci_readl(xhci, xhci->usb3_ports[i]); + if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { + /* + * Compliance Mode Detected. Letting USB Core + * handle the Warm Reset + */ + xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", + i + 1); + xhci_dbg(xhci, "Attempting Recovery routine!\n"); + hcd = xhci->shared_hcd; + + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + usb_hcd_poll_rh_status(hcd); + } + } + + if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) + mod_timer(&xhci->comp_mode_recovery_timer, + jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +} + +/* + * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver + * that causes ports behind that hardware to enter compliance mode sometimes. + * The quirk creates a timer that polls every 2 seconds the link state of + * each host controller's port and recovers it by issuing a Warm reset + * if Compliance mode is detected, otherwise the port will become "dead" (no + * device connections or disconnections will be detected anymore). Becasue no + * status event is generated when entering compliance mode (per xhci spec), + * this quirk is needed on systems that have the failing hardware installed. + */ +static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) +{ + xhci->port_status_u0 = 0; + init_timer(&xhci->comp_mode_recovery_timer); + + xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; + xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; + xhci->comp_mode_recovery_timer.expires = jiffies + + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); + + set_timer_slack(&xhci->comp_mode_recovery_timer, + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); + add_timer(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +} + +/* + * This function identifies the systems that have installed the SN65LVPE502CP + * USB3.0 re-driver and that need the Compliance Mode Quirk. + * Systems: + * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 + */ +static bool compliance_mode_recovery_timer_quirk_check(void) +{ + const char *dmi_product_name, *dmi_sys_vendor; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + + if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) + return false; + + if (strstr(dmi_product_name, "Z420") || + strstr(dmi_product_name, "Z620") || + strstr(dmi_product_name, "Z820")) + return true; + + return false; +} + +static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) +{ + return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); +} + + /* * Initialize memory for HCD and xHC (one-time init). * @@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd) retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); + /* Initializing Compliance Mode Recovery Data If Needed */ + if (compliance_mode_recovery_timer_quirk_check()) { + xhci->quirks |= XHCI_COMP_MODE_QUIRK; + compliance_mode_recovery_timer_init(xhci); + } + return retval; } @@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd) del_timer_sync(&xhci->event_ring_timer); #endif + /* Deleting Compliance Mode Recovery Timer */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) + del_timer_sync(&xhci->comp_mode_recovery_timer); + if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); @@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci) } spin_unlock_irq(&xhci->lock); + /* + * Deleting Compliance Mode Recovery Timer because the xHCI Host + * is about to be suspended. + */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); + } + /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); @@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(xhci->shared_hcd); } + + /* + * If system is subject to the Quirk, Compliance Mode Timer needs to + * be re-initialized Always after a system resume. Ports are subject + * to suffer the Compliance Mode issue again. It doesn't matter if + * ports have entered previously to U0 before system's suspension. + */ + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + return retval; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c713256297ac..1a05908c6673 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1495,6 +1495,7 @@ struct xhci_hcd { #define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_INTEL_HOST (1 << 12) #define XHCI_SPURIOUS_REBOOT (1 << 13) +#define XHCI_COMP_MODE_QUIRK (1 << 14) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ @@ -1511,6 +1512,11 @@ struct xhci_hcd { unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; + /* Compliance Mode Recovery Data */ + struct timer_list comp_mode_recovery_timer; + u32 port_status_u0; +/* Compliance Mode Timer Triggered every 2 seconds */ +#define COMP_MODE_RCVRY_MSECS 2000 }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ -- cgit v1.2.3 From 319acdfc064169023cd9ada5085b434fbcdacec2 Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Fri, 10 Aug 2012 09:58:30 +0300 Subject: usb: host: xhci-plat: use ioremap_nocache Use the ioremap_nocache variant of the ioremap API in order to make sure our memory will be marked uncachable. This patch should be backported to kernels as old as 3.4, that contain the commit 3429e91a661e1f383aecc86c6bbcf65afb15c892 "usb: host: xhci: add platform driver support". Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-plat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 689bc18b051d..df90fe51b4aa 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; -- cgit v1.2.3 From 296365781903226a3fb8758901eaeec09d2798e4 Mon Sep 17 00:00:00 2001 From: Moiz Sonasath Date: Wed, 5 Sep 2012 08:34:26 +0300 Subject: usb: host: xhci: fix compilation error for non-PCI based stacks For non PCI-based stacks, this function call usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); made from xhci_shutdown is not applicable. Ideally, we wouldn't have any PCI-specific code on a generic driver such as the xHCI stack, but it looks like we should just stub usb_disable_xhci_ports() out for non-PCI devices. [ balbi@ti.com: slight improvement to commit log ] This patch should be backported to kernels as old as 3.0, since the commit it fixes (e95829f474f0db3a4d940cae1423783edd966027 "xhci: Switch PPT ports to EHCI on shutdown.") was marked for stable. Signed-off-by: Moiz Sonasath Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/pci-quirks.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index ef004a5de20f..7f69a39163ce 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} +static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} #endif /* CONFIG_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ -- cgit v1.2.3 From 9ec1882df244c4ee1baa692676fef5e8b0f5487d Mon Sep 17 00:00:00 2001 From: Xinyu Chen Date: Mon, 27 Aug 2012 09:36:51 +0200 Subject: tty: serial: imx: console write routing is unsafe on SMP The console feature's write routing is unsafe on SMP with the startup/shutdown call. There could be several consumers of the console * the kernel printk * the init process using /dev/kmsg to call printk to show log * shell, which open /dev/console and write with sys_write() The shell goes into the normal uart open/write routing, but the other two go into the console operations. The open routing calls imx serial startup, which will write USR1/2 register without any lock and critical with imx_console_write call. Add a spin_lock for startup/shutdown/console_write routing. This patch is a port from Freescale's Android kernel. Signed-off-by: Xinyu Chen Tested-by: Dirk Behme CC: Sascha Hauer Acked-by: Shawn Guo Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d5c689d6217e..908178fc5a33 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -754,6 +754,7 @@ static int imx_startup(struct uart_port *port) } } + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -807,7 +808,6 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -837,10 +837,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -869,12 +872,14 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1217,6 +1222,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1242,6 +1250,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); + + spin_unlock_irqrestore(&sport->port.lock, flags); } /* -- cgit v1.2.3 From 7be0670f7b9198382938a03ff3db7f47ef6b4780 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Fri, 31 Aug 2012 10:02:47 +0200 Subject: tty: serial: imx: don't reinit clock in imx_setup_ufcr() Remove the clock configuration from imx_setup_ufcr(). This isn't needed here and will cause garbage output if done. To be be sure that we only touch the bits we want (TXTL and RXTL) we have to mask out all other bits of the UFCR register. Add one non-existing bit macro for this, too (bit 6, DCEDTE on i.MX6). Signed-off-by: Dirk Behme CC: Shawn Guo CC: Sascha Hauer CC: Troy Kisky CC: Xinyu Chen Cc: stable Acked-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 908178fc5a33..e309e8b0aaba 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -132,6 +132,7 @@ #define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */ #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ #define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ @@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state) static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) { unsigned int val; - unsigned int ufcr_rfdiv; - - /* set receiver / transmitter trigger level. - * RFDIV is set such way to satisfy requested uartclk value - */ - val = TXTL << 10 | RXTL; - ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2) - / sport->port.uartclk; - - if(!ufcr_rfdiv) - ufcr_rfdiv = 1; - - val |= UFCR_RFDIV_REG(ufcr_rfdiv); + /* set receiver / transmitter trigger level */ + val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE); + val |= TXTL << UFCR_TXTL_SHF | RXTL; writel(val, sport->port.membase + UFCR); - return 0; } -- cgit v1.2.3 From 804d74abe2e3f361ead5c5c6850d5b1ab0203862 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Jul 2012 15:40:07 -0700 Subject: drm: use drm_compat_ioctl for 32-bit apps Most of the DRM drivers appear to be missing the .compat_ioctl file operation entry necessary for 32-bit application compatibility. This patch uses drm_compat_ioctl for all drivers which don't have their own, and which are using drm_ioctl for .unlocked_ioctl. This leaves drivers/gpu/drm/psb/psb_drv.c unchanged; it has a custom .unlocked_ioctl and will presumably need a custom .compat_ioctl as well. Signed-off-by: Keith Packard Signed-off-by: Dave Airlie --- drivers/gpu/drm/ast/ast_drv.c | 3 +++ drivers/gpu/drm/cirrus/cirrus_drv.c | 3 +++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 +++ drivers/gpu/drm/i810/i810_dma.c | 3 +++ drivers/gpu/drm/i810/i810_drv.c | 3 +++ drivers/gpu/drm/mgag200/mgag200_drv.c | 3 +++ drivers/gpu/drm/savage/savage_drv.c | 3 +++ drivers/gpu/drm/sis/sis_drv.c | 3 +++ drivers/gpu/drm/tdfx/tdfx_drv.c | 3 +++ drivers/gpu/drm/udl/udl_drv.c | 3 +++ drivers/gpu/drm/via/via_drv.c | 3 +++ 11 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index d0c4574ef49c..36164806b9d4 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -193,6 +193,9 @@ static const struct file_operations ast_fops = { .mmap = ast_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c6596..b83a2d7ddd1a 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = cirrus_mmap, .poll = drm_poll, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .fasync = drm_fasync, }; static struct drm_driver driver = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index ebacec6f1e48..6345abe9fdee 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -241,6 +241,9 @@ static const struct file_operations exynos_drm_driver_fops = { .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .release = drm_release, }; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 57d892eaaa6e..463ec6871fe9 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = { .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index f9924ad04d09..48cfcca2b350 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ea1024d79974..e5f145d2cb3b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = { .mmap = mgag200_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .read = drm_read, }; diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index d31d4cca9a4c..c5a164337bd5 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f119870147c..867dc03000e6 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 90f6b13acfac..a7f4d6bd1330 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 6e52069894b3..9f84128505bb 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = { .unlocked_ioctl = drm_ioctl, .release = drm_release, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e927b4c052f5..af1b914b17e3 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = { .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif .llseek = noop_llseek, }; -- cgit v1.2.3 From d90c92fee89ccd75ef2646f3bde0b4c0450666c3 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Tue, 4 Sep 2012 14:41:37 +0000 Subject: ibmveth: Fix alignment of rx queue bug This patch fixes a bug found by Nish Aravamudan (https://lkml.org/lkml/2012/5/15/220) where the driver is not following the spec (it is not aligning the rx buffer on a 16-byte boundary) and the hypervisor aborts the registration, making the device unusable. The fix follows BenH's recommendation (https://lkml.org/lkml/2012/7/20/461) to replace the kmalloc+map for a single call to dma_alloc_coherent() because that function always aligns to a 16-byte boundary. The stable trees will run into this bug whenever the rx buffer kmalloc call returns something not aligned on a 16-byte boundary. Cc: Signed-off-by: Santiago Leon Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmveth.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc3..b68d28a130e6 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } if (adapter->rx_queue.queue_addr != NULL) { - if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { - dma_unmap_single(dev, - adapter->rx_queue.queue_dma, - adapter->rx_queue.queue_len, - DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = DMA_ERROR_CODE; - } - kfree(adapter->rx_queue.queue_addr); + dma_free_coherent(dev, adapter->rx_queue.queue_len, + adapter->rx_queue.queue_addr, + adapter->rx_queue.queue_dma); adapter->rx_queue.queue_addr = NULL; } @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } + dev = &adapter->vdev->dev; + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, - GFP_KERNEL); + adapter->rx_queue.queue_addr = + dma_alloc_coherent(dev, adapter->rx_queue.queue_len, + &adapter->rx_queue.queue_dma, GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } - dev = &adapter->vdev->dev; - adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = dma_map_single(dev, - adapter->rx_queue.queue_addr, - adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || - (dma_mapping_error(dev, adapter->filter_list_dma)) || - (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { + (dma_mapping_error(dev, adapter->filter_list_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; -- cgit v1.2.3 From dafc4f7be1a556ca3868d343c00127728b397068 Mon Sep 17 00:00:00 2001 From: Éric Piel Date: Tue, 4 Sep 2012 17:25:06 +0200 Subject: USB: ftdi-sio: add support for more Physik Instrumente devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b69cc672052540 added support for the E-861. After acquiring a C-867, I realised that every Physik Instrumente's device has a different PID. They are listed in the Windows device driver's .inf file. So here are all PIDs for the current (and probably future) USB devices from Physik Instrumente. Compiled, but only actually tested on the E-861 and C-867. Signed-off-by: Éric Piel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 17 +++++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 21 ++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5620db6469e5..1197d4780b9a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -810,7 +810,24 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(FTDI_VID, PI_C865_PID) }, + { USB_DEVICE(FTDI_VID, PI_C857_PID) }, + { USB_DEVICE(PI_VID, PI_C866_PID) }, + { USB_DEVICE(PI_VID, PI_C663_PID) }, + { USB_DEVICE(PI_VID, PI_C725_PID) }, + { USB_DEVICE(PI_VID, PI_E517_PID) }, + { USB_DEVICE(PI_VID, PI_C863_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(PI_VID, PI_C867_PID) }, + { USB_DEVICE(PI_VID, PI_E609_PID) }, + { USB_DEVICE(PI_VID, PI_E709_PID) }, + { USB_DEVICE(PI_VID, PI_100F_PID) }, + { USB_DEVICE(PI_VID, PI_1011_PID) }, + { USB_DEVICE(PI_VID, PI_1012_PID) }, + { USB_DEVICE(PI_VID, PI_1013_PID) }, + { USB_DEVICE(PI_VID, PI_1014_PID) }, + { USB_DEVICE(PI_VID, PI_1015_PID) }, + { USB_DEVICE(PI_VID, PI_1016_PID) }, { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5dd96ca6c380..080d1580db99 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -791,8 +791,27 @@ * Physik Instrumente * http://www.physikinstrumente.com/en/products/ */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ + #define PI_VID 0x1a72 /* Vendor ID */ -#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ +#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID 0x1007 /* PI C-863 */ +#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ +#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ +#define PI_1012_PID 0x1012 /* PI Motion Controller */ +#define PI_1013_PID 0x1013 /* PI Motion Controller */ +#define PI_1014_PID 0x1014 /* PI Device */ +#define PI_1015_PID 0x1015 /* PI Device */ +#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ /* * Kondo Kagaku Co.Ltd. -- cgit v1.2.3 From 26a538b9ea2a3ee10dafc0068f0560dfd7b7ba37 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 31 Aug 2012 00:00:28 +0200 Subject: USB: ftdi_sio: PID for NZR SEM 16+ USB This adds the USB PID for the NZR SEM 16+ USB energy monitor device . It works perfectly with the GPL software on . Signed-off-by: Horst Schirmeier Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1197d4780b9a..e2fa7881067d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 080d1580db99..9bcaf9c3d3e4 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -75,6 +75,9 @@ #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ + /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) */ -- cgit v1.2.3 From 6fffb77c8393151b0cf8cef1b9c2ba90587dd2e8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 29 Aug 2012 11:49:18 +0200 Subject: USB: ohci-at91: fix PIO handling in relation with number of ports If the number of ports present on the SoC/board is not the maximum and that the platform data is not filled with all data, there is an easy way to mess the PIO setup for this interface. This quick fix addresses mis-configuration in USB host platform data that is common in at91 boards since commit 0ee6d1e (USB: ohci-at91: change maximum number of ports) that did not modified the associatd board files. Reported-by: Klaus Falkner Signed-off-by: Nicolas Ferre Cc: Stable [3.4+] Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a665b3eaa746..aaa8d2bce217 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -570,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (pdata) { at91_for_each_port(i) { + /* + * do not configure PIO if not in relation with + * real USB port on board + */ + if (i >= pdata->ports) { + pdata->vbus_pin[i] = -EINVAL; + pdata->overcurrent_pin[i] = -EINVAL; + break; + } + if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; -- cgit v1.2.3 From 92fc7a8b0f20bdb243c706daf42658e8e0cd2ef0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 4 Sep 2012 10:41:02 -0400 Subject: USB: add device quirk for Joss Optical touchboard This patch (as1604) adds a CONFIG_INTF_STRINGS quirk for the Joss infrared touchboard device. The device doesn't like to be asked for its interface strings. Signed-off-by: Alan Stern Reported-by: adam ? Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f15501f4c585..e77a8e8eaa23 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Microchip Joss Optical infrared touchboard device */ + { USB_DEVICE(0x04d8, 0x000c), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, -- cgit v1.2.3 From 6138ed2ab8791d7a9c5ba66cadadd5eaf1fc1dac Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:13 +0200 Subject: target: move transport_get_sense_data We will be calling it from transport_complete_cmd, avoid forward declarations. No semantic change. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 110 ++++++++++++++++----------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 3425098ef728..d0afdaa06255 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -567,6 +567,61 @@ static void target_complete_failure_work(struct work_struct *work) transport_generic_request_failure(cmd); } +/* + * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + */ +static int transport_get_sense_data(struct se_cmd *cmd) +{ + unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + struct se_device *dev = cmd->se_dev; + unsigned long flags; + u32 offset = 0; + + WARN_ON(!cmd->se_lun); + + if (!dev) + return 0; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return 0; + } + + if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) + goto out; + + if (!dev->transport->get_sense_buffer) { + pr_err("dev->transport->get_sense_buffer is NULL\n"); + goto out; + } + + sense_buffer = dev->transport->get_sense_buffer(cmd); + if (!sense_buffer) { + pr_err("ITT 0x%08x cmd %p: Unable to locate" + " sense buffer for task with sense\n", + cmd->se_tfo->get_task_tag(cmd), cmd); + goto out; + } + + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); + + memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); + + /* Automatically padded */ + cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; + + pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return 0; + +out: + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return -1; +} + void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) { struct se_device *dev = cmd->se_dev; @@ -1820,61 +1875,6 @@ execute: } EXPORT_SYMBOL(target_execute_cmd); -/* - * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd - */ -static int transport_get_sense_data(struct se_cmd *cmd) -{ - unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; - struct se_device *dev = cmd->se_dev; - unsigned long flags; - u32 offset = 0; - - WARN_ON(!cmd->se_lun); - - if (!dev) - return 0; - - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return 0; - } - - if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) - goto out; - - if (!dev->transport->get_sense_buffer) { - pr_err("dev->transport->get_sense_buffer is NULL\n"); - goto out; - } - - sense_buffer = dev->transport->get_sense_buffer(cmd); - if (!sense_buffer) { - pr_err("ITT 0x%08x cmd %p: Unable to locate" - " sense buffer for task with sense\n", - cmd->se_tfo->get_task_tag(cmd), cmd); - goto out; - } - - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - - offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - - memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); - - /* Automatically padded */ - cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - - pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", - dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return 0; - -out: - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return -1; -} - /* * Process all commands up to the last received ORDERED task attribute which * requires another blocking boundary -- cgit v1.2.3 From 27a2709912ac19c755d34c79fe11994b0bf8082b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:14 +0200 Subject: target: simplify code around transport_get_sense_data The error conditions in transport_get_sense_data are superfluous and complicate the code unnecessarily: * SCF_TRANSPORT_TASK_SENSE is checked in the caller; * it's simply part of the invariants of dev->transport->get_sense_buffer that it must be there if transport_complete ever returns 1, and that it must not return NULL. Besides, the entire callback will disappear with the next patch. * similarly in the caller we can expect that sense data is only sent for non-zero cmd->scsi_status. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 49 +++++++++------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d0afdaa06255..040f05fde4d6 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -570,7 +570,7 @@ static void target_complete_failure_work(struct work_struct *work) /* * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd */ -static int transport_get_sense_data(struct se_cmd *cmd) +static void transport_get_sense_data(struct se_cmd *cmd) { unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; struct se_device *dev = cmd->se_dev; @@ -580,30 +580,15 @@ static int transport_get_sense_data(struct se_cmd *cmd) WARN_ON(!cmd->se_lun); if (!dev) - return 0; + return; spin_lock_irqsave(&cmd->t_state_lock, flags); if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return 0; - } - - if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) - goto out; - - if (!dev->transport->get_sense_buffer) { - pr_err("dev->transport->get_sense_buffer is NULL\n"); - goto out; + return; } sense_buffer = dev->transport->get_sense_buffer(cmd); - if (!sense_buffer) { - pr_err("ITT 0x%08x cmd %p: Unable to locate" - " sense buffer for task with sense\n", - cmd->se_tfo->get_task_tag(cmd), cmd); - goto out; - } - spin_unlock_irqrestore(&cmd->t_state_lock, flags); offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); @@ -615,11 +600,6 @@ static int transport_get_sense_data(struct se_cmd *cmd) pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); - return 0; - -out: - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return -1; } void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) @@ -1990,7 +1970,7 @@ static void transport_handle_queue_full( static void target_complete_ok_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - int reason = 0, ret; + int ret; /* * Check if we need to move delayed/dormant tasks from cmds on the @@ -2011,19 +1991,16 @@ static void target_complete_ok_work(struct work_struct *work) * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { - if (transport_get_sense_data(cmd) < 0) - reason = TCM_NON_EXISTENT_LUN; - - if (cmd->scsi_status) { - ret = transport_send_check_condition_and_sense( - cmd, reason, 1); - if (ret == -EAGAIN || ret == -ENOMEM) - goto queue_full; + WARN_ON(!cmd->scsi_status); + transport_get_sense_data(cmd); + ret = transport_send_check_condition_and_sense( + cmd, 0, 1); + if (ret == -EAGAIN || ret == -ENOMEM) + goto queue_full; - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; - } + transport_lun_remove_cmd(cmd); + transport_cmd_check_stop_to_fabric(cmd); + return; } /* * Check for a callback, used by amongst other things -- cgit v1.2.3 From d5829eac5f7cfff89c6d1cf11717eee97cf030d0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Sep 2012 17:09:15 +0200 Subject: target: fix use-after-free with PSCSI sense data The pointer to the sense buffer is fetched by transport_get_sense_data, but this is called by target_complete_ok_work long after pscsi_req_done has freed the struct that contains it. Pass instead the fabric's sense buffer to transport_complete, and copy the data to it directly in transport_complete. Setting SCF_TRANSPORT_TASK_SENSE also becomes a duty of transport_complete. Signed-off-by: Paolo Bonzini Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 21 +++++++------------- drivers/target/target_core_transport.c | 36 +++++++++++++--------------------- include/target/target_core_backend.h | 4 +++- 3 files changed, 24 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5552fa7426bc..5f7151d90344 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -667,7 +667,8 @@ static void pscsi_free_device(void *p) kfree(pdv); } -static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) +static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, + unsigned char *sense_buffer) { struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr; struct scsi_device *sd = pdv->pdv_sd; @@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) * not been allocated because TCM is handling the emulation directly. */ if (!pt) - return 0; + return; cdb = &pt->pscsi_cdb[0]; result = pt->pscsi_result; @@ -750,10 +751,10 @@ after_mode_sense: } after_mode_select: - if (status_byte(result) & CHECK_CONDITION) - return 1; - - return 0; + if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) { + memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER); + cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; + } } enum { @@ -1184,13 +1185,6 @@ fail: return -ENOMEM; } -static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd) -{ - struct pscsi_plugin_task *pt = cmd->priv; - - return pt->pscsi_sense; -} - /* pscsi_get_device_rev(): * * @@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = { .check_configfs_dev_params = pscsi_check_configfs_dev_params, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, - .get_sense_buffer = pscsi_get_sense_buffer, .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 040f05fde4d6..8a29e3fd0195 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -568,38 +568,31 @@ static void target_complete_failure_work(struct work_struct *work) } /* - * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd + * Used when asking transport to copy Sense Data from the underlying + * Linux/SCSI struct scsi_cmnd */ -static void transport_get_sense_data(struct se_cmd *cmd) +static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd) { - unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; + unsigned char *buffer = cmd->sense_buffer; struct se_device *dev = cmd->se_dev; - unsigned long flags; u32 offset = 0; WARN_ON(!cmd->se_lun); if (!dev) - return; - - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return; - } + return NULL; - sense_buffer = dev->transport->get_sense_buffer(cmd); - spin_unlock_irqrestore(&cmd->t_state_lock, flags); + if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) + return NULL; offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); - memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); - /* Automatically padded */ cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; - pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n", + pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n", dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status); + return &buffer[offset]; } void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) @@ -615,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) cmd->transport_state &= ~CMD_T_BUSY; if (dev && dev->transport->transport_complete) { - if (dev->transport->transport_complete(cmd, - cmd->t_data_sg) != 0) { - cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; + dev->transport->transport_complete(cmd, + cmd->t_data_sg, + transport_get_sense_buffer(cmd)); + if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) success = 1; - } } /* @@ -1987,12 +1980,11 @@ static void target_complete_ok_work(struct work_struct *work) schedule_work(&cmd->se_dev->qf_work_queue); /* - * Check if we need to retrieve a sense buffer from + * Check if we need to send a sense buffer from * the struct se_cmd in question. */ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { WARN_ON(!cmd->scsi_status); - transport_get_sense_data(cmd); ret = transport_send_check_condition_and_sense( cmd, 0, 1); if (ret == -EAGAIN || ret == -ENOMEM) diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index f1405d335a96..941c84bf1065 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -23,7 +23,9 @@ struct se_subsystem_api { struct se_device *(*create_virtdevice)(struct se_hba *, struct se_subsystem_dev *, void *); void (*free_device)(void *); - int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *); + void (*transport_complete)(struct se_cmd *cmd, + struct scatterlist *, + unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); ssize_t (*check_configfs_dev_params)(struct se_hba *, -- cgit v1.2.3 From 8a55ade76551e3927b4e41ee9e7751875d18bc25 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 15:10:08 +0100 Subject: dj: memory scribble in logi_dj Allocate a structure not a pointer to it ! Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/hid/hid-logitech-dj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 0f9c146fc00d..4d524b5f52f5 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -439,7 +439,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; @@ -456,7 +456,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report; int retval; - dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL); + dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; dj_report->report_id = REPORT_ID_DJ_SHORT; -- cgit v1.2.3 From 80ba77dfbce85f2d1be54847de3c866de1b18a9a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 5 Sep 2012 16:35:20 -0400 Subject: xen/pciback: Fix proper FLR steps. When we do FLR and save PCI config we did it in the wrong order. The end result was that if a PCI device was unbind from its driver, then binded to xen-pciback, and then back to its driver we would get: > lspci -s 04:00.0 04:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection 13:42:12 # 4 :~/ > echo "0000:04:00.0" > /sys/bus/pci/drivers/pciback/unbind > modprobe e1000e e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0-k e1000e: Copyright(c) 1999 - 2012 Intel Corporation. e1000e 0000:04:00.0: Disabling ASPM L0s L1 e1000e 0000:04:00.0: enabling device (0000 -> 0002) xen: registering gsi 48 triggering 0 polarity 1 Already setup the GSI :48 e1000e 0000:04:00.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode e1000e: probe of 0000:04:00.0 failed with error -2 This fixes it by first saving the PCI configuration space, then doing the FLR. Reported-by: Ren, Yongjie Reported-and-Tested-by: Tobias Geiger Signed-off-by: Konrad Rzeszutek Wilk CC: stable@vger.kernel.org --- drivers/xen/xen-pciback/pci_stub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 097e536e8672..03342728bf23 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; - dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); - __pci_reset_function_locked(dev); - /* We need the device active to save the state. */ dev_dbg(&dev->dev, "save state of device\n"); pci_save_state(dev); dev_data->pci_saved_state = pci_store_saved_state(dev); if (!dev_data->pci_saved_state) dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); - + else { + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + } /* Now disable the device (this also ensures some private device * data is setup before we export) */ -- cgit v1.2.3 From ea0e627623e236e4cbec9f44b4a755bc4a4b852d Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 11 Jun 2012 11:13:15 +0200 Subject: usb: gadget: add multiple definition guards If f_fs.c and u_serial.c are combined together using #include, which has been a common practice so far, the pr_vdebug macro is defined multiple times. Define it only once. Acked-by: Randy Dunlap Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 4 ++++ drivers/usb/gadget/u_serial.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 8adc79d1b402..829aba75a6df 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -34,11 +34,15 @@ /* Debugging ****************************************************************/ #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug # define pr_vdebug pr_debug +#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) \ print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) #else +#ifndef pr_vdebug # define pr_vdebug(...) do { } while (0) +#endif /* pr_vdebug */ # define ffs_dump_mem(prefix, ptr, len) do { } while (0) #endif /* VERBOSE_DEBUG */ diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 5b3f5fffea92..da6d479ff9a6 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -132,11 +132,15 @@ static unsigned n_ports; #ifdef VERBOSE_DEBUG +#ifndef pr_vdebug #define pr_vdebug(fmt, arg...) \ pr_debug(fmt, ##arg) +#endif /* pr_vdebug */ #else +#ifndef pr_vdebig #define pr_vdebug(fmt, arg...) \ ({ if (0) pr_debug(fmt, ##arg); }) +#endif /* pr_vdebug */ #endif /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 0416e494ce7dc84e2719bc9fb7daecb330476074 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 10 Aug 2012 13:42:16 +0530 Subject: usb: dwc3: ep0: correct cache sync issue in case of ep0_bounced In case of ep0 out, if length is not aligned to maxpacket size then we use dwc->ep_bounce_addr for dma transfer and not request->dma. Since, we have alreday done memcpy from dwc->ep0_bounce to request->buf, so we do not need to issue cache sync function. In fact, cache sync function will bring wrong data in request->buf from request->dma in this scenario. So, cache sync function must not be executed in case of ep0 bounced. Cc: # v3.4 v3.5 Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 1 - drivers/usb/dwc3/gadget.c | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9b94886b66e5..e4d5ca86b9da 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, transferred = min_t(u32, ur->length, transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); - dwc->ep0_bounced = false; } else { transferred = ur->length - length; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad96b4d..c99568eb4292 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); + if (dwc->ep0_bounced && dep->number == 0) + dwc->ep0_bounced = false; + else + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, -- cgit v1.2.3 From c8e6507bdec67f1c50390a69a14568c5115cc658 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:34 +0200 Subject: usb: gadget: s3c-hsotg.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b13e0bb5f5b8..0bb617e1dda2 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) if (hsotg->num_of_eps == 0) { dev_err(dev, "wrong number of EPs (zero)\n"); + ret = -EINVAL; goto err_supplies; } @@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!eps) { dev_err(dev, "cannot get memory\n"); + ret = -ENOMEM; goto err_supplies; } @@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); + ret = -ENOMEM; goto err_ep_mem; } -- cgit v1.2.3 From 1b68a4ca2d038addb7314211d122fb6d7002b38b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 19 Aug 2012 21:54:58 +0200 Subject: usb: gadget: dummy_hcd: fixup error probe path If USB2 host controller probes fine but USB3 does not then we don't remove the USB controller properly and lock up the system while the HUB code will try to enumerate the USB2 controller and access memory which is no longer available in case the dummy_hcd was compiled as a module. This is a problem since 448b6eb1 ("USB: Make sure to fetch the BOS desc for roothubs.) if used in USB3 mode because dummy does not provide this descriptor and explodes later. Cc: stable@vger.kernel.org # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index b799106027ad..0e58a46956ae 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -2503,10 +2503,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) hs_hcd->has_tt = 1; retval = usb_add_hcd(hs_hcd, 0, 0); - if (retval != 0) { - usb_put_hcd(hs_hcd); - return retval; - } + if (retval) + goto put_usb2_hcd; if (mod_data.is_super_speed) { ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2525,6 +2523,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) put_usb3_hcd: usb_put_hcd(ss_hcd); dealloc_usb2_hcd: + usb_remove_hcd(hs_hcd); +put_usb2_hcd: usb_put_hcd(hs_hcd); the_controller.hs_hcd = the_controller.ss_hcd = NULL; return retval; -- cgit v1.2.3 From 3b9c1c5ba7a95caae8440ea47308496b14f7301a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 19 Aug 2012 21:54:59 +0200 Subject: usb: gadget: dummy_hcd: add support for USB_DT_BOS on rh Without a reply for USB_DT_BOS the USB3 mode does not work since 448b6eb1 ("USB: Make sure to fetch the BOS desc for roothubs.). Cc: stable@vger.kernel.org #v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 0e58a46956ae..afdbb1cbf5d9 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1916,6 +1916,27 @@ done: return retval; } +/* usb 3.0 root hub device descriptor */ +struct { + struct usb_bos_descriptor bos; + struct usb_ss_cap_descriptor ss_cap; +} __packed usb3_bos_desc = { + + .bos = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)), + .bNumDeviceCaps = 1, + }, + .ss_cap = { + .bLength = USB_DT_USB_SS_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_SS_CAP_TYPE, + .wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION), + .bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION), + }, +}; + static inline void ss_hub_descriptor(struct usb_hub_descriptor *desc) { @@ -2006,6 +2027,18 @@ static int dummy_hub_control( else hub_descriptor((struct usb_hub_descriptor *) buf); break; + + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: + if (hcd->speed != HCD_USB3) + goto error; + + if ((wValue >> 8) != USB_DT_BOS) + goto error; + + memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc)); + retval = sizeof(usb3_bos_desc); + break; + case GetHubStatus: *(__le32 *) buf = cpu_to_le32(0); break; -- cgit v1.2.3 From 3067779b1566ae5fb6af40f03ae874ac47035523 Mon Sep 17 00:00:00 2001 From: yuzheng ma Date: Wed, 15 Aug 2012 16:11:40 +0800 Subject: usb: musb: host: fix for musb_start_urb Oops when using musb_urb_enqueue to submit three urbs to the same endpoint, when hep->hcpriv is NULL, qh will be allocated when the first urb is completed. When the IRQ completes the next two urbs, qh->hep->hcpriv will be set to NULL. Now the second urb get musb->lock and executes musb_schedule(), but next_urb(qh) is NULL, so musb_start_urb will Oops. [ balbi@ti.com : practically rewrote commit log so it makes sense ] Signed-off-by: mayuzheng Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4bb717d0bd41..1ae378d5fc6f 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2049,7 +2049,7 @@ static int musb_urb_enqueue( * we only have work to do in the former case. */ spin_lock_irqsave(&musb->lock, flags); - if (hep->hcpriv) { + if (hep->hcpriv || !next_urb(qh)) { /* some concurrent activity submitted another urb to hep... * odd, rare, error prone, but legal. */ -- cgit v1.2.3 From ff41aaa3b6c181a713078d8ad96da4ba822de436 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 20 Aug 2012 22:31:41 +0400 Subject: usb: musb: tusb6010: fix error path in tusb_probe() On platform_device_add() failure, the TUSB6010 glue layer forgets to call platform_device_put() -- probably due to a typo... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi --- drivers/usb/musb/tusb6010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1a1bd9cf40c5..341625442377 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; + goto err2; } return 0; -- cgit v1.2.3 From 7effdbd6512083e21c007edbaca0ceff4aa5159f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 20 Aug 2012 22:34:46 +0400 Subject: usb: musb: musbhsdma: fix IRQ check dma_controller_create() in this MUSB DMA driver only regards 0 as a wrong IRQ number, despite platform_get_irq_byname() that it calls returns -ENXIO in that case. It leads to calling request_irq() with a negative IRQ number, and when it naturally fails, the following is printed to the console: request_irq -6 failed! and the DMA controller is not created. Fix this function to filter out the error values as well as 0. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi --- drivers/usb/musb/musbhsdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 57a608584e16..c1be687e00ec 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) struct platform_device *pdev = to_platform_device(dev); int irq = platform_get_irq_byname(pdev, "dma"); - if (irq == 0) { + if (irq <= 0) { dev_err(dev, "No DMA interrupt line!\n"); return NULL; } -- cgit v1.2.3 From 066618bc350cc6035c3a0fc559a8ac02f55785a9 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 21 Aug 2012 14:56:16 +0530 Subject: usb: dwc3: core: fix incorrect usage of resource pointer Populate the resources for xhci afresh instead of directly using the *struct resource* of core. *resource* structure has parent, sibling, child pointers which should be filled only by resource API's. By directly using the *resource* pointer of core in xhci, these parent, sibling, child pointers are already populated even before *platform_device_add* causing side effects. Cc: stable@vger.kernel.org # v3.4, v3.5 Reported-by: Ruchika Kharwar Tested-by: Moiz Sonasath Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a7304f..a68ff53124dc 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev) dev_err(dev, "missing IRQ\n"); return -ENODEV; } - dwc->xhci_resources[1] = *res; + dwc->xhci_resources[1].start = res->start; + dwc->xhci_resources[1].end = res->end; + dwc->xhci_resources[1].flags = res->flags; + dwc->xhci_resources[1].name = res->name; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } - dwc->xhci_resources[0] = *res; + dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; + dwc->xhci_resources[0].flags = res->flags; + dwc->xhci_resources[0].name = res->name; /* * Request memory region but exclude xHCI regs, -- cgit v1.2.3 From 8b7dda554cf61e87523dee412eaf598f8646bd79 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 20 Jul 2012 20:34:24 +0200 Subject: usb: gadget: at91udc: don't overwrite driver data The driver was converted to the new start/stop interface in f3d8bf34c2 ("usb: gadget: at91_udc: convert to new style start/stop interface"). I overlooked that the driver is overwritting the private data which is used by the composite framework. The udc driver doesn't read it, it is only written here. Tested-by: Fabio Porcedda Tested-by: Mario Isidoro Cc: # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index c9e66dfb02e6..14df835991af 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1635,7 +1635,6 @@ static int at91_start(struct usb_gadget *gadget, udc->driver = driver; udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->pdev->dev.of_node; - dev_set_drvdata(&udc->gadget.dev, &driver->driver); udc->enabled = 1; udc->selfpowered = 1; @@ -1656,7 +1655,6 @@ static int at91_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&udc->lock, flags); udc->gadget.dev.driver = NULL; - dev_set_drvdata(&udc->gadget.dev, NULL); udc->driver = NULL; DBG("unbound from %s\n", driver->driver.name); -- cgit v1.2.3 From f3bb8e63a8ee0398dffe412e774d8801db7e1bf1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 20 Jul 2012 20:34:25 +0200 Subject: usb: gadget: at91udc: Don't check for ep->ep.desc Earlier we used to check for ep->ep.desc to figure out if this ep has already been enabled and if so, abort. Ido Shayevitz removed the usb_endpoint_descriptor from private udc structure 5a6506f00 ("usb: gadget: Update at91_udc to use usb_endpoint_descriptor inside the struct usb_ep") but did not fix up the ep_enable condition because _now_ the member is always true and we can't check if this ep is enabled twice. Cc: Ido Shayevitz Tested-by: Fabio Porcedda Tested-by: Mario Isidoro Cc: # v3.5 Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 14df835991af..1e35963bd4ed 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep, unsigned long flags; if (!_ep || !ep - || !desc || ep->ep.desc - || _ep->name == ep0name + || !desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || (maxpacket = usb_endpoint_maxp(desc)) == 0 || maxpacket > ep->maxpacket) { @@ -530,7 +529,6 @@ ok: tmp |= AT91_UDP_EPEDS; __raw_writel(tmp, ep->creg); - ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; /* -- cgit v1.2.3 From 77975eec149506e457e6abe2ce43259895a9a16e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2012 18:01:13 -0700 Subject: usb: renesas_usbhs: fixup DMA transport data alignment renesas_usbhs dma can transport 8byte alignment data, not 4byte. This patch fixup it. Reported-by: Sugnan Prabhu S Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index ecd173032fd4..143c4e9e1be4 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_is_dcp(pipe)) goto usbhsf_pio_prepare_push; - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ @@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) /* use PIO if packet is less than pio_dma_border */ len = usbhsf_fifo_rcv_len(priv, fifo); len = min(pkt->length - pkt->actual, len); - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_pop_unselect; if (len < usbhs_get_dparam(priv, pio_dma_border)) -- cgit v1.2.3 From f4a53c55117b82e895ec98b1765c9d66940377fc Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Thu, 30 Aug 2012 12:21:43 +0530 Subject: usb: dwc3: gadget: fix pending isoc handling If xfernotready is received and there is no request in request_list then REQUEST_PENDING flag must be set, so that next request in ep queue is executed. In case of isoc transfer, if xfernotready is already elapsed and even first request has not been queued to request_list, then issue END TRANSFER, so that you can receive xfernotready again and can have notion of current microframe. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c99568eb4292..c2813c2b005a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1029,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, if (list_empty(&dep->request_list)) { dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", dep->name); + dep->flags |= DWC3_EP_PENDING_REQUEST; return; } @@ -1092,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (dep->flags & DWC3_EP_PENDING_REQUEST) { int ret; + /* + * If xfernotready is already elapsed and it is a case + * of isoc transfer, then issue END TRANSFER, so that + * you can receive xfernotready again and can have + * notion of current microframe. + */ + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + dwc3_stop_active_transfer(dwc, dep->number); + return 0; + } + ret = __dwc3_gadget_kick_transfer(dep, 0, true); if (ret && ret != -EBUSY) { struct dwc3 *dwc = dep->dwc; -- cgit v1.2.3 From 3b75a2c126c4b573553856e0fe08d1bb020ca8c3 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Thu, 23 Aug 2012 18:39:57 -0400 Subject: crypto/caam: Export gen_split_key symbol for other modules In 3.6-rc3, without this patch, the following error occurs with a modular build: ERROR: "gen_split_key" [drivers/crypto/caam/caamhash.ko] undefined! ERROR: "gen_split_key" [drivers/crypto/caam/caamalg.ko] undefined! Signed-off-by: Ben Collins Cc: Yuan Kang Acked-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/key_gen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 002888185f17..d216cd3cc569 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -120,3 +120,4 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, return ret; } +EXPORT_SYMBOL(gen_split_key); -- cgit v1.2.3 From 5d2afab958f8cd203a8fe639082b5b5e74f748f9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 21:38:49 -0400 Subject: drm/vmwgfx: allow a kconfig option to choose if fbcon is enabled This makes things easier for distros where we'd like to have fbcon enabled all the time. Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/Kconfig | 8 ++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig index 794ff67c5701..b71bcd0bfbbf 100644 --- a/drivers/gpu/drm/vmwgfx/Kconfig +++ b/drivers/gpu/drm/vmwgfx/Kconfig @@ -12,3 +12,11 @@ config DRM_VMWGFX This is a KMS enabled DRM driver for the VMware SVGA2 virtual hardware. The compiled module will be called "vmwgfx.ko". + +config DRM_VMWGFX_FBCON + depends on DRM_VMWGFX + bool "Enable framebuffer console under vmwgfx by default" + help + Choose this option if you are shipping a new vmwgfx + userspace driver that supports using the kernel driver. + diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4d9edead01ac..7f4f4eecf45a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -183,7 +183,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0, 0, 0} }; -static int enable_fbdev; +static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); -- cgit v1.2.3 From c4903429a92be60e6fe59868924a65eca4cd1a38 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 21:40:51 -0400 Subject: drm/vmwgfx: add MODULE_DEVICE_TABLE so vmwgfx loads at boot This will cause udev to load vmwgfx instead of waiting for X to do it. Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7f4f4eecf45a..33bfc2033009 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,6 +182,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII}, {0, 0, 0} }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); -- cgit v1.2.3 From aad932e75c573aec37a0652ff1c27a975d8d5373 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Thu, 30 Aug 2012 14:37:14 +0200 Subject: HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured c1dcad2d32d0252e8a3023d20311b52a187ecda3 added a new driver configured by HID_LENOVO_TPKBD but made the hid_have_special_driver entry non-optional which lead to a recognized but non-working device if the new driver wasn't configured (which is the correct default). Signed-off-by: Andres Freund Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b8485a0106c9..8bcd168fffae 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1559,7 +1559,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, +#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD) + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, +#endif { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, -- cgit v1.2.3 From a8edc3bf05a3465726afdf635a820761fae0d50b Mon Sep 17 00:00:00 2001 From: Hadar Hen Zion Date: Wed, 5 Sep 2012 22:50:48 +0000 Subject: net/mlx4_core: Put Firmware flow steering structures in common header files To allow for usage of the flow steering Firmware structures in more locations over the driver, such as the resource tracker, move them from mcg.c to common header files. Signed-off-by: Hadar Hen Zion Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 90 +++---------------------------- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 76 ++++++++++++++++++++++++++ include/linux/mlx4/device.h | 2 + 3 files changed, 85 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index a018ea2a43de..2673f3ba935f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port, return err; } -struct mlx4_net_trans_rule_hw_ctrl { - __be32 ctrl; - __be32 vf_vep_port; - __be32 qpn; - __be32 reserved; -}; - static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, struct mlx4_net_trans_rule_hw_ctrl *hw) { @@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl, hw->qpn = cpu_to_be32(ctrl->qpn); } -struct mlx4_net_trans_rule_hw_ib { - u8 size; - u8 rsvd1; - __be16 id; - u32 rsvd2; - __be32 qpn; - __be32 qpn_mask; - u8 dst_gid[16]; - u8 dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { - u8 size; - u8 rsvd; - __be16 id; - u8 rsvd1[6]; - u8 dst_mac[6]; - u16 rsvd2; - u8 dst_mac_msk[6]; - u16 rsvd3; - u8 src_mac[6]; - u16 rsvd4; - u8 src_mac_msk[6]; - u8 rsvd5; - u8 ether_type_enable; - __be16 ether_type; - __be16 vlan_id_msk; - __be16 vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { - u8 size; - u8 rsvd; - __be16 id; - __be16 rsvd1[3]; - __be16 dst_port; - __be16 rsvd2; - __be16 dst_port_msk; - __be16 rsvd3; - __be16 src_port; - __be16 rsvd4; - __be16 src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { - u8 size; - u8 rsvd; - __be16 id; - __be32 rsvd1; - __be32 dst_ip; - __be32 dst_ip_msk; - __be32 src_ip; - __be32 src_ip_msk; -} __packed; - -struct _rule_hw { - union { - struct { - u8 size; - u8 rsvd; - __be16 id; - }; - struct mlx4_net_trans_rule_hw_eth eth; - struct mlx4_net_trans_rule_hw_ib ib; - struct mlx4_net_trans_rule_hw_ipv4 ipv4; - struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; - }; +const u16 __sw_id_hw[] = { + [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, + [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, + [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, + [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, + [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, + [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 }; static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec, struct _rule_hw *rule_hw) { - static const u16 __sw_id_hw[] = { - [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001, - [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005, - [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003, - [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002, - [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004, - [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006 - }; - static const size_t __rule_hw_sz[] = { [MLX4_NET_TRANS_RULE_ID_ETH] = sizeof(struct mlx4_net_trans_rule_hw_eth), diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d9df8f2a126..dba69d98734a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -690,6 +690,82 @@ struct mlx4_steer { struct list_head steer_entries[MLX4_NUM_STEERS]; }; +struct mlx4_net_trans_rule_hw_ctrl { + __be32 ctrl; + __be32 vf_vep_port; + __be32 qpn; + __be32 reserved; +}; + +struct mlx4_net_trans_rule_hw_ib { + u8 size; + u8 rsvd1; + __be16 id; + u32 rsvd2; + __be32 qpn; + __be32 qpn_mask; + u8 dst_gid[16]; + u8 dst_gid_msk[16]; +} __packed; + +struct mlx4_net_trans_rule_hw_eth { + u8 size; + u8 rsvd; + __be16 id; + u8 rsvd1[6]; + u8 dst_mac[6]; + u16 rsvd2; + u8 dst_mac_msk[6]; + u16 rsvd3; + u8 src_mac[6]; + u16 rsvd4; + u8 src_mac_msk[6]; + u8 rsvd5; + u8 ether_type_enable; + __be16 ether_type; + __be16 vlan_id_msk; + __be16 vlan_id; +} __packed; + +struct mlx4_net_trans_rule_hw_tcp_udp { + u8 size; + u8 rsvd; + __be16 id; + __be16 rsvd1[3]; + __be16 dst_port; + __be16 rsvd2; + __be16 dst_port_msk; + __be16 rsvd3; + __be16 src_port; + __be16 rsvd4; + __be16 src_port_msk; +} __packed; + +struct mlx4_net_trans_rule_hw_ipv4 { + u8 size; + u8 rsvd; + __be16 id; + __be32 rsvd1; + __be32 dst_ip; + __be32 dst_ip_msk; + __be32 src_ip; + __be32 src_ip_msk; +} __packed; + +struct _rule_hw { + union { + struct { + u8 size; + u8 rsvd; + __be16 id; + }; + struct mlx4_net_trans_rule_hw_eth eth; + struct mlx4_net_trans_rule_hw_ib ib; + struct mlx4_net_trans_rule_hw_ipv4 ipv4; + struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; + }; +}; + struct mlx4_priv { struct mlx4_dev dev; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index bd6c9fcdf2dd..244ba902ab72 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -796,6 +796,8 @@ enum mlx4_net_trans_rule_id { MLX4_NET_TRANS_RULE_NUM, /* should be last */ }; +extern const u16 __sw_id_hw[]; + enum mlx4_net_trans_promisc_mode { MLX4_FS_PROMISC_NONE = 0, MLX4_FS_PROMISC_UPLINK, -- cgit v1.2.3 From 7fb40f87c4195ec1728527f30bc744c47a45b366 Mon Sep 17 00:00:00 2001 From: Hadar Hen Zion Date: Wed, 5 Sep 2012 22:50:49 +0000 Subject: net/mlx4_core: Add security check / enforcement for flow steering rules set for VMs Since VFs may be mapped to VMs which aren't trusted entities, flow steering rules attached through the wrapper on behalf of VFs must be checked to make sure that their L2 specification relate to MAC address assigned to that VF, and add L2 specification if its missing. Signed-off-by: Hadar Hen Zion Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx4/resource_tracker.c | 116 +++++++++++++++++++++ include/linux/mlx4/device.h | 11 ++ 2 files changed, 127 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 94ceddd17ab2..293c9e820c49 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "mlx4.h" #include "fw.h" @@ -2776,18 +2777,133 @@ ex_put: return err; } +/* + * MAC validation for Flow Steering rules. + * VF can attach rules only with a mac address which is assigned to it. + */ +static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, + struct list_head *rlist) +{ + struct mac_res *res, *tmp; + __be64 be_mac; + + /* make sure it isn't multicast or broadcast mac*/ + if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && + !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { + list_for_each_entry_safe(res, tmp, rlist, list) { + be_mac = cpu_to_be64(res->mac << 16); + if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) + return 0; + } + pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", + eth_header->eth.dst_mac, slave); + return -EINVAL; + } + return 0; +} + +/* + * In case of missing eth header, append eth header with a MAC address + * assigned to the VF. + */ +static int add_eth_header(struct mlx4_dev *dev, int slave, + struct mlx4_cmd_mailbox *inbox, + struct list_head *rlist, int header_id) +{ + struct mac_res *res, *tmp; + u8 port; + struct mlx4_net_trans_rule_hw_ctrl *ctrl; + struct mlx4_net_trans_rule_hw_eth *eth_header; + struct mlx4_net_trans_rule_hw_ipv4 *ip_header; + struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; + __be64 be_mac = 0; + __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); + + ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; + port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; + eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); + + /* Clear a space in the inbox for eth header */ + switch (header_id) { + case MLX4_NET_TRANS_RULE_ID_IPV4: + ip_header = + (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); + memmove(ip_header, eth_header, + sizeof(*ip_header) + sizeof(*l4_header)); + break; + case MLX4_NET_TRANS_RULE_ID_TCP: + case MLX4_NET_TRANS_RULE_ID_UDP: + l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) + (eth_header + 1); + memmove(l4_header, eth_header, sizeof(*l4_header)); + break; + default: + return -EINVAL; + } + list_for_each_entry_safe(res, tmp, rlist, list) { + if (port == res->port) { + be_mac = cpu_to_be64(res->mac << 16); + break; + } + } + if (!be_mac) { + pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", + port); + return -EINVAL; + } + + memset(eth_header, 0, sizeof(*eth_header)); + eth_header->size = sizeof(*eth_header) >> 2; + eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); + memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); + memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); + + return 0; + +} + int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd) { + + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; + struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; int err; + struct mlx4_net_trans_rule_hw_ctrl *ctrl; + struct _rule_hw *rule_header; + int header_id; if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) return -EOPNOTSUPP; + ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; + rule_header = (struct _rule_hw *)(ctrl + 1); + header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); + + switch (header_id) { + case MLX4_NET_TRANS_RULE_ID_ETH: + if (validate_eth_header_mac(slave, rule_header, rlist)) + return -EINVAL; + break; + case MLX4_NET_TRANS_RULE_ID_IPV4: + case MLX4_NET_TRANS_RULE_ID_TCP: + case MLX4_NET_TRANS_RULE_ID_UDP: + pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); + if (add_eth_header(dev, slave, inbox, rlist, header_id)) + return -EINVAL; + vhcr->in_modifier += + sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; + break; + default: + pr_err("Corrupted mailbox.\n"); + return -EINVAL; + } + err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, vhcr->in_modifier, 0, MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 244ba902ab72..6e1b0f973a03 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -798,6 +798,17 @@ enum mlx4_net_trans_rule_id { extern const u16 __sw_id_hw[]; +static inline int map_hw_to_sw_id(u16 header_id) +{ + + int i; + for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) { + if (header_id == __sw_id_hw[i]) + return i; + } + return -EINVAL; +} + enum mlx4_net_trans_promisc_mode { MLX4_FS_PROMISC_NONE = 0, MLX4_FS_PROMISC_UPLINK, -- cgit v1.2.3 From 60d31c1475f20b6966f7efbd646b1123d0fba5b1 Mon Sep 17 00:00:00 2001 From: Aviad Yehezkel Date: Wed, 5 Sep 2012 22:50:50 +0000 Subject: net/mlx4_core: Looking for promiscuous entries on the correct port The search for promisc entries was always done on the first port, While the addition is done on the correct port. This lead to resource leackage of promisc entries on the second port and brought to a state where we could no longer enter to promiscuous mode after enough iterations of "ifconfig promisc" on the second port. Fix that by using the correct port when searching. Reported-by: Marcelo Ricardo Leitner Signed-off-by: Aviad Yehezkel Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mcg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 2673f3ba935f..e151c21baf2b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, return err; } -static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, +static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port, enum mlx4_steer_type steer, u32 qpn) { - struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; + struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1]; struct mlx4_promisc_qp *pqp; list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { @@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, /* If the given qpn is also a promisc qp, * it should be inserted to duplicates list */ - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (pqp) { dqp = kmalloc(sizeof *dqp, GFP_KERNEL); if (!dqp) { @@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (!pqp) return 0; /* nothing to do */ @@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; /* if qp is not promisc, it cannot be duplicated */ - if (!get_promisc_qp(dev, 0, steer, qpn)) + if (!get_promisc_qp(dev, port, steer, qpn)) return false; /* The qp is promisc qp so it is a duplicate on this index @@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, members_count = be32_to_cpu(mgm->members_count) & 0xffffff; for (i = 0; i < members_count; i++) { qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; - if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { + if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) { /* the qp is not promisc, the entry can't be removed */ goto out; } @@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, mutex_lock(&priv->mcg_table.mutex); - if (get_promisc_qp(dev, 0, steer, qpn)) { + if (get_promisc_qp(dev, port, steer, qpn)) { err = 0; /* Noting to do, already exists */ goto out_mutex; } @@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, s_steer = &mlx4_priv(dev)->steer[port - 1]; mutex_lock(&priv->mcg_table.mutex); - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, port, steer, qpn); if (unlikely(!pqp)) { mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); /* nothing to do */ -- cgit v1.2.3 From bef772eb06051f49e84c3168f189b65074f19c3d Mon Sep 17 00:00:00 2001 From: Aviad Yehezkel Date: Wed, 5 Sep 2012 22:50:51 +0000 Subject: net/mlx4_core: Fixing error flow in case of QUERY_FW failure The order of operations was wrong on the teardown flow. Signed-off-by: Aviad Yehezkel Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 827b72dfce99..0fadac546b00 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev) mlx4_info(dev, "non-primary physical function, skipping.\n"); else mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - goto unmap_bf; + return err; } err = mlx4_load_fw(dev); if (err) { mlx4_err(dev, "Failed to start FW, aborting.\n"); - goto unmap_bf; + return err; } mlx4_cfg.log_pg_sz_m = 1; @@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_init_slave(dev); if (err) { mlx4_err(dev, "Failed to initialize slave\n"); - goto unmap_bf; + return err; } err = mlx4_slave_cap(dev); @@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) err = mlx4_QUERY_ADAPTER(dev, &adapter); if (err) { mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); - goto err_close; + goto unmap_bf; } priv->eq_table.inta_pin = adapter.inta_pin; @@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev) return 0; +unmap_bf: + unmap_bf_area(dev); + err_close: mlx4_close_hca(dev); @@ -1344,8 +1347,6 @@ err_stop_fw: mlx4_UNMAP_FA(dev); mlx4_free_icm(dev, priv->fw.fw_icm, 0); } -unmap_bf: - unmap_bf_area(dev); return err; } -- cgit v1.2.3 From 521130d11fd37b328543477df5522704a0e7cf2c Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Wed, 5 Sep 2012 22:50:52 +0000 Subject: net/mlx4_core: Return the error value in case of command initialization failure If mlx4_cmd_init() failed, the init_one function returned success, although no resources were opened. Signed-off-by: Eugenia Emantayev Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 0fadac546b00..2f816c6aed72 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1997,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) } slave_start: - if (mlx4_cmd_init(dev)) { + err = mlx4_cmd_init(dev); + if (err) { mlx4_err(dev, "Failed to init command interface, aborting.\n"); goto err_sriov; } -- cgit v1.2.3 From b8dfc6a0a7235aed452c0e376b6feff182a86992 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 6 Sep 2012 00:47:05 +0000 Subject: |PATCH] seeq: Add missing spinlock init It doesn't seem this spinlock was properly initialized. Signed-off-by: Jean Delvare Signed-off-by: David S. Miller --- drivers/net/ethernet/seeq/sgiseeq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index bb8c8222122b..4d15bf413bdc 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) sp->srings = sr; sp->rx_desc = sp->srings->rxvector; sp->tx_desc = sp->srings->txvector; + spin_lock_init(&sp->tx_lock); /* A couple calculations now, saves many cycles later. */ setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); -- cgit v1.2.3 From 306c11b28d7bb85a7adda741798a2b6b60dd305a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:32 +0200 Subject: target: go through normal processing for zero-length PSCSI commands Right now, commands with a zero-size payload are skipped completely. This is wrong; such commands should be passed down to the device and processed normally. For physical backends, this ignores completely things such as START STOP UNIT. For virtual backends, we have a hack in place to clear a unit attention state on a zero-size REQUEST SENSE, but we still do not report errors properly on zero-length commands---out-of-bounds 0-block reads and writes, too small parameter list lengths, etc. This patch fixes this for PSCSI. Uses of transport_kmap_data_sg are guarded with a check for non-zero cmd->data_length; for all other commands a zero length is handled properly in pscsi_execute_cmd. The sole exception will be for now REPORT LUNS, which is handled through the normal SPC emulation. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 8 ++++---- drivers/target/target_core_transport.c | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5f7151d90344..9d7ce3daa262 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -688,11 +688,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, * Hack to make sure that Write-Protect modepage is set if R/O mode is * forced. */ + if (!cmd->se_deve || !cmd->data_length) + goto after_mode_sense; + if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { - if (!cmd->se_deve) - goto after_mode_sense; - if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { unsigned char *buf = transport_kmap_data_sg(cmd); @@ -709,7 +709,7 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, } after_mode_sense: - if (sd->type != TYPE_TAPE) + if (sd->type != TYPE_TAPE || !cmd->data_length) goto after_mode_select; /* diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 8a29e3fd0195..7ddb0c33f644 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2300,7 +2300,9 @@ int transport_generic_new_cmd(struct se_cmd *cmd) * into the fabric for data transfers, go ahead and complete it right * away. */ - if (!cmd->data_length) { + if (!cmd->data_length && + (cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV || + cmd->t_task_cdb[0] == REPORT_LUNS) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; -- cgit v1.2.3 From 0d7f1299ca5540b9a63ab6e8bf0e89ea963eb6af Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:33 +0200 Subject: target: report too-small parameter lists everywhere Several places were not checking that the parameter list length was large enough, and thus accessing invalid memory. Zero-length parameter lists are just a special case of this. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 7 +++++++ drivers/target/target_core_iblock.c | 17 +++++++++++++++-- drivers/target/target_core_pr.c | 8 ++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 91799973081a..41641ba54828 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } + if (cmd->data_length < 4) { + pr_warn("SET TARGET PORT GROUPS parameter list length %u too" + " small\n", cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; + } + buf = transport_kmap_data_sg(cmd); /* diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 76db75e836ed..9ba495477fd2 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd) struct iblock_dev *ibd = dev->dev_ptr; unsigned char *buf, *ptr = NULL; sector_t lba; - int size = cmd->data_length; + int size; u32 range; int ret = 0; int dl, bd_dl; + if (cmd->data_length < 8) { + pr_warn("UNMAP parameter list length %u too small\n", + cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + return -EINVAL; + } + buf = transport_kmap_data_sg(cmd); dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); - size = min(size - 8, bd_dl); + size = cmd->data_length - 8; + if (bd_dl > size) + pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", + cmd->data_length, bd_dl); + else + size = bd_dl; + if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ret = -EINVAL; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1e946502c378..956c84c6b666 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); + if (cmd->data_length < 28) { + pr_warn("SPC-PR: Received PR OUT parameter list" + " length too small: %u\n", cmd->data_length); + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto out; + } + buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, -- cgit v1.2.3 From 9b16b9edb4fd0dc86ee0fbe1f7ede580e26e85f4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:34 +0200 Subject: target: fail REPORT LUNS with less than 16 bytes of payload SPC says: "The ALLOCATION LENGTH field is defined in 4.3.5.6. The allocation length should be at least 16. Device servers compliant with SPC return CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB when the allocation length is less than 16 bytes". Testcase: sg_raw -r8 /dev/sdb a0 00 00 00 00 00 00 00 00 08 00 00 should fail with ILLEGAL REQUEST / INVALID FIELD IN CDB sense does not fail without the patch fails correctly with the patch Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index cf2c66f3c116..9fc9a6006ca0 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd) unsigned char *buf; u32 lun_count = 0, offset = 8, i; + if (se_cmd->data_length < 16) { + pr_warn("REPORT LUNS allocation length %u too small\n", + se_cmd->data_length); + se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + buf = transport_kmap_data_sg(se_cmd); if (!buf) return -ENOMEM; -- cgit v1.2.3 From 3717ef0c63e90686d959158e9728a13a49229be6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:35 +0200 Subject: target: support zero-size allocation lengths in transport_kmap_data_sg In order to support zero-size allocation lengths, do not assert that we have a scatterlist until after checking cmd->data_length. But once we do this, we can have two cases of transport_kmap_data_sg returning NULL: a zero-size allocation length, or an out-of-memory condition. Report the latter using sense codes, so that the SCSI command that triggered it will fail. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7ddb0c33f644..4403477882b3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2190,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) struct page **pages; int i; - BUG_ON(!sg); /* * We need to take into account a possible offset here for fabrics like * tcm_loop who may be using a contig buffer from the SCSI midlayer for @@ -2198,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) */ if (!cmd->t_data_nents) return NULL; - else if (cmd->t_data_nents == 1) + + BUG_ON(!sg); + if (cmd->t_data_nents == 1) return kmap(sg_page(sg)) + sg->offset; /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) + if (!pages) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return NULL; + } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2213,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) + if (!cmd->t_data_vmap) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return NULL; + } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } -- cgit v1.2.3 From 32a8811ff164f882712c17946e58e52444f464a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:36 +0200 Subject: target: support zero allocation length in REQUEST SENSE Similar to INQUIRY and MODE SENSE, construct the sense data in a buffer and later copy it to the scatterlist. Do not do anything, but still clear a pending unit attention condition, if the allocation length is zero. However, SPC tells us that "If a REQUEST SENSE command is terminated with CHECK CONDITION status [and] the REQUEST SENSE command was received on an I_T nexus with a pending unit attention condition (i.e., before the device server reports CHECK CONDITION status), then the device server shall not clear the pending unit attention condition." Do the transport_kmap_data_sg early to detect this case. It also tells us "Device servers shall not adjust the additional sense length to reflect truncation if the allocation length is less than the sense data available", so do not do that! Note that the err variable is write-only. Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_spc.c | 35 ++++++++++++++++++----------------- include/target/target_core_base.h | 1 + 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4c861de538c9..388a922c8f6d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd) static int spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned char *buf; + unsigned char *rbuf; u8 ua_asc = 0, ua_ascq = 0; - int err = 0; + unsigned char buf[SE_SENSE_BUF]; + + memset(buf, 0, SE_SENSE_BUF); if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" @@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return -ENOSYS; } - buf = transport_kmap_data_sg(cmd); - - if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + rbuf = transport_kmap_data_sg(cmd); + if (cmd->scsi_sense_reason != 0) { + /* + * Out of memory. We will fail with CHECK CONDITION, so + * we must not clear the unit attention condition. + */ + target_complete_cmd(cmd, CHECK_CONDITION); + return 0; + } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - if (cmd->data_length < 18) { - buf[7] = 0x00; - err = -EINVAL; - goto end; - } /* * The Additional Sense Code (ASC) from the UNIT ATTENTION */ @@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; - if (cmd->data_length < 18) { - buf[7] = 0x00; - err = -EINVAL; - goto end; - } /* * NO ADDITIONAL SENSE INFORMATION */ @@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } -end: - transport_kunmap_data_sg(cmd); + if (rbuf) { + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); + } + target_complete_cmd(cmd, GOOD); return 0; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 015cea01ae39..5be89373ceac 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -121,6 +121,7 @@ #define SE_INQUIRY_BUF 512 #define SE_MODE_PAGE_BUF 512 +#define SE_SENSE_BUF 96 /* struct se_hba->hba_flags */ enum hba_flags_table { -- cgit v1.2.3 From 6abbdf38363f064c8a50150c9b709682764483b3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Sep 2012 17:30:37 +0200 Subject: target: go through normal processing for zero-length REQUEST_SENSE Now that spc_emulate_request_sense has been taught to process zero-length REQUEST SENSE correctly, drop the special handling of unit attention conditions from transport_generic_new_cmd. However, for now REQUEST SENSE will be the only command that goes through emulation for zero lengths. (nab: Fix up zero-length check in transport_generic_new_cmd) Signed-off-by: Paolo Bonzini Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4403477882b3..269f54488397 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2306,20 +2306,13 @@ int transport_generic_new_cmd(struct se_cmd *cmd) * away. */ if (!cmd->data_length && - (cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV || - cmd->t_task_cdb[0] == REPORT_LUNS) { + cmd->t_task_cdb[0] != REQUEST_SENSE && + cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) { spin_lock_irq(&cmd->t_state_lock); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); - if (cmd->t_task_cdb[0] == REQUEST_SENSE) { - u8 ua_asc = 0, ua_ascq = 0; - - core_scsi3_ua_clear_for_request_sense(cmd, - &ua_asc, &ua_ascq); - } - INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; -- cgit v1.2.3 From 99d0b1db6ccd0c0e554398e8a579ff3dd4d119ee Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Fri, 31 Aug 2012 15:50:55 +0300 Subject: drm/i915: initialize dpio_lock spin lock This thing is killing lockdep. Signed-off-by: Alexander Shishkin [Jani: move the init next to the other spin lock inits] Signed-off-by: Jani Nikula Acked-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9cf7dfe022b9..914c0dfabe60 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->rps_lock); + spin_lock_init(&dev_priv->dpio_lock); if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) dev_priv->num_pipe = 3; -- cgit v1.2.3 From 4a8f1ddde942e232387e6129ce4f4c412e43802f Mon Sep 17 00:00:00 2001 From: James Ralston Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: i2c-i801: Add Device IDs for Intel Lynx Point-LP PCH Add the SMBus Device IDs for the Intel Lynx Point-LP PCH. Signed-off-by: James Ralston Signed-off-by: Jean Delvare --- Documentation/i2c/busses/i2c-i801 | 1 + drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 3 +++ 3 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 615142da4ef6..157416e78cc4 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,6 +21,7 @@ Supported adapters: * Intel DH89xxCC (PCH) * Intel Panther Point (PCH) * Intel Lynx Point (PCH) + * Intel Lynx Point-LP (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b4aaa1bd6728..af8bc83fd857 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801 DH89xxCC (PCH) Panther Point (PCH) Lynx Point (PCH) + Lynx Point-LP (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 898dcf9c7ade..33e9b0c09af2 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@ DH89xxCC (PCH) 0x2330 32 hard yes yes yes Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes + Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -155,6 +156,7 @@ #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 struct i801_priv { struct i2c_adapter adapter; @@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, { 0, } }; -- cgit v1.2.3 From e68bb91baa0bb9817567bd45d560919e8e26373b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: i2c-designware: Fix build error if CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y This patch adds config I2C_DESIGNWARE_CORE in Kconfig, and let I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI select I2C_DESIGNWARE_CORE. Because both I2C_DESIGNWARE_PLATFORM and I2C_DESIGNWARE_PCI can be built as built-in or module, we also need to export the functions in i2c-designware-core. This fixes below build error when CONFIG_I2C_DESIGNWARE_PLATFORM=y && CONFIG_I2C_DESIGNWARE_PCI=y: LD drivers/i2c/busses/built-in.o drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_clear_int': i2c-designware-core.c:(.text+0xa10): multiple definition of `i2c_dw_clear_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x928): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_init': i2c-designware-core.c:(.text+0x178): multiple definition of `i2c_dw_init' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x90): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_readl': i2c-designware-core.c:(.text+0xe8): multiple definition of `dw_readl' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_isr': i2c-designware-core.c:(.text+0x724): multiple definition of `i2c_dw_isr' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x63c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer': i2c-designware-core.c:(.text+0x4b0): multiple definition of `i2c_dw_xfer' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c8): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_is_enabled': i2c-designware-core.c:(.text+0x9d4): multiple definition of `i2c_dw_is_enabled' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8ec): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `dw_writel': i2c-designware-core.c:(.text+0x124): multiple definition of `dw_writel' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x3c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_xfer_msg': i2c-designware-core.c:(.text+0x2e8): multiple definition of `i2c_dw_xfer_msg' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x200): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_enable': i2c-designware-core.c:(.text+0x9c8): multiple definition of `i2c_dw_enable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8e0): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_read_comp_param': i2c-designware-core.c:(.text+0xa24): multiple definition of `i2c_dw_read_comp_param' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x93c): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable': i2c-designware-core.c:(.text+0x9dc): multiple definition of `i2c_dw_disable' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x8f4): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_func': i2c-designware-core.c:(.text+0x710): multiple definition of `i2c_dw_func' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x628): first defined here drivers/i2c/busses/i2c-designware-pci.o: In function `i2c_dw_disable_int': i2c-designware-core.c:(.text+0xa18): multiple definition of `i2c_dw_disable_int' drivers/i2c/busses/i2c-designware-platform.o:i2c-designware-platdrv.c:(.text+0x930): first defined here make[3]: *** [drivers/i2c/busses/built-in.o] Error 1 make[2]: *** [drivers/i2c/busses] Error 2 make[1]: *** [drivers/i2c] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Jean Delvare Tested-by: Jiri Slaby Cc: stable@vger.kernel.org [3.2+] --- drivers/i2c/busses/Kconfig | 5 +++++ drivers/i2c/busses/Makefile | 5 +++-- drivers/i2c/busses/i2c-designware-core.c | 11 +++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index af8bc83fd857..970a1612e795 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -355,9 +355,13 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE + tristate + config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platform" depends on HAVE_CLK + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -368,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ce3c2be7fb40..37c4182cc98b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 1e48bec80edf..7b8ebbefb581 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@ * ---------------------------------------------------------------------------- * */ +#include #include #include #include @@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; } +EXPORT_SYMBOL_GPL(i2c_dw_init); /* * Waiting for bus not busy @@ -568,12 +570,14 @@ done: return ret; } +EXPORT_SYMBOL_GPL(i2c_dw_xfer); u32 i2c_dw_func(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); return dev->functionality; } +EXPORT_SYMBOL_GPL(i2c_dw_func); static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { @@ -678,17 +682,20 @@ tx_aborted: return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(i2c_dw_isr); void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_enable); u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled); void i2c_dw_disable(struct dw_i2c_dev *dev) { @@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_disable); void i2c_dw_clear_int(struct dw_i2c_dev *dev) { dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int); void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int); u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_COMP_PARAM_1); } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); -- cgit v1.2.3 From 390946b17260797635cd9e65496b5a17b2db0a5d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 10 Sep 2012 10:14:02 +0200 Subject: i2c-core: Fix for lockdep validator If kernel is compiled with CONFIG_PROVE_LOCKING the validator raises an error when a multiplexer is removed via sysfs and sub-clients are connected to it. This is a false positive. Documentation/lockdep-design.txt recommends to handle this via calls to mutex_lock_nested(). Based on an earlier fix from Michael Lawnick. Note that the extra code resolves to nothing unless CONFIG_DEBUG_LOCK_ALLOC=y. Signed-off-by: Jean Delvare Cc: Michael Lawnick --- drivers/i2c/i2c-core.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2efa56c5ff2c..2091ae8f539a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } +/* + * This function is only needed for mutex_lock_nested, so it is never + * called unless locking correctness checking is enabled. Thus we + * make it inline to avoid a compiler warning. That's what gcc ends up + * doing anyway. + */ +static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +{ + unsigned int depth = 0; + + while ((adapter = i2c_parent_is_i2c_adapter(adapter))) + depth++; + + return depth; +} + /* * Let users instantiate I2C devices through sysfs. This can be used when * platform initialization code doesn't contain the proper data for @@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, /* Make sure the device was added through sysfs */ res = -ENOENT; - mutex_lock(&adap->userspace_clients_lock); + mutex_lock_nested(&adap->userspace_clients_lock, + i2c_adapter_depth(adap)); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { if (client->addr == addr) { @@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) return res; /* Remove devices instantiated from sysfs */ - mutex_lock(&adap->userspace_clients_lock); + mutex_lock_nested(&adap->userspace_clients_lock, + i2c_adapter_depth(adap)); list_for_each_entry_safe(client, next, &adap->userspace_clients, detected) { dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, -- cgit v1.2.3 From c06fad9d28c95b024ea10455cf1397432b12848d Mon Sep 17 00:00:00 2001 From: "Philip, Avinash" Date: Thu, 23 Aug 2012 12:29:46 +0530 Subject: pwm: pwm-tiecap: Disable APWM mode after configure APWM mode is enabled while configuring PWM device. This was done to handle shadow & immediate mode update of period and compare registers. However, leaving it enabled after configuring will cause APWM output on PWM pin even before enabling PWM device. Fix the same by disabling APWM mode after configuring if PWM device is not running. Signed-off-by: Philip, Avinash Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tiecap.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 0b66d0f25922..4b6688909fee 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } + if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + reg_val = readw(pc->mmio_base + ECCTL2); + /* Disable APWM mode to put APWM output Low */ + reg_val &= ~ECCTL2_APWM_MODE; + writew(reg_val, pc->mmio_base + ECCTL2); + } + pm_runtime_put_sync(pc->chip.dev); return 0; } -- cgit v1.2.3 From 01b2d4536f0215c6d97d77e157afee04300ffc90 Mon Sep 17 00:00:00 2001 From: "Philip, Avinash" Date: Thu, 6 Sep 2012 10:44:25 +0530 Subject: pwm: pwm-tiehrpwm: Fix conflicting channel period setting EHRPWM hardware supports 2 independent PWM channels. However the device uses only one register to handle period setting for both channels. So both channels should be configured for same period (in nsec). Fix the same by returning error for conflicting period values. However, allow 1. Configuration of period settings if not conflicting with other channels 2. Re-configuring of period settings if no other channels being configured Signed-off-by: Philip, Avinash Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tiehrpwm.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index c3756d1be194..b1996bcd5b78 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip { struct pwm_chip chip; unsigned int clk_rate; void __iomem *mmio_base; + unsigned long period_cycles[NUM_PWM_CHANNEL]; }; static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) @@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; + int i; if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) return -ERANGE; @@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty_cycles = (unsigned long)c; } + /* + * Period values should be same for multiple PWM channels as IP uses + * same period register for multiple channels. + */ + for (i = 0; i < NUM_PWM_CHANNEL; i++) { + if (pc->period_cycles[i] && + (pc->period_cycles[i] != period_cycles)) { + /* + * Allow channel to reconfigure period if no other + * channels being configured. + */ + if (i == pwm->hwpwm) + continue; + + dev_err(chip->dev, "Period value conflicts with channel %d\n", + i); + return -EINVAL; + } + } + + pc->period_cycles[pwm->hwpwm] = period_cycles; + /* Configure clock prescaler to support Low frequency PWM wave */ if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, &tb_divval)) { @@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + if (test_bit(PWMF_ENABLED, &pwm->flags)) { dev_warn(chip->dev, "Removing PWM device without disabling\n"); pm_runtime_put_sync(chip->dev); } + + /* set period value to zero on free */ + pc->period_cycles[pwm->hwpwm] = 0; } static const struct pwm_ops ehrpwm_pwm_ops = { -- cgit v1.2.3 From f08dea734844aa42ec57c229b0b73b3d7d21f810 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Mon, 10 Sep 2012 12:01:05 +0200 Subject: USB: ftdi_sio: do not claim CDC ACM function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Microchip vid:pid 04d8:000a is used for their CDC ACM demo firmware application. This is a device with a single function conforming to the CDC ACM specification and with the intention of demonstrating CDC ACM class firmware and driver interaction. The demo is used on a number of development boards, and may also be used unmodified by vendors using Microchip hardware. Some vendors have re-used this vid:pid for other types of firmware, emulating FTDI chips. Attempting to continue to support such devices without breaking class based applications that by matching on interface class/subclass/proto being ff/ff/00. I have no information about the actual device or interface descriptors, but this will at least make the proper CDC ACM devices work again. Anyone having details of the offending device's descriptors should update this entry with the details. Reported-by: Florian Wöhrl Reported-by: Xiaofan Chen Cc: stable Cc: Alan Cox Cc: Bruno Thomsen Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 +++- drivers/usb/serial/ftdi_sio_ids.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e2fa7881067d..f906b3aec217 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -805,7 +805,9 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, + { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, 0x00) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9bcaf9c3d3e4..41fe5826100c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -542,7 +542,10 @@ /* * Microchip Technology, Inc. * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications. The VID/PID has also been used in firmware + * emulating FTDI serial chips by: * Hornby Elite - Digital Command Control Console * http://www.hornby.com/hornby-dcc/controllers/ */ -- cgit v1.2.3 From 2120c52da6fe741454a60644018ad2a6abd957ac Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Fri, 7 Sep 2012 12:14:02 +0000 Subject: sierra_net: Endianess bug fix. I discovered I couldn't get sierra_net to work on a powerpc. Turns out the firmware attribute check assumes the system is little endian and hence fails because the attributes is a 16 bit value. Signed-off-by: Len Sorensen Signed-off-by: David S. Miller --- drivers/net/usb/sierra_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 7be49ea60b6d..8e22417fa6c1 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = *attrdata; + *datap = le16_to_cpu(*attrdata); kfree(attrdata); return result; -- cgit v1.2.3 From 974a3b0f9f05b748fe11f1afc31efc32aa5160cb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 9 Sep 2012 11:54:16 +0200 Subject: drm/i915: set the right gen3 flip_done mode also at resume Currently we've only frobbed this bit at irq_init time, but did not restore it at resume time. Move it to the gen3 clock gating function to fix this. Notice while reading through code. Cc: stable@vger.kernel.org (for 3.5 only) Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 3 --- drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a3828528b9d..5249640cce13 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev) dev->driver->irq_handler = i8xx_irq_handler; dev->driver->irq_uninstall = i8xx_irq_uninstall; } else if (INTEL_INFO(dev)->gen == 3) { - /* IIR "flip pending" means done if this bit is set */ - I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); - dev->driver->irq_preinstall = i915_irq_preinstall; dev->driver->irq_postinstall = i915_irq_postinstall; dev->driver->irq_uninstall = i915_irq_uninstall; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1881c8c83f0e..ba8a27b1757a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3672,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev) if (IS_PINEVIEW(dev)) I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); + + /* IIR "flip pending" means done if this bit is set */ + I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); } static void i85x_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3 From 0b836ddde177bdd5790ade83772860940bd481ea Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 10 Sep 2012 14:06:58 +0200 Subject: ixp4xx_hss: fix build failure due to missing linux/module.h inclusion Commit 36a1211970193ce215de50ed1e4e1272bc814df1 (netprio_cgroup.h: dont include module.h from other includes) made the following build error on ixp4xx_hss pop up: CC [M] drivers/net/wan/ixp4xx_hss.o drivers/net/wan/ixp4xx_hss.c:1412:20: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1413:25: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1414:21: error: expected ';', ',' or ')' before string constant drivers/net/wan/ixp4xx_hss.c:1415:19: error: expected ';', ',' or ')' before string constant make[8]: *** [drivers/net/wan/ixp4xx_hss.o] Error 1 This was previously hidden because ixp4xx_hss includes linux/hdlc.h which includes linux/netdevice.h which includes linux/netprio_cgroup.h which used to include linux/module.h. The real issue was actually present since the initial commit that added this driver since it uses macros from linux/module.h without including this file. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/wan/ixp4xx_hss.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa2293..3f575afd8cfc 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include -- cgit v1.2.3 From 6a44886899ef8cc396e230e492e6a56a883889f3 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Mon, 10 Sep 2012 22:17:34 +0200 Subject: USB: cdc-wdm: fix wdm_find_device* return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A logic error made the wdm_find_device* functions return a bogus pointer into static data instead of the intended NULL no matching device was found. Cc: stable # v3.4+ Cc: Oliver Neukum Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 65a55abb791f..5f0cb417b736 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -109,12 +109,14 @@ static struct usb_driver wdm_driver; /* return intfdata if we own the interface, else look up intf in the list */ static struct wdm_device *wdm_find_device(struct usb_interface *intf) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf == intf) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; @@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device_by_minor(int minor) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf->minor == minor) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; -- cgit v1.2.3 From abf02cfc179bb4bd30d05f582d61b3b8f429b813 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 Sep 2012 21:22:11 +0200 Subject: staging: r8712u: fix bug in r8712_recv_indicatepkt() 64bit arches have a buggy r8712u driver, let's fix it. skb->tail must be set properly or network stack behavior is undefined. Addresses https://bugzilla.redhat.com/show_bug.cgi?id=847525 Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45071 Signed-off-by: Eric Dumazet Cc: Dave Jones Cc: stable [2.6.37+] Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0e26d5f6cf2d..495ee1205e02 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter, if (skb == NULL) goto _recv_indicatepkt_drop; skb->data = precv_frame->u.hdr.rx_data; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - - precv_frame->u.hdr.rx_head); -#else - skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; -#endif skb->len = precv_frame->u.hdr.len; + skb_set_tail_pointer(skb, skb->len); if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) skb->ip_summed = CHECKSUM_UNNECESSARY; else -- cgit v1.2.3 From 3d037774b42ed677f699b1dce7d548d55f4e4c2b Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 7 Sep 2012 11:23:28 +0530 Subject: EHCI: Update qTD next pointer in QH overlay region during unlink There is a possibility of QH overlay region having reference to a stale qTD pointer during unlink. Consider an endpoint having two pending qTD before unlink process begins. The endpoint's QH queue looks like this. qTD1 --> qTD2 --> Dummy To unlink qTD2, QH is removed from asynchronous list and Asynchronous Advance Doorbell is programmed. The qTD1's next qTD pointer is set to qTD2'2 next qTD pointer and qTD2 is retired upon controller's doorbell interrupt. If QH's current qTD pointer points to qTD1, transfer overlay region still have reference to qTD2. But qtD2 is just unlinked and freed. This may cause EHCI system error. Fix this by updating qTD next pointer in QH overlay region with the qTD next pointer of the current qTD. Signed-off-by: Pavankumar Kondeti Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 9bc39ca460c8..4b66374bdc8e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) else { qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); - /* first qtd may already be partially processed */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) + /* + * first qtd may already be partially processed. + * If we come here during unlink, the QH overlay region + * might have reference to the just unlinked qtd. The + * qtd is updated in qh_completions(). Update the QH + * overlay here. + */ + if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { + qh->hw->hw_qtd_next = qtd->hw_next; qtd = NULL; + } } if (qtd) -- cgit v1.2.3 From 0b0d7b62bed81a76dd2b3f12ba6a33eb144a1df6 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 5 Sep 2012 16:48:53 -0500 Subject: drm/omap: update for interlaced 'struct omap_video_timings' was updated w/ a 'bool interlaced'. Without a matching update in omap_connector, this field could have undefined values from the stack, which isn't quite ideal. Update the fxns to convert omapdss<->drm timings structs, and zero-init 'struct omap_video_timings' when it is declared on stack to avoid issues like this in the future. Signed-off-by: Rob Clark Reviewed-by: Sumit Semwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_connector.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c0e0bb..5f4a89be3dda 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -48,13 +48,10 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, mode->vsync_end = mode->vsync_start + timings->vsw; mode->vtotal = mode->vsync_end + timings->vbp; - /* note: whether or not it is interlaced, +/- h/vsync, etc, - * which should be set in the mode flags, is not exposed in - * the omap_video_timings struct.. but hdmi driver tracks - * those separately so all we have to have to set the mode - * is the way to recover these timings values, and the - * omap_dss_driver would do the rest. - */ + mode->flags = 0; + + if (timings->interlace) + mode->flags |= DRM_MODE_FLAG_INTERLACE; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -71,6 +68,8 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vfp = mode->vsync_start - mode->vdisplay; timings->vsw = mode->vsync_end - mode->vsync_start; timings->vbp = mode->vtotal - mode->vsync_end; + + timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); } static void omap_connector_dpms(struct drm_connector *connector, int mode) @@ -187,7 +186,7 @@ static int omap_connector_get_modes(struct drm_connector *connector) } } else { struct drm_display_mode *mode = drm_mode_create(dev); - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; dssdrv->get_timings(dssdev, &timings); @@ -291,7 +290,7 @@ void omap_connector_mode_set(struct drm_connector *connector, struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; - struct omap_video_timings timings; + struct omap_video_timings timings = {0}; copy_timings_drm_to_omap(&timings, mode); -- cgit v1.2.3 From 94254edc9c5b4e864767c97bfa0e4ccff2ecb5e5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 7 Sep 2012 12:59:45 -0500 Subject: drm/omap: add more new timings fields Without these, DVI is broken. Signed-off-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/staging/omapdrm/omap_connector.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5f4a89be3dda..55e9c8655850 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -52,6 +52,16 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, if (timings->interlace) mode->flags |= DRM_MODE_FLAG_INTERLACE; + + if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + mode->flags |= DRM_MODE_FLAG_NVSYNC; } static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, @@ -70,6 +80,20 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, timings->vbp = mode->vtotal - mode->vsync_end; timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + else + timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW; + + timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; + timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; } static void omap_connector_dpms(struct drm_connector *connector, int mode) -- cgit v1.2.3 From b48d6f8bed430922f78f648d1f73f7c1591e472c Mon Sep 17 00:00:00 2001 From: Pierre Sauter Date: Mon, 10 Sep 2012 07:02:59 +0000 Subject: net: qmi_wwan: fix Gobi device probing for un2430 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HP un2430 is a Gobi 3000 device. It was mistakenly treated as Gobi 1000 in patch b9f90eb2740203ff2592efe640409ad48335d1c2. I own this device and qmi_wwan works again with this fix. Signed-off-by: Pierre Sauter Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index adfab3fc5478..17b8f3e37687 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -398,7 +398,6 @@ static const struct usb_device_id products[] = { /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ @@ -440,6 +439,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ -- cgit v1.2.3 From 75c5da279e06577190abba52cabf0dc2a56edb97 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Sep 2012 21:58:29 +0200 Subject: drm/i915: fix up the IBX transcoder B check This has been added in commit de9a35abb3b343a25065449234e47a76c4f3454a Author: Daniel Vetter Date: Tue Jun 5 11:03:40 2012 +0200 drm/i915: assert that the IBX port transcoder select w/a is implemented Unfortunately I've failed to notice that these checks are not just called for the port that is about to be disabled, but for all (which makes sense for an assert ...), and the WARN missfired when disabling another pipe than the one with the dp port. Hence also check whether the port is actually disabled. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54688 Reviewed-by: Paulo Zanoni Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2dfa6cf4886b..bc2ad348e5d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1376,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 + && (val & DP_PIPEB_SELECT), "IBX PCH dp port still using transcoder B\n"); } @@ -1388,7 +1389,8 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), + WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0 + && (val & SDVO_PIPE_B_SELECT), "IBX PCH hdmi port still using transcoder B\n"); } -- cgit v1.2.3 From ba9edaa468869a8cea242a411066b0f490751798 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Tue, 11 Sep 2012 09:40:31 +0200 Subject: USB: option: replace ZTE K5006-Z entry with vendor class rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the ZTE K5006-Z entry so that it actually matches anything commit f1b5c997 USB: option: add ZTE K5006-Z added a device specific entry assuming that the device would use class/subclass/proto == ff/ff/ff like other ZTE devices. It turns out that ZTE has started using vendor specific subclass and protocol codes: T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=19d2 ProdID=1018 Rev= 0.00 S: Manufacturer=ZTE,Incorporated S: Product=ZTE LTE Technologies MSM S: SerialNumber=MF821Vxxxxxxx C:* #Ifs= 5 Cfg#= 1 Atr=c0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=86 Prot=10 Driver=(none) E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=02 Prot=05 Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=02 Prot=01 Driver=(none) E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=06 Prot=00 Driver=qmi_wwan E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms We do not have any information on how ZTE intend to use these codes, but let us assume for now that the 3 sets matching serial functions in the K5006-Z always will identify a serial function in a ZTE device. Cc: Thomas Schäfer Cc: stable Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cc40f47ecea1..5ce88d1bc6f1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ -- cgit v1.2.3 From 73d7c119255615a26070f9d6cdb722a166a29015 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 19 Jun 2012 08:00:00 -0700 Subject: hwmon: (twl4030-madc-hwmon) Initialize uninitialized structure elements twl4030_madc_conversion uses do_avg and type structure elements of twl4030_madc_request. Initialize structure to avoid random operation. Fix for: Coverity CID 200794 Uninitialized scalar variable. Cc: Keerthy Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Acked-by: Keerthy --- drivers/hwmon/twl4030-madc-hwmon.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 0018c7dd0097..1a174f0a3cde 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req; + struct twl4030_madc_request req = { + .channels = 1 << attr->index, + .method = TWL4030_MADC_SW2, + .type = TWL4030_MADC_WAIT, + }; long val; - req.channels = (1 << attr->index); - req.method = TWL4030_MADC_SW2; - req.func_cb = NULL; val = twl4030_madc_conversion(&req); if (val < 0) return val; -- cgit v1.2.3 From 080b98e9ab30734bda2f1b8b33cd55a4c4ef406a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 11 Sep 2012 08:22:14 -0700 Subject: hwmon: (ina2xx) Fix word size register read and write operations The driver uses be16_to_cpu and cpu_to_be16 to convert data in SMBus word operations from chip to host byte order. However, the data passed from and to the SMBus word API functions is in host byte order, not in chip byte order. Conversion should therefore use swab16 instead of be16 to change the byte order. Replace driver internal word conversion functions with SMBus API functions to solve the problem. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org # 3.5+ Acked-by: Jean Delvare --- drivers/hwmon/ina2xx.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 7f3f4a385729..602148299f68 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -69,22 +69,6 @@ struct ina2xx_data { u16 regs[INA2XX_MAX_REGISTERS]; }; -int ina2xx_read_word(struct i2c_client *client, int reg) -{ - int val = i2c_smbus_read_word_data(client, reg); - if (unlikely(val < 0)) { - dev_dbg(&client->dev, - "Failed to read register: %d\n", reg); - return val; - } - return be16_to_cpu(val); -} - -void ina2xx_write_word(struct i2c_client *client, int reg, int data) -{ - i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); -} - static struct ina2xx_data *ina2xx_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -102,7 +86,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev) /* Read all registers */ for (i = 0; i < data->registers; i++) { - int rv = ina2xx_read_word(client, i); + int rv = i2c_smbus_read_word_swapped(client, i); if (rv < 0) { ret = ERR_PTR(rv); goto abort; @@ -279,22 +263,26 @@ static int ina2xx_probe(struct i2c_client *client, switch (data->kind) { case ina219: /* device configuration */ - ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT); + i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, + INA219_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 13 in datasheet) */ - ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt); + i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, + 40960000 / shunt); dev_info(&client->dev, "power monitor INA219 (Rshunt = %li uOhm)\n", shunt); data->registers = INA219_REGISTERS; break; case ina226: /* device configuration */ - ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT); + i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, + INA226_CONFIG_DEFAULT); /* set current LSB to 1mA, shunt is in uOhms */ /* (equation 1 in datasheet)*/ - ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt); + i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, + 5120000 / shunt); dev_info(&client->dev, "power monitor INA226 (Rshunt = %li uOhm)\n", shunt); data->registers = INA226_REGISTERS; -- cgit v1.2.3 From b3aafe80c83097403d2b5edccfc440fac3d5f028 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Aug 2012 09:42:31 +0200 Subject: i2c: pnx: Fix bit definitions The I2C Control Register bits RFDAIE and RFFIE were mixed up. In addition to this fix, this patch adds the missing bit DRSIE for completeness. Signed-off-by: Roland Stigge Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d54416770b0..b36e21f9fd53 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -48,8 +48,9 @@ enum { mcntrl_afie = 0x00000002, mcntrl_naie = 0x00000004, mcntrl_drmie = 0x00000008, - mcntrl_daie = 0x00000020, - mcntrl_rffie = 0x00000040, + mcntrl_drsie = 0x00000010, + mcntrl_rffie = 0x00000020, + mcntrl_daie = 0x00000040, mcntrl_tffie = 0x00000080, mcntrl_reset = 0x00000100, mcntrl_cdbmode = 0x00000400, -- cgit v1.2.3 From c076ada4e4aaf45e1a31ad6de7c6cce36081e045 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Aug 2012 09:42:32 +0200 Subject: i2c: pnx: Fix read transactions of >= 2 bytes On transactions with n>=2 bytes, the controller actually wrongly clocks in n+1 bytes. This is caused by the (wrong) assumption that RFE in the Status Register is 1 iff there is no byte already ordered (via a dummy TX byte). This lead to the implementation of synchronized byte ordering, e.g.: Dummy-TX - RX - Dummy-TX - RX - ... But since RFE actually stays high after some Dummy-TX, it rather looks like: Dummy-TX - Dummy-TX - RX - Dummy-TX - RX - (RX) The last RX byte is clocked in by the bus controller, but ignored by the kernel when filling the userspace buffer. This patch fixes the issue by asking for RX via Dummy-TX asynchronously. Introducing a separate counter for TX bytes. Signed-off-by: Roland Stigge Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 48 ++++++++++++++++++++++++++------------------ include/linux/i2c-pnx.h | 1 + 2 files changed, 29 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index b36e21f9fd53..8488bddfe465 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -291,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) * or we didn't 'ask' for it yet. */ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&alg_data->adapter.dev, - "%s(): Write dummy data to fill Rx-fifo...\n", - __func__); + /* 'Asking' is done asynchronously, e.g. dummy TX of several + * bytes is done before the first actual RX arrives in FIFO. + * Therefore, ordered bytes (via TX) are counted separately. + */ + if (alg_data->mif.order) { + dev_dbg(&alg_data->adapter.dev, + "%s(): Write dummy data to fill Rx-fifo...\n", + __func__); - if (alg_data->mif.len == 1) { - /* Last byte, do not acknowledge next rcv. */ - val |= stop_bit; + if (alg_data->mif.order == 1) { + /* Last byte, do not acknowledge next rcv. */ + val |= stop_bit; + + /* + * Enable interrupt RFDAIE (data in Rx fifo), + * and disable DRMIE (need data for Tx) + */ + ctl = ioread32(I2C_REG_CTL(alg_data)); + ctl |= mcntrl_rffie | mcntrl_daie; + ctl &= ~mcntrl_drmie; + iowrite32(ctl, I2C_REG_CTL(alg_data)); + } /* - * Enable interrupt RFDAIE (data in Rx fifo), - * and disable DRMIE (need data for Tx) + * Now we'll 'ask' for data: + * For each byte we want to receive, we must + * write a (dummy) byte to the Tx-FIFO. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl |= mcntrl_rffie | mcntrl_daie; - ctl &= ~mcntrl_drmie; - iowrite32(ctl, I2C_REG_CTL(alg_data)); + iowrite32(val, I2C_REG_TX(alg_data)); + alg_data->mif.order--; } - - /* - * Now we'll 'ask' for data: - * For each byte we want to receive, we must - * write a (dummy) byte to the Tx-FIFO. - */ - iowrite32(val, I2C_REG_TX(alg_data)); - return 0; } @@ -515,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) alg_data->mif.buf = pmsg->buf; alg_data->mif.len = pmsg->len; + alg_data->mif.order = pmsg->len; alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? I2C_SMBUS_READ : I2C_SMBUS_WRITE; alg_data->mif.ret = 0; @@ -567,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) /* Cleanup to be sure... */ alg_data->mif.buf = NULL; alg_data->mif.len = 0; + alg_data->mif.order = 0; dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", __func__, ioread32(I2C_REG_STS(alg_data))); diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h index 1bc74afe7a35..49ed17fdf055 100644 --- a/include/linux/i2c-pnx.h +++ b/include/linux/i2c-pnx.h @@ -22,6 +22,7 @@ struct i2c_pnx_mif { struct timer_list timer; /* Timeout */ u8 * buf; /* Data buffer */ int len; /* Length of data buffer */ + int order; /* RX Bytes to order via TX */ }; struct i2c_pnx_algo_data { -- cgit v1.2.3 From 72ee734a6716aac5aaf336da70a811e308d2a84e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 8 Sep 2012 17:28:06 +0200 Subject: i2c: mxs: correctly setup speed for non devicetree Commit cd4f2d4 (i2c: mxs: Set I2C timing registers for mxs-i2c) only covered the case for devicetree and made platform_data based boards bail out with -EINVAL. Correctly support the latter one, too. Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mxs.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 088c5c1ed17d..51f05b8520ed 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) struct device_node *node = dev->of_node; int ret; - if (!node) - return -EINVAL; - - i2c->speed = &mxs_i2c_95kHz_config; ret = of_property_read_u32(node, "clock-frequency", &speed); if (ret) dev_warn(dev, "No I2C speed selected, using 100kHz\n"); @@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) return err; i2c->dev = dev; + i2c->speed = &mxs_i2c_95kHz_config; - err = mxs_i2c_get_ofdata(i2c); - if (err) - return err; + if (dev->of_node) { + err = mxs_i2c_get_ofdata(i2c); + if (err) + return err; + } platform_set_drvdata(pdev, i2c); -- cgit v1.2.3 From 7f67c38bdcb6d8bce02e10521fbf1618b586319f Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:00 +0300 Subject: usb: chipidea: udc: fix setup of endpoint maxpacket size This patch changes the setup of the endpoint maxpacket size. All non control endpoints are initialized with an undefined ((unsigned short)~0) maxpacket size. The maxpacket size of Endpoint 0 will be kept at CTRL_PAYLOAD_MAX. Some gadget drivers check for the maxpacket size before they enable the endpoint, which leads to a wrong state in these drivers. Cc: stable Signed-off-by: Michael Grzeschik Acked-by: Felipe Balbi Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c7a032a4f0c5..7801a3f8be90 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1455,7 +1455,12 @@ static int init_eps(struct ci13xxx *ci) mEp->ep.name = mEp->name; mEp->ep.ops = &usb_ep_ops; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; + /* + * for ep0: maxP defined in desc, for other + * eps, maxP is set by epautoconfig() called + * by gadget layer + */ + mEp->ep.maxpacket = (unsigned short)~0; INIT_LIST_HEAD(&mEp->qh.queue); mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, @@ -1475,6 +1480,7 @@ static int init_eps(struct ci13xxx *ci) else ci->ep0in = mEp; + mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; continue; } -- cgit v1.2.3 From c0a48e6c75f2ac190d812bea5fc339696e434c2e Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:01 +0300 Subject: usb: chipidea: udc: add pullup fuction, needed by the uvc gadget Add function to physicaly enable or disable of pullup connection on the USB-D+ line. The uvc gaget will fail, if this function is not implemented. Cc: stable Signed-off-by: Michael Grzeschik Acked-by: Felipe Balbi Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 7801a3f8be90..32ee8701e199 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) } /** - * hw_device_state: enables/disables interrupts & starts/stops device (execute - * without interruption) + * hw_device_state: enables/disables interrupts (execute without interruption) * @dma: 0 => disable, !0 => enable and set dma engine * * This function returns an error code @@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) /* interrupt, error, port change, reset, sleep/suspend */ hw_write(ci, OP_USBINTR, ~0, USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); - hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); } else { - hw_write(ci, OP_USBCMD, USBCMD_RS, 0); hw_write(ci, OP_USBINTR, ~0, 0); } return 0; @@ -1420,6 +1417,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) return -ENOTSUPP; } +/* Change Data+ pullup status + * this func is used by usb_gadget_connect/disconnet + */ +static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) +{ + struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); + + if (is_on) + hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); + else + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); + + return 0; +} + static int ci13xxx_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int ci13xxx_stop(struct usb_gadget *gadget, @@ -1432,6 +1444,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, static const struct usb_gadget_ops usb_gadget_ops = { .vbus_session = ci13xxx_vbus_session, .wakeup = ci13xxx_wakeup, + .pullup = ci13xxx_pullup, .vbus_draw = ci13xxx_vbus_draw, .udc_start = ci13xxx_start, .udc_stop = ci13xxx_stop, -- cgit v1.2.3 From c9d1f947a85e38b6dded469470c95ed62430cb3f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Sep 2012 14:58:02 +0300 Subject: usb: chipidea: udc: fix error path in udc_start() This patch fixes the error path of udc_start(). Now NULL is used to unset the peripheral with otg_set_peripheral(). Cc: stable Reviewed-by: Richard Zhao Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 32ee8701e199..3a755e5160cf 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1748,7 +1748,7 @@ static int udc_start(struct ci13xxx *ci) remove_trans: if (!IS_ERR_OR_NULL(ci->transceiver)) { - otg_set_peripheral(ci->transceiver->otg, &ci->gadget); + otg_set_peripheral(ci->transceiver->otg, NULL); if (ci->global_phy) usb_put_phy(ci->transceiver); } -- cgit v1.2.3 From ad6b1b97fe8504957d017cd6e4168cac8903d3f3 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 12 Sep 2012 14:58:03 +0300 Subject: usb: chipidea: cleanup dma_pool if udc_start() fails If udc_start() fails the qh_pool dma-pool cannot be closed because it's still in use. This patch factors out the dma_pool_free() loop into destroy_eps() and calls it in the error path of udc_start(), too. Cc: stable Reviewed-by: Richard Zhao Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 3a755e5160cf..2d8b6092f80d 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1503,6 +1503,17 @@ static int init_eps(struct ci13xxx *ci) return retval; } +static void destroy_eps(struct ci13xxx *ci) +{ + int i; + + for (i = 0; i < ci->hw_ep_max; i++) { + struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; + + dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); + } +} + /** * ci13xxx_start: register a gadget driver * @gadget: our gadget @@ -1710,7 +1721,7 @@ static int udc_start(struct ci13xxx *ci) if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (ci->transceiver == NULL) { retval = -ENODEV; - goto free_pools; + goto destroy_eps; } } @@ -1761,6 +1772,8 @@ unreg_device: put_transceiver: if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) usb_put_phy(ci->transceiver); +destroy_eps: + destroy_eps(ci); free_pools: dma_pool_destroy(ci->td_pool); free_qh_pool: @@ -1775,18 +1788,12 @@ free_qh_pool: */ static void udc_stop(struct ci13xxx *ci) { - int i; - if (ci == NULL) return; usb_del_gadget_udc(&ci->gadget); - for (i = 0; i < ci->hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; - - dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); - } + destroy_eps(ci); dma_pool_destroy(ci->td_pool); dma_pool_destroy(ci->qh_pool); -- cgit v1.2.3 From db89960e50f45274c07dc60926b5a49489b8a7a0 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 12 Sep 2012 14:58:04 +0300 Subject: usb: chipidea: udc: don't stall endpoint if request list is empty in isr_tr_complete_low When attaching an imx28 or imx53 in USB gadget mode to a Windows host and starting a rndis connection we see this message every 4-10 seconds: g_ether gadget: high speed config #2: RNDIS Analysis shows that each time this message is printed, the rndis connection is re-establish due to a reset because of a stalled endpoint (ep 0, dir 1). The endpoint is stalled because the reqeust complete bit on that endpoint is set, but in isr_tr_complete_low() the endpoint request list (mEp->qh.queue) is empty. This patch removed this check, because the code doesn't take the following situation into account: The loop over all endpoints in isr_tr_complete_handler() will call ep_nuke() on both ep0/dir0 and ep/dir1 in the first loop. Pending reqeusts will be flushed and completed here. There seems to be a race condition, the request is nuked, but the request complete bit will be set, too. The subsequent check (in ep0/dir1's loop cycle) for endpoint request list (mEp->qh.queue) empty will fail. Both other mainline chipidea drivers (mv_udc_core.c and fsl_udc_core.c) don't have this check. Cc: stable Signed-off-by: Michael Grzeschik Signed-off-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 2d8b6092f80d..d214448b677e 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -771,10 +771,7 @@ __acquires(mEp->lock) { struct ci13xxx_req *mReq, *mReqTemp; struct ci13xxx_ep *mEpTemp = mEp; - int uninitialized_var(retval); - - if (list_empty(&mEp->qh.queue)) - return -EINVAL; + int retval = 0; list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, queue) { -- cgit v1.2.3 From 26df641eac05abe1a3276eea441359b4d1120816 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 12 Sep 2012 10:05:04 +0000 Subject: gma500: Fix regression on Oaktrail devices The register map patches didn't set one value for the GMA600 which means the Fujitsu Q550 dies on boot with the GMA500 driver enabled. Add the map entry so we don't read from the device MMIO + 0 by mistake. Signed-off-by: Alan Cox Cc: Horses Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/oaktrail_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 0f9b7db80f6b..cf49ba5a54bf 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPAPOS, .surf = DSPASURF, .addr = MRST_DSPABASE, + .base = MRST_DSPABASE, .status = PIPEASTAT, .linoff = DSPALINOFF, .tileoff = DSPATILEOFF, @@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPBPOS, .surf = DSPBSURF, .addr = DSPBBASE, + .base = DSPBBASE, .status = PIPEBSTAT, .linoff = DSPBLINOFF, .tileoff = DSPBTILEOFF, -- cgit v1.2.3 From 5e1782d224c79b26ab7d5c31e3f87657000714fb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 28 Aug 2012 01:53:54 +0000 Subject: vmwgfx: add dumb ioctl support Testing and works with the -modesetting driver, Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 10 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 73 ++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 33bfc2033009..ba2c35dbf10e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1155,6 +1155,11 @@ static struct drm_driver driver = { .open = vmw_driver_open, .preclose = vmw_preclose, .postclose = vmw_postclose, + + .dumb_create = vmw_dumb_create, + .dumb_map_offset = vmw_dumb_map_offset, + .dumb_destroy = vmw_dumb_destroy, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee27..29c984ff7f23 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); /** * Overlay control - vmwgfx_overlay.c */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 22bf9a21ec71..2c6ffe0e2c07 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ err_ref: vmw_resource_unreference(&res); return ret; } + + +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct vmw_user_dma_buffer *vmw_user_bo; + struct ttm_buffer_object *tmp; + int ret; + + args->pitch = args->width * ((args->bpp + 7) / 8); + args->size = args->pitch * args->height; + + vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); + if (vmw_user_bo == NULL) + return -ENOMEM; + + ret = ttm_read_lock(&vmaster->lock, true); + if (ret != 0) { + kfree(vmw_user_bo); + return ret; + } + + ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, + &vmw_vram_sys_placement, true, + &vmw_user_dmabuf_destroy); + if (ret != 0) + goto out_no_dmabuf; + + tmp = ttm_bo_reference(&vmw_user_bo->dma.base); + ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, + &vmw_user_bo->base, + false, + ttm_buffer_type, + &vmw_user_dmabuf_release, NULL); + if (unlikely(ret != 0)) + goto out_no_base_object; + + args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: + ttm_bo_unref(&tmp); +out_no_dmabuf: + ttm_read_unlock(&vmaster->lock); + return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_dma_buffer *out_buf; + int ret; + + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); + if (ret != 0) + return -EINVAL; + + *offset = out_buf->base.addr_space_offset; + vmw_dmabuf_unreference(&out_buf); + return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle) +{ + return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); +} -- cgit v1.2.3 From 7ba073cdd8b770f990916a7b506d7b31fadb70a5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:16 +0530 Subject: drm/exynos: Remove redundant check in exynos_hdmi.c file devm_request_and_ioremap function checks the validity of the pointer returned by platform_get_resource. Hence an additional check in the probe function is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 409e2ec1207c..bb504cbd7898 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - DRM_ERROR("failed to find registers\n"); - ret = -ENOENT; - goto err_resource; - } hdata->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hdata->regs) { -- cgit v1.2.3 From 16e197417de3414af7c183f7f4abfa2c7e37f297 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:17 +0530 Subject: drm/exynos: Remove redundant check in exynos_drm_fimd.c file devm_request_and_ioremap function checks the validity of the pointer returned by platform_get_resource. Hence an additional check in the probe function is not necessary. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a68d2b313f03..b19cd93e7047 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to find registers\n"); - ret = -ENOENT; - goto err_clk; - } ctx->regs = devm_request_and_ioremap(&pdev->dev, res); if (!ctx->regs) { -- cgit v1.2.3 From 59848db5055765a5d012ad7c428124eca1fcc625 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:18 +0530 Subject: drm/exynos: Use devm_kzalloc in exynos_drm_vidi.c file devm_kzalloc is a device managed function and makes freeing and error handling simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index bb1550c4dd57..537027a74fd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev) ctx->raw_edid = NULL; } - kfree(ctx); - return 0; } -- cgit v1.2.3 From ae18294018c7cf098777a33086073321477f723f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:19 +0530 Subject: drm/exynos: Use devm_kzalloc in exynos_drm_hdmi.c file devm_kzalloc is a device managed function and makes freeing and error handling simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 8ffcdf8b9e22..3fdf0b65f47e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_LOG_KMS("failed to alloc common hdmi context.\n"); return -ENOMEM; @@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); exynos_drm_subdrv_unregister(&ctx->subdrv); - kfree(ctx); return 0; } -- cgit v1.2.3 From b767593349c92049dcea4a8ce5c534c4a470099b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 6 Aug 2012 12:16:20 +0530 Subject: drm/exynos: Use devm_* functions in exynos_drm_g2d.c file devm_* functions are device managed functions and make error handling and cleanup cleaner and simpler. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 50 +++++++-------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index d2d88f22a037..6adfa4e03265 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -129,7 +129,6 @@ struct g2d_runqueue_node { struct g2d_data { struct device *dev; struct clk *gate_clk; - struct resource *regs_res; void __iomem *regs; int irq; struct workqueue_struct *g2d_workq; @@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) struct exynos_drm_subdrv *subdrv; int ret; - g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); + g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL); if (!g2d) { dev_err(dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev) g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", sizeof(struct g2d_runqueue_node), 0, 0, NULL); - if (!g2d->runqueue_slab) { - ret = -ENOMEM; - goto err_free_mem; - } + if (!g2d->runqueue_slab) + return -ENOMEM; g2d->dev = dev; @@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev) pm_runtime_enable(dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to get I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - g2d->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!g2d->regs_res) { - dev_err(dev, "failed to request I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - - g2d->regs = ioremap(res->start, resource_size(res)); + g2d->regs = devm_request_and_ioremap(&pdev->dev, res); if (!g2d->regs) { dev_err(dev, "failed to remap I/O memory\n"); ret = -ENXIO; - goto err_release_res; + goto err_put_clk; } g2d->irq = platform_get_irq(pdev, 0); if (g2d->irq < 0) { dev_err(dev, "failed to get irq\n"); ret = g2d->irq; - goto err_unmap_base; + goto err_put_clk; } - ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); + ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, + "drm_g2d", g2d); if (ret < 0) { dev_err(dev, "irq request failed\n"); - goto err_unmap_base; + goto err_put_clk; } platform_set_drvdata(pdev, g2d); @@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev) ret = exynos_drm_subdrv_register(subdrv); if (ret < 0) { dev_err(dev, "failed to register drm g2d device\n"); - goto err_free_irq; + goto err_put_clk; } dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", @@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev) return 0; -err_free_irq: - free_irq(g2d->irq, g2d); -err_unmap_base: - iounmap(g2d->regs); -err_release_res: - release_resource(g2d->regs_res); - kfree(g2d->regs_res); err_put_clk: pm_runtime_disable(dev); clk_put(g2d->gate_clk); @@ -862,8 +840,6 @@ err_destroy_workqueue: destroy_workqueue(g2d->g2d_workq); err_destroy_slab: kmem_cache_destroy(g2d->runqueue_slab); -err_free_mem: - kfree(g2d); return ret; } @@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev) cancel_work_sync(&g2d->runqueue_work); exynos_drm_subdrv_unregister(&g2d->subdrv); - free_irq(g2d->irq, g2d); while (g2d->runqueue_node) { g2d_free_runqueue_node(g2d, g2d->runqueue_node); g2d->runqueue_node = g2d_get_runqueue_node(g2d); } - iounmap(g2d->regs); - release_resource(g2d->regs_res); - kfree(g2d->regs_res); - pm_runtime_disable(&pdev->dev); clk_put(g2d->gate_clk); g2d_fini_cmdlist(g2d); destroy_workqueue(g2d->g2d_workq); kmem_cache_destroy(g2d->runqueue_slab); - kfree(g2d); return 0; } -- cgit v1.2.3 From 4fbd9a4539e4eda1e9588509eb31e9dc38ffd653 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 7 Aug 2012 08:57:25 +0200 Subject: drm/exynos: Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(.. [1] The semantic patch that makes this change is available in scripts/coccinelle/api/err_cast.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index f9efde40c097..da4e3ca219fa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -122,7 +122,7 @@ fail: __free_page(pages[i]); drm_free_large(pages); - return ERR_PTR(PTR_ERR(p)); + return ERR_CAST(p); } static void exynos_gem_put_pages(struct drm_gem_object *obj, -- cgit v1.2.3 From 7da5907c84f8b092dc42b47b5c19684c1b3b4c98 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 17 Aug 2012 15:24:03 +0900 Subject: drm/exynos: fixed page align bug. do not align in page unit at dumb creation. the align is done by exynos_drm_gem_create() to be called commonly. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index da4e3ca219fa..a38051c95ec4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, */ args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = PAGE_ALIGN(args->pitch * args->height); + args->size = args->pitch * args->height; exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); if (IS_ERR(exynos_gem_obj)) -- cgit v1.2.3 From 254d4d111ee159a39d4afb30d9515036d1e0b027 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 14 Aug 2012 12:07:20 +0530 Subject: drm/exynos: Add dependency for G2D in Kconfig Select Exynos DRM based G2D only if non-DRM based Exynos G2D driver is not selected. Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 7f5096763b7d..59a26e577b57 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI config DRM_EXYNOS_G2D bool "Exynos DRM G2D" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D help Choose this option if you want to use Exynos G2D for DRM. -- cgit v1.2.3 From 9e1355e7d9c0dac39b9bc4e146a49d379f43ba42 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 28 Aug 2012 14:11:41 +0530 Subject: drm/exynos: Make g2d_pm_ops static Fixes the following warning: drivers/gpu/drm/exynos/exynos_drm_g2d.c:897:1: warning: symbol 'g2d_pm_ops' was not declared. Should it be static? Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6adfa4e03265..1065e90d0919 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -894,7 +894,7 @@ static int g2d_resume(struct device *dev) } #endif -SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); +static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); struct platform_driver g2d_driver = { .probe = g2d_probe, -- cgit v1.2.3 From adc837ac3c6eb76d734e471512eaeba210fa5e98 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 Aug 2012 15:50:47 +0530 Subject: drm/exynos: Add missing braces around sizeof in exynos_hdmi.c Fixes the following checkpatch warnings: WARNING: sizeof *res should be sizeof(*res) WARNING: sizeof res->regul_bulk[0] should be sizeof(res->regul_bulk[0]) WARNING: sizeof *res should be sizeof(*res) Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index bb504cbd7898..a6aea6f3ea1a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) DRM_DEBUG_KMS("HDMI resource init\n"); - memset(res, 0, sizeof *res); + memset(res, 0, sizeof(*res)); /* get clocks, power */ res->hdmi = clk_get(dev, "hdmi"); @@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata) clk_set_parent(res->sclk_hdmi, res->sclk_pixel); res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * - sizeof res->regul_bulk[0], GFP_KERNEL); + sizeof(res->regul_bulk[0]), GFP_KERNEL); if (!res->regul_bulk) { DRM_ERROR("failed to get memory for regulators\n"); goto fail; @@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata) clk_put(res->sclk_hdmi); if (!IS_ERR_OR_NULL(res->hdmi)) clk_put(res->hdmi); - memset(res, 0, sizeof *res); + memset(res, 0, sizeof(*res)); return 0; } -- cgit v1.2.3 From e25e1b6654e3d80da7a40561ec6dba6c5e7e12d3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 31 Aug 2012 15:50:48 +0530 Subject: drm/exynos: Add missing braces around sizeof in exynos_mixer.c Fixes the following checkpatch warnings: WARNING: sizeof filter_y_horiz_tap8 should be sizeof(filter_y_horiz_tap8) WARNING: sizeof filter_y_vert_tap4 should be sizeof(filter_y_vert_tap4) WARNING: sizeof filter_cr_horiz_tap4 should be sizeof(filter_cr_horiz_tap4) Signed-off-by: Sachin Kamat Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_mixer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 30fcc12f81dd..25b97d5e5fcb 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res, static void vp_default_filter(struct mixer_resources *res) { vp_filter_set(res, VP_POLY8_Y0_LL, - filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); + filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); vp_filter_set(res, VP_POLY4_Y0_LL, - filter_y_vert_tap4, sizeof filter_y_vert_tap4); + filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); vp_filter_set(res, VP_POLY4_C0_LL, - filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); + filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); } static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) -- cgit v1.2.3 From b716d46e003fc12f64bbdd71e5b9fd733e59b8d4 Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski Date: Wed, 5 Sep 2012 19:31:56 +0900 Subject: drm/exynos: add dummy support for dmabuf-mmap This patch adds a stub function for DMABUF mmap. This allows to export a DMABUF. Signed-off-by: Tomasz Stanislawski Signed-off-by: Kyungmin Park Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 613bf8a5d9b2..ae13febe0eaa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, /* TODO */ } +static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, + struct vm_area_struct *vma) +{ + return -ENOTTY; +} + static struct dma_buf_ops exynos_dmabuf_ops = { .map_dma_buf = exynos_gem_map_dma_buf, .unmap_dma_buf = exynos_gem_unmap_dma_buf, @@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = { .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, .kunmap = exynos_gem_dmabuf_kunmap, .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, + .mmap = exynos_gem_dmabuf_mmap, .release = exynos_dmabuf_release, }; -- cgit v1.2.3 From 525ee699f08c0d2516103e4ffd57c21041405d0c Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Thu, 6 Sep 2012 09:49:23 -0700 Subject: drm/exynos: fix double call of drm_prime_(init/destroy)_file_private The double invocations are incorrect but seem to be safe so I don't think this will fix any bugs. Before: [ 7.639366] drm_prime_init_file ee3675d0 [ 7.639377] drm_prime_init_file ee3675d0 [ 7.639507] drm_prime_destroy_file ee3675d0 [ 7.639518] drm_prime_destroy_file ee3675d0 [ 7.639802] drm_prime_init_file ee372390 [ 7.639810] drm_prime_init_file ee372390 [ 8.473316] drm_prime_init_file ee356390 [ 8.473331] drm_prime_init_file ee356390 After: [ 6.363842] drm_prime_init_file edc2e5d0 [ 6.363994] drm_prime_destroy_file edc2e5d0 [ 6.364260] drm_prime_init_file edc2e750 [ 8.004837] drm_prime_init_file ee36ded0 Signed-off-by: Mandeep Singh Baines Acked-by: Seung-Woo Kim Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 6345abe9fdee..d07071937453 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (!file_priv) return -ENOMEM; - drm_prime_init_file_private(&file->prime); file->driver_priv = file_priv; return exynos_drm_subdrv_open(dev, file); @@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev, e->base.destroy(&e->base); } } - drm_prime_destroy_file_private(&file->prime); spin_unlock_irqrestore(&dev->event_lock, flags); exynos_drm_subdrv_close(dev, file); -- cgit v1.2.3 From ece82d624cd0ca783e3fa2377fbbce6dd01ec1b3 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 7 Sep 2012 16:18:15 +0900 Subject: drm/exynos: remove DRM_FORMAT_NV12M from plane module this patch removes DRM_FORMAT_NV12M from plane module because this format is same as DRM_FORMAT_NV12. DRM_FORMAT_NV12M will be identified by mode_cmd->handles and mode_cmd->offsets fields internally. Signed-off-by: Inki Dae Signed-off-by: Kyungmin.park --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index b89829e5043a..e1f94b746bd7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -29,7 +29,6 @@ static const uint32_t formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_NV12, - DRM_FORMAT_NV12M, DRM_FORMAT_NV12MT, }; -- cgit v1.2.3 From 1fefb8fdc6562057a0e4e4542f3d4323981c9686 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 10 Sep 2012 01:09:04 +0100 Subject: ahci: Add JMicron 362 device IDs The JMicron JMB362 controller supports AHCI only, but some revisions use the IDE class code. These need to be matched by device ID. These additions have apparently been included by QNAP in their NAS devices using these controllers. References: http://bugs.debian.org/634180 Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 50d5dea0ff59..c3f52eb97fca 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -268,6 +268,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, + /* JMicron 362B and 362C have an AHCI function with IDE class code */ + { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, + { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ -- cgit v1.2.3 From 17c60c6b763cb5b83b0185e7d38d01d18e55a05a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:07:18 +0100 Subject: ahci: Add alternate identifier for the 88SE9172 This can also appear as 0x9192. Reported in bugzilla and confirmed with the board documentation for these boards. Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42970 Signed-off-by: Alan Cox Cc: The Stables Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c3f52eb97fca..51548dd60977 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -396,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(0x1b4b, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, -- cgit v1.2.3 From 7b4f6ecacb14f384adc1a5a67ad95eb082c02bd1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 Sep 2012 16:25:25 +0100 Subject: ahci: Add identifiers for ASM106x devices They don't always appear as AHCI class devices but instead as IDE class. Based on an initial patch by Hiroaki Nito Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=42804 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 51548dd60977..7862d17976b7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -405,7 +405,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From 4b921eda53366b319602351ff4d7256fafa4bd1b Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Thu, 13 Sep 2012 04:36:20 +0000 Subject: mISDN: Fix wrong usage of flush_work_sync while holding locks It is a bad idea to hold a spinlock and call flush_work_sync. Move the workqueue cleanup outside the spinlock and use cancel_work_sync, on closing the channel this seems to be the more correct function. Remove the never used and constant return value of mISDN_freebchannel. Signed-off-by: Karsten Keil Cc: Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/avmfritz.c | 3 ++- drivers/isdn/hardware/mISDN/mISDNipac.c | 3 ++- drivers/isdn/hardware/mISDN/mISDNisar.c | 3 ++- drivers/isdn/hardware/mISDN/netjet.c | 3 ++- drivers/isdn/hardware/mISDN/w6692.c | 3 ++- drivers/isdn/mISDN/hwchannel.c | 9 ++++----- include/linux/mISDNhw.h | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index fa6ca4733725..dceaec821b0e 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&fc->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); modehdlc(bch, ISDN_P_NONE); spin_unlock_irqrestore(&fc->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 752e0825591f..ccd7d851be26 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(hx->ip->hwlock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); hscx_mode(hx, ISDN_P_NONE); spin_unlock_irqrestore(hx->ip->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index be5973ded6d6..182ecf0626c2 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(ich->is->hwlock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); modeisar(ich, ISDN_P_NONE); spin_unlock_irqrestore(ich->is->hwlock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index c3e3e7686273..9bcade59eb73 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); mode_tiger(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 26a86b846099..335fe6455002 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) switch (cmd) { case CLOSE_CHANNEL: test_and_clear_bit(FLG_OPEN, &bch->Flags); + cancel_work_sync(&bch->workq); spin_lock_irqsave(&card->lock, flags); - mISDN_freebchannel(bch); + mISDN_clear_bchannel(bch); w6692_mode(bc, ISDN_P_NONE); spin_unlock_irqrestore(&card->lock, flags); ch->protocol = ISDN_P_NONE; diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index ef34fd40867c..2602be23f341 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch) ch->next_minlen = ch->init_minlen; ch->maxlen = ch->init_maxlen; ch->next_maxlen = ch->init_maxlen; + skb_queue_purge(&ch->rqueue); + ch->rcount = 0; } EXPORT_SYMBOL(mISDN_clear_bchannel); -int +void mISDN_freebchannel(struct bchannel *ch) { + cancel_work_sync(&ch->workq); mISDN_clear_bchannel(ch); - skb_queue_purge(&ch->rqueue); - ch->rcount = 0; - flush_work_sync(&ch->workq); - return 0; } EXPORT_SYMBOL(mISDN_freebchannel); diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h index d0752eca9b44..9d96d5d4dfed 100644 --- a/include/linux/mISDNhw.h +++ b/include/linux/mISDNhw.h @@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short, unsigned short); extern int mISDN_freedchannel(struct dchannel *); extern void mISDN_clear_bchannel(struct bchannel *); -extern int mISDN_freebchannel(struct bchannel *); +extern void mISDN_freebchannel(struct bchannel *); extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); extern void queue_ch_frame(struct mISDNchannel *, u_int, int, struct sk_buff *); -- cgit v1.2.3 From 8624dd2a3e33b647cd672211b54ba276ddee2a2c Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Wed, 12 Sep 2012 20:44:35 +0000 Subject: net: qmi_wwan: call subdriver with control intf only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a hang on suspend due to calling wdm_suspend on the unregistered data interface. The hang should have been a NULL pointer reference had it not been for a logic error in the cdc_wdm code. commit 230718bd net: qmi_wwan: bind to both control and data interface changed qmi_wwan to use cdc_wdm as a subdriver for devices with a two-interface QMI/wwan function. The commit failed to update qmi_wwan_suspend and qmi_wwan_resume, which were written to handle either a single combined interface function, or no subdriver at all. The result was that we called into the subdriver both when the control interface was suspended and when the data interface was suspended. Calling the subdriver suspend function with an unregistered interface is not supported and will make the subdriver bug out. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 17b8f3e37687..b1ba68f1a049 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) if (ret < 0) goto err; - if (info->subdriver && info->subdriver->suspend) + if (intf == info->control && info->subdriver && info->subdriver->suspend) ret = info->subdriver->suspend(intf, message); if (ret < 0) usbnet_resume(intf); @@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf) struct usbnet *dev = usb_get_intfdata(intf); struct qmi_wwan_state *info = (void *)&dev->data; int ret = 0; + bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume); - if (info->subdriver && info->subdriver->resume) + if (callsub) ret = info->subdriver->resume(intf); if (ret < 0) goto err; ret = usbnet_resume(intf); - if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend) + if (ret < 0 && callsub && info->subdriver->suspend) info->subdriver->suspend(intf, PMSG_SUSPEND); err: return ret; -- cgit v1.2.3 From 985f61f7ee647ad570c05eab0b74915da2ac8e19 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 31 Aug 2012 11:56:50 -0400 Subject: drm/radeon: rework pll selection (v3) For DP we can use the same PPLL for all active DP encoders. Take advantage of that to prevent cases where we may end up sharing a PPLL between DP and non-DP which won't work. Also clean up the code a bit. v2: - fix missing pll_id assignment in crtc init v3: - fix DP PPLL check - document functions - break in main encoder search loop after matching. no need to keep checking additional encoders. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=54471 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 163 ++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2817101fb167..e721e3087b99 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1479,14 +1479,98 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) } } +/** + * radeon_get_pll_use_mask - look up a mask of which pplls are in use + * + * @crtc: drm crtc + * + * Returns the mask of which PPLLs (Pixel PLLs) are in use. + */ +static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc *test_crtc; + struct radeon_crtc *radeon_test_crtc; + u32 pll_in_use = 0; + + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + + radeon_test_crtc = to_radeon_crtc(test_crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + pll_in_use |= (1 << radeon_test_crtc->pll_id); + } + return pll_in_use; +} + +/** + * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is + * also in DP mode. For DP, a single PPLL can be used for all DP + * crtcs/encoders. + */ +static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_encoder *test_encoder; + struct radeon_crtc *radeon_test_crtc; + + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + if (test_encoder->crtc && (test_encoder->crtc != crtc)) { + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* for DP use the same PLL for all */ + radeon_test_crtc = to_radeon_crtc(test_encoder->crtc); + if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) + return radeon_test_crtc->pll_id; + } + } + } + return ATOM_PPLL_INVALID; +} + +/** + * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors + * a single PPLL can be used for all DP crtcs/encoders. For non-DP + * monitors a dedicated PPLL must be used. If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself. If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * Asic specific PLL information + * + * DCE 6.1 + * - PPLL2 is only available to UNIPHYA (both DP and non-DP) + * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) + * + * DCE 6.0 + * - PPLL0 is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 5.0 + * - DCPLL is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 3.0/4.0/4.1 + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + */ static int radeon_atom_pick_pll(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct drm_encoder *test_encoder; - struct drm_crtc *test_crtc; - uint32_t pll_in_use = 0; + u32 pll_in_use; + int pll; if (ASIC_IS_DCE61(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { @@ -1498,32 +1582,40 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) if ((test_radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && - (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ + (dig->linkb == false)) + /* UNIPHY A uses PPLL2 */ return ATOM_PPLL2; + else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { + /* UNIPHY B/C/D/E/F */ + if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + } + break; } } /* UNIPHY B/C/D/E/F */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || - (radeon_test_crtc->pll_id == ATOM_PPLL1)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 4)) + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL0))) return ATOM_PPLL0; - return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else if (ASIC_IS_DCE4(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { if (test_encoder->crtc && (test_encoder->crtc == crtc)) { /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, * depending on the asic: * DCE4: PPLL or ext clock - * DCE5: DCPLL or ext clock + * DCE5: PPLL, DCPLL, or ext clock + * DCE6: PPLL, PPLL0, or ext clock * * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip * PPLL/DCPLL programming and only program the DP DTO for the @@ -1531,31 +1623,34 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { if (rdev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ return ATOM_PPLL_INVALID; else if (ASIC_IS_DCE6(rdev)) + /* use PPLL0 for all DP */ return ATOM_PPLL0; else if (ASIC_IS_DCE5(rdev)) + /* use DCPLL for all DP */ return ATOM_DCPLL; + else { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } } + break; } } - - /* otherwise, pick one of the plls */ - list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_test_crtc; - - if (crtc == test_crtc) - continue; - - radeon_test_crtc = to_radeon_crtc(test_crtc); - if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && - (radeon_test_crtc->pll_id <= ATOM_PPLL2)) - pll_in_use |= (1 << radeon_test_crtc->pll_id); - } - if (!(pll_in_use & 1)) + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; - return ATOM_PPLL2; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; } else + /* use PPLL1 or PPLL2 */ return radeon_crtc->crtc_id; } @@ -1697,7 +1792,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) break; } done: - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; } static const struct drm_crtc_helper_funcs atombios_helper_funcs = { @@ -1746,6 +1841,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev, else radeon_crtc->crtc_offset = 0; } - radeon_crtc->pll_id = -1; + radeon_crtc->pll_id = ATOM_PPLL_INVALID; drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); } -- cgit v1.2.3 From f492c171a38d77fc13a8998a0721f2da50835224 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 13 Sep 2012 10:33:47 +0200 Subject: drm/radeon: make 64bit fences more robust v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only increase the higher 32bits if we really detect a wrap around. v2: instead of increasing the higher 32bits just use the higher 32bits from the last emitted fence. v3: also use last emitted fence value as upper limit. The intention of this patch is to make fences as robust as they where before introducing 64bit fences. This is necessary because on older systems it looks like the fence value gets corrupted on initialization. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=51344 Should also fix: https://bugs.freedesktop.org/show_bug.cgi?id=54129 https://bugs.freedesktop.org/show_bug.cgi?id=54662 https://bugzilla.redhat.com/show_bug.cgi?id=846505 https://bugzilla.redhat.com/show_bug.cgi?id=845639 3.5 needs a separate patch due to changes in the fence code. Will send that out separately. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fence.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7b737b9339ad..2a59375dbe52 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev, */ void radeon_fence_process(struct radeon_device *rdev, int ring) { - uint64_t seq, last_seq; + uint64_t seq, last_seq, last_emitted; unsigned count_loop = 0; bool wake = false; @@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) */ last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq); do { + last_emitted = rdev->fence_drv[ring].sync_seq[ring]; seq = radeon_fence_read(rdev, ring); seq |= last_seq & 0xffffffff00000000LL; if (seq < last_seq) { - seq += 0x100000000LL; + seq &= 0xffffffff; + seq |= last_emitted & 0xffffffff00000000LL; } - if (seq == last_seq) { + if (seq <= last_seq || seq > last_emitted) { break; } /* If we loop over we don't want to return without -- cgit v1.2.3 From bef05406ac0ea6f468e1e25e9934f3011ea9259b Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 11 Sep 2012 04:34:08 +0000 Subject: bnx2x: Avoid sending multiple statistics queries During traffic when DCB is enabled, it is possible for multiple instances of statistics queries to be sent to the chip - this may cause the FW to assert. This patch prevents the sending of an additional instance of statistics query while the previous query hasn't completed. Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 332db64dd5be..d848dc9db7b0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1151,9 +1151,11 @@ static void bnx2x_stats_update(struct bnx2x *bp) if (bp->port.pmf) bnx2x_hw_stats_update(bp); - if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { - BNX2X_ERR("storm stats were not updated for 3 times\n"); - bnx2x_panic(); + if (bnx2x_storm_stats_update(bp)) { + if (bp->stats_pending++ == 3) { + BNX2X_ERR("storm stats were not updated for 3 times\n"); + bnx2x_panic(); + } return; } -- cgit v1.2.3 From 217aeb896a4a9f00006ce4b193c216f739234296 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 11 Sep 2012 04:34:09 +0000 Subject: bnx2x: fix stats copying logic FW needs the driver statistics for management. Current logic is broken in that the function that gathers the port statistics does not copy its own statistics to a place where the FW can use it. This patch causes every function that can pass statistics to the FW to do so. Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index d848dc9db7b0..a1d0446b39b3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) if (CHIP_REV_IS_SLOW(bp)) return; + /* Update MCP's statistics if possible */ + if (bp->func_stx) + memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, + sizeof(bp->func_stats)); + /* loader */ if (bp->executer_idx) { int loader_idx = PMF_DMAE_C(bp); @@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp) } else if (bp->func_stx) { *stats_comp = 0; - memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, - sizeof(bp->func_stats)); bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp)); } } -- cgit v1.2.3 From 375944cb7c96bf66914a73b1858e5865c439b335 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:10 +0000 Subject: bnx2x: prevent timeouts when using PFC Prevent updating the xmac PFC configuration when using a link speed slower than 10G -the umac block is responsible for 1G or slower connections, therefore it is possible the xmac block is reset when connection is slower. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index f4beb46c4709..40a7b8d877cf 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params, return bnx2x_status; DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n"); - if (CHIP_IS_E3(bp)) - bnx2x_update_pfc_xmac(params, vars, 0); - else { + + if (CHIP_IS_E3(bp)) { + if (vars->mac_type == MAC_TYPE_XMAC) + bnx2x_update_pfc_xmac(params, vars, 0); + } else { val = REG_RD(bp, MISC_REG_RESET_REG_2); if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) -- cgit v1.2.3 From 430d172a635c3dd791a56c59573418e02735b006 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:11 +0000 Subject: bnx2x: display the correct duplex value Prior to this fix, the driver reported the chip's active duplex state is always 'full', even if using half-duplex mode. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 40a7b8d877cf..b046beb435b2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -5434,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, switch (speed_mask) { case GP_STATUS_10M: vars->line_speed = SPEED_10; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_10TFD; else vars->link_status |= LINK_10THD; @@ -5442,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_100M: vars->line_speed = SPEED_100; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_100TXFD; else vars->link_status |= LINK_100TXHD; @@ -5451,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_1G: case GP_STATUS_1G_KX: vars->line_speed = SPEED_1000; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_1000TFD; else vars->link_status |= LINK_1000THD; @@ -5459,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, case GP_STATUS_2_5G: vars->line_speed = SPEED_2500; - if (vars->duplex == DUPLEX_FULL) + if (is_duplex == DUPLEX_FULL) vars->link_status |= LINK_2500TFD; else vars->link_status |= LINK_2500THD; @@ -5533,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy, if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { if (SINGLE_MEDIA_DIRECT(params)) { + vars->duplex = duplex; bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status); if (phy->req_line_speed == SPEED_AUTO_NEG) bnx2x_xgxs_an_resolve(phy, params, vars, @@ -5627,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, LINK_STATUS_PARALLEL_DETECTION_USED; } bnx2x_ext_phy_resolve_fc(phy, params, vars); + vars->duplex = duplex; } } -- cgit v1.2.3 From 5cd75f0c0fd2b068dbd0ce3cb9460c3aafc0aae7 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Tue, 11 Sep 2012 04:34:12 +0000 Subject: bnx2x: correct advertisement of pause capabilities This patch propagates users' requested flow-control into the link layer, which will later be used to advertise this flow-control for auto-negotiation (until now these values were ignored). Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c37a68d68090..bbf4cf00dd19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev, bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO; } + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE; + if (epause->rx_pause) + bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX; + + if (epause->tx_pause) + bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX; } DP(BNX2X_MSG_ETHTOOL, -- cgit v1.2.3 From 2ace95103df2bcb574c9da5df96807e9b46f9b38 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 11 Sep 2012 04:34:13 +0000 Subject: bnx2x: fix registers dumped Under traffic, there are several registers that when read (e.g., via 'ethtool -d') may cause the chip to stall. This patch corrects the registers read in such flows. Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h | 25 +++++++--------------- .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 +- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index 3e4cff9b1ebe..b926f58e983b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = { { 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE }, { 0x78000, 8192, RI_E3E3B0_OFFLINE }, - { 0x85000, 3, RI_ALL_ONLINE }, - { 0x8501c, 7, RI_ALL_ONLINE }, - { 0x85048, 1, RI_ALL_ONLINE }, - { 0x85200, 32, RI_ALL_ONLINE }, - { 0xb0000, 16384, RI_E1H_ONLINE }, + { 0x85000, 3, RI_ALL_OFFLINE }, + { 0x8501c, 7, RI_ALL_OFFLINE }, + { 0x85048, 1, RI_ALL_OFFLINE }, + { 0x85200, 32, RI_ALL_OFFLINE }, + { 0xb0000, 16384, RI_E1H_OFFLINE }, { 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2E3E3B0_ONLINE }, { 0xc1800, 2, RI_ALL_ONLINE }, @@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = { { 0x140188, 3, RI_E1E1HE2E3_ONLINE }, { 0x140194, 13, RI_ALL_ONLINE }, { 0x140200, 6, RI_E1E1HE2E3_ONLINE }, - { 0x140220, 4, RI_E2E3_ONLINE }, - { 0x140240, 4, RI_E2E3_ONLINE }, { 0x140260, 4, RI_E2E3_ONLINE }, { 0x140280, 4, RI_E2E3_ONLINE }, - { 0x1402a0, 4, RI_E2E3_ONLINE }, - { 0x1402c0, 4, RI_E2E3_ONLINE }, { 0x1402e0, 2, RI_E2E3_ONLINE }, { 0x1402e8, 2, RI_E2E3E3B0_ONLINE }, { 0x1402f0, 9, RI_E2E3_ONLINE }, { 0x140314, 44, RI_E3B0_ONLINE }, - { 0x1403d0, 70, RI_E3B0_ONLINE }, { 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE }, { 0x14c000, 4, RI_E1E1H_ONLINE }, @@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = { { 0x180398, 1, RI_E2E3E3B0_ONLINE }, { 0x1803a0, 5, RI_E2E3E3B0_ONLINE }, { 0x1803b4, 2, RI_E3E3B0_ONLINE }, - { 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE }, { 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE }, @@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = { { 0x1b905c, 1, RI_E3E3B0_ONLINE }, { 0x1b9064, 1, RI_E3B0_ONLINE }, { 0x1b9080, 10, RI_E3B0_ONLINE }, - { 0x1b9400, 14, RI_E2E3E3B0_ONLINE }, - { 0x1b943c, 19, RI_E2E3E3B0_ONLINE }, - { 0x1b9490, 10, RI_E2E3E3B0_ONLINE }, + { 0x1b9400, 14, RI_E2E3E3B0_OFFLINE }, + { 0x1b943c, 19, RI_E2E3E3B0_OFFLINE }, + { 0x1b9490, 10, RI_E2E3E3B0_OFFLINE }, { 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE }, { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE }, @@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = { { 0x200398, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2003a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x200400, 1, RI_ALL_ONLINE }, { 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE }, { 0x202010, 2044, RI_ALL_OFFLINE }, @@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = { { 0x280398, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a0, 1, RI_E2E3E3B0_ONLINE }, { 0x2803a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x280400, 1, RI_ALL_ONLINE }, { 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE }, { 0x282010, 2044, RI_ALL_OFFLINE }, @@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = { { 0x300398, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a0, 1, RI_E2E3E3B0_ONLINE }, { 0x3003a8, 2, RI_E2E3E3B0_ONLINE }, - { 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE }, { 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE }, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index bbf4cf00dd19..ebf40cd7aa10 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); struct dump_hdr dump_hdr = {0}; - regs->version = 0; + regs->version = 1; memset(p, 0, regs->len); if (!netif_running(bp->dev)) -- cgit v1.2.3 From 7b5342d9026d537cbc01fd30b7cd9bac9b07b5ad Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 11 Sep 2012 04:34:14 +0000 Subject: bnx2x: Add missing afex code Commit a334872224a67b614dc888460377862621f3dac7 added afex support but lacked several logical changes. This lack can cause afex to crash, and also have a slight effect on other flows (i.e., driver always assumes the Tx ring has less available buffers than what it actually has). This patch adds the missing segments, fixing said issues. Signed-off-by: Yuval Mintz Signed-off-by: Barak Witkowski Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 11 +++++------ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 21 ++++++++++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 21b553229ea4..dfd86a55f1dc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp, prod = txdata->tx_bd_prod; cons = txdata->tx_bd_cons; - /* NUM_TX_RINGS = number of "next-page" entries - It will be used as a threshold */ - used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; + used = SUB_S16(prod, cons); #ifdef BNX2X_STOP_ON_ERROR WARN_ON(used < 0); - WARN_ON(used > bp->tx_ring_size); - WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); + WARN_ON(used > txdata->tx_ring_size); + WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL); #endif - return (s16)(bp->tx_ring_size) - used; + return (s16)(txdata->tx_ring_size) - used; } static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) @@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp, txdata->txq_index = txq_index; txdata->tx_cons_sb = tx_cons_sb; txdata->parent_fp = fp; + txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size; DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n", txdata->cid, txdata->txq_index); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 21054987257a..211753e01f81 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, } rc = bnx2x_config_vlan_mac(bp, &ramrod_param); - if (rc < 0) + + if (rc == -EEXIST) { + DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc); + /* do not treat adding same MAC as error */ + rc = 0; + } else if (rc < 0) BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); + return rc; } @@ -10294,13 +10300,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) dev_info.port_hw_config[port]. fcoe_wwn_node_name_lower); } else if (!IS_MF_SD(bp)) { - u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); - /* * Read the WWN info only if the FCoE feature is enabled for * this function. */ - if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) + if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp)) bnx2x_get_ext_wwn_info(bp, func); } else if (IS_MF_FCOE_SD(bp)) @@ -11073,7 +11077,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp) netdev_for_each_uc_addr(ha, dev) { rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true, BNX2X_UC_LIST_MAC, &ramrod_flags); - if (rc < 0) { + if (rc == -EEXIST) { + DP(BNX2X_MSG_SP, + "Failed to schedule ADD operations: %d\n", rc); + /* do not treat adding same MAC as error */ + rc = 0; + + } else if (rc < 0) { + BNX2X_ERR("Failed to schedule ADD operations: %d\n", rc); return rc; -- cgit v1.2.3 From 07f377da7e8a7d3c3a6626333516f9c808637c9e Mon Sep 17 00:00:00 2001 From: Bernhard Froemel Date: Sat, 25 Aug 2012 10:30:49 +0200 Subject: apple-gmux: Obtain version info from indexed gmux This patch extracts and displays version information from the indexed gmux device as it is also done for the classic gmux device. Signed-off-by: Bernhard Froemel Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index dfb1a92ce949..c9558d1ea88c 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -461,18 +461,22 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { if (gmux_is_indexed(gmux_data)) { + u32 version; mutex_init(&gmux_data->index_lock); gmux_data->indexed = true; + version = gmux_read32(gmux_data, + GMUX_PORT_VERSION_MAJOR); + ver_major = (version >> 24) & 0xff; + ver_minor = (version >> 16) & 0xff; + ver_release = (version >> 8) & 0xff; } else { pr_info("gmux device not present\n"); ret = -ENODEV; goto err_release; } - pr_info("Found indexed gmux\n"); - } else { - pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, - ver_release); } + pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, + ver_release, (gmux_data->indexed ? "indexed" : "classic")); memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; -- cgit v1.2.3 From c5a5052923c55990e32a3d64bdb4779b01162646 Mon Sep 17 00:00:00 2001 From: Bernhard Froemel Date: Sat, 25 Aug 2012 10:30:48 +0200 Subject: apple-gmux: Fix index read functions Study of Apple's binary driver revealed that the GMUX_READ_PORT should be written between calls to gmux_index_wait_ready and gmux_index_wait_complete (i.e., the new index protocol must be followed). If this is not done correctly, the indexed gmux device only partially accepts writes which lead to problems concerning GPU switching. Special thanks to Seth Forshee who helped greatly with identifying unnecessary changes. Signed-off-by: Bernhard Froemel Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index c9558d1ea88c..0e43477de337 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -142,8 +142,9 @@ static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) u8 val; mutex_lock(&gmux_data->index_lock); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); gmux_index_wait_ready(gmux_data); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_complete(gmux_data); val = inb(gmux_data->iostart + GMUX_PORT_VALUE); mutex_unlock(&gmux_data->index_lock); @@ -166,8 +167,9 @@ static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) u32 val; mutex_lock(&gmux_data->index_lock); - outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); gmux_index_wait_ready(gmux_data); + outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); + gmux_index_wait_complete(gmux_data); val = inl(gmux_data->iostart + GMUX_PORT_VALUE); mutex_unlock(&gmux_data->index_lock); -- cgit v1.2.3 From e6d9d3d59ca08fc87688c5953061b4da0d17bf15 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Tue, 21 Aug 2012 21:56:49 -0500 Subject: apple-gmux: Fix port address calculation in gmux_pio_write32() This function fails to add the start address of the gmux I/O range to the requested port address and thus writes to the wrong location. Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/apple-gmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 0e43477de337..5c17ba895692 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -101,7 +101,7 @@ static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, for (i = 0; i < 4; i++) { tmpval = (val >> (i * 8)) & 0xff; - outb(tmpval, port + i); + outb(tmpval, gmux_data->iostart + port + i); } } -- cgit v1.2.3 From 689db7843d503fae0eb46cb849e4caab35588170 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 20 Aug 2012 23:01:50 +0200 Subject: drivers-platform-x86: remove useless #ifdef CONFIG_ACPI_VIDEO Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/acer-wmi.c | 2 -- drivers/platform/x86/apple-gmux.c | 4 ---- drivers/platform/x86/asus-wmi.c | 4 ---- drivers/platform/x86/samsung-laptop.c | 4 ---- 4 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3782e1cd3697..934d861a3235 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2196,10 +2196,8 @@ static int __init acer_wmi_init(void) interface->capability &= ~ACER_CAP_BRIGHTNESS; pr_info("Brightness must be controlled by acpi video driver\n"); } else { -#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); -#endif } if (wmi_has_guid(WMID_GUID3)) { diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 5c17ba895692..db8f63841b42 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -511,9 +511,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * Disable the other backlight choices. */ acpi_video_dmi_promote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_unregister(); -#endif apple_bl_unregister(); gmux_data->power_state = VGA_SWITCHEROO_ON; @@ -599,9 +597,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) kfree(gmux_data); acpi_video_dmi_demote_vendor(); -#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE) acpi_video_register(); -#endif apple_bl_register(); } diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 2eb9fe8e8efd..c0e9ff489b24 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -47,9 +47,7 @@ #include #include #include -#ifdef CONFIG_ACPI_VIDEO #include -#endif #include "asus-wmi.h" @@ -1704,10 +1702,8 @@ static int asus_wmi_add(struct platform_device *pdev) if (asus->driver->quirks->wmi_backlight_power) acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { -#ifdef CONFIG_ACPI_VIDEO pr_info("Disabling ACPI video driver\n"); acpi_video_unregister(); -#endif err = asus_wmi_backlight_init(asus); if (err && err != -ENODEV) goto fail_backlight; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index c1ca7bcebb66..dd90d15f5210 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,9 +26,7 @@ #include #include #include -#ifdef CONFIG_ACPI_VIDEO #include -#endif /* * This driver is needed because a number of Samsung laptops do not hook @@ -1558,9 +1556,7 @@ static int __init samsung_init(void) samsung->handle_backlight = false; } else if (samsung->quirks->broken_acpi_video) { pr_info("Disabling ACPI video driver\n"); -#ifdef CONFIG_ACPI_VIDEO acpi_video_unregister(); -#endif } #endif -- cgit v1.2.3 From 8871e99f89b7d7b1ea99de550eea2a56273f42ab Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 20 Aug 2012 23:01:51 +0200 Subject: asus-laptop: HRWS/HWRS typo Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=24222 Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e38f91be0b10..110c7778cbf9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HRWS value : %#x\n", + len += sprintf(page + len, "HWRS value : %#x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) * The significance of others is yet to be found. */ status = - acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) - pr_notice(" HRWS returned %x", (int)hwrs_result); + pr_notice(" HWRS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; -- cgit v1.2.3 From 3f5449bf39896587ca9f87b76832c5aa30f0f5c7 Mon Sep 17 00:00:00 2001 From: Maxim Nikulin Date: Mon, 20 Aug 2012 23:01:52 +0200 Subject: platform/x86: fix asus_laptop.wled_type description MODULE_PARM_DESC for wlan_status is further in the same file Signed-off-by: Maxim A. Nikulin Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 110c7778cbf9..4b568df56643 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -85,7 +85,7 @@ static char *wled_type = "unknown"; static char *bled_type = "unknown"; module_param(wled_type, charp, 0444); -MODULE_PARM_DESC(wlan_status, "Set the wled type on boot " +MODULE_PARM_DESC(wled_type, "Set the wled type on boot " "(unknown, led or rfkill). " "default is unknown"); -- cgit v1.2.3 From f661848b74b33069b0b7068c414bd282c407781d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 14 Sep 2012 00:21:59 +0800 Subject: eeepc-laptop: fix device reference count leakage in eeepc_rfkill_hotplug() Fix a device reference count leakage issue in function eeepc_rfkill_hotplug(). Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Signed-off-by: Matthew Garrett --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index dab91b48d22c..5ca264179f4e 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (!bus) { pr_warn("Unable to find PCI bus 1?\n"); - goto out_unlock; + goto out_put_dev; } if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { pr_err("Unable to read PCI config space?\n"); - goto out_unlock; + goto out_put_dev; } absent = (l == 0xffffffff); @@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) absent ? "absent" : "present"); pr_warn("skipped wireless hotplug as probably " "inappropriate for this model\n"); - goto out_unlock; + goto out_put_dev; } if (!blocked) { @@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) if (dev) { /* Device already present */ pci_dev_put(dev); - goto out_unlock; + goto out_put_dev; } dev = pci_scan_single_device(bus, 0); if (dev) { @@ -650,6 +650,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle) pci_dev_put(dev); } } +out_put_dev: + pci_dev_put(port); } out_unlock: -- cgit v1.2.3 From eceeb4371240aff22e9a535a2bc57d2311820942 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 1 Sep 2012 12:54:07 -0700 Subject: thinkpad_acpi: buffer overflow in fan_get_status() The acpi_evalf() function modifies four bytes of data but in fan_get_status() we pass a pointer to u8. I have modified the function to use type checking now. Signed-off-by: Dan Carpenter Signed-off-by: Matthew Garrett --- drivers/platform/x86/thinkpad_acpi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 80e377949314..52daaa816e53 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ */ static int acpi_evalf(acpi_handle handle, - void *res, char *method, char *fmt, ...) + int *res, char *method, char *fmt, ...) { char *fmt0 = fmt; struct acpi_object_list params; @@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle, success = (status == AE_OK && out_obj.type == ACPI_TYPE_INTEGER); if (success && res) - *(int *)res = out_obj.integer.value; + *res = out_obj.integer.value; break; case 'v': /* void */ success = status == AE_OK; @@ -7386,17 +7386,18 @@ static int fan_get_status(u8 *status) * Add TPACPI_FAN_RD_ACPI_FANS ? */ switch (fan_status_access_mode) { - case TPACPI_FAN_RD_ACPI_GFAN: + case TPACPI_FAN_RD_ACPI_GFAN: { /* 570, 600e/x, 770e, 770x */ + int res; - if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) + if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d"))) return -EIO; if (likely(status)) - *status = s & 0x07; + *status = res & 0x07; break; - + } case TPACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ if (unlikely(!acpi_ec_read(fan_status_offset, &s))) -- cgit v1.2.3 From 8f7412a792bc989d1bddd3c802282eec09456d57 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 14 Sep 2012 00:26:24 +0200 Subject: ACPI / PM: Infer parent power state from child if unknown, v2 It turns out that there are ACPI BIOSes defining device objects with _PSx and without either _PSC or _PRx. For devices corresponding to those ACPI objetcs __acpi_bus_get_power() returns ACPI_STATE_UNKNOWN and their initial power states are regarded as unknown as a result. If such a device is a parent of another power-manageable device, the child cannot be put into a low-power state through ACPI, because __acpi_bus_set_power() refuses to change power states of devices whose parents' power states are unknown. To work around this problem, observe that the ACPI power state of a device cannot be higher-power (lower-number) than the power state of its parent. Thus, if the device's _PSC method or the configuration of its power resources indicates that the device is in D0, the device's parent has to be in D0 as well. Consequently, if the parent's power state is unknown when we've just learned that its child's power state is D0, we can safely set the parent's power.state field to ACPI_STATE_D0. Tested-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9628652e080c..e0596954290b 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state) } else if (result == ACPI_STATE_D3_HOT) { result = ACPI_STATE_D3; } + + /* + * If we were unsure about the device parent's power state up to this + * point, the fact that the device is in D0 implies that the parent has + * to be in D0 too. + */ + if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN + && result == ACPI_STATE_D0) + device->parent->power.state = ACPI_STATE_D0; + *state = result; out: -- cgit v1.2.3 From 40bf66ec9791f1452b90b82aadc3b6e6aee201f5 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 14 Sep 2012 00:26:33 +0200 Subject: ACPI / PM: Fix resource_lock dead lock in acpi_power_on_device Commit 0090def("ACPI: Add interface to register/unregister device to/from power resources") used resource_lock to protect the devices list that relies on power resource. It caused a mutex dead lock, as below acpi_power_on ---> lock resource_lock __acpi_power_on acpi_power_on_device acpi_power_get_inferred_state acpi_power_get_list_state ---> lock resource_lock This patch adds a new mutex "devices_lock" to protect the devices list and calls acpi_power_on_device in acpi_power_on, instead of __acpi_power_on, after the resource_lock is released. [rjw: Changed data type of a boolean variable to bool.] Signed-off-by: Lin Ming Signed-off-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc1803414629..cc2a2dcff336 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -107,6 +107,7 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; + struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { - struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); - while (device_list) { - acpi_power_on_device(device_list->device); - - device_list = device_list->next; - } - return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; + bool resume_device = false; struct acpi_power_resource *resource = NULL; + struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; + else + resume_device = true; } mutex_unlock(&resource->resource_lock); + if (!resume_device) + return result; + + mutex_lock(&resource->devices_lock); + + device_list = resource->devices; + while (device_list) { + acpi_power_on_device(device_list->device); + device_list = device_list->next; + } + + mutex_unlock(&resource->devices_lock); + return result; } @@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); return 0; } @@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); + mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); -- cgit v1.2.3 From 610bd7da160f76f1644ecb4cd7f39511b49a22cc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 14 Sep 2012 13:28:23 +1000 Subject: drm/nouveau: fix booting with plymouth + dumb support We noticed a plymouth bug on Fedora 18, and I then noticed this stupid thinko, fixing it fixed the problem with plymouth. Cc: stable@vger.kernel.org Acked-by: Ben Skeggs Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 69688ef5cf46..7e16dc5e6467 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); + ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); if (ret) return ret; -- cgit v1.2.3 From 5f71a3ef3753ac2068009637eee619e163f44b30 Mon Sep 17 00:00:00 2001 From: Thomas Kavanagh Date: Thu, 13 Sep 2012 08:16:55 -0700 Subject: i2c: algo: pca: Fix mode selection for PCA9665 The code currently always selects turbo mode for PCA9665, no matter which clock frequency is configured. This is because it compares the clock frequency against constants reflecting (boundary / 100). Compare against real boundary frequencies to fix the problem. Signed-off-by: Thomas Kavanagh Signed-off-by: Guenter Roeck Signed-off-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-pca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 73133b1063f0..6f5f98d69af7 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap) /* To avoid integer overflow, use clock/100 for calculations */ clock = pca_clock(pca_data) / 100; - if (pca_data->i2c_clock > 10000) { + if (pca_data->i2c_clock > 1000000) { mode = I2C_PCA_MODE_TURBO; min_tlow = 14; min_thi = 5; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 4000) { + } else if (pca_data->i2c_clock > 400000) { mode = I2C_PCA_MODE_FASTP; min_tlow = 17; min_thi = 9; raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 1000) { + } else if (pca_data->i2c_clock > 100000) { mode = I2C_PCA_MODE_FAST; min_tlow = 44; min_thi = 20; -- cgit v1.2.3 From f25b70613c048ceb1df052576fda03321ebf41cf Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 14 Sep 2012 20:54:44 +0200 Subject: ACPI / PM: Use KERN_DEBUG when no power resources are found commit a606dac368eed5696fb38e16b1394f1d049c09e9 adds support to link devices which have _PRx, if a device does not have _PRx, a warning message will be printed. This commit is for ZPODD on Intel ZPODD capable platforms, on other platforms, it has no problem if there is no power resource for this device, so a warning here is not appropriate, change it to debug. Reported-by: Borislav Petkov Signed-off-by: Aaron Lu Cc: stable@vger.kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index cc2a2dcff336..40e38a06ba85 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -473,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); + printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); return -ENODEV; } EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); -- cgit v1.2.3 From 0848c94fb4a5cc213a7fb0fb3a5721ad6e16f096 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Sep 2012 15:16:36 +0800 Subject: mfd: core: Push irqdomain mapping out into devices Currently the MFD core supports remapping MFD cell interrupts using an irqdomain but only if the MFD is being instantiated using device tree and only if the device tree bindings use the pattern of registering IPs in the device tree with compatible properties. This will be actively harmful for drivers which support non-DT platforms and use this pattern for their DT bindings as it will mean that the core will silently change remapping behaviour and it is also limiting for drivers which don't do DT with this particular pattern. There is also a potential fragility if there are interrupts not associated with MFD cells and all the cells are omitted from the device tree for some reason. Instead change the code to take an IRQ domain as an optional argument, allowing drivers to take the decision about the parent domain for their interrupts. The one current user of this feature is ab8500-core, it has the domain lookup pushed out into the driver. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 5 +++-- drivers/mfd/88pm805.c | 3 ++- drivers/mfd/88pm860x-core.c | 21 +++++++++++---------- drivers/mfd/aat2870-core.c | 2 +- drivers/mfd/ab3100-core.c | 2 +- drivers/mfd/ab8500-core.c | 10 +++++----- drivers/mfd/arizona-core.c | 6 +++--- drivers/mfd/asic3.c | 6 +++--- drivers/mfd/cs5535-mfd.c | 2 +- drivers/mfd/da9052-core.c | 2 +- drivers/mfd/davinci_voicecodec.c | 2 +- drivers/mfd/db8500-prcmu.c | 2 +- drivers/mfd/htc-pasic3.c | 5 +++-- drivers/mfd/intel_msic.c | 4 ++-- drivers/mfd/janz-cmodio.c | 2 +- drivers/mfd/jz4740-adc.c | 3 ++- drivers/mfd/lm3533-core.c | 7 ++++--- drivers/mfd/lpc_ich.c | 4 ++-- drivers/mfd/lpc_sch.c | 6 ++++-- drivers/mfd/max77686.c | 2 +- drivers/mfd/max77693.c | 2 +- drivers/mfd/max8925-core.c | 12 ++++++------ drivers/mfd/max8997.c | 2 +- drivers/mfd/max8998.c | 8 ++++---- drivers/mfd/mc13xxx-core.c | 2 +- drivers/mfd/mfd-core.c | 12 ++++++------ drivers/mfd/palmas.c | 3 ++- drivers/mfd/rc5t583.c | 2 +- drivers/mfd/rdc321x-southbridge.c | 3 ++- drivers/mfd/sec-core.c | 8 ++++---- drivers/mfd/sta2x11-mfd.c | 4 ++-- drivers/mfd/stmpe.c | 2 +- drivers/mfd/t7l66xb.c | 2 +- drivers/mfd/tc3589x.c | 8 ++++---- drivers/mfd/tc6387xb.c | 2 +- drivers/mfd/tc6393xb.c | 4 ++-- drivers/mfd/ti-ssp.c | 2 +- drivers/mfd/timberdale.c | 12 ++++++------ drivers/mfd/tps6105x.c | 2 +- drivers/mfd/tps6507x.c | 2 +- drivers/mfd/tps65090.c | 2 +- drivers/mfd/tps65217.c | 2 +- drivers/mfd/tps6586x.c | 3 ++- drivers/mfd/tps65910.c | 2 +- drivers/mfd/tps65912-core.c | 2 +- drivers/mfd/twl4030-audio.c | 2 +- drivers/mfd/twl6040-core.c | 2 +- drivers/mfd/vx855.c | 2 +- drivers/mfd/wl1273-core.c | 2 +- drivers/mfd/wm831x-core.c | 16 ++++++++-------- drivers/mfd/wm8400-core.c | 2 +- drivers/mfd/wm8994-core.c | 4 ++-- drivers/staging/nvec/nvec.c | 2 +- include/linux/mfd/core.h | 4 +++- 54 files changed, 125 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index b67a3018b136..ce229ea933d1 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -470,7 +470,8 @@ static int __devinit device_800_init(struct pm80x_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, + NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -481,7 +482,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip, rtc_devs[0].platform_data = pdata->rtc; rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0); + ARRAY_SIZE(rtc_devs), NULL, 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out_dev; diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 6146583589f6..c20a31136f04 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -216,7 +216,8 @@ static int __devinit device_805_init(struct pm80x_chip *chip) } ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0, + NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add codec subdev\n"); goto out_codec; diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index d09918cf1b15..b73f033b2c60 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip, bk_devs[i].resources = &bk_resources[j]; ret = mfd_add_devices(chip->dev, 0, &bk_devs[i], 1, - &bk_resources[j], 0); + &bk_resources[j], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add " "backlight subdev\n"); @@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip, led_devs[i].resources = &led_resources[j], ret = mfd_add_devices(chip->dev, 0, &led_devs[i], 1, - &led_resources[j], 0); + &led_resources[j], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add " "led subdev\n"); @@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip, regulator_devs[i].resources = ®ulator_resources[seq]; ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, - ®ulator_resources[seq], 0); + ®ulator_resources[seq], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out; @@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip, rtc_devs[0].resources = &rtc_resources[0]; ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), &rtc_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add rtc subdev\n"); } @@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip, touch_devs[0].resources = &touch_resources[0]; ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), &touch_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add touch subdev\n"); } @@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[0].num_resources = ARRAY_SIZE(battery_resources); power_devs[0].resources = &battery_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, - &battery_resources[0], chip->irq_base); + &battery_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add battery subdev\n"); @@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[1].num_resources = ARRAY_SIZE(charger_resources); power_devs[1].resources = &charger_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, - &charger_resources[0], chip->irq_base); + &charger_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); @@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip, power_devs[2].num_resources = ARRAY_SIZE(preg_resources); power_devs[2].resources = &preg_resources[0], ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, - &preg_resources[0], chip->irq_base); + &preg_resources[0], chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add preg subdev\n"); } @@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip, onkey_devs[0].resources = &onkey_resources[0], ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), &onkey_resources[0], - chip->irq_base); + chip->irq_base, NULL); if (ret < 0) dev_err(chip->dev, "Failed to add onkey subdev\n"); } @@ -815,7 +815,8 @@ static void __devinit device_codec_init(struct pm860x_chip *chip, codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); codec_devs[0].resources = &codec_resources[0], ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], - ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + ARRAY_SIZE(codec_devs), &codec_resources[0], 0, + NULL); if (ret < 0) dev_err(chip->dev, "Failed to add codec subdev\n"); } diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 44a3fdbadef4..f1beb4971f87 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs, - ARRAY_SIZE(aat2870_devs), NULL, 0); + ARRAY_SIZE(aat2870_devs), NULL, 0, NULL); if (ret != 0) { dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret); goto out_disable; diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 78fca2902c8d..01781ae5d0d7 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, } err = mfd_add_devices(&client->dev, 0, ab3100_devs, - ARRAY_SIZE(ab3100_devs), NULL, 0); + ARRAY_SIZE(ab3100_devs), NULL, 0, NULL); ab3100_setup_debugfs(ab3100); diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 626b4ecaf647..47adf800024e 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; if (is_ab9540(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); else ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; if (is_ab9540(ab8500) || is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) goto out_freeirq; @@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev) /* Add battery management devices */ ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, ARRAY_SIZE(ab8500_bm_devs), NULL, - ab8500->irq_base); + ab8500->irq_base, ab8500->domain); if (ret) dev_err(ab8500->dev, "error adding bm devices\n"); } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c7983e862549..1b48f2094806 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) } ret = mfd_add_devices(arizona->dev, -1, early_devs, - ARRAY_SIZE(early_devs), NULL, 0); + ARRAY_SIZE(early_devs), NULL, 0, NULL); if (ret != 0) { dev_err(dev, "Failed to add early children: %d\n", ret); return ret; @@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0); + ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); break; case WM5110: ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0); + ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); break; } diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 683e18a23329..62f0883a7630 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, if (pdata->clock_rate) { ds1wm_pdata.clock_rate = pdata->clock_rate; ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_ds1wm, 1, mem, asic->irq_base); + &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL); if (ret < 0) goto out; } if (mem_sdio && (irq >= 0)) { ret = mfd_add_devices(&pdev->dev, pdev->id, - &asic3_cell_mmc, 1, mem_sdio, irq); + &asic3_cell_mmc, 1, mem_sdio, irq, NULL); if (ret < 0) goto out; } @@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]); } ret = mfd_add_devices(&pdev->dev, 0, - asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0); + asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL); } out: diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index 3419e726de47..2b282133c725 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev, } err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, - ARRAY_SIZE(cs5535_mfd_cells), NULL, 0); + ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); if (err) { dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); goto err_disable; diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 2544910e1fd6..a0a62b24621b 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret); ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, - ARRAY_SIZE(da9052_subdev_info), NULL, 0); + ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL); if (ret) goto err; diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index 4e2af2cb2d26..45e83a68641b 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) cell->pdata_size = sizeof(*davinci_vc); ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells, - DAVINCI_VC_CELLS, NULL, 0); + DAVINCI_VC_CELLS, NULL, 0, NULL); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); goto fail4; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7040a0081130..0e63cdd9b52a 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL); if (err) { pr_err("prcmu: Failed to add subdevices\n"); return err; diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 04c7093d6499..9e5453d21a68 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev) /* the first 5 PASIC3 registers control the DS1WM */ ds1wm_resources[0].end = (5 << asic->bus_shift) - 1; ret = mfd_add_devices(&pdev->dev, pdev->id, - &ds1wm_cell, 1, r, irq); + &ds1wm_cell, 1, r, irq, NULL); if (ret < 0) dev_warn(dev, "failed to register DS1WM\n"); } @@ -176,7 +176,8 @@ static int __init pasic3_probe(struct platform_device *pdev) if (pdata && pdata->led_pdata) { led_cell.platform_data = pdata->led_pdata; led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); - ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0); + ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, + 0, NULL); if (ret < 0) dev_warn(dev, "failed to register LED device\n"); } diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index 59df5584cb58..266bdc5bd96d 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic) continue; ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, - pdata->irq[i]); + pdata->irq[i], NULL); if (ret) goto fail; } ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, - ARRAY_SIZE(msic_other_devs), NULL, 0); + ARRAY_SIZE(msic_other_devs), NULL, 0, NULL); if (ret) goto fail; diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 2ea99989551a..965c4801df8a 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv) } return mfd_add_devices(&pdev->dev, 0, priv->cells, - num_probed, NULL, pdev->irq); + num_probed, NULL, pdev->irq, NULL); } /* diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 87662a17dec6..c6b6d7dda517 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -287,7 +287,8 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev) writeb(0xff, adc->base + JZ_REG_ADC_CTRL); ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells, - ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base); + ARRAY_SIZE(jz4740_adc_cells), mem_base, + irq_base, NULL); if (ret < 0) goto err_clk_put; diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 0b2879b87fd9..24212f45b201 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -393,7 +393,8 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533) lm3533_als_devs[0].platform_data = pdata->als; lm3533_als_devs[0].pdata_size = sizeof(*pdata->als); - ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0); + ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, + 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add ALS device\n"); return ret; @@ -422,7 +423,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs, - pdata->num_backlights, NULL, 0); + pdata->num_backlights, NULL, 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add backlight devices\n"); return ret; @@ -451,7 +452,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533) } ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs, - pdata->num_leds, NULL, 0); + pdata->num_leds, NULL, 0, NULL); if (ret) { dev_err(lm3533->dev, "failed to add LED devices\n"); return ret; diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index a05fdfc2ebcf..092ad4b44b6d 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -750,7 +750,7 @@ gpe0_done: lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO], - 1, NULL, 0); + 1, NULL, 0, NULL); gpio_done: if (acpi_conflict) @@ -807,7 +807,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], - 1, NULL, 0); + 1, NULL, 0, NULL); wdt_done: return ret; diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c index 9f20abc5e393..f6b9c5c96b24 100644 --- a/drivers/mfd/lpc_sch.c +++ b/drivers/mfd/lpc_sch.c @@ -127,7 +127,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, lpc_sch_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, - lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); + lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, + 0, NULL); if (ret) goto out_dev; @@ -153,7 +154,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev, tunnelcreek_cells[i].id = id->device; ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells, - ARRAY_SIZE(tunnelcreek_cells), NULL, 0); + ARRAY_SIZE(tunnelcreek_cells), NULL, + 0, NULL); } return ret; diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index c03e12b51924..d9e24c849a00 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686_irq_init(max77686); ret = mfd_add_devices(max77686->dev, -1, max77686_devs, - ARRAY_SIZE(max77686_devs), NULL, 0); + ARRAY_SIZE(max77686_devs), NULL, 0, NULL); if (ret < 0) goto err_mfd; diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index a1811cb50ec7..4fdd03d28539 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -159,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max77693->dev); ret = mfd_add_devices(max77693->dev, -1, max77693_devs, - ARRAY_SIZE(max77693_devs), NULL, 0); + ARRAY_SIZE(max77693_devs), NULL, 0, NULL); if (ret < 0) goto err_mfd; diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 825a7f06d9ba..ee53757beca7 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], chip->irq_base); + &rtc_resources[0], chip->irq_base, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; @@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], ARRAY_SIZE(onkey_devs), - &onkey_resources[0], 0); + &onkey_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; @@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata) { ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], ARRAY_SIZE(regulator_devs), - ®ulator_resources[0], 0); + ®ulator_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add regulator subdev\n"); goto out_dev; @@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->backlight) { ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], ARRAY_SIZE(backlight_devs), - &backlight_resources[0], 0); + &backlight_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add backlight subdev\n"); goto out_dev; @@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->power) { ret = mfd_add_devices(chip->dev, 0, &power_devs[0], ARRAY_SIZE(power_devs), - &power_supply_resources[0], 0); + &power_supply_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add power supply " "subdev\n"); @@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, if (pdata && pdata->touch) { ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], ARRAY_SIZE(touch_devs), - &touch_resources[0], 0); + &touch_resources[0], 0, NULL); if (ret < 0) { dev_err(chip->dev, "Failed to add touch subdev\n"); goto out_dev; diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 10b629c245b6..f123517065ec 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c, mfd_add_devices(max8997->dev, -1, max8997_devs, ARRAY_SIZE(max8997_devs), - NULL, 0); + NULL, 0, NULL); /* * TODO: enable others (flash, muic, rtc, battery, ...) and diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index 6ef56d28c056..d7218cc90945 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c, switch (id->driver_data) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, - lp3974_devs, ARRAY_SIZE(lp3974_devs), - NULL, 0); + lp3974_devs, ARRAY_SIZE(lp3974_devs), + NULL, 0, NULL); break; case TYPE_MAX8998: ret = mfd_add_devices(max8998->dev, -1, - max8998_devs, ARRAY_SIZE(max8998_devs), - NULL, 0); + max8998_devs, ARRAY_SIZE(max8998_devs), + NULL, 0, NULL); break; default: ret = -EINVAL; diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index b801dc72f041..1ec79b54bd2f 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, if (!cell.name) return -ENOMEM; - return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0); + return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL); } static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 0c3a01cde2f7..f8b77711ad2d 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -74,12 +74,11 @@ static int mfd_platform_add_cell(struct platform_device *pdev, static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, struct resource *mem_base, - int irq_base) + int irq_base, struct irq_domain *domain) { struct resource *res; struct platform_device *pdev; struct device_node *np = NULL; - struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -97,7 +96,6 @@ static int mfd_add_device(struct device *parent, int id, for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { pdev->dev.of_node = np; - domain = irq_find_host(parent->of_node); break; } } @@ -177,7 +175,7 @@ fail_alloc: int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base) + int irq_base, struct irq_domain *domain) { int i; int ret = 0; @@ -191,7 +189,8 @@ int mfd_add_devices(struct device *parent, int id, for (i = 0; i < n_devs; i++) { atomic_set(&cnts[i], 0); cells[i].usage_count = &cnts[i]; - ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); + ret = mfd_add_device(parent, id, cells + i, mem_base, + irq_base, domain); if (ret) break; } @@ -247,7 +246,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) + if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, + NULL)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index c4a69f193a1d..a345f9bb7b47 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -453,7 +453,8 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(palmas->dev, -1, children, ARRAY_SIZE(palmas_children), - NULL, regmap_irq_chip_get_base(palmas->irq_data)); + NULL, regmap_irq_chip_get_base(palmas->irq_data), + NULL); kfree(children); if (ret < 0) diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c index cdc1df7fa0e9..3a8fa88567b1 100644 --- a/drivers/mfd/rc5t583.c +++ b/drivers/mfd/rc5t583.c @@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c, } ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs, - ARRAY_SIZE(rc5t583_subdevs), NULL, 0); + ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL); if (ret) { dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret); goto err_add_devs; diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c index 685d61e431ad..0f70dce61160 100644 --- a/drivers/mfd/rdc321x-southbridge.c +++ b/drivers/mfd/rdc321x-southbridge.c @@ -87,7 +87,8 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, rdc321x_wdt_pdata.sb_pdev = pdev; return mfd_add_devices(&pdev->dev, -1, - rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); + rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), + NULL, 0, NULL); } static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 2988efde11eb..49d361a618d0 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c, switch (sec_pmic->device_type) { case S5M8751X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, - ARRAY_SIZE(s5m8751_devs), NULL, 0); + ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); break; case S5M8763X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, - ARRAY_SIZE(s5m8763_devs), NULL, 0); + ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); break; case S5M8767X: ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, - ARRAY_SIZE(s5m8767_devs), NULL, 0); + ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); break; case S2MPS11X: ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, - ARRAY_SIZE(s2mps11_devs), NULL, 0); + ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); break; default: /* If this happens the probe function is problem */ diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c index d31fed07aefb..d35da6820bea 100644 --- a/drivers/mfd/sta2x11-mfd.c +++ b/drivers/mfd/sta2x11-mfd.c @@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar0, ARRAY_SIZE(sta2x11_mfd_bar0), &pdev->resource[0], - 0); + 0, NULL); if (err) { dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); goto err_disable; @@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, sta2x11_mfd_bar1, ARRAY_SIZE(sta2x11_mfd_bar1), &pdev->resource[1], - 0); + 0, NULL); if (err) { dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err); goto err_disable; diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 2dd8d49cb30b..c94f521f392c 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell, int irq) { return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, - NULL, stmpe->irq_base + irq); + NULL, stmpe->irq_base + irq, NULL); } static int __devinit stmpe_devices_init(struct stmpe *stmpe) diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 2d9e8799e733..b32940ec9034 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev) ret = mfd_add_devices(&dev->dev, dev->id, t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells), - iomem, t7l66xb->irq_base); + iomem, t7l66xb->irq_base, NULL); if (!ret) return 0; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 048bf0532a09..b56ba6b43294 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_GPIO) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, - ARRAY_SIZE(tc3589x_dev_gpio), NULL, - tc3589x->irq_base); + ARRAY_SIZE(tc3589x_dev_gpio), NULL, + tc3589x->irq_base, NULL); if (ret) { dev_err(tc3589x->dev, "failed to add gpio child\n"); return ret; @@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) if (blocks & TC3589x_BLOCK_KEYPAD) { ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, - ARRAY_SIZE(tc3589x_dev_keypad), NULL, - tc3589x->irq_base); + ARRAY_SIZE(tc3589x_dev_keypad), NULL, + tc3589x->irq_base, NULL); if (ret) { dev_err(tc3589x->dev, "failed to keypad child\n"); return ret; diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index d20a284ad4ba..413c891102f8 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev) printk(KERN_INFO "Toshiba tc6387xb initialised\n"); ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells, - ARRAY_SIZE(tc6387xb_cells), iomem, irq); + ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL); if (!ret) return 0; diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9612264f0e6d..dcab026fcbb2 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data); ret = mfd_add_devices(&dev->dev, dev->id, - tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), - iomem, tcpd->irq_base); + tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells), + iomem, tcpd->irq_base, NULL); if (!ret) return 0; diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 4fb0e6c8e8fe..7c3675a74f93 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev) cells[id].data_size = data->pdata_size; } - error = mfd_add_devices(dev, 0, cells, 2, NULL, 0); + error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); if (error < 0) { dev_err(dev, "cannot add mfd cells\n"); goto error_enable; diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index a447f4ec11fb..cccc626c83c8 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg0, ARRAY_SIZE(timberdale_cells_bar0_cfg0), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER1: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg1, ARRAY_SIZE(timberdale_cells_bar0_cfg1), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER2: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg2, ARRAY_SIZE(timberdale_cells_bar0_cfg2), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; case TIMB_HW_VER3: err = mfd_add_devices(&dev->dev, -1, timberdale_cells_bar0_cfg3, ARRAY_SIZE(timberdale_cells_bar0_cfg3), - &dev->resource[0], msix_entries[0].vector); + &dev->resource[0], msix_entries[0].vector, NULL); break; default: dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", @@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev, err = mfd_add_devices(&dev->dev, 0, timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), - &dev->resource[1], msix_entries[0].vector); + &dev->resource[1], msix_entries[0].vector, NULL); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; @@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev, ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, ARRAY_SIZE(timberdale_cells_bar2), - &dev->resource[2], msix_entries[0].vector); + &dev->resource[2], msix_entries[0].vector, NULL); if (err) { dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); goto err_mfd2; diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index a293b978e27c..14051bdc714b 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, 0, tps6105x_cells, - ARRAY_SIZE(tps6105x_cells), NULL, 0); + ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL); if (ret) goto fail; diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c index 33ba7723c967..1b203499c744 100644 --- a/drivers/mfd/tps6507x.c +++ b/drivers/mfd/tps6507x.c @@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps6507x->dev, -1, tps6507x_devs, ARRAY_SIZE(tps6507x_devs), - NULL, 0); + NULL, 0, NULL); if (ret < 0) goto err; diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 80e24f4b47bf..50fd87c87a1c 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps65090->dev, -1, tps65090s, - ARRAY_SIZE(tps65090s), NULL, 0); + ARRAY_SIZE(tps65090s), NULL, 0, NULL); if (ret) { dev_err(&client->dev, "add mfd devices failed with err: %d\n", ret); diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 3bc274409b58..a95e9421b735 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -191,7 +191,7 @@ static int __devinit tps65217_probe(struct i2c_client *client, } ret = mfd_add_devices(tps->dev, -1, tps65217s, - ARRAY_SIZE(tps65217s), NULL, 0); + ARRAY_SIZE(tps65217s), NULL, 0, NULL); if (ret < 0) { dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 353c34812120..5f58370ccf55 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -493,7 +493,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, } ret = mfd_add_devices(tps6586x->dev, -1, - tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); + tps6586x_cell, ARRAY_SIZE(tps6586x_cell), + NULL, 0, NULL); if (ret < 0) { dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); goto err_mfd_add; diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 1c563792c777..d3ce4d569deb 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(tps65910->dev, -1, tps65910s, ARRAY_SIZE(tps65910s), - NULL, 0); + NULL, 0, NULL); if (ret < 0) { dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret); return ret; diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 74fd8cb5f372..4658b5bdcd84 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912) ret = mfd_add_devices(tps65912->dev, -1, tps65912s, ARRAY_SIZE(tps65912s), - NULL, 0); + NULL, 0, NULL); if (ret < 0) goto err; diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 838ce4eb444e..77c9acb14583 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) if (childs) ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells, - childs, NULL, 0); + childs, NULL, 0, NULL); else { dev_err(&pdev->dev, "No platform data found for childs\n"); ret = -ENODEV; diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index b0fad0ffca56..3dca5c195a20 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client, } ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children, - NULL, 0); + NULL, 0, NULL); if (ret) goto mfd_err; diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c index 872aff21e4be..b9a636d44c7f 100644 --- a/drivers/mfd/vx855.c +++ b/drivers/mfd/vx855.c @@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev, vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3; ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells), - NULL, 0); + NULL, 0, NULL); /* we always return -ENODEV here in order to enable other * drivers like old, not-yet-platform_device ported i2c-viapro */ diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c index f39b756df561..86e0e4309fc2 100644 --- a/drivers/mfd/wl1273-core.c +++ b/drivers/mfd/wl1273-core.c @@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client, __func__, children); r = mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0); + children, NULL, 0, NULL); if (r) goto err; diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 946698fd2dc6..301731035940 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8310: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8310_devs, ARRAY_SIZE(wm8310_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8311: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8311_devs, ARRAY_SIZE(wm8311_devs), - NULL, 0); + NULL, 0, NULL); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8312: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8312_devs, ARRAY_SIZE(wm8312_devs), - NULL, 0); + NULL, 0, NULL); if (!pdata || !pdata->disable_touch) mfd_add_devices(wm831x->dev, wm831x_num, touch_devs, ARRAY_SIZE(touch_devs), - NULL, 0); + NULL, 0, NULL); break; case WM8320: @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) case WM8326: ret = mfd_add_devices(wm831x->dev, wm831x_num, wm8320_devs, ARRAY_SIZE(wm8320_devs), - NULL, 0); + NULL, 0, NULL); break; default: @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) if (ret & WM831X_XTAL_ENA) { ret = mfd_add_devices(wm831x->dev, wm831x_num, rtc_devs, ARRAY_SIZE(rtc_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); goto err_irq; @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) /* Treat errors as non-critical */ ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, ARRAY_SIZE(backlight_devs), NULL, - 0); + 0, NULL); if (ret < 0) dev_err(wm831x->dev, "Failed to add backlight: %d\n", ret); diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 4b7d378551d5..639ca359242f 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400) .pdata_size = sizeof(*wm8400), }; - return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); + return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL); } /* diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index eec74aa55fdf..2febf88cfce8 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_regulator_devs, ARRAY_SIZE(wm8994_regulator_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err; @@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) ret = mfd_add_devices(wm8994->dev, -1, wm8994_devs, ARRAY_SIZE(wm8994_devs), - NULL, 0); + NULL, 0, NULL); if (ret != 0) { dev_err(wm8994->dev, "Failed to add children: %d\n", ret); goto err_irq; diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 695ea35f75b0..d0a7e408efe9 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) } ret = mfd_add_devices(nvec->dev, -1, nvec_devices, - ARRAY_SIZE(nvec_devices), base, 0); + ARRAY_SIZE(nvec_devices), base, 0, NULL); if (ret) dev_err(nvec->dev, "error adding subdevices\n"); diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 3a8435a8058f..cebe97ee98b8 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -16,6 +16,8 @@ #include +struct irq_domain; + /* * This struct describes the MFD part ("cell"). * After registration the copy of this structure will become the platform data @@ -98,7 +100,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) extern int mfd_add_devices(struct device *parent, int id, struct mfd_cell *cells, int n_devs, struct resource *mem_base, - int irq_base); + int irq_base, struct irq_domain *irq_domain); extern void mfd_remove_devices(struct device *parent); -- cgit v1.2.3 From d51f42d2c5b7e11b47876b8b5c53f0ac317fef24 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 21 Aug 2012 15:15:52 +0900 Subject: mfd: MAX77693: Fix interrupt handling bug This patch fix bug related to interrupt handling for MAX77693 devices. - Unmask interrupt masking bit for charger/flash/muic to revolve that interrupt isn't happened when external connector is attached. - Fix wrong regmap instance when muic interrupt is happened. This patch were discussed and confirm discussion about this patch on below url: http://lkml.org/lkml/2012/7/16/118 Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Acked-by: Greg Kroah-Hartman Signed-off-by: Samuel Ortiz --- drivers/mfd/max77693-irq.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c index 2b403569e0a6..1029d018c739 100644 --- a/drivers/mfd/max77693-irq.c +++ b/drivers/mfd/max77693-irq.c @@ -137,6 +137,9 @@ static void max77693_irq_mask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); + if (irq_data->group >= MAX77693_IRQ_GROUP_NR) + return; + if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask; else @@ -149,6 +152,9 @@ static void max77693_irq_unmask(struct irq_data *data) const struct max77693_irq_data *irq_data = irq_to_max77693_irq(max77693, data->irq); + if (irq_data->group >= MAX77693_IRQ_GROUP_NR) + return; + if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3) max77693->irq_masks_cur[irq_data->group] |= irq_data->mask; else @@ -200,7 +206,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data) if (irq_src & MAX77693_IRQSRC_MUIC) /* MUIC INT1 ~ INT3 */ - max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1, + max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1, MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]); /* Apply masking */ @@ -255,7 +261,8 @@ int max77693_irq_init(struct max77693_dev *max77693) { struct irq_domain *domain; int i; - int ret; + int ret = 0; + u8 intsrc_mask; mutex_init(&max77693->irqlock); @@ -287,19 +294,38 @@ int max77693_irq_init(struct max77693_dev *max77693) &max77693_irq_domain_ops, max77693); if (!domain) { dev_err(max77693->dev, "could not create irq domain\n"); - return -ENODEV; + ret = -ENODEV; + goto err_irq; } max77693->irq_domain = domain; + /* Unmask max77693 interrupt */ + ret = max77693_read_reg(max77693->regmap, + MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask); + if (ret < 0) { + dev_err(max77693->dev, "fail to read PMIC register\n"); + goto err_irq; + } + + intsrc_mask &= ~(MAX77693_IRQSRC_CHG); + intsrc_mask &= ~(MAX77693_IRQSRC_FLASH); + intsrc_mask &= ~(MAX77693_IRQSRC_MUIC); + ret = max77693_write_reg(max77693->regmap, + MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask); + if (ret < 0) { + dev_err(max77693->dev, "fail to write PMIC register\n"); + goto err_irq; + } + ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77693-irq", max77693); - if (ret) dev_err(max77693->dev, "Failed to request IRQ %d: %d\n", max77693->irq, ret); - return 0; +err_irq: + return ret; } void max77693_irq_exit(struct max77693_dev *max77693) -- cgit v1.2.3 From b186b12487efc80c44f2f0d26cc26eb249cf1524 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 21 Aug 2012 15:16:23 +0900 Subject: mfd: MAX77693: Fix NULL pointer error when initializing irqs This patch initialize register map of MUIC device because mfd driver of Maxim MAX77693 use regmap-muic instance of MUIC device when irqs of Maxim MAX77693 is initialized before call max77693-muic probe() function. Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park Reported-by: Sylwester Nawrocki Acked-by: Greg Kroah-Hartman Signed-off-by: Samuel Ortiz --- drivers/extcon/extcon-max77693.c | 19 ++++++++++++------- drivers/mfd/max77693.c | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 920a609b2c35..38f9e52f358b 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -669,13 +669,18 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) } info->dev = &pdev->dev; info->max77693 = max77693; - info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, - &max77693_muic_regmap_config); - if (IS_ERR(info->max77693->regmap_muic)) { - ret = PTR_ERR(info->max77693->regmap_muic); - dev_err(max77693->dev, - "failed to allocate register map: %d\n", ret); - goto err_regmap; + if (info->max77693->regmap_muic) + dev_dbg(&pdev->dev, "allocate register map\n"); + else { + info->max77693->regmap_muic = devm_regmap_init_i2c( + info->max77693->muic, + &max77693_muic_regmap_config); + if (IS_ERR(info->max77693->regmap_muic)) { + ret = PTR_ERR(info->max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; + } } platform_set_drvdata(pdev, info); mutex_init(&info->mutex); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index 4fdd03d28539..cc5155e20494 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -152,6 +152,20 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); i2c_set_clientdata(max77693->haptic, max77693); + /* + * Initialize register map for MUIC device because use regmap-muic + * instance of MUIC device when irq of max77693 is initialized + * before call max77693-muic probe() function. + */ + max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic, + &max77693_regmap_config); + if (IS_ERR(max77693->regmap_muic)) { + ret = PTR_ERR(max77693->regmap_muic); + dev_err(max77693->dev, + "failed to allocate register map: %d\n", ret); + goto err_regmap; + } + ret = max77693_irq_init(max77693); if (ret < 0) goto err_irq; -- cgit v1.2.3