[PATCH] powerpc/pseries/eeh: Fix dumb linebreaks

2020-08-17 Thread Oliver O'Halloran
These annoy me every time I see them. Why are they here? They're not even
needed for 80cols compliance.

Signed-off-by: Oliver O'Halloran 
---
 arch/powerpc/platforms/pseries/eeh_pseries.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c 
b/arch/powerpc/platforms/pseries/eeh_pseries.c
index cb2d9a970b7b..1db74cec72bc 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -161,8 +161,7 @@ static int pseries_eeh_phb_reset(struct pci_controller 
*phb, int config_addr, in
BUID_LO(phb->buid), option);
 
/* If fundamental-reset not supported, try hot-reset */
-   if (option == EEH_RESET_FUNDAMENTAL &&
-   ret == -8) {
+   if (option == EEH_RESET_FUNDAMENTAL && ret == -8) {
option = EEH_RESET_HOT;
ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
config_addr, BUID_HI(phb->buid),
@@ -170,8 +169,7 @@ static int pseries_eeh_phb_reset(struct pci_controller 
*phb, int config_addr, in
}
 
/* We need reset hold or settlement delay */
-   if (option == EEH_RESET_FUNDAMENTAL ||
-   option == EEH_RESET_HOT)
+   if (option == EEH_RESET_FUNDAMENTAL || option == EEH_RESET_HOT)
msleep(EEH_PE_RST_HOLD_TIME);
else
msleep(EEH_PE_RST_SETTLE_TIME);
@@ -621,8 +619,7 @@ static int pseries_eeh_set_option(struct eeh_pe *pe, int 
option)
/* Not support */
return 0;
default:
-   pr_err("%s: Invalid option %d\n",
-   __func__, option);
+   pr_err("%s: Invalid option %d\n", __func__, option);
return -EINVAL;
}
 
@@ -954,8 +951,7 @@ static int pseries_notify_resume(struct eeh_dev *edev)
if (!edev)
return -EEXIST;
 
-   if (rtas_token("ibm,open-sriov-allow-unfreeze")
-   == RTAS_UNKNOWN_SERVICE)
+   if (rtas_token("ibm,open-sriov-allow-unfreeze") == RTAS_UNKNOWN_SERVICE)
return -EINVAL;
 
if (edev->pdev->is_physfn || edev->pdev->is_virtfn)
-- 
2.26.2



[RFC PATCH 2/2] powerpc/64s/radix: Fix mm_cpumask trimming race vs kthread_use_mm

2020-08-17 Thread Nicholas Piggin
Commit 0cef77c7798a7 ("powerpc/64s/radix: flush remote CPUs out of
single-threaded mm_cpumask") added a mechanism to trim the mm_cpumask of
a process under certain conditions. One of the assumptions is that
mm_users would not be incremented via a reference outside the process
context with mmget_not_zero() then go on to kthread_use_mm() via that
reference.

That invariant was broken by io_uring code (see previous sparc64 fix),
but I'll point Fixes: to the original powerpc commit because we are
changing that assumption going forward, so this will make backports
match up.

Fix this by no longer relying on that assumption, but by having each CPU
check the mm is not being used, and clearing their own bit from the mask
if it's okay. This relies on commit 38cf307c1f20 ("mm: fix
kthread_use_mm() vs TLB invalidate") to disable irqs over the mm switch.

Fixes: 0cef77c7798a7 ("powerpc/64s/radix: flush remote CPUs out of 
single-threaded mm_cpumask")
not-yet-Signed-off-by: Nicholas Piggin 
---
 arch/powerpc/include/asm/tlb.h   | 13 -
 arch/powerpc/mm/book3s64/radix_tlb.c | 23 ---
 2 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h
index fbc6f3002f23..d97f061fecac 100644
--- a/arch/powerpc/include/asm/tlb.h
+++ b/arch/powerpc/include/asm/tlb.h
@@ -66,19 +66,6 @@ static inline int mm_is_thread_local(struct mm_struct *mm)
return false;
return cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm));
 }
-static inline void mm_reset_thread_local(struct mm_struct *mm)
-{
-   WARN_ON(atomic_read(>context.copros) > 0);
-   /*
-* It's possible for mm_access to take a reference on mm_users to
-* access the remote mm from another thread, but it's not allowed
-* to set mm_cpumask, so mm_users may be > 1 here.
-*/
-   WARN_ON(current->mm != mm);
-   atomic_set(>context.active_cpus, 1);
-   cpumask_clear(mm_cpumask(mm));
-   cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-}
 #else /* CONFIG_PPC_BOOK3S_64 */
 static inline int mm_is_thread_local(struct mm_struct *mm)
 {
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c 
b/arch/powerpc/mm/book3s64/radix_tlb.c
index 0d233763441f..a421a0e3f930 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -645,19 +645,29 @@ static void do_exit_flush_lazy_tlb(void *arg)
struct mm_struct *mm = arg;
unsigned long pid = mm->context.id;
 
+   /*
+* A kthread could have done a mmget_not_zero() after the flushing CPU
+* checked mm_users == 1, and be in the process of kthread_use_mm when
+* interrupted here. In that case, current->mm will be set to mm,
+* because kthread_use_mm() setting ->mm and switching to the mm is
+* done with interrupts off.
+*/
if (current->mm == mm)
-   return; /* Local CPU */
+   goto out_flush;
 
if (current->active_mm == mm) {
-   /*
-* Must be a kernel thread because sender is single-threaded.
-*/
-   BUG_ON(current->mm);
+   WARN_ON_ONCE(current->mm != NULL);
+   /* Is a kernel thread and is using mm as the lazy tlb */
mmgrab(_mm);
-   switch_mm(mm, _mm, current);
current->active_mm = _mm;
+   switch_mm_irqs_off(mm, _mm, current);
mmdrop(mm);
}
+
+   atomic_dec(>context.active_cpus);
+   cpumask_clear_cpu(smp_processor_id(), mm_cpumask(mm));
+
+out_flush:
_tlbiel_pid(pid, RIC_FLUSH_ALL);
 }
 
@@ -672,7 +682,6 @@ static void exit_flush_lazy_tlbs(struct mm_struct *mm)
 */
smp_call_function_many(mm_cpumask(mm), do_exit_flush_lazy_tlb,
(void *)mm, 1);
-   mm_reset_thread_local(mm);
 }
 
 void radix__flush_tlb_mm(struct mm_struct *mm)
-- 
2.23.0



[RFC PATCH 1/2] sparc64: remove mm_cpumask clearing to fix kthread_use_mm race

2020-08-17 Thread Nicholas Piggin
The de facto (and apparently uncommented) standard for using an mm had,
thanks to this code in sparc if nothing else, been that you must have a
reference on mm_users *and that reference must have been obtained with
mmget()*, i.e., from a thread with a reference to mm_users that had used
the mm.

The introduction of mmget_not_zero() in commit d2005e3f41d4
("userfaultfd: don't pin the user memory in userfaultfd_file_create()")
allowed mm_count holders to aoperate on user mappings asynchronously
from the actual threads using the mm, but they were not to load those
mappings into their TLB (i.e., walking vmas and page tables is okay,
kthread_use_mm() is not).

io_uring 2b188cc1bb857 ("Add io_uring IO interface") added code which
does a kthread_use_mm() from a mmget_not_zero() refcount.

The problem with this is code which previously assumed mm == current->mm
and mm->mm_users == 1 implies the mm will remain single-threaded at
least until this thread creates another mm_users reference, has now
broken.

arch/sparc/kernel/smp_64.c:

if (atomic_read(>mm_users) == 1) {
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
goto local_flush_and_out;
}

vs fs/io_uring.c

if (unlikely(!(ctx->flags & IORING_SETUP_SQPOLL) ||
 !mmget_not_zero(ctx->sqo_mm)))
return -EFAULT;
kthread_use_mm(ctx->sqo_mm);

mmget_not_zero() could come in right after the mm_users == 1 test, then
kthread_use_mm() which sets its CPU in the mm_cpumask. That update could
be lost if cpumask_copy() occurs afterward.

I propose we fix this by allowing mmget_not_zero() to be a first-class
reference, and not have this obscure undocumented and unchecked
restriction.

The basic fix for sparc64 is to remove its mm_cpumask clearing code. The
optimisation could be effectively restored by sending IPIs to mm_cpumask
members and having them remove themselves from mm_cpumask. This is more
tricky so I leave it as an exercise for someone with a sparc64 SMP.
powerpc has a (currently similarly broken) example.

not-yet-Signed-off-by: Nicholas Piggin 
---
 arch/sparc/kernel/smp_64.c | 58 ++
 1 file changed, 9 insertions(+), 49 deletions(-)

diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index e286e2badc8a..41423c6077d0 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1039,38 +1039,9 @@ void smp_fetch_global_pmu(void)
  * are flush_tlb_*() routines, and these run after flush_cache_*()
  * which performs the flushw.
  *
- * The SMP TLB coherency scheme we use works as follows:
- *
- * 1) mm->cpu_vm_mask is a bit mask of which cpus an address
- *space has (potentially) executed on, this is the heuristic
- *we use to avoid doing cross calls.
- *
- *Also, for flushing from kswapd and also for clones, we
- *use cpu_vm_mask as the list of cpus to make run the TLB.
- *
- * 2) TLB context numbers are shared globally across all processors
- *in the system, this allows us to play several games to avoid
- *cross calls.
- *
- *One invariant is that when a cpu switches to a process, and
- *that processes tsk->active_mm->cpu_vm_mask does not have the
- *current cpu's bit set, that tlb context is flushed locally.
- *
- *If the address space is non-shared (ie. mm->count == 1) we avoid
- *cross calls when we want to flush the currently running process's
- *tlb state.  This is done by clearing all cpu bits except the current
- *processor's in current->mm->cpu_vm_mask and performing the
- *flush locally only.  This will force any subsequent cpus which run
- *this task to flush the context from the local tlb if the process
- *migrates to another cpu (again).
- *
- * 3) For shared address spaces (threads) and swapping we bite the
- *bullet for most cases and perform the cross call (but only to
- *the cpus listed in cpu_vm_mask).
- *
- *The performance gain from "optimizing" away the cross call for threads is
- *questionable (in theory the big win for threads is the massive sharing of
- *address space state across processors).
+ * mm->cpu_vm_mask is a bit mask of which cpus an address
+ * space has (potentially) executed on, this is the heuristic
+ * we use to limit cross calls.
  */
 
 /* This currently is only used by the hugetlb arch pre-fault
@@ -1082,16 +1053,10 @@ void smp_flush_tlb_mm(struct mm_struct *mm)
u32 ctx = CTX_HWBITS(mm->context);
int cpu = get_cpu();
 
-   if (atomic_read(>mm_users) == 1) {
-   cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
-   goto local_flush_and_out;
-   }
-
smp_cross_call_masked(_flush_tlb_mm,
  ctx, 0, 0,
  mm_cpumask(mm));
 
-local_flush_and_out:
__flush_tlb_mm(ctx, SECONDARY_CONTEXT);
 
put_cpu();
@@ -1120,11 +1085,8 @@ void smp_flush_tlb_pending(struct mm_struct *mm, 
unsigned long nr, unsigned long

Re: [PATCH 1/2] powerpc/64s: remove PROT_SAO support

2020-08-17 Thread Shawn Anastasio

I'm a bit concerned about the removal of PROT_SAO.

From what I can see, a feature like this would be extremely useful for
emulating architectures with stronger memory models. QEMU's multi-
threaded TCG project in particular looks like it would be a good
candidate, since as far as I'm aware it is currently completely
unable to perform strong-on-weak emulation.

Without hardware support like SAO provides, the only way I could see
to achieve this would be by emitting tons of unnecessary and costly
memory barrier instructions.

I understand that ISA 3.1 and POWER10 have dropped SAO, but as a POWER9
user it seems a bit silly to have a potentially useful feature dropped
from the kernel just because a future processor doesn't support it.

Curious to hear more thoughts on this.

Regards,
Shawn

On 6/7/20 7:02 AM, Nicholas Piggin wrote:

ISA v3.1 does not support the SAO storage control attribute required to
implement PROT_SAO. PROT_SAO was used by specialised system software
(Lx86) that has been discontinued for about 7 years, and is not thought
to be used elsewhere, so removal should not cause problems.

We rather remove it than keep support for older processors, because
live migrating guest partitions to newer processors may not be possible
if SAO is in use.

Signed-off-by: Nicholas Piggin 
---
  arch/powerpc/include/asm/book3s/64/pgtable.h  |  8 ++--
  arch/powerpc/include/asm/cputable.h   |  9 ++--
  arch/powerpc/include/asm/kvm_book3s_64.h  |  3 +-
  arch/powerpc/include/asm/mman.h   | 24 +++
  arch/powerpc/include/asm/nohash/64/pgtable.h  |  2 -
  arch/powerpc/kernel/dt_cpu_ftrs.c |  2 +-
  arch/powerpc/mm/book3s64/hash_utils.c |  2 -
  include/linux/mm.h|  2 -
  include/trace/events/mmflags.h|  2 -
  mm/ksm.c  |  4 --
  tools/testing/selftests/powerpc/mm/.gitignore |  1 -
  tools/testing/selftests/powerpc/mm/Makefile   |  4 +-
  tools/testing/selftests/powerpc/mm/prot_sao.c | 42 ---
  13 files changed, 18 insertions(+), 87 deletions(-)
  delete mode 100644 tools/testing/selftests/powerpc/mm/prot_sao.c

diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h 
b/arch/powerpc/include/asm/book3s/64/pgtable.h
index f17442c3a092..d9e92586f8dc 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -20,9 +20,13 @@
  #define _PAGE_RW  (_PAGE_READ | _PAGE_WRITE)
  #define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
  #define _PAGE_PRIVILEGED  0x8 /* kernel access only */
-#define _PAGE_SAO  0x00010 /* Strong access order */
+
+#define _PAGE_CACHE_CTL0x00030 /* Bits for the folowing cache 
modes */
+   /*  No bits set is normal cacheable memory */
+   /*  0x00010 unused, is SAO bit on radix POWER9 */
  #define _PAGE_NON_IDEMPOTENT  0x00020 /* non idempotent memory */
  #define _PAGE_TOLERANT0x00030 /* tolerant memory, cache 
inhibited */
+
  #define _PAGE_DIRTY   0x00080 /* C: page changed */
  #define _PAGE_ACCESSED0x00100 /* R: page referenced */
  /*
@@ -825,8 +829,6 @@ static inline void __set_pte_at(struct mm_struct *mm, 
unsigned long addr,
return hash__set_pte_at(mm, addr, ptep, pte, percpu);
  }
  
-#define _PAGE_CACHE_CTL	(_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)

-
  #define pgprot_noncached pgprot_noncached
  static inline pgprot_t pgprot_noncached(pgprot_t prot)
  {
diff --git a/arch/powerpc/include/asm/cputable.h 
b/arch/powerpc/include/asm/cputable.h
index bac2252c839e..c7e923ba 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -191,7 +191,6 @@ static inline void cpu_feature_keys_init(void) { }
  #define CPU_FTR_SPURR LONG_ASM_CONST(0x0100)
  #define CPU_FTR_DSCR  LONG_ASM_CONST(0x0200)
  #define CPU_FTR_VSX   LONG_ASM_CONST(0x0400)
-#define CPU_FTR_SAOLONG_ASM_CONST(0x0800)
  #define CPU_FTR_CP_USE_DCBTZ  LONG_ASM_CONST(0x1000)
  #define CPU_FTR_UNALIGNED_LD_STD  LONG_ASM_CONST(0x2000)
  #define CPU_FTR_ASYM_SMT  LONG_ASM_CONST(0x4000)
@@ -435,7 +434,7 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | \
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-   CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
+   CPU_FTR_DSCR | CPU_FTR_ASYM_SMT | \
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
CPU_FTR_CFAR | CPU_FTR_HVMODE | \
CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX | CPU_FTR_PKEY)
@@ -444,7 +443,7 @@ static inline void 

Re: [PATCH v4] selftests/powerpc: Fix pkey syscall redefinitions

2020-08-17 Thread Michael Ellerman
On Tue, 4 Aug 2020 23:01:37 +0530, Sandipan Das wrote:
> On distros using older glibc versions, the pkey tests
> encounter build failures due to redefinition of the
> pkey syscall numbers.
> 
> For compatibility, commit 743f3544fffb added a wrapper
> for the gettid() syscall and included syscall.h if the
> version of glibc used is older than 2.30. This leads
> to different definitions of SYS_pkey_* as the ones in
> the pkey test header set numeric constants where as the
> ones from syscall.h reuse __NR_pkey_*. The compiler
> complains about redefinitions since they are different.
> 
> [...]

Applied to powerpc/fixes.

[1/1] selftests/powerpc: Fix pkey syscall redefinitions
  https://git.kernel.org/powerpc/c/a7aaa2f26bfd932a654706b19859e7adf802bee2

cheers


Re: [PATCH] powerpc: Fix P10 PVR revision in /proc/cpuinfo for SMT4 cores

2020-08-17 Thread Michael Ellerman
On Mon, 3 Aug 2020 13:56:00 +1000, Michael Neuling wrote:
> On POWER10 bit 12 in the PVR indicates if the core is SMT4 or
> SMT8. Bit 12 is set for SMT4.
> 
> Without this patch, /proc/cpuinfo on a SMT4 DD1 POWER10 looks like
> this:
> cpu : POWER10, altivec supported
> revision: 17.0 (pvr 0080 1100)

Applied to powerpc/fixes.

[1/1] powerpc: Fix P10 PVR revision in /proc/cpuinfo for SMT4 cores
  https://git.kernel.org/powerpc/c/030a2c689fb46e1690f7ded8b194bab7678efb28

cheers


Re: [PATCH 1/2] powerpc/kernel/cputable: cleanup the function declarations

2020-08-17 Thread Michael Ellerman
On Mon, 17 Aug 2020 06:26:17 +0530, Madhavan Srinivasan wrote:
> __machine_check_early_realmode_p*() are currently declared
> as extern in cputable.c and because of this when compiled
> with "C=1" (which enables semantic checker) produces these
> warnings.
> 
>   CHECK   arch/powerpc/kernel/mce_power.c
> arch/powerpc/kernel/mce_power.c:709:6: warning: symbol 
> '__machine_check_early_realmode_p7' was not declared. Should it be static?
> arch/powerpc/kernel/mce_power.c:717:6: warning: symbol 
> '__machine_check_early_realmode_p8' was not declared. Should it be static?
> arch/powerpc/kernel/mce_power.c:722:6: warning: symbol 
> '__machine_check_early_realmode_p9' was not declared. Should it be static?
> arch/powerpc/kernel/mce_power.c:740:6: warning: symbol 
> '__machine_check_early_realmode_p10' was not declared. Should it be static?
> 
> [...]

Applied to powerpc/fixes.

[1/2] powerpc/kernel: Cleanup machine check function declarations
  https://git.kernel.org/powerpc/c/388692e943a58f28aac0fe83e75f5994da9ff8a1
[2/2] powerpc: Add POWER10 raw mode cputable entry
  https://git.kernel.org/powerpc/c/327da008e65a25b8206b36b7fc0c9e4edbb36a58

cheers


Re: [PATCH V6 0/2] powerpc/perf: Add support for perf extended regs in powerpc

2020-08-17 Thread Michael Ellerman
On Fri, 7 Aug 2020 06:04:59 -0400, Athira Rajeev wrote:
> Patch set to add support for perf extended register capability in
> powerpc. The capability flag PERF_PMU_CAP_EXTENDED_REGS, is used to
> indicate the PMU which support extended registers. The generic code
> define the mask of extended registers as 0 for non supported architectures.
> 
> patch 1/2 defines the PERF_PMU_CAP_EXTENDED_REGS mask to output the
> values of mmcr0,mmcr1,mmcr2 for POWER9. Defines `PERF_REG_EXTENDED_MASK`
> at runtime which contains mask value of the supported registers under
> extended regs.
> 
> [...]

Applied to powerpc/fixes.

[1/2] powerpc/perf: Add support for outputting extended regs in perf intr_regs
  https://git.kernel.org/powerpc/c/781fa4811d95314c1965c0c3337c9ac36ef26093
[2/2] powerpc/perf: Add extended regs support for power10 platform
  https://git.kernel.org/powerpc/c/d735599a069f6936c1392e07075c34a19bda949a

cheers


[PATCH v1 10/10] powerpc/pseries/iommu: Rename "direct window" to "dma window"

2020-08-17 Thread Leonardo Bras
A previous change introduced the usage of DDW as a bigger indirect DMA
mapping when the DDW available size does not map the whole partition.

As most of the code that manipulates direct mappings was reused for
indirect mappings, it's necessary to rename all names and debug/info
messages to reflect that it can be used for both kinds of mapping.

Also, defines DEFAULT_DMA_WIN as "ibm,dma-window" to document that
it's the name of the default DMA window.

Those changes are not supposed to change how the code works in any
way, just adjust naming.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 110 +
 1 file changed, 57 insertions(+), 53 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index 9544e3c91ced..c1454f9cd254 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -355,7 +355,7 @@ struct dynamic_dma_window_prop {
 
 #define DDW_FLAGS_DIRECT   0x01
 
-struct direct_window {
+struct dma_win {
struct device_node *device;
const struct dynamic_dma_window_prop *prop;
struct list_head list;
@@ -375,12 +375,13 @@ struct ddw_create_response {
u32 addr_lo;
 };
 
-static LIST_HEAD(direct_window_list);
+static LIST_HEAD(dma_win_list);
 /* prevents races between memory on/offline and window creation */
-static DEFINE_SPINLOCK(direct_window_list_lock);
+static DEFINE_SPINLOCK(dma_win_list_lock);
 /* protects initializing window twice for same device */
-static DEFINE_MUTEX(direct_window_init_mutex);
+static DEFINE_MUTEX(dma_win_init_mutex);
 #define DMA64_PROPNAME "linux,dma64-ddr-window-info"
+#define DEFAULT_DMA_WIN "ibm,dma-window"
 
 static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
unsigned long num_pfn, const void *arg)
@@ -713,15 +714,18 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus 
*bus)
pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n",
 dn);
 
-   /* Find nearest ibm,dma-window, walking up the device tree */
+   /*
+* Find nearest ibm,dma-window (default DMA window), walking up the
+* device tree
+*/
for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
-   dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+   dma_window = of_get_property(pdn, DEFAULT_DMA_WIN, NULL);
if (dma_window != NULL)
break;
}
 
if (dma_window == NULL) {
-   pr_debug("  no ibm,dma-window property !\n");
+   pr_debug("  no %s property !\n", DEFAULT_DMA_WIN);
return;
}
 
@@ -819,11 +823,11 @@ static void remove_dma_window(struct device_node *np, u32 
*ddw_avail,
 
ret = rtas_call(ddw_avail[DDW_REMOVE_PE_DMA_WIN], 1, 1, NULL, liobn);
if (ret)
-   pr_warn("%pOF: failed to remove direct window: rtas returned "
+   pr_warn("%pOF: failed to remove dma window: rtas returned "
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
np, ret, ddw_avail[DDW_REMOVE_PE_DMA_WIN], liobn);
else
-   pr_debug("%pOF: successfully removed direct window: rtas 
returned "
+   pr_debug("%pOF: successfully removed dma window: rtas returned "
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
np, ret, ddw_avail[DDW_REMOVE_PE_DMA_WIN], liobn);
 }
@@ -851,36 +855,36 @@ static void remove_ddw(struct device_node *np, bool 
remove_prop)
 
ret = of_remove_property(np, win);
if (ret)
-   pr_warn("%pOF: failed to remove direct window property: %d\n",
+   pr_warn("%pOF: failed to remove dma window property: %d\n",
np, ret);
 }
 
 static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, bool 
*direct_mapping)
 {
-   struct direct_window *window;
-   const struct dynamic_dma_window_prop *direct64;
+   struct dma_win *window;
+   const struct dynamic_dma_window_prop *dma64;
bool found = false;
 
-   spin_lock(_window_list_lock);
+   spin_lock(_win_list_lock);
/* check if we already created a window and dupe that config if so */
-   list_for_each_entry(window, _window_list, list) {
+   list_for_each_entry(window, _win_list, list) {
if (window->device == pdn) {
-   direct64 = window->prop;
-   *dma_addr = be64_to_cpu(direct64->dma_base);
-   *direct_mapping = be32_to_cpu(direct64->flags) & 
DDW_FLAGS_DIRECT;
+   dma64 = window->prop;
+   *dma_addr = be64_to_cpu(dma64->dma_base);
+   *direct_mapping = be32_to_cpu(dma64->flags) & 
DDW_FLAGS_DIRECT;
found = true;

[PATCH v1 09/10] powerpc/pseries/iommu: Make use of DDW even if it does not map the partition

2020-08-17 Thread Leonardo Bras
As of today, if the biggest DDW that can be created can't map the whole
partition, it's creation is skipped and the default DMA window
"ibm,dma-window" is used instead.

DDW is 16x bigger than the default DMA window, having the same amount of
pages, but increasing the page size to 64k.
Besides larger DMA window, it performs better for allocations over 4k,
so it would be nice to use it instead.

The DDW created will be used for direct mapping by default.
If it's not available, indirect mapping will be used instead.

For indirect mapping, it's necessary to update the iommu_table so
iommu_alloc() can use the DDW created. For this,
iommu_table_update_window() is called when everything else succeeds
at enable_ddw().

Removing the default DMA window for using DDW with indirect mapping
is only allowed if there is no current IOMMU memory allocated in
the iommu_table. enable_ddw() is aborted otherwise.

As there will never have both direct and indirect mappings at the same
time, the same property name can be used for the created DDW.

So renaming
define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
to
define DMA64_PROPNAME "linux,dma64-ddr-window-info"
looks the right thing to do.

To make sure the property differentiates both cases, a new u32 for flags
was added at the end of the property, where BIT(0) set means direct
mapping.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 108 +++--
 1 file changed, 84 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index 3a1ef02ad9d5..9544e3c91ced 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -350,8 +350,11 @@ struct dynamic_dma_window_prop {
__be64  dma_base;   /* address hi,lo */
__be32  tce_shift;  /* ilog2(tce_page_size) */
__be32  window_shift;   /* ilog2(tce_window_size) */
+   __be32  flags;  /* DDW properties, see bellow */
 };
 
+#define DDW_FLAGS_DIRECT   0x01
+
 struct direct_window {
struct device_node *device;
const struct dynamic_dma_window_prop *prop;
@@ -377,7 +380,7 @@ static LIST_HEAD(direct_window_list);
 static DEFINE_SPINLOCK(direct_window_list_lock);
 /* protects initializing window twice for same device */
 static DEFINE_MUTEX(direct_window_init_mutex);
-#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+#define DMA64_PROPNAME "linux,dma64-ddr-window-info"
 
 static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
unsigned long num_pfn, const void *arg)
@@ -836,7 +839,7 @@ static void remove_ddw(struct device_node *np, bool 
remove_prop)
if (ret)
return;
 
-   win = of_find_property(np, DIRECT64_PROPNAME, NULL);
+   win = of_find_property(np, DMA64_PROPNAME, NULL);
if (!win)
return;
 
@@ -852,7 +855,7 @@ static void remove_ddw(struct device_node *np, bool 
remove_prop)
np, ret);
 }
 
-static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr)
+static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, bool 
*direct_mapping)
 {
struct direct_window *window;
const struct dynamic_dma_window_prop *direct64;
@@ -864,6 +867,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 
*dma_addr)
if (window->device == pdn) {
direct64 = window->prop;
*dma_addr = be64_to_cpu(direct64->dma_base);
+   *direct_mapping = be32_to_cpu(direct64->flags) & 
DDW_FLAGS_DIRECT;
found = true;
break;
}
@@ -901,8 +905,8 @@ static int find_existing_ddw_windows(void)
if (!firmware_has_feature(FW_FEATURE_LPAR))
return 0;
 
-   for_each_node_with_property(pdn, DIRECT64_PROPNAME) {
-   direct64 = of_get_property(pdn, DIRECT64_PROPNAME, );
+   for_each_node_with_property(pdn, DMA64_PROPNAME) {
+   direct64 = of_get_property(pdn, DMA64_PROPNAME, );
if (!direct64)
continue;
 
@@ -1124,7 +1128,8 @@ static void reset_dma_window(struct pci_dev *dev, struct 
device_node *par_dn)
 }
 
 static int ddw_property_create(struct property **ddw_win, const char *propname,
-  u32 liobn, u64 dma_addr, u32 page_shift, u32 
window_shift)
+  u32 liobn, u64 dma_addr, u32 page_shift,
+  u32 window_shift, bool direct_mapping)
 {
struct dynamic_dma_window_prop *ddwprop;
struct property *win64;
@@ -1144,6 +1149,36 @@ static int ddw_property_create(struct property 
**ddw_win, const char *propname,
ddwprop->dma_base = cpu_to_be64(dma_addr);
ddwprop->tce_shift = cpu_to_be32(page_shift);
ddwprop->window_shift = 

[PATCH v1 08/10] powerpc/pseries/iommu: Add ddw_property_create() and refactor enable_ddw()

2020-08-17 Thread Leonardo Bras
Code used to create a ddw property that was previously scattered in
enable_ddw() is now gathered in ddw_property_create(), which deals with
allocation and filling the property, letting it ready for
of_property_add(), which now occurs in sequence.

This created an opportunity to reorganize the second part of enable_ddw():

Without this patch enable_ddw() does, in order:
kzalloc() property & members, create_ddw(), fill ddwprop inside property,
ddw_list_add(), do tce_setrange_multi_pSeriesLP_walk in all memory,
of_add_property().

With this patch enable_ddw() does, in order:
create_ddw(), ddw_property_create(), of_add_property(), ddw_list_add(),
do tce_setrange_multi_pSeriesLP_walk in all memory.

This change requires of_remove_property() in case anything fails after
of_add_property(), but we get to do tce_setrange_multi_pSeriesLP_walk
in all memory, which looks the most expensive operation, only if
everything else succeeds.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 97 +++---
 1 file changed, 57 insertions(+), 40 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index 4031127c9537..3a1ef02ad9d5 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1123,6 +1123,31 @@ static void reset_dma_window(struct pci_dev *dev, struct 
device_node *par_dn)
 ret);
 }
 
+static int ddw_property_create(struct property **ddw_win, const char *propname,
+  u32 liobn, u64 dma_addr, u32 page_shift, u32 
window_shift)
+{
+   struct dynamic_dma_window_prop *ddwprop;
+   struct property *win64;
+
+   *ddw_win = win64 = kzalloc(sizeof(*win64), GFP_KERNEL);
+   if (!win64)
+   return -ENOMEM;
+
+   win64->name = kstrdup(propname, GFP_KERNEL);
+   ddwprop = kzalloc(sizeof(*ddwprop), GFP_KERNEL);
+   win64->value = ddwprop;
+   win64->length = sizeof(*ddwprop);
+   if (!win64->name || !win64->value)
+   return -ENOMEM;
+
+   ddwprop->liobn = cpu_to_be32(liobn);
+   ddwprop->dma_base = cpu_to_be64(dma_addr);
+   ddwprop->tce_shift = cpu_to_be32(page_shift);
+   ddwprop->window_shift = cpu_to_be32(window_shift);
+
+   return 0;
+}
+
 /*
  * If the PE supports dynamic dma windows, and there is space for a table
  * that can map all pages in a linear offset, then setup such a table,
@@ -1140,12 +1165,11 @@ static bool enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
struct ddw_query_response query;
struct ddw_create_response create;
int page_shift;
-   u64 max_addr;
+   u64 max_addr, win_addr;
struct device_node *dn;
u32 ddw_avail[DDW_APPLICABLE_SIZE];
struct direct_window *window;
-   struct property *win64;
-   struct dynamic_dma_window_prop *ddwprop;
+   struct property *win64 = NULL;
struct failed_ddw_pdn *fpdn;
bool default_win_removed = false;
 
@@ -1244,38 +1268,34 @@ static bool enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
goto out_failed;
}
len = order_base_2(max_addr);
-   win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
-   if (!win64) {
-   dev_info(>dev,
-   "couldn't allocate property for 64bit dma window\n");
+
+   ret = create_ddw(dev, ddw_avail, , page_shift, len);
+   if (ret != 0)
goto out_failed;
-   }
-   win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
-   win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
-   win64->length = sizeof(*ddwprop);
-   if (!win64->name || !win64->value) {
+
+   dev_dbg(>dev, "created tce table LIOBN 0x%x for %pOF\n",
+   create.liobn, dn);
+
+   win_addr = ((u64)create.addr_hi << 32) | create.addr_lo;
+   ret = ddw_property_create(, DIRECT64_PROPNAME, create.liobn, 
win_addr,
+ page_shift, len);
+   if (ret) {
dev_info(>dev,
-   "couldn't allocate property name and value\n");
+"couldn't allocate property, property name, or 
value\n");
goto out_free_prop;
}
 
-   ret = create_ddw(dev, ddw_avail, , page_shift, len);
-   if (ret != 0)
+   ret = of_add_property(pdn, win64);
+   if (ret) {
+   dev_err(>dev, "unable to add dma window property for %pOF: 
%d",
+   pdn, ret);
goto out_free_prop;
-
-   ddwprop->liobn = cpu_to_be32(create.liobn);
-   ddwprop->dma_base = cpu_to_be64(((u64)create.addr_hi << 32) |
-   create.addr_lo);
-   ddwprop->tce_shift = cpu_to_be32(page_shift);
-   ddwprop->window_shift = cpu_to_be32(len);
-
-   dev_dbg(>dev, "created tce table LIOBN 0x%x for %pOF\n",
- create.liobn, dn);
+  

[PATCH v1 07/10] powerpc/pseries/iommu: Allow DDW windows starting at 0x00

2020-08-17 Thread Leonardo Bras
enable_ddw() currently returns the address of the DMA window, which is
considered invalid if has the value 0x00.

Also, it only considers valid an address returned from find_existing_ddw
if it's not 0x00.

Changing this behavior makes sense, given the users of enable_ddw() only
need to know if direct mapping is possible. It can also allow a DMA window
starting at 0x00 to be used.

This will be helpful for using a DDW with indirect mapping, as the window
address will be different than 0x00, but it will not map the whole
partition.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 30 --
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index fcdefcc0f365..4031127c9537 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -852,24 +852,25 @@ static void remove_ddw(struct device_node *np, bool 
remove_prop)
np, ret);
 }
 
-static u64 find_existing_ddw(struct device_node *pdn)
+static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr)
 {
struct direct_window *window;
const struct dynamic_dma_window_prop *direct64;
-   u64 dma_addr = 0;
+   bool found = false;
 
spin_lock(_window_list_lock);
/* check if we already created a window and dupe that config if so */
list_for_each_entry(window, _window_list, list) {
if (window->device == pdn) {
direct64 = window->prop;
-   dma_addr = be64_to_cpu(direct64->dma_base);
+   *dma_addr = be64_to_cpu(direct64->dma_base);
+   found = true;
break;
}
}
spin_unlock(_window_list_lock);
 
-   return dma_addr;
+   return found;
 }
 
 static struct direct_window *ddw_list_add(struct device_node *pdn,
@@ -1131,15 +1132,15 @@ static void reset_dma_window(struct pci_dev *dev, 
struct device_node *par_dn)
  * pdn: the parent pe node with the ibm,dma_window property
  * Future: also check if we can remap the base window for our base page size
  *
- * returns the dma offset for use by the direct mapped DMA code.
+ * returns true if can map all pages (direct mapping), false otherwise..
  */
-static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
 {
int len, ret;
struct ddw_query_response query;
struct ddw_create_response create;
int page_shift;
-   u64 dma_addr, max_addr;
+   u64 max_addr;
struct device_node *dn;
u32 ddw_avail[DDW_APPLICABLE_SIZE];
struct direct_window *window;
@@ -1150,8 +1151,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
 
mutex_lock(_window_init_mutex);
 
-   dma_addr = find_existing_ddw(pdn);
-   if (dma_addr != 0)
+   if (find_existing_ddw(pdn, >dev.archdata.dma_offset))
goto out_unlock;
 
/*
@@ -1292,7 +1292,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
goto out_free_window;
}
 
-   dma_addr = be64_to_cpu(ddwprop->dma_base);
+   dev->dev.archdata.dma_offset = be64_to_cpu(ddwprop->dma_base);
goto out_unlock;
 
 out_free_window:
@@ -1309,6 +1309,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
kfree(win64->name);
kfree(win64->value);
kfree(win64);
+   win64 = NULL;
 
 out_failed:
if (default_win_removed)
@@ -1322,7 +1323,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
 
 out_unlock:
mutex_unlock(_window_init_mutex);
-   return dma_addr;
+   return win64;
 }
 
 static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
@@ -1401,11 +1402,8 @@ static bool iommu_bypass_supported_pSeriesLP(struct 
pci_dev *pdev, u64 dma_mask)
break;
}
 
-   if (pdn && PCI_DN(pdn)) {
-   pdev->dev.archdata.dma_offset = enable_ddw(pdev, pdn);
-   if (pdev->dev.archdata.dma_offset)
-   return true;
-   }
+   if (pdn && PCI_DN(pdn))
+   return enable_ddw(pdev, pdn);
 
return false;
 }
-- 
2.25.4



[PATCH v1 06/10] powerpc/pseries/iommu: Add ddw_list_add() helper

2020-08-17 Thread Leonardo Bras
There are two functions adding DDW to the direct_window_list in a
similar way, so create a ddw_list_add() to avoid duplicity and
simplify those functions.

Also, on enable_ddw(), add list_del() on out_free_window to allow
removing the window from list if any error occurs.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 42 --
 1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index 39617ce0ec83..fcdefcc0f365 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -872,6 +872,24 @@ static u64 find_existing_ddw(struct device_node *pdn)
return dma_addr;
 }
 
+static struct direct_window *ddw_list_add(struct device_node *pdn,
+ const struct dynamic_dma_window_prop 
*dma64)
+{
+   struct direct_window *window;
+
+   window = kzalloc(sizeof(*window), GFP_KERNEL);
+   if (!window)
+   return NULL;
+
+   window->device = pdn;
+   window->prop = dma64;
+   spin_lock(_window_list_lock);
+   list_add(>list, _window_list);
+   spin_unlock(_window_list_lock);
+
+   return window;
+}
+
 static int find_existing_ddw_windows(void)
 {
int len;
@@ -887,18 +905,11 @@ static int find_existing_ddw_windows(void)
if (!direct64)
continue;
 
-   window = kzalloc(sizeof(*window), GFP_KERNEL);
-   if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
+   window = ddw_list_add(pdn, direct64);
+   if (!window || len < sizeof(*direct64)) {
kfree(window);
remove_ddw(pdn, true);
-   continue;
}
-
-   window->device = pdn;
-   window->prop = direct64;
-   spin_lock(_window_list_lock);
-   list_add(>list, _window_list);
-   spin_unlock(_window_list_lock);
}
 
return 0;
@@ -1261,7 +1272,8 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
dev_dbg(>dev, "created tce table LIOBN 0x%x for %pOF\n",
  create.liobn, dn);
 
-   window = kzalloc(sizeof(*window), GFP_KERNEL);
+   /* Add new window to existing DDW list */
+   window = ddw_list_add(pdn, ddwprop);
if (!window)
goto out_clear_window;
 
@@ -1280,16 +1292,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct 
device_node *pdn)
goto out_free_window;
}
 
-   window->device = pdn;
-   window->prop = ddwprop;
-   spin_lock(_window_list_lock);
-   list_add(>list, _window_list);
-   spin_unlock(_window_list_lock);
-
dma_addr = be64_to_cpu(ddwprop->dma_base);
goto out_unlock;
 
 out_free_window:
+   spin_lock(_window_list_lock);
+   list_del(>list);
+   spin_unlock(_window_list_lock);
+
kfree(window);
 
 out_clear_window:
-- 
2.25.4



[PATCH v1 05/10] powerpc/pseries/iommu: Add iommu_pseries_alloc_table() helper

2020-08-17 Thread Leonardo Bras
Creates a helper to allow allocating a new iommu_table without the need
to reallocate the iommu_group.

This will be helpful for replacing the iommu_table for the new DMA window,
after we remove the old one with iommu_tce_table_put().

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/platforms/pseries/iommu.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index 8fe23b7dff3a..39617ce0ec83 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -53,28 +53,31 @@ enum {
DDW_EXT_QUERY_OUT_SIZE = 2
 };
 
-static struct iommu_table_group *iommu_pseries_alloc_group(int node)
+static struct iommu_table *iommu_pseries_alloc_table(int node)
 {
-   struct iommu_table_group *table_group;
struct iommu_table *tbl;
 
-   table_group = kzalloc_node(sizeof(struct iommu_table_group), GFP_KERNEL,
-  node);
-   if (!table_group)
-   return NULL;
-
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, node);
if (!tbl)
-   goto free_group;
+   return NULL;
 
INIT_LIST_HEAD_RCU(>it_group_list);
kref_init(>it_kref);
+   return tbl;
+}
 
-   table_group->tables[0] = tbl;
+static struct iommu_table_group *iommu_pseries_alloc_group(int node)
+{
+   struct iommu_table_group *table_group;
+
+   table_group = kzalloc_node(sizeof(*table_group), GFP_KERNEL, node);
+   if (!table_group)
+   return NULL;
 
-   return table_group;
+   table_group->tables[0] = iommu_pseries_alloc_table(node);
+   if (table_group->tables[0])
+   return table_group;
 
-free_group:
kfree(table_group);
return NULL;
 }
-- 
2.25.4



[PATCH v1 04/10] powerpc/kernel/iommu: Add new iommu_table_in_use() helper

2020-08-17 Thread Leonardo Bras
Having a function to check if the iommu table has any allocation helps
deciding if a tbl can be reset for using a new DMA window.

It should be enough to replace all instances of !bitmap_empty(tbl...).

iommu_table_in_use() skips reserved memory, so we don't need to worry about
releasing it before testing. This causes iommu_table_release_pages() to
become unnecessary, given it is only used to remove reserved memory for
testing.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/include/asm/iommu.h |  1 +
 arch/powerpc/kernel/iommu.c  | 62 ++--
 2 files changed, 37 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index 5032f1593299..2913e5c8b1f8 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -154,6 +154,7 @@ extern int iommu_tce_table_put(struct iommu_table *tbl);
  */
 extern struct iommu_table *iommu_init_table(struct iommu_table *tbl,
int nid, unsigned long res_start, unsigned long res_end);
+bool iommu_table_in_use(struct iommu_table *tbl);
 
 #define IOMMU_TABLE_GROUP_MAX_TABLES   2
 
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 7f603d4e62d4..c5d5d36ab65e 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -668,21 +668,6 @@ static void iommu_table_reserve_pages(struct iommu_table 
*tbl,
set_bit(i - tbl->it_offset, tbl->it_map);
 }
 
-static void iommu_table_release_pages(struct iommu_table *tbl)
-{
-   int i;
-
-   /*
-* In case we have reserved the first bit, we should not emit
-* the warning below.
-*/
-   if (tbl->it_offset == 0)
-   clear_bit(0, tbl->it_map);
-
-   for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
-   clear_bit(i - tbl->it_offset, tbl->it_map);
-}
-
 /*
  * Build a iommu_table structure.  This contains a bit map which
  * is used to manage allocation of the tce space.
@@ -743,6 +728,38 @@ struct iommu_table *iommu_init_table(struct iommu_table 
*tbl, int nid,
return tbl;
 }
 
+bool iommu_table_in_use(struct iommu_table *tbl)
+{
+   bool in_use;
+   unsigned long p1_start = 0, p1_end, p2_start, p2_end;
+
+   /*ignore reserved bit0*/
+   if (tbl->it_offset == 0)
+   p1_start = 1;
+
+   /* Check if reserved memory is valid*/
+   if (tbl->it_reserved_start >= tbl->it_offset &&
+   tbl->it_reserved_start <= (tbl->it_offset + tbl->it_size) &&
+   tbl->it_reserved_end   >= tbl->it_offset &&
+   tbl->it_reserved_end   <= (tbl->it_offset + tbl->it_size)) {
+   p1_end = tbl->it_reserved_start - tbl->it_offset;
+   p2_start = tbl->it_reserved_end - tbl->it_offset + 1;
+   p2_end = tbl->it_size;
+   } else {
+   p1_end = tbl->it_size;
+   p2_start = 0;
+   p2_end = 0;
+   }
+
+   in_use = (find_next_bit(tbl->it_map, p1_end, p1_start) != p1_end);
+   if (in_use || p2_start == 0)
+   return in_use;
+
+   in_use = (find_next_bit(tbl->it_map, p2_end, p2_start) != p2_end);
+
+   return in_use;
+}
+
 static void iommu_table_free(struct kref *kref)
 {
unsigned long bitmap_sz;
@@ -759,10 +776,8 @@ static void iommu_table_free(struct kref *kref)
return;
}
 
-   iommu_table_release_pages(tbl);
-
/* verify that table contains no entries */
-   if (!bitmap_empty(tbl->it_map, tbl->it_size))
+   if (iommu_table_in_use(tbl))
pr_warn("%s: Unexpected TCEs\n", __func__);
 
/* calculate bitmap size in bytes */
@@ -1069,18 +1084,13 @@ int iommu_take_ownership(struct iommu_table *tbl)
for (i = 0; i < tbl->nr_pools; i++)
spin_lock(>pools[i].lock);
 
-   iommu_table_release_pages(tbl);
-
-   if (!bitmap_empty(tbl->it_map, tbl->it_size)) {
+   if (iommu_table_in_use(tbl)) {
pr_err("iommu_tce: it_map is not empty");
ret = -EBUSY;
-   /* Undo iommu_table_release_pages, i.e. restore bit#0, etc */
-   iommu_table_reserve_pages(tbl, tbl->it_reserved_start,
-   tbl->it_reserved_end);
-   } else {
-   memset(tbl->it_map, 0xff, sz);
}
 
+   memset(tbl->it_map, 0xff, sz);
+
for (i = 0; i < tbl->nr_pools; i++)
spin_unlock(>pools[i].lock);
spin_unlock_irqrestore(>large_pool.lock, flags);
-- 
2.25.4



[PATCH v1 03/10] powerpc/kernel/iommu: Use largepool as a last resort when !largealloc

2020-08-17 Thread Leonardo Bras
As of today, doing iommu_range_alloc() only for !largealloc (npages <= 15)
will only be able to use 3/4 of the available pages, given pages on
largepool  not being available for !largealloc.

This could mean some drivers not being able to fully use all the available
pages for the DMA window.

Add pages on largepool as a last resort for !largealloc, making all pages
of the DMA window available.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/kernel/iommu.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d7086087830f..7f603d4e62d4 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -261,6 +261,15 @@ static unsigned long iommu_range_alloc(struct device *dev,
pass++;
goto again;
 
+   } else if (pass == tbl->nr_pools + 1) {
+   /* Last resort: try largepool */
+   spin_unlock(>lock);
+   pool = >large_pool;
+   spin_lock(>lock);
+   pool->hint = pool->start;
+   pass++;
+   goto again;
+
} else {
/* Give up */
spin_unlock_irqrestore(&(pool->lock), flags);
-- 
2.25.4



[PATCH v1 02/10] powerpc/kernel/iommu: Align size for IOMMU_PAGE_SIZE on iommu_*_coherent()

2020-08-17 Thread Leonardo Bras
Both iommu_alloc_coherent() and iommu_free_coherent() assume that once
size is aligned to PAGE_SIZE it will be aligned to IOMMU_PAGE_SIZE.

Update those functions to guarantee alignment with requested size
using IOMMU_PAGE_ALIGN() before doing iommu_alloc() / iommu_free().

Also, on iommu_range_alloc(), replace ALIGN(n, 1 << tbl->it_page_shift)
with IOMMU_PAGE_ALIGN(n, tbl), which seems easier to read.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/kernel/iommu.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 9704f3f76e63..d7086087830f 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -237,10 +237,9 @@ static unsigned long iommu_range_alloc(struct device *dev,
}
 
if (dev)
-   boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- 1 << tbl->it_page_shift);
+   boundary_size = IOMMU_PAGE_ALIGN(dma_get_seg_boundary(dev) + 1, 
tbl);
else
-   boundary_size = ALIGN(1UL << 32, 1 << tbl->it_page_shift);
+   boundary_size = IOMMU_PAGE_ALIGN(1UL << 32, tbl);
/* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
 
n = iommu_area_alloc(tbl->it_map, limit, start, npages, tbl->it_offset,
@@ -858,6 +857,7 @@ void *iommu_alloc_coherent(struct device *dev, struct 
iommu_table *tbl,
unsigned int order;
unsigned int nio_pages, io_order;
struct page *page;
+   size_t size_io = size;
 
size = PAGE_ALIGN(size);
order = get_order(size);
@@ -884,8 +884,9 @@ void *iommu_alloc_coherent(struct device *dev, struct 
iommu_table *tbl,
memset(ret, 0, size);
 
/* Set up tces to cover the allocated range */
-   nio_pages = size >> tbl->it_page_shift;
-   io_order = get_iommu_order(size, tbl);
+   size_io = IOMMU_PAGE_ALIGN(size_io, tbl);
+   nio_pages = size_io >> tbl->it_page_shift;
+   io_order = get_iommu_order(size_io, tbl);
mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
  mask >> tbl->it_page_shift, io_order, 0);
if (mapping == DMA_MAPPING_ERROR) {
@@ -900,11 +901,11 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t 
size,
 void *vaddr, dma_addr_t dma_handle)
 {
if (tbl) {
-   unsigned int nio_pages;
+   size_t size_io = IOMMU_PAGE_ALIGN(size, tbl);
+   unsigned int nio_pages = size_io >> tbl->it_page_shift;
 
-   size = PAGE_ALIGN(size);
-   nio_pages = size >> tbl->it_page_shift;
iommu_free(tbl, dma_handle, nio_pages);
+
size = PAGE_ALIGN(size);
free_pages((unsigned long)vaddr, get_order(size));
}
-- 
2.25.4



[PATCH v1 01/10] powerpc/pseries/iommu: Replace hard-coded page shift

2020-08-17 Thread Leonardo Bras
Some functions assume IOMMU page size can only be 4K (pageshift == 12).
Update them to accept any page size passed, so we can use 64K pages.

In the process, some defines like TCE_SHIFT were made obsolete, and then
removed. TCE_RPN_MASK was updated to generate a mask according to
the pageshift used.

Most places had a tbl struct, so using tbl->it_page_shift was simple.
tce_free_pSeriesLP() was a special case, since callers not always have a
tbl struct, so adding a tceshift parameter seems the right thing to do.

Signed-off-by: Leonardo Bras 
---
 arch/powerpc/include/asm/tce.h | 10 ++
 arch/powerpc/platforms/pseries/iommu.c | 42 --
 2 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/include/asm/tce.h b/arch/powerpc/include/asm/tce.h
index db5fc2f2262d..971cba2d87cc 100644
--- a/arch/powerpc/include/asm/tce.h
+++ b/arch/powerpc/include/asm/tce.h
@@ -19,15 +19,9 @@
 #define TCE_VB 0
 #define TCE_PCI1
 
-/* TCE page size is 4096 bytes (1 << 12) */
-
-#define TCE_SHIFT  12
-#define TCE_PAGE_SIZE  (1 << TCE_SHIFT)
-
 #define TCE_ENTRY_SIZE 8   /* each TCE is 64 bits */
-
-#define TCE_RPN_MASK   0xfful  /* 40-bit RPN (4K pages) */
-#define TCE_RPN_SHIFT  12
+#define TCE_RPN_BITS   52  /* Bits 0-51 represent RPN on 
TCE */
+#define TCE_RPN_MASK(ps)   ((1ul << (TCE_RPN_BITS - (ps))) - 1)
 #define TCE_VALID  0x800   /* TCE valid */
 #define TCE_ALLIO  0x400   /* TCE valid for all lpars */
 #define TCE_PCI_WRITE  0x2 /* write from PCI allowed */
diff --git a/arch/powerpc/platforms/pseries/iommu.c 
b/arch/powerpc/platforms/pseries/iommu.c
index e4198700ed1a..8fe23b7dff3a 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -107,6 +107,9 @@ static int tce_build_pSeries(struct iommu_table *tbl, long 
index,
u64 proto_tce;
__be64 *tcep;
u64 rpn;
+   const unsigned long tceshift = tbl->it_page_shift;
+   const unsigned long pagesize = IOMMU_PAGE_SIZE(tbl);
+   const u64 rpn_mask = TCE_RPN_MASK(tceshift);
 
proto_tce = TCE_PCI_READ; // Read allowed
 
@@ -117,10 +120,10 @@ static int tce_build_pSeries(struct iommu_table *tbl, 
long index,
 
while (npages--) {
/* can't move this out since we might cross MEMBLOCK boundary */
-   rpn = __pa(uaddr) >> TCE_SHIFT;
-   *tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << 
TCE_RPN_SHIFT);
+   rpn = __pa(uaddr) >> tceshift;
+   *tcep = cpu_to_be64(proto_tce | (rpn & rpn_mask) << tceshift);
 
-   uaddr += TCE_PAGE_SIZE;
+   uaddr += pagesize;
tcep++;
}
return 0;
@@ -146,7 +149,7 @@ static unsigned long tce_get_pseries(struct iommu_table 
*tbl, long index)
return be64_to_cpu(*tcep);
 }
 
-static void tce_free_pSeriesLP(unsigned long liobn, long, long);
+static void tce_free_pSeriesLP(unsigned long liobn, long, long, long);
 static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
 
 static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
@@ -159,6 +162,7 @@ static int tce_build_pSeriesLP(unsigned long liobn, long 
tcenum, long tceshift,
u64 rpn;
int ret = 0;
long tcenum_start = tcenum, npages_start = npages;
+   const u64 rpn_mask = TCE_RPN_MASK(tceshift);
 
rpn = __pa(uaddr) >> tceshift;
proto_tce = TCE_PCI_READ;
@@ -166,12 +170,12 @@ static int tce_build_pSeriesLP(unsigned long liobn, long 
tcenum, long tceshift,
proto_tce |= TCE_PCI_WRITE;
 
while (npages--) {
-   tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift;
+   tce = proto_tce | (rpn & rpn_mask) << tceshift;
rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce);
 
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
-   tce_free_pSeriesLP(liobn, tcenum_start,
+   tce_free_pSeriesLP(liobn, tcenum_start, tceshift,
   (npages_start - (npages + 1)));
break;
}
@@ -205,10 +209,12 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table 
*tbl, long tcenum,
long tcenum_start = tcenum, npages_start = npages;
int ret = 0;
unsigned long flags;
+   const unsigned long tceshift = tbl->it_page_shift;
+   const u64 rpn_mask = TCE_RPN_MASK(tceshift);
 
if ((npages == 1) || !firmware_has_feature(FW_FEATURE_PUT_TCE_IND)) {
return tce_build_pSeriesLP(tbl->it_index, tcenum,
-  tbl->it_page_shift, npages, uaddr,
+  tceshift, npages, 

[PATCH v1 00/10] DDW indirect mapping

2020-08-17 Thread Leonardo Bras
This patchset must be applied on top of:
http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=194179=%2A=both

As of today, if the biggest DDW that can be created can't map the whole
partition, it's creation is skipped and the default DMA window
ibm,dma-window" is used instead.

Usually, the available DDW will be 16x bigger than the default DMA window,
as it keep the same page count and raise the page size from 4k to 64k.
Besides the increased window size, it performs better on allocations
bigger than 4k, so it would be nice to use it instead.

Patch #1 replaces hard-coded 4K page size with a variable containing the
correct page size for the window.

Patch #2 makes sure alignment is correct in iommu_*_coherent().

Patch #3 let small allocations use largepool if there is no more space
left in the other pools, thus allowing the whole DMA window to be used by
smaller allocations.

Patch #4 introduces iommu_table_in_use(), and replace manual bit-field
checking where it's used. It will be used for aborting enable_ddw() if
there is any current iommu allocation and we are trying single window
indirect mapping.

Patch #5 introduces iommu_pseries_alloc_table() that will be helpful
when indirect mapping needs to replace the iommu_table.

Patch #6 adds helpers for adding and removing DDWs in the list.

Patch #7 refactors enable_ddw() so it returns if direct mapping is
possible, instead of DMA offset. It helps for next patches on
indirect DMA mapping and also allows DMA windows starting at 0x00.

Patch #8 bring new helper to simplify enable_ddw(), allowing
some reorganization for introducing indirect mapping DDW.

Patch #9:
Instead of destroying the created DDW if it doesn't map the whole
partition, make use of it instead of the default DMA window as it improves
performance. Also, update the iommu_table and re-generate the pools.

Patch #10:
Does some renaming of 'direct window' to 'dma window', given the DDW
created can now be also used in indirect mapping if direct mapping is not
available.

All patches were tested into an LPAR with an Ethernet VF:
4005:01:00.0 Ethernet controller: Mellanox Technologies MT27700 Family
[ConnectX-4 Virtual Function]

Patchset was tested with a 64GB DDW which did not map the whole
partition (128G).

Leonardo Bras (10):
  powerpc/pseries/iommu: Replace hard-coded page shift
  powerpc/kernel/iommu: Align size for IOMMU_PAGE_SIZE on
iommu_*_coherent()
  powerpc/kernel/iommu: Use largepool as a last resort when !largealloc
  powerpc/kernel/iommu: Add new iommu_table_in_use() helper
  powerpc/pseries/iommu: Add iommu_pseries_alloc_table() helper
  powerpc/pseries/iommu: Add ddw_list_add() helper
  powerpc/pseries/iommu: Allow DDW windows starting at 0x00
  powerpc/pseries/iommu: Add ddw_property_create() and refactor
enable_ddw()
  powerpc/pseries/iommu: Make use of DDW even if it does not map the
partition
  powerpc/pseries/iommu: Rename "direct window" to "dma window"

 arch/powerpc/include/asm/iommu.h   |   1 +
 arch/powerpc/include/asm/tce.h |  10 +-
 arch/powerpc/kernel/iommu.c|  88 +++---
 arch/powerpc/platforms/pseries/iommu.c | 394 -
 4 files changed, 305 insertions(+), 188 deletions(-)

-- 
2.25.4



Re: [oss-drivers] [PATCH 16/20] ethernet: netronome: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Simon Horman
On Mon, Aug 17, 2020 at 01:54:30PM +0530, Allen Pais wrote:
> In preparation for unconditionally passing the
> struct tasklet_struct pointer to all tasklet
> callbacks, switch to using the new tasklet_setup()
> and from_tasklet() to pass the tasklet pointer explicitly.
> 
> Signed-off-by: Romain Perier 
> Signed-off-by: Allen Pais 

Reviewed-by: Simon Horman 

But:

This series should be targeted at net-next, and thus have net-next in its
subject

[PATCH net-next x/y] ...

And it should be posted when net-next is open: it is currently closed.

http://vger.kernel.org/~davem/net-next.html

> ---
>  drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c 
> b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> index 39ee23e8c0bf..1dcd24d899f5 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> @@ -2287,9 +2287,9 @@ static bool nfp_ctrl_rx(struct nfp_net_r_vector *r_vec)
>   return budget;
>  }
>  
> -static void nfp_ctrl_poll(unsigned long arg)
> +static void nfp_ctrl_poll(struct tasklet_struct *t)
>  {
> - struct nfp_net_r_vector *r_vec = (void *)arg;
> + struct nfp_net_r_vector *r_vec = from_tasklet(r_vec, t, tasklet);
>  
>   spin_lock(_vec->lock);
>   nfp_net_tx_complete(r_vec->tx_ring, 0);
> @@ -2337,8 +2337,7 @@ static void nfp_net_vecs_init(struct nfp_net *nn)
>  
>   __skb_queue_head_init(_vec->queue);
>   spin_lock_init(_vec->lock);
> - tasklet_init(_vec->tasklet, nfp_ctrl_poll,
> -  (unsigned long)r_vec);
> + tasklet_setup(_vec->tasklet, nfp_ctrl_poll);
>   tasklet_disable(_vec->tasklet);
>   }
>  
> -- 
> 2.17.1
> 


Re: [PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()

2020-08-17 Thread James Bottomley
On Mon, 2020-08-17 at 12:28 -0700, Kees Cook wrote:
> On Mon, Aug 17, 2020 at 07:41:58AM -0700, James Bottomley wrote:
> > On Mon, 2020-08-17 at 14:24 +0530, Allen Pais wrote:
> > > From: Allen Pais 
> > > 
> > > Commit 12cc923f1ccc ("tasklet: Introduce new initialization
> > > API")' introduced a new tasklet initialization API. This series
> > > converts all the scsi drivers to use the new tasklet_setup() API
> > 
> > I've got to say I agree with Jens, this was a silly obfuscation:
> > 
> > +#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
> > +   container_of(callback_tasklet, typeof(*var),
> > tasklet_fieldname)
> > 
> > Just use container_of directly since we all understand what it
> > does.
> 
> But then the lines get really long, wrapped, etc.

I really don't think that's a problem but if you want to add a new
generic container_of that does typeof instead of insisting on the type,
I'd be sort of OK with that ... provided you don't gratuitously alter
the argument order.

The thing I object to is that this encourages everyone to roll their
own unnecessary container_of type macros in spite of the fact that it's
function is wholly generic.  It's fine if you're eliminating one of the
arguments, or actually making the macro specific to the type, but in
this case you're not, you're making a completely generic macro where
the name is the only thing that's specific to this case.

>  This is what the timer_struct conversion did too (added a
> container_of wrapper), so I think it makes sense here too.

I didn't see that one to object to it ...

James



Re: [PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()

2020-08-17 Thread James Bottomley
On Mon, 2020-08-17 at 14:24 +0530, Allen Pais wrote:
> From: Allen Pais 
> 
> Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
> introduced a new tasklet initialization API. This series converts 
> all the scsi drivers to use the new tasklet_setup() API

I've got to say I agree with Jens, this was a silly obfuscation:

+#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
+   container_of(callback_tasklet, typeof(*var), tasklet_fieldname)

Just use container_of directly since we all understand what it does.

James



Re: [PATCH v4 6/8] mm: Move vmap_range from lib/ioremap.c to mm/vmalloc.c

2020-08-17 Thread Tang Yizhou
Hi Nicholas,

We may change the title as follows:
mm: Move vmap_range from mm/ioremap.c to mm/vmalloc.c

Yizhou



Re: [PATCH] swiotlb: Allow allocating buffer anywhere in memory

2020-08-17 Thread Thiago Jung Bauermann


Hello Christoph,

Christoph Hellwig  writes:

> On Sat, Aug 15, 2020 at 05:45:36PM -0300, Thiago Jung Bauermann wrote:
>> POWER secure guests (i.e., guests which use the Protection Execution
>> Facility) need to use SWIOTLB to be able to do I/O with the hypervisor, but
>> they don't need the SWIOTLB memory to be in low addresses since the
>> hypervisor doesn't have any addressing limitation.
>> 
>> This solves a SWIOTLB initialization problem we are seeing in secure guests
>> with 128 GB of RAM: they are configured with 4 GB of crashkernel reserved
>> memory, which leaves no space for SWIOTLB in low addresses.
>
> What about just open coding the allocation and using
> swiotlb_init_with_tbl?

Yes, that works too. I just sent a v2 implementing that change. I just
had to add a small accessor function so that I could set no_iotlb_memory
from outside swiotlb.c.

Thank you for the quick review.

-- 
Thiago Jung Bauermann
IBM Linux Technology Center


[PATCH v2] powerpc/pseries/svm: Allocate SWIOTLB buffer anywhere in memory

2020-08-17 Thread Thiago Jung Bauermann
POWER secure guests (i.e., guests which use the Protection Execution
Facility) need to use SWIOTLB to be able to do I/O with the hypervisor, but
they don't need the SWIOTLB memory to be in low addresses since the
hypervisor doesn't have any addressing limitation.

This solves a SWIOTLB initialization problem we are seeing in secure guests
with 128 GB of RAM: they are configured with 4 GB of crashkernel reserved
memory, which leaves no space for SWIOTLB in low addresses.

To do this, we use mostly the same code as swiotlb_init(), but allocate the
buffer using memblock_alloc() instead of memblock_alloc_low().

We also need to add swiotlb_set_no_iotlb_memory() in order to set the
no_iotlb_memory flag if initialization fails.

Signed-off-by: Thiago Jung Bauermann 
---
 arch/powerpc/include/asm/svm.h   |  4 
 arch/powerpc/mm/mem.c|  6 +-
 arch/powerpc/platforms/pseries/svm.c | 27 +++
 include/linux/swiotlb.h  |  1 +
 kernel/dma/swiotlb.c |  5 +
 5 files changed, 42 insertions(+), 1 deletion(-)

Changes from v1:
- Open-code swiotlb_init() in arch-specific code, as suggested by
  Christoph.

diff --git a/arch/powerpc/include/asm/svm.h b/arch/powerpc/include/asm/svm.h
index 85580b30aba4..7546402d796a 100644
--- a/arch/powerpc/include/asm/svm.h
+++ b/arch/powerpc/include/asm/svm.h
@@ -15,6 +15,8 @@ static inline bool is_secure_guest(void)
return mfmsr() & MSR_S;
 }
 
+void __init svm_swiotlb_init(void);
+
 void dtl_cache_ctor(void *addr);
 #define get_dtl_cache_ctor()   (is_secure_guest() ? dtl_cache_ctor : NULL)
 
@@ -25,6 +27,8 @@ static inline bool is_secure_guest(void)
return false;
 }
 
+static inline void svm_swiotlb_init(void) {}
+
 #define get_dtl_cache_ctor() NULL
 
 #endif /* CONFIG_PPC_SVM */
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index c2c11eb8dcfc..0f21bcb16405 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -290,7 +291,10 @@ void __init mem_init(void)
 * back to to-down.
 */
memblock_set_bottom_up(true);
-   swiotlb_init(0);
+   if (is_secure_guest())
+   svm_swiotlb_init();
+   else
+   swiotlb_init(0);
 #endif
 
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
diff --git a/arch/powerpc/platforms/pseries/svm.c 
b/arch/powerpc/platforms/pseries/svm.c
index 40c0637203d5..d592e663a8d6 100644
--- a/arch/powerpc/platforms/pseries/svm.c
+++ b/arch/powerpc/platforms/pseries/svm.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -34,6 +35,32 @@ static int __init init_svm(void)
 }
 machine_early_initcall(pseries, init_svm);
 
+/*
+ * Initialize SWIOTLB. Essentially the same as swiotlb_init(), except that it
+ * can allocate the buffer anywhere in memory. Since the hypervisor doesn't 
have
+ * any addressing limitation, we don't need to allocate it in low addresses.
+ */
+void __init svm_swiotlb_init(void)
+{
+   unsigned char *vstart;
+   unsigned long bytes, io_tlb_nslabs;
+
+   io_tlb_nslabs = (swiotlb_size_or_default() >> IO_TLB_SHIFT);
+   io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+
+   bytes = io_tlb_nslabs << IO_TLB_SHIFT;
+
+   vstart = memblock_alloc(PAGE_ALIGN(bytes), PAGE_SIZE);
+   if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, false))
+   return;
+
+   if (io_tlb_start)
+   memblock_free_early(io_tlb_start,
+   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
+   pr_warn("Cannot allocate SWIOTLB buffer");
+   swiotlb_set_no_iotlb_memory(true);
+}
+
 int set_memory_encrypted(unsigned long addr, int numpages)
 {
if (!PAGE_ALIGNED(addr))
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 046bb94bd4d6..991e9f13e663 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -35,6 +35,7 @@ extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
 extern void __init swiotlb_update_mem_attributes(void);
+void __init swiotlb_set_no_iotlb_memory(bool value);
 
 /*
  * Enumeration for sync targets
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index c19379fabd20..ed2b8818ff67 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -132,6 +132,11 @@ early_param("swiotlb", setup_io_tlb_npages);
 
 static bool no_iotlb_memory;
 
+void __init swiotlb_set_no_iotlb_memory(bool value)
+{
+   no_iotlb_memory = value;
+}
+
 unsigned long swiotlb_nr_tbl(void)
 {
return unlikely(no_iotlb_memory) ? 0 : io_tlb_nslabs;


Re: [PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Kees Cook
On Mon, Aug 17, 2020 at 07:41:58AM -0700, James Bottomley wrote:
> On Mon, 2020-08-17 at 14:24 +0530, Allen Pais wrote:
> > From: Allen Pais 
> > 
> > Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
> > introduced a new tasklet initialization API. This series converts 
> > all the scsi drivers to use the new tasklet_setup() API
> 
> I've got to say I agree with Jens, this was a silly obfuscation:
> 
> +#define from_tasklet(var, callback_tasklet, tasklet_fieldname) \
> +   container_of(callback_tasklet, typeof(*var), tasklet_fieldname)
> 
> Just use container_of directly since we all understand what it does.

But then the lines get really long, wrapped, etc. This is what the
timer_struct conversion did too (added a container_of wrapper), so I
think it makes sense here too.

-- 
Kees Cook


Re: [RFC PATCH] powerpc/drmem: use global variable instead of fetching again

2020-08-17 Thread Hari Bathini




On 06/08/20 6:22 pm, Aneesh Kumar K.V wrote:

use mem_addr_cells/mem_size_cells instead of fetching the values
again from device tree.



Looks good to me.


Signed-off-by: Aneesh Kumar K.V 
---
  arch/powerpc/mm/drmem.c | 24 ++--
  1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
index b2eeea39684c..f533a7b04ab9 100644
--- a/arch/powerpc/mm/drmem.c
+++ b/arch/powerpc/mm/drmem.c
@@ -14,8 +14,6 @@
  #include 
  #include 
  
-static int n_root_addr_cells, n_root_size_cells;

-
  static struct drmem_lmb_info __drmem_info;
  struct drmem_lmb_info *drmem_info = &__drmem_info;
  
@@ -196,8 +194,8 @@ static void read_drconf_v1_cell(struct drmem_lmb *lmb,

  {
const __be32 *p = *prop;
  
-	lmb->base_addr = of_read_number(p, n_root_addr_cells);

-   p += n_root_addr_cells;
+   lmb->base_addr = of_read_number(p, mem_addr_cells);
+   p += mem_addr_cells;
lmb->drc_index = of_read_number(p++, 1);
  
  	p++; /* skip reserved field */

@@ -233,8 +231,8 @@ static void read_drconf_v2_cell(struct of_drconf_cell_v2 
*dr_cell,
const __be32 *p = *prop;
  
  	dr_cell->seq_lmbs = of_read_number(p++, 1);

-   dr_cell->base_addr = of_read_number(p, n_root_addr_cells);
-   p += n_root_addr_cells;
+   dr_cell->base_addr = of_read_number(p, mem_addr_cells);
+   p += mem_addr_cells;
dr_cell->drc_index = of_read_number(p++, 1);
dr_cell->aa_index = of_read_number(p++, 1);
dr_cell->flags = of_read_number(p++, 1);
@@ -285,10 +283,6 @@ int __init walk_drmem_lmbs_early(unsigned long node, void 
*data,
if (!prop || len < dt_root_size_cells * sizeof(__be32))
return ret;
  
-	/* Get the address & size cells */

-   n_root_addr_cells = dt_root_addr_cells;
-   n_root_size_cells = dt_root_size_cells;
-
drmem_info->lmb_size = dt_mem_next_cell(dt_root_size_cells, );
  
  	usm = of_get_flat_dt_prop(node, "linux,drconf-usable-memory", );

@@ -318,12 +312,12 @@ static int init_drmem_lmb_size(struct device_node *dn)
return 0;
  
  	prop = of_get_property(dn, "ibm,lmb-size", );

-   if (!prop || len < n_root_size_cells * sizeof(__be32)) {
+   if (!prop || len < mem_size_cells * sizeof(__be32)) {
pr_info("Could not determine LMB size\n");
return -1;
}
  
-	drmem_info->lmb_size = of_read_number(prop, n_root_size_cells);

+   drmem_info->lmb_size = of_read_number(prop, mem_size_cells);
return 0;
  }
  
@@ -353,12 +347,6 @@ int walk_drmem_lmbs(struct device_node *dn, void *data,

if (!of_root)
return ret;
  
-	/* Get the address & size cells */

-   of_node_get(of_root);
-   n_root_addr_cells = of_n_addr_cells(of_root);
-   n_root_size_cells = of_n_size_cells(of_root);
-   of_node_put(of_root);
-
if (init_drmem_lmb_size(dn))
return ret;
  



Thanks
Hari


Re: [PATCH] powerpc/book3s64/radix: Fix boot failure with large amount of guest memory

2020-08-17 Thread Aneesh Kumar K.V

On 8/17/20 9:13 PM, Hari Bathini wrote:



On 13/08/20 9:50 pm, Aneesh Kumar K.V wrote:
If the hypervisor doesn't support hugepages, the kernel ends up 
allocating a large

number of page table pages. The early page table allocation was wrongly
setting the max memblock limit to ppc64_rma_size with radix translation
which resulted in boot failure as shown below.

Kernel panic - not syncing:
early_alloc_pgtable: Failed to allocate 16777216 bytes align=0x100 
nid=-1 from=0x max_addr=0x

  CPU: 0 PID: 0 Comm: swapper Not tainted 5.8.0-24.9-default+ #2
  Call Trace:
  [c16f3d00] [c07c6470] dump_stack+0xc4/0x114 
(unreliable)

  [c16f3d40] [c014c78c] panic+0x164/0x418
  [c16f3dd0] [c0098890] early_alloc_pgtable+0xe0/0xec
  [c16f3e60] [c10a5440] radix__early_init_mmu+0x360/0x4b4
  [c16f3ef0] [c1099bac] early_init_mmu+0x1c/0x3c
  [c16f3f10] [c109a320] early_setup+0x134/0x170

This was because the kernel was checking for the radix feature before 
we enable the
feature via mmu_features. This resulted in the kernel using hash 
restrictions on

radix.

Rework the early init code such that the kernel boot with memblock 
restrictions

as imposed by hash. At that point, the kernel still hasn't finalized the
translation the kernel will end up using.

We have three different ways of detecting radix.

1. dt_cpu_ftrs_scan -> used only in case of PowerNV
2. ibm,pa-features -> Used when we don't use cpu_dt_ftr_scan
3. CAS -> Where we negotiate with hypervisor about the supported 
translation.


We look at 1 or 2 early in the boot and after that, we look at the CAS 
vector to
finalize the translation the kernel will use. We also support a kernel 
command

line option (disable_radix) to switch to hash.

Update the memblock limit after mmu_early_init_devtree() if the kernel 
is going
to use radix translation. This forces some of the memblock allocations 
we do before

mmu_early_init_devtree() to be within the RMA limit.


Minor comments below. Nonetheless...

Reviewed-by: Hari Bathini 



Fixes: 2bfd65e45e87 ("powerpc/mm/radix: Add radix callbacks for early 
init routines")

Reported-by: Shirisha Ganta 
Signed-off-by: Aneesh Kumar K.V 
---
  arch/powerpc/include/asm/book3s/64/mmu.h | 8 +---
  arch/powerpc/kernel/prom.c   | 6 ++
  arch/powerpc/mm/book3s64/radix_pgtable.c | 2 ++
  3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h 
b/arch/powerpc/include/asm/book3s/64/mmu.h

index 55442d45c597..4245f99453f5 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -244,9 +244,11 @@ extern void 
radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
  static inline void setup_initial_memory_limit(phys_addr_t 
first_memblock_base,

    phys_addr_t first_memblock_size)
  {
-    if (early_radix_enabled())
-    return radix__setup_initial_memory_limit(first_memblock_base,
-   first_memblock_size);
+    /*
+ * Hash has more strict restrictions. At this point we don't
+ * know which translations we will pick. Hence got with hash


:s/got with/go with/


+ * restrictions.
+ */
  return hash__setup_initial_memory_limit(first_memblock_base,
 first_memblock_size);
  }
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d8a2fb87ba0c..340900ae95a4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -811,6 +811,12 @@ void __init early_init_devtree(void *params)
  mmu_early_init_devtree();
+    /*
+ * Reset ppc64_rma_size and memblock memory limit
+ */
+    if (early_radix_enabled())
+    radix__setup_initial_memory_limit(memstart_addr, 
first_memblock_size);

+
  #ifdef CONFIG_PPC_POWERNV
  /* Scan and build the list of machine check recoverable ranges */
  of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c 
b/arch/powerpc/mm/book3s64/radix_pgtable.c

index 28c784976bed..094daf16acac 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -747,6 +747,8 @@ void radix__setup_initial_memory_limit(phys_addr_t 
first_memblock_base,

   * Radix mode is not limited by RMA / VRMA addressing.
   */
  ppc64_rma_size = ULONG_MAX;



+
+    memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);


Probably the same thing but I would prefer the below instead:

memblock_set_current_limit(ppc64_rma_size);


This is not really related to ppc64_rma_size right? On radix what we 
actually want is memblock alloc from anywhere. Actually what we want is


memblock_set_current_limit(memblock_limit_from_rma(ppc64_rma_size))


But that is unnecessary complication?

-aneesh



Re: [PATCH v2 2/4] powerpc/mem: Store the dt_root_size/addr cell values for later usage

2020-08-17 Thread Aneesh Kumar K.V

On 8/17/20 9:00 PM, Hari Bathini wrote:



On 06/08/20 9:53 pm, Aneesh Kumar K.V wrote:

dt_root_addr_cells and dt_root_size_cells are __initdata variables.
So make a copy of the same which can be used post init.



This avoids doing the same thing at multiple places.
So, thanks for the patch, Aneesh.

Looks good to me.

but nitpick below...


Signed-off-by: Aneesh Kumar K.V 
---
  arch/powerpc/include/asm/drmem.h | 2 ++
  arch/powerpc/kernel/prom.c   | 7 +++
  arch/powerpc/mm/numa.c   | 1 +
  3 files changed, 10 insertions(+)

diff --git a/arch/powerpc/include/asm/drmem.h 
b/arch/powerpc/include/asm/drmem.h

index d719cbac34b2..ffb59caa88ee 100644
--- a/arch/powerpc/include/asm/drmem.h
+++ b/arch/powerpc/include/asm/drmem.h
@@ -123,4 +123,6 @@ static inline void lmb_clear_nid(struct drmem_lmb 
*lmb)

  }
  #endif
+extern int mem_addr_cells, mem_size_cells;


Should this be in include/asm/prom.h instead, given the definition
comes from kernel/prom.c file?



We added the variable definition to prom.c because that is where we are 
doing early device tree scanning. But the users should not really be 
including prom.h. The variables are related drmem and hence I used 
drmem.h for include.



+
  #endif /* _ASM_POWERPC_LMB_H */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d8a2fb87ba0c..9a1701e85747 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -73,6 +73,7 @@ u64 ppc64_rma_size;
  #endif
  static phys_addr_t first_memblock_size;
  static int __initdata boot_cpu_count;
+int mem_addr_cells, mem_size_cells;
  static int __init early_parse_mem(char *p)
  {
@@ -536,6 +537,12 @@ static int __init 
early_init_dt_scan_memory_ppc(unsigned long node,

  const char *uname,
  int depth, void *data)
  {
+    /*
+ * Make a copy from __initdata variable
+ */
+    mem_addr_cells = dt_root_addr_cells;
+    mem_size_cells = dt_root_size_cells;
+
  #ifdef CONFIG_PPC_PSERIES
  if (depth == 1 &&
  strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) {
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 058fee9a0835..77d41d9775d2 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -368,6 +368,7 @@ static void __init get_n_mem_cells(int 
*n_addr_cells, int *n_size_cells)

  of_node_put(memory);
  }
+/*  dt_mem_next_cell is __init  */
  static unsigned long read_n_cells(int n, const __be32 **buf)
  {
  unsigned long result = 0;





Re: [PATCH 10/11] powerpc: use non-set_fs based maccess routines

2020-08-17 Thread Christophe Leroy




Le 17/08/2020 à 09:32, Christoph Hellwig a écrit :

Provide __get_kernel_nofault and __put_kernel_nofault routines to
implement the maccess routines without messing with set_fs and without
opening up access to user space.


__get_user_size() opens access to user space. You have to use 
__get_user_size_allowed() when user access is already allowed (or when 
not needed to allow it).


Christophe



Signed-off-by: Christoph Hellwig 
---
  arch/powerpc/include/asm/uaccess.h | 16 
  1 file changed, 16 insertions(+)

diff --git a/arch/powerpc/include/asm/uaccess.h 
b/arch/powerpc/include/asm/uaccess.h
index 00699903f1efca..a31de40ac00b62 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -623,4 +623,20 @@ do {   
\
__put_user_goto(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), 
e);\
  } while (0)
  
+#define HAVE_GET_KERNEL_NOFAULT

+
+#define __get_kernel_nofault(dst, src, type, err_label)
\
+do {   \
+   int __kr_err;   \
+   \
+   __get_user_size(*((type *)(dst)), (__force type __user *)(src), \
+   sizeof(type), __kr_err);\
+   if (unlikely(__kr_err)) \
+   goto err_label; \
+} while (0)
+
+#define __put_kernel_nofault(dst, src, type, err_label)
\
+   __put_user_size_goto(*((type *)(src)),  \
+   (__force type __user *)(dst), sizeof(type), err_label)
+
  #endif/* _ARCH_POWERPC_UACCESS_H */



Re: [PATCH] powerpc/book3s64/radix: Fix boot failure with large amount of guest memory

2020-08-17 Thread Hari Bathini




On 13/08/20 9:50 pm, Aneesh Kumar K.V wrote:

If the hypervisor doesn't support hugepages, the kernel ends up allocating a 
large
number of page table pages. The early page table allocation was wrongly
setting the max memblock limit to ppc64_rma_size with radix translation
which resulted in boot failure as shown below.

Kernel panic - not syncing:
early_alloc_pgtable: Failed to allocate 16777216 bytes align=0x100 nid=-1 
from=0x max_addr=0x
  CPU: 0 PID: 0 Comm: swapper Not tainted 5.8.0-24.9-default+ #2
  Call Trace:
  [c16f3d00] [c07c6470] dump_stack+0xc4/0x114 (unreliable)
  [c16f3d40] [c014c78c] panic+0x164/0x418
  [c16f3dd0] [c0098890] early_alloc_pgtable+0xe0/0xec
  [c16f3e60] [c10a5440] radix__early_init_mmu+0x360/0x4b4
  [c16f3ef0] [c1099bac] early_init_mmu+0x1c/0x3c
  [c16f3f10] [c109a320] early_setup+0x134/0x170

This was because the kernel was checking for the radix feature before we enable 
the
feature via mmu_features. This resulted in the kernel using hash restrictions on
radix.

Rework the early init code such that the kernel boot with memblock restrictions
as imposed by hash. At that point, the kernel still hasn't finalized the
translation the kernel will end up using.

We have three different ways of detecting radix.

1. dt_cpu_ftrs_scan -> used only in case of PowerNV
2. ibm,pa-features -> Used when we don't use cpu_dt_ftr_scan
3. CAS -> Where we negotiate with hypervisor about the supported translation.

We look at 1 or 2 early in the boot and after that, we look at the CAS vector to
finalize the translation the kernel will use. We also support a kernel command
line option (disable_radix) to switch to hash.

Update the memblock limit after mmu_early_init_devtree() if the kernel is going
to use radix translation. This forces some of the memblock allocations we do 
before
mmu_early_init_devtree() to be within the RMA limit.


Minor comments below. Nonetheless...

Reviewed-by: Hari Bathini 



Fixes: 2bfd65e45e87 ("powerpc/mm/radix: Add radix callbacks for early init 
routines")
Reported-by: Shirisha Ganta 
Signed-off-by: Aneesh Kumar K.V 
---
  arch/powerpc/include/asm/book3s/64/mmu.h | 8 +---
  arch/powerpc/kernel/prom.c   | 6 ++
  arch/powerpc/mm/book3s64/radix_pgtable.c | 2 ++
  3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h 
b/arch/powerpc/include/asm/book3s/64/mmu.h
index 55442d45c597..4245f99453f5 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -244,9 +244,11 @@ extern void radix__setup_initial_memory_limit(phys_addr_t 
first_memblock_base,
  static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
  phys_addr_t first_memblock_size)
  {
-   if (early_radix_enabled())
-   return radix__setup_initial_memory_limit(first_memblock_base,
-  first_memblock_size);
+   /*
+* Hash has more strict restrictions. At this point we don't
+* know which translations we will pick. Hence got with hash


:s/got with/go with/


+* restrictions.
+*/
return hash__setup_initial_memory_limit(first_memblock_base,
   first_memblock_size);
  }
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d8a2fb87ba0c..340900ae95a4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -811,6 +811,12 @@ void __init early_init_devtree(void *params)
  
  	mmu_early_init_devtree();
  
+	/*

+* Reset ppc64_rma_size and memblock memory limit
+*/
+   if (early_radix_enabled())
+   radix__setup_initial_memory_limit(memstart_addr, 
first_memblock_size);
+
  #ifdef CONFIG_PPC_POWERNV
/* Scan and build the list of machine check recoverable ranges */
of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c 
b/arch/powerpc/mm/book3s64/radix_pgtable.c
index 28c784976bed..094daf16acac 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -747,6 +747,8 @@ void radix__setup_initial_memory_limit(phys_addr_t 
first_memblock_base,
 * Radix mode is not limited by RMA / VRMA addressing.
 */
ppc64_rma_size = ULONG_MAX;



+
+   memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);


Probably the same thing but I would prefer the below instead:

memblock_set_current_limit(ppc64_rma_size);

Thanks
Hari


Re: [PATCH 08/20] ethernet: hinic: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Jakub Kicinski
On Mon, 17 Aug 2020 13:54:22 +0530 Allen Pais wrote:
> In preparation for unconditionally passing the
> struct tasklet_struct pointer to all tasklet
> callbacks, switch to using the new tasklet_setup()
> and from_tasklet() to pass the tasklet pointer explicitly.
> 
> Signed-off-by: Romain Perier 
> Signed-off-by: Allen Pais 

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c:374: warning: Function 
parameter or member 't' not described in 'ceq_tasklet'
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c:374: warning: Excess function 
parameter 'ceq_data' description in 'ceq_tasklet'


Re: [PATCH 06/20] ethernet: chelsio: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Jakub Kicinski
On Mon, 17 Aug 2020 13:54:20 +0530 Allen Pais wrote:
> In preparation for unconditionally passing the
> struct tasklet_struct pointer to all tasklet
> callbacks, switch to using the new tasklet_setup()
> and from_tasklet() to pass the tasklet pointer explicitly.
> 
> Signed-off-by: Romain Perier 
> Signed-off-by: Allen Pais 

You need to adjust kdoc when you change functions:

drivers/net/ethernet/chelsio/cxgb4/sge.c:2664: warning: Function parameter or 
member 't' not described in 'restart_ctrlq'
drivers/net/ethernet/chelsio/cxgb4/sge.c:2664: warning: Excess function 
parameter 'data' description in 'restart_ctrlq'
drivers/net/ethernet/chelsio/cxgb4/sge.c:2965: warning: Function parameter or 
member 't' not described in 'restart_ofldq'
drivers/net/ethernet/chelsio/cxgb4/sge.c:2965: warning: Excess function 
parameter 'data' description in 'restart_ofldq'


Re: [PATCH v2 2/4] powerpc/mem: Store the dt_root_size/addr cell values for later usage

2020-08-17 Thread Hari Bathini




On 06/08/20 9:53 pm, Aneesh Kumar K.V wrote:

dt_root_addr_cells and dt_root_size_cells are __initdata variables.
So make a copy of the same which can be used post init.



This avoids doing the same thing at multiple places.
So, thanks for the patch, Aneesh.

Looks good to me.

but nitpick below...


Signed-off-by: Aneesh Kumar K.V 
---
  arch/powerpc/include/asm/drmem.h | 2 ++
  arch/powerpc/kernel/prom.c   | 7 +++
  arch/powerpc/mm/numa.c   | 1 +
  3 files changed, 10 insertions(+)

diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
index d719cbac34b2..ffb59caa88ee 100644
--- a/arch/powerpc/include/asm/drmem.h
+++ b/arch/powerpc/include/asm/drmem.h
@@ -123,4 +123,6 @@ static inline void lmb_clear_nid(struct drmem_lmb *lmb)
  }
  #endif
  
+extern int mem_addr_cells, mem_size_cells;


Should this be in include/asm/prom.h instead, given the definition
comes from kernel/prom.c file?


+
  #endif /* _ASM_POWERPC_LMB_H */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d8a2fb87ba0c..9a1701e85747 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -73,6 +73,7 @@ u64 ppc64_rma_size;
  #endif
  static phys_addr_t first_memblock_size;
  static int __initdata boot_cpu_count;
+int mem_addr_cells, mem_size_cells;
  
  static int __init early_parse_mem(char *p)

  {
@@ -536,6 +537,12 @@ static int __init early_init_dt_scan_memory_ppc(unsigned 
long node,
const char *uname,
int depth, void *data)
  {
+   /*
+* Make a copy from __initdata variable
+*/
+   mem_addr_cells = dt_root_addr_cells;
+   mem_size_cells = dt_root_size_cells;
+
  #ifdef CONFIG_PPC_PSERIES
if (depth == 1 &&
strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) {
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 058fee9a0835..77d41d9775d2 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -368,6 +368,7 @@ static void __init get_n_mem_cells(int *n_addr_cells, int 
*n_size_cells)
of_node_put(memory);
  }
  
+/*  dt_mem_next_cell is __init  */

  static unsigned long read_n_cells(int n, const __be32 **buf)
  {
unsigned long result = 0;



Re: [PATCH v2 1/3] powerpc/numa: Introduce logical numa id

2020-08-17 Thread Srikar Dronamraju
* Aneesh Kumar K.V  [2020-08-17 17:04:24]:

> On 8/17/20 4:29 PM, Srikar Dronamraju wrote:
> > * Aneesh Kumar K.V  [2020-08-17 16:02:36]:
> > 
> > > We use ibm,associativity and ibm,associativity-lookup-arrays to derive 
> > > the numa
> > > node numbers. These device tree properties are firmware indicated 
> > > grouping of
> > > resources based on their hierarchy in the platform. These numbers (group 
> > > id) are
> > > not sequential and hypervisor/firmware can follow different numbering 
> > > schemes.
> > > For ex: on powernv platforms, we group them in the below order.
> > > 
> > >   * - CCM node ID
> > >   * - HW card ID
> > >   * - HW module ID
> > >   * - Chip ID
> > >   * - Core ID
> > > 
> > > Based on ibm,associativity-reference-points we use one of the above group 
> > > ids as
> > > Linux NUMA node id. (On PowerNV platform Chip ID is used). This results
> > > in Linux reporting non-linear NUMA node id and which also results in Linux
> > > reporting empty node 0 NUMA nodes.
> > > 
> > > This can  be resolved by mapping the firmware provided group id to a 
> > > logical Linux
> > > NUMA id. In this patch, we do this only for pseries platforms considering 
> > > the
> > > firmware group id is a virtualized entity and users would not have drawn 
> > > any
> > > conclusion based on the Linux Numa Node id.
> > > 
> > > On PowerNV platform since we have historically mapped Chip ID as Linux 
> > > NUMA node
> > > id, we keep the existing Linux NUMA node id numbering.
> > 
> > I still dont understand how you are going to handle numa distances.
> > With your patch, have you tried dlpar add/remove on a sparsely noded 
> > machine?
> > 
> 
> We follow the same steps when fetching distance information. Instead of
> using affinity domain id, we now use the mapped node id. The relevant hunk
> in the patch is
> 
> + nid = affinity_domain_to_nid();
> 
>   if (nid > 0 &&
> - of_read_number(associativity, 1) >= distance_ref_points_depth) {
> + of_read_number(associativity, 1) >= distance_ref_points_depth) {
>   /*
>* Skip the length field and send start of associativity array
>*/
> 
> I haven't tried dlpar add/remove. I don't have a setup to try that. Do you
> see a problem there?
> 

Yes, I think there can be 2 problems.

1. distance table may be filled with incorrect data.
2. numactl -H distance table shows symmetric data, the symmetric nature may
be lost.

> -aneesh
> 
> 

-- 
Thanks and Regards
Srikar Dronamraju


Re: [PATCH v2 1/3] powerpc/numa: Introduce logical numa id

2020-08-17 Thread Aneesh Kumar K.V

On 8/17/20 4:29 PM, Srikar Dronamraju wrote:

* Aneesh Kumar K.V  [2020-08-17 16:02:36]:


We use ibm,associativity and ibm,associativity-lookup-arrays to derive the numa
node numbers. These device tree properties are firmware indicated grouping of
resources based on their hierarchy in the platform. These numbers (group id) are
not sequential and hypervisor/firmware can follow different numbering schemes.
For ex: on powernv platforms, we group them in the below order.

  * - CCM node ID
  * - HW card ID
  * - HW module ID
  * - Chip ID
  * - Core ID

Based on ibm,associativity-reference-points we use one of the above group ids as
Linux NUMA node id. (On PowerNV platform Chip ID is used). This results
in Linux reporting non-linear NUMA node id and which also results in Linux
reporting empty node 0 NUMA nodes.

This can  be resolved by mapping the firmware provided group id to a logical 
Linux
NUMA id. In this patch, we do this only for pseries platforms considering the
firmware group id is a virtualized entity and users would not have drawn any
conclusion based on the Linux Numa Node id.

On PowerNV platform since we have historically mapped Chip ID as Linux NUMA node
id, we keep the existing Linux NUMA node id numbering.


I still dont understand how you are going to handle numa distances.
With your patch, have you tried dlpar add/remove on a sparsely noded machine?



We follow the same steps when fetching distance information. Instead of 
using affinity domain id, we now use the mapped node id. The relevant 
hunk in the patch is


+   nid = affinity_domain_to_nid();

if (nid > 0 &&
-   of_read_number(associativity, 1) >= distance_ref_points_depth) {
+   of_read_number(associativity, 1) >= distance_ref_points_depth) {
/*
 * Skip the length field and send start of associativity array
 */

I haven't tried dlpar add/remove. I don't have a setup to try that. Do 
you see a problem there?


-aneesh




Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Allen Pais
>
> Is this targeted for 5.9 or 5.10?

This is targeted for 5.9.

> I have a patch set to drop the whole tasklet usage in sound/*
> (destined for 5.10, to be submitted soon), so if that's for 5.10,
> it'll be likely superfluous.

 I have picked patches from your tree to adapt to this new API.
Those can be picked in 5.10 I suppose.

Thanks.


[PATCH 7/7] usb: mos7720: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/serial/mos7720.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 2ec4eeacebc7..5eed1078fac8 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -282,11 +282,12 @@ static void destroy_urbtracker(struct kref *kref)
  * port callback had to be deferred because the disconnect mutex could not be
  * obtained at the time.
  */
-static void send_deferred_urbs(unsigned long _mos_parport)
+static void send_deferred_urbs(struct tasklet_struct *t)
 {
int ret_val;
unsigned long flags;
-   struct mos7715_parport *mos_parport = (void *)_mos_parport;
+   struct mos7715_parport *mos_parport = from_tasklet(mos_parport, t,
+  urb_tasklet);
struct urbtracker *urbtrack, *tmp;
struct list_head *cursor, *next;
struct device *dev;
@@ -716,8 +717,7 @@ static int mos7715_parport_init(struct usb_serial *serial)
INIT_LIST_HEAD(_parport->deferred_urbs);
usb_set_serial_data(serial, mos_parport); /* hijack private pointer */
mos_parport->serial = serial;
-   tasklet_init(_parport->urb_tasklet, send_deferred_urbs,
-(unsigned long) mos_parport);
+   tasklet_setup(_parport->urb_tasklet, send_deferred_urbs);
init_completion(_parport->syncmsg_compl);
 
/* cycle parallel port reset bit */
-- 
2.17.1



[PATCH 6/7] usb: xhci: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/host/xhci-dbgtty.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index b8918f73a432..ae4e4ab638b5 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -288,14 +288,14 @@ static const struct tty_operations dbc_tty_ops = {
.unthrottle = dbc_tty_unthrottle,
 };
 
-static void dbc_rx_push(unsigned long _port)
+static void dbc_rx_push(struct tasklet_struct *t)
 {
struct dbc_request  *req;
struct tty_struct   *tty;
unsigned long   flags;
booldo_push = false;
booldisconnect = false;
-   struct dbc_port *port = (void *)_port;
+   struct dbc_port *port = from_tasklet(port, t, push);
struct list_head*queue = >read_queue;
 
spin_lock_irqsave(>port_lock, flags);
@@ -382,7 +382,7 @@ xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct 
dbc_port *port)
 {
tty_port_init(>port);
spin_lock_init(>port_lock);
-   tasklet_init(>push, dbc_rx_push, (unsigned long)port);
+   tasklet_setup(>push, dbc_rx_push);
INIT_LIST_HEAD(>read_pool);
INIT_LIST_HEAD(>read_queue);
INIT_LIST_HEAD(>write_pool);
-- 
2.17.1



[PATCH 5/7] usb/gadget: fsl_qe_udc: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/udc/fsl_qe_udc.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c 
b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 2707be628298..fa66449b3907 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -923,9 +923,9 @@ static int qe_ep_rxframe_handle(struct qe_ep *ep)
return 0;
 }
 
-static void ep_rx_tasklet(unsigned long data)
+static void ep_rx_tasklet(struct tasklet_struct *t)
 {
-   struct qe_udc *udc = (struct qe_udc *)data;
+   struct qe_udc *udc = from_tasklet(udc, t, rx_tasklet);
struct qe_ep *ep;
struct qe_frame *pframe;
struct qe_bd __iomem *bd;
@@ -2553,8 +2553,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
DMA_TO_DEVICE);
}
 
-   tasklet_init(>rx_tasklet, ep_rx_tasklet,
-   (unsigned long)udc);
+   tasklet_setup(>rx_tasklet, ep_rx_tasklet);
/* request irq and disable DR  */
udc->usb_irq = irq_of_parse_and_map(np, 0);
if (!udc->usb_irq) {
-- 
2.17.1



[PATCH 4/7] usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/gadget/function/f_midi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/function/f_midi.c 
b/drivers/usb/gadget/function/f_midi.c
index 46af0aa07e2e..85cb15734aa8 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -698,9 +698,9 @@ static void f_midi_transmit(struct f_midi *midi)
f_midi_drop_out_substreams(midi);
 }
 
-static void f_midi_in_tasklet(unsigned long data)
+static void f_midi_in_tasklet(struct tasklet_struct *t)
 {
-   struct f_midi *midi = (struct f_midi *) data;
+   struct f_midi *midi = from_tasklet(midi, t, tasklet);
f_midi_transmit(midi);
 }
 
@@ -875,7 +875,7 @@ static int f_midi_bind(struct usb_configuration *c, struct 
usb_function *f)
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
 
midi->gadget = cdev->gadget;
-   tasklet_init(>tasklet, f_midi_in_tasklet, (unsigned long) midi);
+   tasklet_setup(>tasklet, f_midi_in_tasklet);
status = f_midi_register_card(midi);
if (status < 0)
goto fail_register;
-- 
2.17.1



[PATCH 3/7] usb: hcd: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/core/hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index a33b849e8beb..2c6b9578a7d3 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1657,9 +1657,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
usb_put_urb(urb);
 }
 
-static void usb_giveback_urb_bh(unsigned long param)
+static void usb_giveback_urb_bh(struct tasklet_struct *t)
 {
-   struct giveback_urb_bh *bh = (struct giveback_urb_bh *)param;
+   struct giveback_urb_bh *bh = from_tasklet(bh, t, bh);
struct list_head local_list;
 
spin_lock_irq(>lock);
@@ -2403,7 +2403,7 @@ static void init_giveback_urb_bh(struct giveback_urb_bh 
*bh)
 
spin_lock_init(>lock);
INIT_LIST_HEAD(>head);
-   tasklet_init(>bh, usb_giveback_urb_bh, (unsigned long)bh);
+   tasklet_setup(>bh, usb_giveback_urb_bh);
 }
 
 struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
-- 
2.17.1



[PATCH 2/7] usb: c67x00: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/c67x00/c67x00-sched.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/c67x00/c67x00-sched.c 
b/drivers/usb/c67x00/c67x00-sched.c
index f7f6229082ca..6275cb77a15b 100644
--- a/drivers/usb/c67x00/c67x00-sched.c
+++ b/drivers/usb/c67x00/c67x00-sched.c
@@ -1122,9 +1122,9 @@ static void c67x00_do_work(struct c67x00_hcd *c67x00)
 
 /* -- 
*/
 
-static void c67x00_sched_tasklet(unsigned long __c67x00)
+static void c67x00_sched_tasklet(struct tasklet_struct *t)
 {
-   struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00;
+   struct c67x00_hcd *c67x00 = from_tasklet(c67x00, t, tasklet);
c67x00_do_work(c67x00);
 }
 
@@ -1135,8 +1135,7 @@ void c67x00_sched_kick(struct c67x00_hcd *c67x00)
 
 int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00)
 {
-   tasklet_init(>tasklet, c67x00_sched_tasklet,
-(unsigned long)c67x00);
+   tasklet_setup(>tasklet, c67x00_sched_tasklet);
return 0;
 }
 
-- 
2.17.1



[PATCH 1/7] usb: atm: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/usb/atm/usbatm.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 4e12a32ca392..56fe30d247da 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -511,9 +511,10 @@ static unsigned int usbatm_write_cells(struct usbatm_data 
*instance,
 **  receive  **
 **/
 
-static void usbatm_rx_process(unsigned long data)
+static void usbatm_rx_process(struct tasklet_struct *t)
 {
-   struct usbatm_data *instance = (struct usbatm_data *)data;
+   struct usbatm_data *instance = from_tasklet(instance, t,
+   rx_channel.tasklet);
struct urb *urb;
 
while ((urb = usbatm_pop_urb(>rx_channel))) {
@@ -564,9 +565,10 @@ static void usbatm_rx_process(unsigned long data)
 **  send  **
 ***/
 
-static void usbatm_tx_process(unsigned long data)
+static void usbatm_tx_process(struct tasklet_struct *t)
 {
-   struct usbatm_data *instance = (struct usbatm_data *)data;
+   struct usbatm_data *instance = from_tasklet(instance, t,
+   tx_channel.tasklet);
struct sk_buff *skb = instance->current_skb;
struct urb *urb = NULL;
const unsigned int buf_size = instance->tx_channel.buf_size;
@@ -1069,8 +1071,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const 
struct usb_device_id *id,
 
usbatm_init_channel(>rx_channel);
usbatm_init_channel(>tx_channel);
-   tasklet_init(>rx_channel.tasklet, usbatm_rx_process, 
(unsigned long)instance);
-   tasklet_init(>tx_channel.tasklet, usbatm_tx_process, 
(unsigned long)instance);
+   tasklet_setup(>rx_channel.tasklet, usbatm_rx_process);
+   tasklet_setup(>tx_channel.tasklet, usbatm_tx_process);
instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;
instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;
instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;
-- 
2.17.1



[PATCH 0/7] usb: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Allen Pais
From: Allen Pais 

Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
introduced a new tasklet initialization API. This series converts 
all the usb drivers to use the new tasklet_setup() API

Allen Pais (7):
  usb: atm: convert tasklets to use new tasklet_setup() API
  usb: c67x00: convert tasklets to use new tasklet_setup() API
  usb: hcd: convert tasklets to use new tasklet_setup() API
  usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API
  usb/gadget: fsl_qe_udc: convert tasklets to use new tasklet_setup()
API
  usb: xhci: convert tasklets to use new tasklet_setup() API
  usb: mos7720: convert tasklets to use new tasklet_setup() API

 drivers/usb/atm/usbatm.c | 14 --
 drivers/usb/c67x00/c67x00-sched.c|  7 +++
 drivers/usb/core/hcd.c   |  6 +++---
 drivers/usb/gadget/function/f_midi.c |  6 +++---
 drivers/usb/gadget/udc/fsl_qe_udc.c  |  7 +++
 drivers/usb/host/xhci-dbgtty.c   |  6 +++---
 drivers/usb/serial/mos7720.c |  8 
 7 files changed, 27 insertions(+), 27 deletions(-)

-- 
2.17.1



[PATCH 10/10] sound: ua101: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/usb/misc/ua101.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 884e740a785c..3b2dce1043f5 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -247,9 +247,9 @@ static inline void add_with_wraparound(struct ua101 *ua,
*value -= ua->playback.queue_length;
 }
 
-static void playback_tasklet(unsigned long data)
+static void playback_tasklet(struct tasklet_struct *t)
 {
-   struct ua101 *ua = (void *)data;
+   struct ua101 *ua = from_tasklet(ua, t, playback_tasklet);
unsigned long flags;
unsigned int frames;
struct ua101_urb *urb;
@@ -1218,8 +1218,7 @@ static int ua101_probe(struct usb_interface *interface,
spin_lock_init(>lock);
mutex_init(>mutex);
INIT_LIST_HEAD(>ready_playback_urbs);
-   tasklet_init(>playback_tasklet,
-playback_tasklet, (unsigned long)ua);
+   tasklet_setup(>playback_tasklet, playback_tasklet);
init_waitqueue_head(>alsa_capture_wait);
init_waitqueue_head(>rate_feedback_wait);
init_waitqueue_head(>alsa_playback_wait);
-- 
2.17.1



[PATCH 09/10] sound: midi: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/usb/midi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index df639fe03118..e8287a05e36b 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -344,10 +344,9 @@ static void snd_usbmidi_do_output(struct 
snd_usb_midi_out_endpoint *ep)
spin_unlock_irqrestore(>buffer_lock, flags);
 }
 
-static void snd_usbmidi_out_tasklet(unsigned long data)
+static void snd_usbmidi_out_tasklet(struct tasklet_struct *t)
 {
-   struct snd_usb_midi_out_endpoint *ep =
-   (struct snd_usb_midi_out_endpoint *) data;
+   struct snd_usb_midi_out_endpoint *ep = from_tasklet(ep, t, tasklet);
 
snd_usbmidi_do_output(ep);
 }
@@ -1441,7 +1440,7 @@ static int snd_usbmidi_out_endpoint_create(struct 
snd_usb_midi *umidi,
}
 
spin_lock_init(>buffer_lock);
-   tasklet_init(>tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);
+   tasklet_setup(>tasklet, snd_usbmidi_out_tasklet);
init_waitqueue_head(>drain_wait);
 
for (i = 0; i < 0x10; ++i)
-- 
2.17.1



[PATCH 08/10] sound/soc: txx9: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/soc/txx9/txx9aclc.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 4b1cd4da3e36..939b33ec39f5 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -134,9 +134,9 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, 
dma_addr_t buf_dma_addr)
 
 #define NR_DMA_CHAIN   2
 
-static void txx9aclc_dma_tasklet(unsigned long data)
+static void txx9aclc_dma_tasklet(struct tasklet_struct *t)
 {
-   struct txx9aclc_dmadata *dmadata = (struct txx9aclc_dmadata *)data;
+   struct txx9aclc_dmadata *dmadata = from_tasklet(dmadata, t, tasklet);
struct dma_chan *chan = dmadata->dma_chan;
struct dma_async_tx_descriptor *desc;
struct snd_pcm_substream *substream = dmadata->substream;
@@ -352,8 +352,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device 
*dev,
"playback" : "capture");
return -EBUSY;
}
-   tasklet_init(>tasklet, txx9aclc_dma_tasklet,
-(unsigned long)dmadata);
+   tasklet_setup(>tasklet, txx9aclc_dma_tasklet);
return 0;
 }
 
-- 
2.17.1



[PATCH 07/10] sound/soc: sh: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/soc/sh/siu_pcm.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index bd9de77c35f3..50fc7810723e 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -198,9 +198,9 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
return 0;
 }
 
-static void siu_io_tasklet(unsigned long data)
+static void siu_io_tasklet(struct tasklet_struct *t)
 {
-   struct siu_stream *siu_stream = (struct siu_stream *)data;
+   struct siu_stream *siu_stream = from_tasklet(siu_stream, t, tasklet);
struct snd_pcm_substream *substream = siu_stream->substream;
struct device *dev = substream->pcm->card->dev;
struct snd_pcm_runtime *rt = substream->runtime;
@@ -520,10 +520,8 @@ static int siu_pcm_new(struct snd_soc_component *component,
(*port_info)->pcm = pcm;
 
/* IO tasklets */
-   tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet,
-(unsigned long)&(*port_info)->playback);
-   tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet,
-(unsigned long)&(*port_info)->capture);
+   tasklet_setup(&(*port_info)->playback.tasklet, siu_io_tasklet);
+   tasklet_setup(&(*port_info)->capture.tasklet, siu_io_tasklet);
}
 
dev_info(card->dev, "SuperH SIU driver initialized.\n");
-- 
2.17.1



[PATCH 06/10] sound/soc: fsl_esai: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/soc/fsl/fsl_esai.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 4ae36099ae82..79b861afd986 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -708,9 +708,9 @@ static void fsl_esai_trigger_stop(struct fsl_esai 
*esai_priv, bool tx)
   ESAI_xFCR_xFR, 0);
 }
 
-static void fsl_esai_hw_reset(unsigned long arg)
+static void fsl_esai_hw_reset(struct tasklet_struct *t)
 {
-   struct fsl_esai *esai_priv = (struct fsl_esai *)arg;
+   struct fsl_esai *esai_priv = from_tasklet(esai_priv, t, task);
bool tx = true, rx = false, enabled[2];
unsigned long lock_flags;
u32 tfcr, rfcr;
@@ -1070,8 +1070,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
 
-   tasklet_init(_priv->task, fsl_esai_hw_reset,
-(unsigned long)esai_priv);
+   tasklet_setup(_priv->task, fsl_esai_hw_reset);
 
pm_runtime_enable(>dev);
 
-- 
2.17.1



[PATCH 05/10] sound: rm9652: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/pci/rme9652/hdsp.c  | 6 +++---
 sound/pci/rme9652/hdspm.c | 7 +++
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 227aece17e39..dda56ecfd33b 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3791,9 +3791,9 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp)
return 0;
 }
 
-static void hdsp_midi_tasklet(unsigned long arg)
+static void hdsp_midi_tasklet(struct tasklet_struct *t)
 {
-   struct hdsp *hdsp = (struct hdsp *)arg;
+   struct hdsp *hdsp = from_tasklet(hdsp, t, midi_tasklet);
 
if (hdsp->midi[0].pending)
snd_hdsp_midi_input_read (>midi[0]);
@@ -5182,7 +5182,7 @@ static int snd_hdsp_create(struct snd_card *card,
 
spin_lock_init(>lock);
 
-   tasklet_init(>midi_tasklet, hdsp_midi_tasklet, (unsigned 
long)hdsp);
+   tasklet_setup(>midi_tasklet, hdsp_midi_tasklet);
 
pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, 
>firmware_rev);
hdsp->firmware_rev &= 0xff;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 0fa49f4d15cf..572350aaf18d 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2169,9 +2169,9 @@ static int snd_hdspm_create_midi(struct snd_card *card,
 }
 
 
-static void hdspm_midi_tasklet(unsigned long arg)
+static void hdspm_midi_tasklet(struct tasklet_struct *t)
 {
-   struct hdspm *hdspm = (struct hdspm *)arg;
+   struct hdspm *hdspm = from_tasklet(hdspm, t, midi_tasklet);
int i = 0;
 
while (i < hdspm->midiPorts) {
@@ -6836,8 +6836,7 @@ static int snd_hdspm_create(struct snd_card *card,
 
}
 
-   tasklet_init(>midi_tasklet,
-   hdspm_midi_tasklet, (unsigned long) hdspm);
+   tasklet_setup(>midi_tasklet, hdspm_midi_tasklet);
 
 
if (hdspm->io_type != MADIface) {
-- 
2.17.1



[PATCH 04/10] sound: riptide: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/pci/riptide/riptide.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index b4f300281822..098c69b3b7aa 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1070,9 +1070,9 @@ getmixer(struct cmdif *cif, short num, unsigned short 
*rval,
return 0;
 }
 
-static void riptide_handleirq(unsigned long dev_id)
+static void riptide_handleirq(struct tasklet_struct *t)
 {
-   struct snd_riptide *chip = (void *)dev_id;
+   struct snd_riptide *chip = from_tasklet(chip, t, riptide_tq);
struct cmdif *cif = chip->cif;
struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
struct snd_pcm_runtime *runtime;
@@ -1843,7 +1843,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev 
*pci,
chip->received_irqs = 0;
chip->handled_irqs = 0;
chip->cif = NULL;
-   tasklet_init(>riptide_tq, riptide_handleirq, (unsigned long)chip);
+   tasklet_setup(>riptide_tq, riptide_handleirq);
 
if ((chip->res_port =
 request_region(chip->port, 64, "RIPTIDE")) == NULL) {
-- 
2.17.1



[PATCH 03/10] sound: asihpi: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/pci/asihpi/asihpi.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index 023c35a2a951..35e76480306e 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -921,10 +921,10 @@ static void snd_card_asihpi_timer_function(struct 
timer_list *t)
add_timer(>timer);
 }
 
-static void snd_card_asihpi_int_task(unsigned long data)
+static void snd_card_asihpi_int_task(struct tasklet_struct *t)
 {
-   struct hpi_adapter *a = (struct hpi_adapter *)data;
-   struct snd_card_asihpi *asihpi;
+   struct snd_card_asihpi *asihpi = from_tasklet(asihpi, t, t);
+   struct hpi_adapter *a = asihpi->hpi;
 
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
@@ -2871,8 +2871,7 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
if (hpi->interrupt_mode) {
asihpi->pcm_start = snd_card_asihpi_pcm_int_start;
asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop;
-   tasklet_init(>t, snd_card_asihpi_int_task,
-   (unsigned long)hpi);
+   tasklet_setup(>t, snd_card_asihpi_int_task);
hpi->interrupt_callback = snd_card_asihpi_isr;
} else {
asihpi->pcm_start = snd_card_asihpi_pcm_timer_start;
-- 
2.17.1



[PATCH 02/10] sound: firewire: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/firewire/amdtp-stream.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index f8586f75441d..ee1c428b1fd3 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -64,7 +64,7 @@
 #define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header.
 #define IT_PKT_HEADER_SIZE_NO_CIP  0 // Nothing.
 
-static void pcm_period_tasklet(unsigned long data);
+static void pcm_period_tasklet(struct tasklet_struct *t);
 
 /**
  * amdtp_stream_init - initialize an AMDTP stream structure
@@ -94,7 +94,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit 
*unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(>mutex);
-   tasklet_init(>period_tasklet, pcm_period_tasklet, (unsigned long)s);
+   tasklet_setup(>period_tasklet, pcm_period_tasklet);
s->packet_index = 0;
 
init_waitqueue_head(>callback_wait);
@@ -441,9 +441,9 @@ static void update_pcm_pointers(struct amdtp_stream *s,
}
 }
 
-static void pcm_period_tasklet(unsigned long data)
+static void pcm_period_tasklet(struct tasklet_struct *t)
 {
-   struct amdtp_stream *s = (void *)data;
+   struct amdtp_stream *s = from_tasklet(s, t, period_tasklet);
struct snd_pcm_substream *pcm = READ_ONCE(s->pcm);
 
if (pcm)
-- 
2.17.1



[PATCH 01/10] sound: core: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 sound/core/timer.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index d9f85f2d66a3..6e27d87b18ed 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -816,9 +816,9 @@ static void snd_timer_clear_callbacks(struct snd_timer 
*timer,
  * timer tasklet
  *
  */
-static void snd_timer_tasklet(unsigned long arg)
+static void snd_timer_tasklet(struct tasklet_struct *t)
 {
-   struct snd_timer *timer = (struct snd_timer *) arg;
+   struct snd_timer *timer = from_tasklet(timer, t, task_queue);
unsigned long flags;
 
if (timer->card && timer->card->shutdown) {
@@ -967,8 +967,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct 
snd_timer_id *tid,
INIT_LIST_HEAD(>ack_list_head);
INIT_LIST_HEAD(>sack_list_head);
spin_lock_init(>lock);
-   tasklet_init(>task_queue, snd_timer_tasklet,
-(unsigned long)timer);
+   tasklet_setup(>task_queue, snd_timer_tasklet);
timer->max_instances = 1000; /* default limit per timer */
if (card != NULL) {
timer->module = card->module;
-- 
2.17.1



[PATCH 00/10] sound: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Allen Pais
From: Allen Pais 

Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
introduced a new tasklet initialization API. This series converts 
all the sound drivers to use the new tasklet_setup() API

Allen Pais (10):
  sound: core: convert tasklets to use new tasklet_setup() API
  sound: firewire: convert tasklets to use new tasklet_setup() API
  sound: asihpi: convert tasklets to use new tasklet_setup() API
  sound: riptide: convert tasklets to use new tasklet_setup() API
  sound: rm9652: convert tasklets to use new tasklet_setup() API
  sound/soc: fsl_esai: convert tasklets to use new tasklet_setup() API
  sound/soc: sh: convert tasklets to use new tasklet_setup() API
  sound/soc: txx9: convert tasklets to use new tasklet_setup() API
  sound: midi: convert tasklets to use new tasklet_setup() API
  sound: ua101: convert tasklets to use new tasklet_setup() API

 sound/core/timer.c|  7 +++
 sound/firewire/amdtp-stream.c |  8 
 sound/pci/asihpi/asihpi.c |  9 -
 sound/pci/riptide/riptide.c   |  6 +++---
 sound/pci/rme9652/hdsp.c  |  6 +++---
 sound/pci/rme9652/hdspm.c |  7 +++
 sound/soc/fsl/fsl_esai.c  |  7 +++
 sound/soc/sh/siu_pcm.c| 10 --
 sound/soc/txx9/txx9aclc.c |  7 +++
 sound/usb/midi.c  |  7 +++
 sound/usb/misc/ua101.c|  7 +++
 11 files changed, 36 insertions(+), 45 deletions(-)

-- 
2.17.1



[PATCH 8/8] scsi: pmcraid: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/pmcraid.c | 29 +++--
 drivers/scsi/pmcraid.h |  9 +++--
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index aa9ae2ae8579..b7bbefcbb11d 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -4198,7 +4198,7 @@ static irqreturn_t pmcraid_isr_msix(int irq, void *dev_id)
}
}
 
-   tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id]));
+   tasklet_schedule(&(pinstance->isr_tasklet[hrrq_id]).tasklet);
 
return IRQ_HANDLED;
 }
@@ -4267,7 +4267,7 @@ static irqreturn_t pmcraid_isr(int irq, void *dev_id)
pinstance->int_regs.ioa_host_interrupt_clr_reg);
 
tasklet_schedule(
-   &(pinstance->isr_tasklet[hrrq_id]));
+   &(pinstance->isr_tasklet[hrrq_id].tasklet));
}
}
 
@@ -4380,20 +4380,20 @@ static void pmcraid_worker_function(struct work_struct 
*workp)
  * Return Value
  * None
  */
-static void pmcraid_tasklet_function(unsigned long instance)
+static void pmcraid_tasklet_function(struct tasklet_struct *t)
 {
-   struct pmcraid_isr_param *hrrq_vector;
-   struct pmcraid_instance *pinstance;
+   struct pmcraid_tsk_param *tsk_param = from_tasklet(tsk_param, t,
+  tasklet);
+   int id = tsk_param->isr_tasklet_id;
+   struct pmcraid_instance *pinstance = container_of(tsk_param,
+ typeof(*pinstance),
+ isr_tasklet[id]);
unsigned long hrrq_lock_flags;
unsigned long pending_lock_flags;
unsigned long host_lock_flags;
spinlock_t *lockp; /* hrrq buffer lock */
-   int id;
u32 resp;
 
-   hrrq_vector = (struct pmcraid_isr_param *)instance;
-   pinstance = hrrq_vector->drv_inst;
-   id = hrrq_vector->hrrq_id;
lockp = &(pinstance->hrrq_lock[id]);
 
/* loop through each of the commands responded by IOA. Each HRRQ buf is
@@ -4882,10 +4882,11 @@ static int pmcraid_allocate_config_buffers(struct 
pmcraid_instance *pinstance)
 static void pmcraid_init_tasklets(struct pmcraid_instance *pinstance)
 {
int i;
-   for (i = 0; i < pinstance->num_hrrq; i++)
-   tasklet_init(>isr_tasklet[i],
-pmcraid_tasklet_function,
-(unsigned long)>hrrq_vector[i]);
+   for (i = 0; i < pinstance->num_hrrq; i++) {
+   pinstance->isr_tasklet[i].isr_tasklet_id = i;
+   tasklet_setup(>isr_tasklet[i].tasklet,
+pmcraid_tasklet_function);
+   }
 }
 
 /**
@@ -4900,7 +4901,7 @@ static void pmcraid_kill_tasklets(struct pmcraid_instance 
*pinstance)
 {
int i;
for (i = 0; i < pinstance->num_hrrq; i++)
-   tasklet_kill(>isr_tasklet[i]);
+   tasklet_kill(>isr_tasklet[i].tasklet);
 }
 
 /**
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index 15c962108075..68dab849d4c1 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -617,6 +617,11 @@ struct pmcraid_isr_param {
u8 hrrq_id; /* hrrq entry index */
 };
 
+/* Tasklet parameters (one for each enabled tasklet) */
+struct pmcraid_tsk_param {
+   struct tasklet_struct tasklet;
+   u8 isr_tasklet_id;  /* isr_tasklet entry index */
+};
 
 /* AEN message header sent as part of event data to applications */
 struct pmcraid_aen_msg {
@@ -752,8 +757,8 @@ struct pmcraid_instance {
spinlock_t free_pool_lock;  /* free pool lock */
spinlock_t pending_pool_lock;   /* pending pool lock */
 
-   /* Tasklet to handle deferred processing */
-   struct tasklet_struct isr_tasklet[PMCRAID_NUM_MSIX_VECTORS];
+   /* Tasklet parameters and tasklets to handle deferred processing */
+   struct pmcraid_tsk_param isr_tasklet[PMCRAID_NUM_MSIX_VECTORS];
 
/* Work-queue (Shared) for deferred reset processing */
struct work_struct worker_q;
-- 
2.17.1



[PATCH 7/8] scsi: pm8001: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/pm8001/pm8001_init.c | 55 ++-
 drivers/scsi/pm8001/pm8001_sas.h  |  6 +++-
 2 files changed, 37 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 20fa96cbc9d3..818816c8b295 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -187,12 +187,15 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
  * @opaque: the passed general host adapter struct
  * Note: pm8001_tasklet is common for pm8001 & pm80xx
  */
-static void pm8001_tasklet(unsigned long opaque)
+static void pm8001_tasklet(struct tasklet_struct *t)
 {
-   struct pm8001_hba_info *pm8001_ha;
+   struct tsk_param *tsk_param = from_tasklet(tsk_param, t, tasklet);
+   struct pm8001_hba_info *pm8001_ha = container_of(tsk_param,
+   typeof(*pm8001_ha),
+   tasklet[tsk_param->irq_id]);
struct isr_param *irq_vector;
 
-   irq_vector = (struct isr_param *)opaque;
+   irq_vector = _ha->irq_vector[tsk_param->irq_id];
pm8001_ha = irq_vector->drv_inst;
if (unlikely(!pm8001_ha))
BUG_ON(1);
@@ -221,7 +224,7 @@ static irqreturn_t pm8001_interrupt_handler_msix(int irq, 
void *opaque)
if (!PM8001_CHIP_DISP->is_our_interrupt(pm8001_ha))
return IRQ_NONE;
 #ifdef PM8001_USE_TASKLET
-   tasklet_schedule(_ha->tasklet[irq_vector->irq_id]);
+   tasklet_schedule(_ha->tasklet[irq_vector->irq_id].tasklet);
 #else
ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 #endif
@@ -246,7 +249,7 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, 
void *dev_id)
return IRQ_NONE;
 
 #ifdef PM8001_USE_TASKLET
-   tasklet_schedule(_ha->tasklet[0]);
+   tasklet_schedule(_ha->tasklet[0].tasklet);
 #else
ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
 #endif
@@ -507,13 +510,16 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct 
pci_dev *pdev,
 #ifdef PM8001_USE_TASKLET
/* Tasklet for non msi-x interrupt handler */
if ((!pdev->msix_cap || !pci_msi_enabled())
-   || (pm8001_ha->chip_id == chip_8001))
-   tasklet_init(_ha->tasklet[0], pm8001_tasklet,
-   (unsigned long)&(pm8001_ha->irq_vector[0]));
-   else
-   for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
-   tasklet_init(_ha->tasklet[j], pm8001_tasklet,
-   (unsigned long)&(pm8001_ha->irq_vector[j]));
+   || (pm8001_ha->chip_id == chip_8001)) {
+   pm8001_ha->tasklet[0].irq_id = 0;
+   tasklet_setup(_ha->tasklet[0].tasklet, pm8001_tasklet);
+   } else {
+   for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) {
+   pm8001_ha->tasklet[j].irq_id = j;
+   tasklet_setup(_ha->tasklet[j].tasklet,
+ pm8001_tasklet);
+   }
+   }
 #endif
pm8001_ioremap(pm8001_ha);
if (!pm8001_alloc(pm8001_ha, ent))
@@ -1162,10 +1168,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
/* For non-msix and msix interrupts */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
(pm8001_ha->chip_id == chip_8001))
-   tasklet_kill(_ha->tasklet[0]);
+   tasklet_kill(_ha->tasklet[0].tasklet);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
-   tasklet_kill(_ha->tasklet[j]);
+   tasklet_kill(_ha->tasklet[j].tasklet);
 #endif
scsi_host_put(pm8001_ha->shost);
pm8001_free(pm8001_ha);
@@ -1212,10 +1218,10 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, 
pm_message_t state)
/* For non-msix and msix interrupts */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
(pm8001_ha->chip_id == chip_8001))
-   tasklet_kill(_ha->tasklet[0]);
+   tasklet_kill(_ha->tasklet[0].tasklet);
else
for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
-   tasklet_kill(_ha->tasklet[j]);
+   tasklet_kill(_ha->tasklet[j].tasklet);
 #endif
device_state = pci_choose_state(pdev, state);
pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -1281,13 +1287,16 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
 #ifdef PM8001_USE_TASKLET
/*  Tasklet for non msi-x interrupt handler */
if ((!pdev->msix_cap || !pci_msi_enabled()) ||
-   (pm8001_ha->chip_id == chip_8001))
-   tasklet_init(_ha->tasklet[0], 

[PATCH 6/8] scsi: mvsas: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/mvsas/mv_init.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index 978f5283c883..53b2d463fa13 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -147,13 +147,14 @@ static void mvs_free(struct mvs_info *mvi)
 }
 
 #ifdef CONFIG_SCSI_MVSAS_TASKLET
-static void mvs_tasklet(unsigned long opaque)
+static void mvs_tasklet(struct tasklet_struct *t)
 {
u32 stat;
u16 core_nr, i = 0;
 
struct mvs_info *mvi;
-   struct sas_ha_struct *sha = (struct sas_ha_struct *)opaque;
+   struct mvs_prv_info *mpi = from_tasklet(mpi, t, mv_tasklet);
+   struct sas_ha_struct *sha = pci_get_drvdata(mpi->mvi[0]->pdev);
 
core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
@@ -564,8 +565,7 @@ static int mvs_pci_init(struct pci_dev *pdev, const struct 
pci_device_id *ent)
} while (nhost < chip->n_host);
mpi = (struct mvs_prv_info *)(SHOST_TO_SAS_HA(shost)->lldd_ha);
 #ifdef CONFIG_SCSI_MVSAS_TASKLET
-   tasklet_init(&(mpi->mv_tasklet), mvs_tasklet,
-(unsigned long)SHOST_TO_SAS_HA(shost));
+   tasklet_setup(&(mpi->mv_tasklet), mvs_tasklet);
 #endif
 
mvs_post_sas_ha_init(shost, chip);
-- 
2.17.1



[PATCH 5/8] scsi: megaraid: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/megaraid/megaraid_mbox.c   |  9 -
 drivers/scsi/megaraid/megaraid_sas.h|  2 +-
 drivers/scsi/megaraid/megaraid_sas_base.c   | 16 +++-
 drivers/scsi/megaraid/megaraid_sas_fusion.c | 14 +++---
 4 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/drivers/scsi/megaraid/megaraid_mbox.c 
b/drivers/scsi/megaraid/megaraid_mbox.c
index 19469a2c0ea3..47b2d8045c9d 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -119,7 +119,7 @@ static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t 
*,
 
 static irqreturn_t megaraid_isr(int, void *);
 
-static void megaraid_mbox_dpc(unsigned long);
+static void megaraid_mbox_dpc(struct tasklet_struct *t);
 
 static ssize_t megaraid_sysfs_show_app_hndl(struct device *, struct 
device_attribute *attr, char *);
 static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct 
device_attribute *attr, char *);
@@ -878,8 +878,7 @@ megaraid_init_mbox(adapter_t *adapter)
}
 
// setup tasklet for DPC
-   tasklet_init(>dpc_h, megaraid_mbox_dpc,
-   (unsigned long)adapter);
+   tasklet_setup(>dpc_h, megaraid_mbox_dpc);
 
con_log(CL_DLEVEL1, (KERN_INFO
"megaraid mbox hba successfully initialized\n"));
@@ -2168,9 +2167,9 @@ megaraid_isr(int irq, void *devp)
  * it is being called.
  */
 static void
-megaraid_mbox_dpc(unsigned long devp)
+megaraid_mbox_dpc(struct tasklet_struct *t)
 {
-   adapter_t   *adapter = (adapter_t *)devp;
+   adapter_t   *adapter = from_tasklet(adapter, t, dpc_h);
mraid_device_t  *raid_dev;
struct list_headclist;
struct scatterlist  *sgl;
diff --git a/drivers/scsi/megaraid/megaraid_sas.h 
b/drivers/scsi/megaraid/megaraid_sas.h
index 5e4137f10e0e..ce361b2b9f14 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2531,7 +2531,7 @@ struct megasas_instance_template {
int (*check_reset)(struct megasas_instance *, \
struct megasas_register_set __iomem *);
irqreturn_t (*service_isr)(int irq, void *devp);
-   void (*tasklet)(unsigned long);
+   void (*tasklet)(struct tasklet_struct *t);
u32 (*init_adapter)(struct megasas_instance *);
u32 (*build_and_issue_cmd) (struct megasas_instance *,
struct scsi_cmnd *);
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c 
b/drivers/scsi/megaraid/megaraid_sas_base.c
index 861f7140f52e..dba60cc1cf41 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -217,7 +217,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance);
 u32
 megasas_build_and_issue_cmd(struct megasas_instance *instance,
struct scsi_cmnd *scmd);
-static void megasas_complete_cmd_dpc(unsigned long instance_addr);
+static void megasas_complete_cmd_dpc(struct tasklet_struct *t);
 int
 wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
int seconds);
@@ -2217,14 +2217,14 @@ megasas_check_and_restore_queue_depth(struct 
megasas_instance *instance)
  *
  * Tasklet to complete cmds
  */
-static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+static void megasas_complete_cmd_dpc(struct tasklet_struct *t)
 {
u32 producer;
u32 consumer;
u32 context;
struct megasas_cmd *cmd;
-   struct megasas_instance *instance =
-   (struct megasas_instance *)instance_addr;
+   struct megasas_instance *instance = from_tasklet(instance, t,
+isr_tasklet);
unsigned long flags;
 
/* If we have already declared adapter dead, donot complete cmds */
@@ -2769,7 +2769,7 @@ static int megasas_wait_for_outstanding(struct 
megasas_instance *instance)
 * Call cmd completion routine. Cmd to be
 * be completed directly without depending on isr.
 */
-   megasas_complete_cmd_dpc((unsigned long)instance);
+   megasas_complete_cmd_dpc(>isr_tasklet);
}
 
msleep(1000);
@@ -6180,8 +6180,7 @@ static int megasas_init_fw(struct megasas_instance 
*instance)
dev_info(>pdev->dev,
"RDPQ mode\t: (%s)\n", instance->is_rdpq ? "enabled" : 
"disabled");
 
-   tasklet_init(>isr_tasklet, instance->instancet->tasklet,
-   (unsigned long)instance);
+   tasklet_setup(>isr_tasklet, instance->instancet->tasklet);
 
  

[PATCH 4/8] scsi: isci: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/isci/host.c | 4 ++--
 drivers/scsi/isci/host.h | 2 +-
 drivers/scsi/isci/init.c | 3 +--
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 7b5deae68d33..599adebd039e 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1113,9 +1113,9 @@ void ireq_done(struct isci_host *ihost, struct 
isci_request *ireq, struct sas_ta
  * @data: This parameter specifies the ISCI host object
  *
  */
-void isci_host_completion_routine(unsigned long data)
+void isci_host_completion_routine(struct tasklet_struct *t)
 {
-   struct isci_host *ihost = (struct isci_host *)data;
+   struct isci_host *ihost = from_tasklet(ihost, t, completion_tasklet);
u16 active;
 
spin_lock_irq(>scic_lock);
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 6bc3f022630a..6abe23682d9b 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -478,7 +478,7 @@ void isci_tci_free(struct isci_host *ihost, u16 tci);
 void ireq_done(struct isci_host *ihost, struct isci_request *ireq, struct 
sas_task *task);
 
 int isci_host_init(struct isci_host *);
-void isci_host_completion_routine(unsigned long data);
+void isci_host_completion_routine(struct tasklet_struct *t);
 void isci_host_deinit(struct isci_host *);
 void sci_controller_disable_interrupts(struct isci_host *ihost);
 bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost);
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 085e285f427d..32a0117b5ff4 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -511,8 +511,7 @@ static struct isci_host *isci_host_alloc(struct pci_dev 
*pdev, int id)
init_waitqueue_head(>eventq);
ihost->sas_ha.dev = >pdev->dev;
ihost->sas_ha.lldd_ha = ihost;
-   tasklet_init(>completion_tasklet,
-isci_host_completion_routine, (unsigned long)ihost);
+   tasklet_setup(>completion_tasklet, isci_host_completion_routine);
 
/* validate module parameters */
/* TODO: kill struct sci_user_parameters and reference directly */
-- 
2.17.1



[PATCH 3/8] scsi: ibmvscsi: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/ibmvscsi/ibmvfc.c   | 6 +++---
 drivers/scsi/ibmvscsi/ibmvscsi.c | 8 
 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 7 +++
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 77f4d37d5bd6..50f025cdabbd 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3204,9 +3204,9 @@ static irqreturn_t ibmvfc_interrupt(int irq, void 
*dev_instance)
  * Returns:
  * Nothing
  **/
-static void ibmvfc_tasklet(void *data)
+static void ibmvfc_tasklet(struct tasklet_struct *t)
 {
-   struct ibmvfc_host *vhost = data;
+   struct ibmvfc_host *vhost = from_tasklet(vhost, t, tasklet);
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_crq *crq;
struct ibmvfc_async_crq *async;
@@ -4676,7 +4676,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
 
retrc = 0;
 
-   tasklet_init(>tasklet, (void *)ibmvfc_tasklet, (unsigned 
long)vhost);
+   tasklet_setup(>tasklet, (void *)ibmvfc_tasklet);
 
if ((rc = request_irq(vdev->irq, ibmvfc_interrupt, 0, IBMVFC_NAME, 
vhost))) {
dev_err(dev, "Couldn't register irq 0x%x. rc=%d\n", vdev->irq, 
rc);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index b1f3017b6547..46b818daa957 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -208,9 +208,10 @@ static int ibmvscsi_send_crq(struct ibmvscsi_host_data 
*hostdata,
  * ibmvscsi_task: - Process srps asynchronously
  * @data:  ibmvscsi_host_data of host
  */
-static void ibmvscsi_task(void *data)
+static void ibmvscsi_task(struct tasklet_struct *t)
 {
-   struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
+   struct ibmvscsi_host_data *hostdata = from_tasklet(hostdata, t,
+  srp_task);
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
struct viosrp_crq *crq;
int done = 0;
@@ -366,8 +367,7 @@ static int ibmvscsi_init_crq_queue(struct crq_queue *queue,
queue->cur = 0;
spin_lock_init(>lock);
 
-   tasklet_init(>srp_task, (void *)ibmvscsi_task,
-(unsigned long)hostdata);
+   tasklet_setup(>srp_task, ibmvscsi_task);
 
if (request_irq(vdev->irq,
ibmvscsi_handle_event,
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c 
b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index d9e94e81da01..e62fd6c67001 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -3328,9 +3328,9 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, 
struct scatterlist *sg,
  *
  * Note: this is an edge triggered interrupt. It can not be shared.
  */
-static void ibmvscsis_handle_crq(unsigned long data)
+static void ibmvscsis_handle_crq(struct tasklet_struct *t)
 {
-   struct scsi_info *vscsi = (struct scsi_info *)data;
+   struct scsi_info *vscsi = from_tasklet(vscsi, t, work_task);
struct viosrp_crq *crq;
long rc;
bool ack = true;
@@ -3541,8 +3541,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
dev_dbg(>dev, "probe hrc %ld, client partition num %d\n",
hrc, vscsi->client_data.partition_number);
 
-   tasklet_init(>work_task, ibmvscsis_handle_crq,
-(unsigned long)vscsi);
+   tasklet_setup(>work_task, ibmvscsis_handle_crq);
 
init_completion(>wait_idle);
init_completion(>unconfig);
-- 
2.17.1



[PATCH 2/8] scsi: esas2r: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/esas2r/esas2r.h  | 2 +-
 drivers/scsi/esas2r/esas2r_init.c | 4 +---
 drivers/scsi/esas2r/esas2r_main.c | 4 ++--
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h
index e30d2f1f5368..b99434e24868 100644
--- a/drivers/scsi/esas2r/esas2r.h
+++ b/drivers/scsi/esas2r/esas2r.h
@@ -992,7 +992,7 @@ int esas2r_write_vda(struct esas2r_adapter *a, const char 
*buf, long off,
 int esas2r_read_fs(struct esas2r_adapter *a, char *buf, long off, int count);
 int esas2r_write_fs(struct esas2r_adapter *a, const char *buf, long off,
int count);
-void esas2r_adapter_tasklet(unsigned long context);
+void esas2r_adapter_tasklet(struct tasklet_struct *t);
 irqreturn_t esas2r_interrupt(int irq, void *dev_id);
 irqreturn_t esas2r_msi_interrupt(int irq, void *dev_id);
 void esas2r_kickoff_timer(struct esas2r_adapter *a);
diff --git a/drivers/scsi/esas2r/esas2r_init.c 
b/drivers/scsi/esas2r/esas2r_init.c
index eb7d139ffc00..55387c14fb8d 100644
--- a/drivers/scsi/esas2r/esas2r_init.c
+++ b/drivers/scsi/esas2r/esas2r_init.c
@@ -401,9 +401,7 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct 
pci_dev *pcid,
return 0;
}
 
-   tasklet_init(>tasklet,
-esas2r_adapter_tasklet,
-(unsigned long)a);
+   tasklet_setup(>tasklet, esas2r_adapter_tasklet);
 
/*
 * Disable chip interrupts to prevent spurious interrupts
diff --git a/drivers/scsi/esas2r/esas2r_main.c 
b/drivers/scsi/esas2r/esas2r_main.c
index 7b49e2e9fcde..7ffa9406ab4d 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -1546,9 +1546,9 @@ void esas2r_complete_request_cb(struct esas2r_adapter *a,
 }
 
 /* Run tasklet to handle stuff outside of interrupt context. */
-void esas2r_adapter_tasklet(unsigned long context)
+void esas2r_adapter_tasklet(struct tasklet_struct *t)
 {
-   struct esas2r_adapter *a = (struct esas2r_adapter *)context;
+   struct esas2r_adapter *a = from_tasklet(a, t, tasklet);
 
if (unlikely(test_bit(AF2_TIMER_TICK, >flags2))) {
clear_bit(AF2_TIMER_TICK, >flags2);
-- 
2.17.1



[PATCH 0/8] scsi: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Allen Pais
From: Allen Pais 

Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
introduced a new tasklet initialization API. This series converts 
all the scsi drivers to use the new tasklet_setup() API

Allen Pais (8):
  scsi: aic94xx: convert tasklets to use new tasklet_setup() API
  scsi: esas2r: convert tasklets to use new tasklet_setup() API
  scsi: ibmvscsi: convert tasklets to use new tasklet_setup() API
  scsi: isci: convert tasklets to use new tasklet_setup() API
  scsi: megaraid: convert tasklets to use new tasklet_setup() API
  scsi: mvsas: convert tasklets to use new tasklet_setup() API
  scsi: pm8001: convert tasklets to use new tasklet_setup() API
  scsi: pmcraid: convert tasklets to use new tasklet_setup() API

 drivers/scsi/aic94xx/aic94xx_hwi.c  |  9 ++--
 drivers/scsi/esas2r/esas2r.h|  2 +-
 drivers/scsi/esas2r/esas2r_init.c   |  4 +-
 drivers/scsi/esas2r/esas2r_main.c   |  4 +-
 drivers/scsi/ibmvscsi/ibmvfc.c  |  6 +--
 drivers/scsi/ibmvscsi/ibmvscsi.c|  8 +--
 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c|  7 ++-
 drivers/scsi/isci/host.c|  4 +-
 drivers/scsi/isci/host.h|  2 +-
 drivers/scsi/isci/init.c|  3 +-
 drivers/scsi/megaraid/megaraid_mbox.c   |  9 ++--
 drivers/scsi/megaraid/megaraid_sas.h|  2 +-
 drivers/scsi/megaraid/megaraid_sas_base.c   | 16 +++---
 drivers/scsi/megaraid/megaraid_sas_fusion.c | 14 +++---
 drivers/scsi/mvsas/mv_init.c|  8 +--
 drivers/scsi/pm8001/pm8001_init.c   | 55 -
 drivers/scsi/pm8001/pm8001_sas.h|  6 ++-
 drivers/scsi/pmcraid.c  | 29 +--
 drivers/scsi/pmcraid.h  |  9 +++-
 19 files changed, 104 insertions(+), 93 deletions(-)

-- 
2.17.1



[PATCH 1/8] scsi: aic94xx: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
From: Allen Pais 

In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/scsi/aic94xx/aic94xx_hwi.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c 
b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 9256ab7b2522..1e4d32246cb9 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -248,7 +248,7 @@ static void asd_get_max_scb_ddb(struct asd_ha_struct 
*asd_ha)
 
 /* -- Done List initialization -- */
 
-static void asd_dl_tasklet_handler(unsigned long);
+static void asd_dl_tasklet_handler(struct tasklet_struct *t);
 
 static int asd_init_dl(struct asd_ha_struct *asd_ha)
 {
@@ -261,8 +261,7 @@ static int asd_init_dl(struct asd_ha_struct *asd_ha)
asd_ha->seq.dl = asd_ha->seq.actual_dl->vaddr;
asd_ha->seq.dl_toggle = ASD_DEF_DL_TOGGLE;
asd_ha->seq.dl_next = 0;
-   tasklet_init(_ha->seq.dl_tasklet, asd_dl_tasklet_handler,
-(unsigned long) asd_ha);
+   tasklet_setup(_ha->seq.dl_tasklet, asd_dl_tasklet_handler);
 
return 0;
 }
@@ -711,9 +710,9 @@ static void asd_chip_reset(struct asd_ha_struct *asd_ha)
 
 /* -- Done List Routines -- */
 
-static void asd_dl_tasklet_handler(unsigned long data)
+static void asd_dl_tasklet_handler(struct tasklet_struct *t)
 {
-   struct asd_ha_struct *asd_ha = (struct asd_ha_struct *) data;
+   struct asd_ha_struct *asd_ha = from_tasklet(asd_ha, t, seq.dl_tasklet);
struct asd_seq_data *seq = _ha->seq;
unsigned long flags;
 
-- 
2.17.1



Re: [PATCH v2 1/3] powerpc/numa: Introduce logical numa id

2020-08-17 Thread Srikar Dronamraju
* Aneesh Kumar K.V  [2020-08-17 16:02:36]:

> We use ibm,associativity and ibm,associativity-lookup-arrays to derive the 
> numa
> node numbers. These device tree properties are firmware indicated grouping of
> resources based on their hierarchy in the platform. These numbers (group id) 
> are
> not sequential and hypervisor/firmware can follow different numbering schemes.
> For ex: on powernv platforms, we group them in the below order.
> 
>  * - CCM node ID
>  * - HW card ID
>  * - HW module ID
>  * - Chip ID
>  * - Core ID
> 
> Based on ibm,associativity-reference-points we use one of the above group ids 
> as
> Linux NUMA node id. (On PowerNV platform Chip ID is used). This results
> in Linux reporting non-linear NUMA node id and which also results in Linux
> reporting empty node 0 NUMA nodes.
> 
> This can  be resolved by mapping the firmware provided group id to a logical 
> Linux
> NUMA id. In this patch, we do this only for pseries platforms considering the
> firmware group id is a virtualized entity and users would not have drawn any
> conclusion based on the Linux Numa Node id.
> 
> On PowerNV platform since we have historically mapped Chip ID as Linux NUMA 
> node
> id, we keep the existing Linux NUMA node id numbering.

I still dont understand how you are going to handle numa distances.
With your patch, have you tried dlpar add/remove on a sparsely noded machine?

-- 
Thanks and Regards
Srikar Dronamraju


[PATCH] powerpc/pkeys: Fix build error with PPC_MEM_KEYS disabled

2020-08-17 Thread Aneesh Kumar K.V
IS_ENABLED() instead of #ifdef still requires variable declaration.
In this specific case, default_uamor is declared in asm/pkeys.h which
is only included if PPC_MEM_KEYS is enabled.

arch/powerpc/mm/book3s64/hash_utils.c: In function 
‘hash__early_init_mmu_secondary’:
arch/powerpc/mm/book3s64/hash_utils.c:1119:21: error: ‘default_uamor’ 
undeclared (first use in this function)
 1119 |   mtspr(SPRN_UAMOR, default_uamor);
  | ^

Fixes: 6553fb799f60 ("powerpc/pkeys: Fix boot failures with Nemo board (A-EON 
AmigaOne X1000)")
Signed-off-by: Aneesh Kumar K.V 
---
 arch/powerpc/mm/book3s64/hash_utils.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/mm/book3s64/hash_utils.c 
b/arch/powerpc/mm/book3s64/hash_utils.c
index 1da9dbba9217..890a71c5293e 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -1115,8 +1115,10 @@ void hash__early_init_mmu_secondary(void)
&& cpu_has_feature(CPU_FTR_HVMODE))
tlbiel_all();
 
-   if (IS_ENABLED(CONFIG_PPC_MEM_KEYS) && mmu_has_feature(MMU_FTR_PKEY))
+#ifdef CONFIG_PPC_MEM_KEYS
+   if (mmu_has_feature(MMU_FTR_PKEY))
mtspr(SPRN_UAMOR, default_uamor);
+#endif
 }
 #endif /* CONFIG_SMP */
 
-- 
2.26.2



[PATCH v2 3/3] powerpc/numa: Move POWER4 restriction to the helper

2020-08-17 Thread Aneesh Kumar K.V
Even though the comment says POWER4 usage, I guess it applies to all
platforms since there is no PVR check there. This patch moves the check
to the helper.

Signed-off-by: Aneesh Kumar K.V 
---
 arch/powerpc/mm/numa.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index d29f60e15777..7319084345e1 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -250,7 +250,8 @@ int affinity_domain_to_nid(struct affinity_domain *domain)
if (!firmware_has_feature(FW_FEATURE_LPAR))
return domain_id;
 
-   if (domain_id ==  -1)
+   /* POWER4 LPAR uses 0x as invalid node */
+   if (domain_id ==  -1 || domain_id == 0x)
return NUMA_NO_NODE;
 
nid = __affinity_domain_to_nid(domain_id, last_nid);
@@ -283,10 +284,6 @@ static int associativity_to_nid(const __be32 
*associativity)
if (of_read_number(associativity, 1) >= min_common_depth)
domain.id = of_read_number([min_common_depth], 1);
 
-   /* POWER4 LPAR uses 0x as invalid node */
-   if (domain.id == 0x)
-   domain.id = -1;
-
nid = affinity_domain_to_nid();
 
if (nid > 0 &&
@@ -499,9 +496,6 @@ static int of_drconf_to_nid_single(struct drmem_lmb *lmb)
index = lmb->aa_index * aa.array_sz + min_common_depth - 1;
domain.id = of_read_number([index], 1);
 
-   if (domain.id == 0x)
-   domain.id = -1;
-
nid = affinity_domain_to_nid();
 
if (nid > 0) {
-- 
2.26.2



[PATCH v2 2/3] powerpc/powernv/cpufreq: Don't assume chip id is same as Linux node id

2020-08-17 Thread Aneesh Kumar K.V
On PowerNV platforms we always have 1:1 mapping between chip ID and
firmware group id. Use the helper to convert firmware group id to
node id instead of directly using chip ID as Linux node id.

NOTE: This doesn't have any functional change. On PowerNV platforms
we continue to have 1:1 mapping between firmware group id and
Linux node id.

Reviewed-by: Gautham R. Shenoy 
Signed-off-by: Aneesh Kumar K.V 
---
 drivers/cpufreq/powernv-cpufreq.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index a9af15e994cc..d7e6eb8aaba1 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -27,6 +27,7 @@
 #include 
 #include  /* Required for cpu_sibling_mask() in UP configs */
 #include 
+#include 
 #include 
 
 #define POWERNV_MAX_PSTATES_ORDER  8
@@ -1070,8 +1071,16 @@ static int init_chip_info(void)
}
 
for (i = 0; i < nr_chips; i++) {
+   struct affinity_domain domain;
+   unsigned int nid;
+
chips[i].id = chip[i];
-   cpumask_copy([i].mask, cpumask_of_node(chip[i]));
+   /*
+* On powervn platforms affinity domain id is same as chipd id.
+*/
+   domain.id = chip[i];
+   nid = affinity_domain_to_nid();
+   cpumask_copy([i].mask, cpumask_of_node(nid));
INIT_WORK([i].throttle, powernv_cpufreq_work_fn);
for_each_cpu(cpu, [i].mask)
per_cpu(chip_info, cpu) =  [i];
-- 
2.26.2



[PATCH v2 1/3] powerpc/numa: Introduce logical numa id

2020-08-17 Thread Aneesh Kumar K.V
We use ibm,associativity and ibm,associativity-lookup-arrays to derive the numa
node numbers. These device tree properties are firmware indicated grouping of
resources based on their hierarchy in the platform. These numbers (group id) are
not sequential and hypervisor/firmware can follow different numbering schemes.
For ex: on powernv platforms, we group them in the below order.

 * - CCM node ID
 * - HW card ID
 * - HW module ID
 * - Chip ID
 * - Core ID

Based on ibm,associativity-reference-points we use one of the above group ids as
Linux NUMA node id. (On PowerNV platform Chip ID is used). This results
in Linux reporting non-linear NUMA node id and which also results in Linux
reporting empty node 0 NUMA nodes.

This can  be resolved by mapping the firmware provided group id to a logical 
Linux
NUMA id. In this patch, we do this only for pseries platforms considering the
firmware group id is a virtualized entity and users would not have drawn any
conclusion based on the Linux Numa Node id.

On PowerNV platform since we have historically mapped Chip ID as Linux NUMA node
id, we keep the existing Linux NUMA node id numbering.

Before Fix:
 # numactl -H
available: 2 nodes (0-1)
node 0 cpus:
node 0 size: 0 MB
node 0 free: 0 MB
node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
node 1 size: 50912 MB
node 1 free: 45248 MB
node distances:
node   0   1
  0:  10  40
  1:  40  10

after fix
 # numactl  -H
available: 1 nodes (0)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
node 0 size: 50912 MB
node 0 free: 49724 MB
node distances:
node   0
  0:  10

Signed-off-by: Aneesh Kumar K.V 
---
 arch/powerpc/include/asm/topology.h |  5 ++
 arch/powerpc/mm/numa.c  | 74 -
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/include/asm/topology.h 
b/arch/powerpc/include/asm/topology.h
index f0b6300e7dd3..7c18883cee9c 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -118,5 +118,10 @@ int get_physical_package_id(int cpu);
 #endif
 #endif
 
+struct affinity_domain {
+   int id;
+};
+
+int affinity_domain_to_nid(struct affinity_domain *domain);
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_TOPOLOGY_H */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 1f61fa2148b5..d29f60e15777 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -221,26 +221,76 @@ static void initialize_distance_lookup_table(int nid,
}
 }
 
+
+static int domain_id_map[MAX_NUMNODES] = {[0 ... MAX_NUMNODES - 1] =  -1 };
+
+static int __affinity_domain_to_nid(int domain_id, int max_nid)
+{
+   int i;
+
+   for (i = 0; i < max_nid; i++) {
+   if (domain_id_map[i] == domain_id)
+   return i;
+   }
+   return NUMA_NO_NODE;
+}
+
+int affinity_domain_to_nid(struct affinity_domain *domain)
+{
+   int nid, domain_id;
+   static int last_nid = 0;
+   static DEFINE_SPINLOCK(node_id_lock);
+
+   domain_id = domain->id;
+   /*
+* For PowerNV we don't change the node id. This helps to avoid
+* confusion w.r.t the expected node ids. On pseries, node numbers
+* are virtualized. Hence do logical node id for pseries.
+*/
+   if (!firmware_has_feature(FW_FEATURE_LPAR))
+   return domain_id;
+
+   if (domain_id ==  -1)
+   return NUMA_NO_NODE;
+
+   nid = __affinity_domain_to_nid(domain_id, last_nid);
+   if (nid == NUMA_NO_NODE) {
+   spin_lock(_id_lock);
+   /*  recheck with lock held */
+   nid = __affinity_domain_to_nid(domain_id, last_nid);
+   if (nid == NUMA_NO_NODE && last_nid < MAX_NUMNODES) {
+   nid = last_nid++;
+   domain_id_map[nid] = domain_id;
+   }
+   spin_unlock(_id_lock);
+   }
+
+   return nid;
+}
+
 /*
  * Returns nid in the range [0..nr_node_ids], or -1 if no useful NUMA
  * info is found.
  */
 static int associativity_to_nid(const __be32 *associativity)
 {
+   struct affinity_domain domain = { .id = -1 };
int nid = NUMA_NO_NODE;
 
if (!numa_enabled)
goto out;
 
if (of_read_number(associativity, 1) >= min_common_depth)
-   nid = of_read_number([min_common_depth], 1);
+   domain.id = of_read_number([min_common_depth], 1);
 
/* POWER4 LPAR uses 0x as invalid node */
-   if (nid == 0x || nid >= nr_node_ids)
-   nid = NUMA_NO_NODE;
+   if (domain.id == 0x)
+   domain.id = 

[PATCH v4 6/6] powerpc/watchpoint/selftests: Tests for kernel accessing user memory

2020-08-17 Thread Ravi Bangoria
Introduce tests to cover simple scenarios where user is watching
memory which can be accessed by kernel as well. We also support
_MODE_EXACT with _SETHWDEBUG interface. Move those testcases out-
side of _BP_RANGE condition. This will help to test _MODE_EXACT
scenarios when CONFIG_HAVE_HW_BREAKPOINT is not set, eg:

  $ ./ptrace-hwbreak
  ...
  PTRACE_SET_DEBUGREG, Kernel Access Userspace, len: 8: Ok
  PPC_PTRACE_SETHWDEBUG, MODE_EXACT, WO, len: 1: Ok
  PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RO, len: 1: Ok
  PPC_PTRACE_SETHWDEBUG, MODE_EXACT, RW, len: 1: Ok
  PPC_PTRACE_SETHWDEBUG, MODE_EXACT, Kernel Access Userspace, len: 1: Ok
  success: ptrace-hwbreak

Suggested-by: Pedro Miraglia Franco de Carvalho 
Signed-off-by: Ravi Bangoria 
---
 .../selftests/powerpc/ptrace/ptrace-hwbreak.c | 48 ++-
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c 
b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
index fc477dfe86a2..2e0d86e0687e 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
@@ -20,6 +20,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "ptrace.h"
 
 #define SPRN_PVR   0x11F
@@ -44,6 +46,7 @@ struct gstruct {
 };
 static volatile struct gstruct gstruct __attribute__((aligned(512)));
 
+static volatile char cwd[PATH_MAX] __attribute__((aligned(8)));
 
 static void get_dbginfo(pid_t child_pid, struct ppc_debug_info *dbginfo)
 {
@@ -138,6 +141,9 @@ static void test_workload(void)
write_var(len);
}
 
+   /* PTRACE_SET_DEBUGREG, Kernel Access Userspace test */
+   syscall(__NR_getcwd, , PATH_MAX);
+
/* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, WO test */
write_var(1);
 
@@ -150,6 +156,9 @@ static void test_workload(void)
else
read_var(1);
 
+   /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, Kernel Access Userspace test */
+   syscall(__NR_getcwd, , PATH_MAX);
+
/* PPC_PTRACE_SETHWDEBUG, MODE_RANGE, DW ALIGNED, WO test */
gstruct.a[rand() % A_LEN] = 'a';
 
@@ -293,6 +302,24 @@ static int test_set_debugreg(pid_t child_pid)
return 0;
 }
 
+static int test_set_debugreg_kernel_userspace(pid_t child_pid)
+{
+   unsigned long wp_addr = (unsigned long)cwd;
+   char *name = "PTRACE_SET_DEBUGREG";
+
+   /* PTRACE_SET_DEBUGREG, Kernel Access Userspace test */
+   wp_addr &= ~0x7UL;
+   wp_addr |= (1Ul << DABR_READ_SHIFT);
+   wp_addr |= (1UL << DABR_WRITE_SHIFT);
+   wp_addr |= (1UL << DABR_TRANSLATION_SHIFT);
+   ptrace_set_debugreg(child_pid, wp_addr);
+   ptrace(PTRACE_CONT, child_pid, NULL, 0);
+   check_success(child_pid, name, "Kernel Access Userspace", wp_addr, 8);
+
+   ptrace_set_debugreg(child_pid, 0);
+   return 0;
+}
+
 static void get_ppc_hw_breakpoint(struct ppc_hw_breakpoint *info, int type,
  unsigned long addr, int len)
 {
@@ -338,6 +365,22 @@ static void test_sethwdebug_exact(pid_t child_pid)
ptrace_delhwdebug(child_pid, wh);
 }
 
+static void test_sethwdebug_exact_kernel_userspace(pid_t child_pid)
+{
+   struct ppc_hw_breakpoint info;
+   unsigned long wp_addr = (unsigned long)
+   char *name = "PPC_PTRACE_SETHWDEBUG, MODE_EXACT";
+   int len = 1; /* hardcoded in kernel */
+   int wh;
+
+   /* PPC_PTRACE_SETHWDEBUG, MODE_EXACT, Kernel Access Userspace test */
+   get_ppc_hw_breakpoint(, PPC_BREAKPOINT_TRIGGER_WRITE, wp_addr, 0);
+   wh = ptrace_sethwdebug(child_pid, );
+   ptrace(PTRACE_CONT, child_pid, NULL, 0);
+   check_success(child_pid, name, "Kernel Access Userspace", wp_addr, len);
+   ptrace_delhwdebug(child_pid, wh);
+}
+
 static void test_sethwdebug_range_aligned(pid_t child_pid)
 {
struct ppc_hw_breakpoint info;
@@ -452,9 +495,10 @@ static void
 run_tests(pid_t child_pid, struct ppc_debug_info *dbginfo, bool dawr)
 {
test_set_debugreg(child_pid);
+   test_set_debugreg_kernel_userspace(child_pid);
+   test_sethwdebug_exact(child_pid);
+   test_sethwdebug_exact_kernel_userspace(child_pid);
if (dbginfo->features & PPC_DEBUG_FEATURE_DATA_BP_RANGE) {
-   test_sethwdebug_exact(child_pid);
-
test_sethwdebug_range_aligned(child_pid);
if (dawr || is_8xx) {
test_sethwdebug_range_unaligned(child_pid);
-- 
2.26.2



[PATCH v4 5/6] powerpc/watchpoint/ptrace: Introduce PPC_DEBUG_FEATURE_DATA_BP_ARCH_31

2020-08-17 Thread Ravi Bangoria
PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 can be used to determine whether
we are running on an ISA 3.1 compliant machine. Which is needed to
determine DAR behaviour, 512 byte boundary limit etc. This was
requested by Pedro Miraglia Franco de Carvalho for extending
watchpoint features in gdb. Note that availability of 2nd DAWR is
independent of this flag and should be checked using
ppc_debug_info->num_data_bps.

Signed-off-by: Ravi Bangoria 
---
 Documentation/powerpc/ptrace.rst  | 1 +
 arch/powerpc/include/uapi/asm/ptrace.h| 1 +
 arch/powerpc/kernel/ptrace/ptrace-noadv.c | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/Documentation/powerpc/ptrace.rst b/Documentation/powerpc/ptrace.rst
index 864d4b61..77725d69eb4a 100644
--- a/Documentation/powerpc/ptrace.rst
+++ b/Documentation/powerpc/ptrace.rst
@@ -46,6 +46,7 @@ features will have bits indicating whether there is support 
for::
   #define PPC_DEBUG_FEATURE_DATA_BP_RANGE  0x4
   #define PPC_DEBUG_FEATURE_DATA_BP_MASK   0x8
   #define PPC_DEBUG_FEATURE_DATA_BP_DAWR   0x10
+  #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_310x20
 
 2. PTRACE_SETHWDEBUG
 
diff --git a/arch/powerpc/include/uapi/asm/ptrace.h 
b/arch/powerpc/include/uapi/asm/ptrace.h
index f5f1ccc740fc..7004cfea3f5f 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -222,6 +222,7 @@ struct ppc_debug_info {
 #define PPC_DEBUG_FEATURE_DATA_BP_RANGE0x0004
 #define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x0008
 #define PPC_DEBUG_FEATURE_DATA_BP_DAWR 0x0010
+#define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31  0x0020
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/ptrace/ptrace-noadv.c 
b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
index 081c39842d84..1d0235db3c1b 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-noadv.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
@@ -57,6 +57,8 @@ void ppc_gethwdinfo(struct ppc_debug_info *dbginfo)
} else {
dbginfo->features = 0;
}
+   if (cpu_has_feature(CPU_FTR_ARCH_31))
+   dbginfo->features |= PPC_DEBUG_FEATURE_DATA_BP_ARCH_31;
 }
 
 int ptrace_get_debugreg(struct task_struct *child, unsigned long addr,
-- 
2.26.2



[PATCH v4 4/6] powerpc/watchpoint: Add hw_len wherever missing

2020-08-17 Thread Ravi Bangoria
There are couple of places where we set len but not hw_len. For
ptrace/perf watchpoints, when CONFIG_HAVE_HW_BREAKPOINT=Y, hw_len
will be calculated and set internally while parsing watchpoint.
But when CONFIG_HAVE_HW_BREAKPOINT=N, we need to manually set
'hw_len'. Similarly for xmon as well, hw_len needs to be set
directly.

Fixes: b57aeab811db ("powerpc/watchpoint: Fix length calculation for unaligned 
target")
Signed-off-by: Ravi Bangoria 
---
 arch/powerpc/kernel/ptrace/ptrace-noadv.c | 1 +
 arch/powerpc/xmon/xmon.c  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/powerpc/kernel/ptrace/ptrace-noadv.c 
b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
index 866597b407bc..081c39842d84 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-noadv.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
@@ -219,6 +219,7 @@ long ppc_set_hwdebug(struct task_struct *child, struct 
ppc_hw_breakpoint *bp_inf
brk.address = ALIGN_DOWN(bp_info->addr, HW_BREAKPOINT_SIZE);
brk.type = HW_BRK_TYPE_TRANSLATE | HW_BRK_TYPE_PRIV_ALL;
brk.len = DABR_MAX_LEN;
+   brk.hw_len = DABR_MAX_LEN;
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
brk.type |= HW_BRK_TYPE_READ;
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index df7bca00f5ec..55c43a6c9111 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -969,6 +969,7 @@ static void insert_cpu_bpts(void)
brk.address = dabr[i].address;
brk.type = (dabr[i].enabled & HW_BRK_TYPE_DABR) | 
HW_BRK_TYPE_PRIV_ALL;
brk.len = 8;
+   brk.hw_len = 8;
__set_breakpoint(i, );
}
}
-- 
2.26.2



[PATCH v4 3/6] powerpc/watchpoint: Fix exception handling for CONFIG_HAVE_HW_BREAKPOINT=N

2020-08-17 Thread Ravi Bangoria
On powerpc, ptrace watchpoint works in one-shot mode. i.e. kernel
disables event every time it fires and user has to re-enable it.
Also, in case of ptrace watchpoint, kernel notifies ptrace user
before executing instruction.

With CONFIG_HAVE_HW_BREAKPOINT=N, kernel is missing to disable
ptrace event and thus it's causing infinite loop of exceptions.
This is especially harmful when user watches on a data which is
also read/written by kernel, eg syscall parameters. In such case,
infinite exceptions happens in kernel mode which causes soft-lockup.

Fixes: 9422de3e953d ("powerpc: Hardware breakpoints rewrite to handle non DABR 
breakpoint registers")
Reported-by: Pedro Miraglia Franco de Carvalho 
Signed-off-by: Ravi Bangoria 
---
 arch/powerpc/include/asm/hw_breakpoint.h  |  3 ++
 arch/powerpc/kernel/process.c | 48 +++
 arch/powerpc/kernel/ptrace/ptrace-noadv.c |  5 +++
 3 files changed, 56 insertions(+)

diff --git a/arch/powerpc/include/asm/hw_breakpoint.h 
b/arch/powerpc/include/asm/hw_breakpoint.h
index f71f08a7e2e0..90d5b3a9f433 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -18,6 +18,7 @@ struct arch_hw_breakpoint {
u16 type;
u16 len; /* length of the target data symbol */
u16 hw_len; /* length programmed in hw */
+   u8  flags;
 };
 
 /* Note: Don't change the first 6 bits below as they are in the same order
@@ -37,6 +38,8 @@ struct arch_hw_breakpoint {
 #define HW_BRK_TYPE_PRIV_ALL   (HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \
 HW_BRK_TYPE_HYP)
 
+#define HW_BRK_FLAG_DISABLED   0x1
+
 /* Minimum granularity */
 #ifdef CONFIG_PPC_8xx
 #define HW_BREAKPOINT_SIZE  0x4
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index e4fcc817c46c..cab6febe6eb6 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -636,6 +636,44 @@ void do_send_trap(struct pt_regs *regs, unsigned long 
address,
(void __user *)address);
 }
 #else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
+
+static void do_break_handler(struct pt_regs *regs)
+{
+   struct arch_hw_breakpoint null_brk = {0};
+   struct arch_hw_breakpoint *info;
+   struct ppc_inst instr = ppc_inst(0);
+   int type = 0;
+   int size = 0;
+   unsigned long ea;
+   int i;
+
+   /*
+* If underneath hw supports only one watchpoint, we know it
+* caused exception. 8xx also falls into this category.
+*/
+   if (nr_wp_slots() == 1) {
+   __set_breakpoint(0, _brk);
+   current->thread.hw_brk[0] = null_brk;
+   current->thread.hw_brk[0].flags |= HW_BRK_FLAG_DISABLED;
+   return;
+   }
+
+   /* Otherwise findout which DAWR caused exception and disable it. */
+   wp_get_instr_detail(regs, , , , );
+
+   for (i = 0; i < nr_wp_slots(); i++) {
+   info = >thread.hw_brk[i];
+   if (!info->address)
+   continue;
+
+   if (wp_check_constraints(regs, instr, ea, type, size, info)) {
+   __set_breakpoint(i, _brk);
+   current->thread.hw_brk[i] = null_brk;
+   current->thread.hw_brk[i].flags |= HW_BRK_FLAG_DISABLED;
+   }
+   }
+}
+
 void do_break (struct pt_regs *regs, unsigned long address,
unsigned long error_code)
 {
@@ -647,6 +685,16 @@ void do_break (struct pt_regs *regs, unsigned long address,
if (debugger_break_match(regs))
return;
 
+   /*
+* We reach here only when watchpoint exception is generated by ptrace
+* event (or hw is buggy!). Now if CONFIG_HAVE_HW_BREAKPOINT is set,
+* watchpoint is already handled by hw_breakpoint_handler() so we don't
+* have to do anything. But when CONFIG_HAVE_HW_BREAKPOINT is not set,
+* we need to manually handle the watchpoint here.
+*/
+   if (!IS_ENABLED(CONFIG_HAVE_HW_BREAKPOINT))
+   do_break_handler(regs);
+
/* Deliver the signal to userspace */
force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)address);
 }
diff --git a/arch/powerpc/kernel/ptrace/ptrace-noadv.c 
b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
index 57a0ab822334..866597b407bc 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-noadv.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
@@ -286,11 +286,16 @@ long ppc_del_hwdebug(struct task_struct *child, long data)
}
return ret;
 #else /* CONFIG_HAVE_HW_BREAKPOINT */
+   if (child->thread.hw_brk[data - 1].flags & HW_BRK_FLAG_DISABLED)
+   goto del;
+
if (child->thread.hw_brk[data - 1].address == 0)
return -ENOENT;
 
+del:
child->thread.hw_brk[data - 1].address = 0;
child->thread.hw_brk[data - 1].type = 0;
+   

[PATCH v4 1/6] powerpc/watchpoint/ptrace: Fix SETHWDEBUG when CONFIG_HAVE_HW_BREAKPOINT=N

2020-08-17 Thread Ravi Bangoria
When kernel is compiled with CONFIG_HAVE_HW_BREAKPOINT=N, user can
still create watchpoint using PPC_PTRACE_SETHWDEBUG, with limited
functionalities. But, such watchpoints are never firing because of
the missing privilege settings. Fix that.

It's safe to set HW_BRK_TYPE_PRIV_ALL because we don't really leak
any kernel address in signal info. Setting HW_BRK_TYPE_PRIV_ALL will
also help to find scenarios when kernel corrupts user memory.

Reported-by: Pedro Miraglia Franco de Carvalho 
Suggested-by: Pedro Miraglia Franco de Carvalho 
Signed-off-by: Ravi Bangoria 
---
 arch/powerpc/kernel/ptrace/ptrace-noadv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/ptrace/ptrace-noadv.c 
b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
index 697c7e4b5877..57a0ab822334 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-noadv.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-noadv.c
@@ -217,7 +217,7 @@ long ppc_set_hwdebug(struct task_struct *child, struct 
ppc_hw_breakpoint *bp_inf
return -EIO;
 
brk.address = ALIGN_DOWN(bp_info->addr, HW_BREAKPOINT_SIZE);
-   brk.type = HW_BRK_TYPE_TRANSLATE;
+   brk.type = HW_BRK_TYPE_TRANSLATE | HW_BRK_TYPE_PRIV_ALL;
brk.len = DABR_MAX_LEN;
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
brk.type |= HW_BRK_TYPE_READ;
-- 
2.26.2



[PATCH v4 2/6] powerpc/watchpoint: Move DAWR detection logic outside of hw_breakpoint.c

2020-08-17 Thread Ravi Bangoria
Power10 hw has multiple DAWRs but hw doesn't tell which DAWR caused
the exception. So we have a sw logic to detect that in hw_breakpoint.c.
But hw_breakpoint.c gets compiled only with CONFIG_HAVE_HW_BREAKPOINT=Y.
Move DAWR detection logic outside of hw_breakpoint.c so that it can be
reused when CONFIG_HAVE_HW_BREAKPOINT is not set.

Signed-off-by: Ravi Bangoria 
---
 arch/powerpc/include/asm/hw_breakpoint.h  |   8 +
 arch/powerpc/kernel/Makefile  |   3 +-
 arch/powerpc/kernel/hw_breakpoint.c   | 149 +
 .../kernel/hw_breakpoint_constraints.c| 152 ++
 4 files changed, 164 insertions(+), 148 deletions(-)
 create mode 100644 arch/powerpc/kernel/hw_breakpoint_constraints.c

diff --git a/arch/powerpc/include/asm/hw_breakpoint.h 
b/arch/powerpc/include/asm/hw_breakpoint.h
index db206a7f38e2..f71f08a7e2e0 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -10,6 +10,7 @@
 #define _PPC_BOOK3S_64_HW_BREAKPOINT_H
 
 #include 
+#include 
 
 #ifdef __KERNEL__
 struct arch_hw_breakpoint {
@@ -51,6 +52,13 @@ static inline int nr_wp_slots(void)
return cpu_has_feature(CPU_FTR_DAWR1) ? 2 : 1;
 }
 
+bool wp_check_constraints(struct pt_regs *regs, struct ppc_inst instr,
+ unsigned long ea, int type, int size,
+ struct arch_hw_breakpoint *info);
+
+void wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr,
+int *type, int *size, unsigned long *ea);
+
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 #include 
 #include 
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index d4d5946224f8..286f85a103de 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -45,7 +45,8 @@ obj-y := cputable.o syscalls.o \
   signal.o sysfs.o cacheinfo.o time.o \
   prom.o traps.o setup-common.o \
   udbg.o misc.o io.o misc_$(BITS).o \
-  of_platform.o prom_parse.o firmware.o
+  of_platform.o prom_parse.o firmware.o \
+  hw_breakpoint_constraints.o
 obj-y  += ptrace/
 obj-$(CONFIG_PPC64)+= setup_64.o \
   paca.o nvram_64.o note.o syscall_64.o
diff --git a/arch/powerpc/kernel/hw_breakpoint.c 
b/arch/powerpc/kernel/hw_breakpoint.c
index 1f4a1efa0074..f4e8f21046f5 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -494,151 +494,6 @@ void thread_change_pc(struct task_struct *tsk, struct 
pt_regs *regs)
}
 }
 
-static bool dar_in_user_range(unsigned long dar, struct arch_hw_breakpoint 
*info)
-{
-   return ((info->address <= dar) && (dar - info->address < info->len));
-}
-
-static bool ea_user_range_overlaps(unsigned long ea, int size,
-  struct arch_hw_breakpoint *info)
-{
-   return ((ea < info->address + info->len) &&
-   (ea + size > info->address));
-}
-
-static bool dar_in_hw_range(unsigned long dar, struct arch_hw_breakpoint *info)
-{
-   unsigned long hw_start_addr, hw_end_addr;
-
-   hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE);
-   hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE);
-
-   return ((hw_start_addr <= dar) && (hw_end_addr > dar));
-}
-
-static bool ea_hw_range_overlaps(unsigned long ea, int size,
-struct arch_hw_breakpoint *info)
-{
-   unsigned long hw_start_addr, hw_end_addr;
-
-   hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE);
-   hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE);
-
-   return ((ea < hw_end_addr) && (ea + size > hw_start_addr));
-}
-
-/*
- * If hw has multiple DAWR registers, we also need to check all
- * dawrx constraint bits to confirm this is _really_ a valid event.
- * If type is UNKNOWN, but privilege level matches, consider it as
- * a positive match.
- */
-static bool check_dawrx_constraints(struct pt_regs *regs, int type,
-   struct arch_hw_breakpoint *info)
-{
-   if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ))
-   return false;
-
-   /*
-* The Cache Management instructions other than dcbz never
-* cause a match. i.e. if type is CACHEOP, the instruction
-* is dcbz, and dcbz is treated as Store.
-*/
-   if ((OP_IS_STORE(type) || type == CACHEOP) && !(info->type & 
HW_BRK_TYPE_WRITE))
-   return false;
-
-   if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL))
-   return false;
-
-   if (user_mode(regs) && !(info->type & HW_BRK_TYPE_USER))
-   return false;
-
-   return true;
-}
-
-/*
- * Return 

[PATCH v4 0/6] powerpc/watchpoint: Bug fixes plus new feature flag

2020-08-17 Thread Ravi Bangoria
Patch #1 fixes a bug about watchpoint not firing when created with
 ptrace PPC_PTRACE_SETHWDEBUG and CONFIG_HAVE_HW_BREAKPOINT=N.
 The fix uses HW_BRK_TYPE_PRIV_ALL for ptrace user which, I
 guess, should be fine because we don't leak any kernel
 addresses and PRIV_ALL will also help to cover scenarios when
 kernel accesses user memory.
Patch #2,#3 fixes infinite exception bug, again the bug happens only
 with CONFIG_HAVE_HW_BREAKPOINT=N.
Patch #4 fixes two places where we are missing to set hw_len.
Patch #5 introduce new feature bit PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
 which will be set when running on ISA 3.1 compliant machine.
Patch #6 finally adds selftest to test scenarios fixed by patch#2,#3
 and also moves MODE_EXACT tests outside of BP_RANGE condition.

Christophe, let me know if this series breaks something for 8xx.

v3: 
https://lore.kernel.org/r/20200805062750.290289-1-ravi.bango...@linux.ibm.com

v3->v4:
  - Patch #1. Allow HW_BRK_TYPE_PRIV_ALL instead of HW_BRK_TYPE_USER
  - Patch #2, #3, #4 and #6 are new.
  - Rebased to powerpc/next.

Ravi Bangoria (6):
  powerpc/watchpoint/ptrace: Fix SETHWDEBUG when
CONFIG_HAVE_HW_BREAKPOINT=N
  powerpc/watchpoint: Move DAWR detection logic outside of
hw_breakpoint.c
  powerpc/watchpoint: Fix exception handling for
CONFIG_HAVE_HW_BREAKPOINT=N
  powerpc/watchpoint: Add hw_len wherever missing
  powerpc/watchpoint/ptrace: Introduce PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
  powerpc/watchpoint/selftests: Tests for kernel accessing user memory

 Documentation/powerpc/ptrace.rst  |   1 +
 arch/powerpc/include/asm/hw_breakpoint.h  |  11 ++
 arch/powerpc/include/uapi/asm/ptrace.h|   1 +
 arch/powerpc/kernel/Makefile  |   3 +-
 arch/powerpc/kernel/hw_breakpoint.c   | 149 +
 .../kernel/hw_breakpoint_constraints.c| 152 ++
 arch/powerpc/kernel/process.c |  48 ++
 arch/powerpc/kernel/ptrace/ptrace-noadv.c |  10 +-
 arch/powerpc/xmon/xmon.c  |   1 +
 .../selftests/powerpc/ptrace/ptrace-hwbreak.c |  48 +-
 10 files changed, 273 insertions(+), 151 deletions(-)
 create mode 100644 arch/powerpc/kernel/hw_breakpoint_constraints.c

-- 
2.26.2



Re: [PATCH] swiotlb: Allow allocating buffer anywhere in memory

2020-08-17 Thread Christoph Hellwig
On Sat, Aug 15, 2020 at 05:45:36PM -0300, Thiago Jung Bauermann wrote:
> POWER secure guests (i.e., guests which use the Protection Execution
> Facility) need to use SWIOTLB to be able to do I/O with the hypervisor, but
> they don't need the SWIOTLB memory to be in low addresses since the
> hypervisor doesn't have any addressing limitation.
> 
> This solves a SWIOTLB initialization problem we are seeing in secure guests
> with 128 GB of RAM: they are configured with 4 GB of crashkernel reserved
> memory, which leaves no space for SWIOTLB in low addresses.

What about just open coding the allocation and using
swiotlb_init_with_tbl?

> 
> Signed-off-by: Thiago Jung Bauermann 
> ---
>  arch/powerpc/mm/mem.c   |  7 ++-
>  include/linux/swiotlb.h |  8 +++-
>  kernel/dma/swiotlb.c| 10 +++---
>  3 files changed, 20 insertions(+), 5 deletions(-)
> 
> Normally I would split changes like this into one patch touching generic
> code and another for the arch-specific part, but in this case I thought it
> would be unneeded complexity. I can split though if people prefer it that
> way.
> 
> diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
> index c2c11eb8dcfc..13f2e3aff8b5 100644
> --- a/arch/powerpc/mm/mem.c
> +++ b/arch/powerpc/mm/mem.c
> @@ -50,6 +50,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  
> @@ -290,7 +291,11 @@ void __init mem_init(void)
>* back to to-down.
>*/
>   memblock_set_bottom_up(true);
> - swiotlb_init(0);
> + /*
> +  * SVM guests can use the SWIOTLB wherever it is in memory,
> +  * even if not DMA-able.
> +  */
> + swiotlb_init_anywhere(0, is_secure_guest());
>  #endif
>  
>   high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 046bb94bd4d6..433f3dbb35b5 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -29,7 +29,13 @@ enum swiotlb_force {
>   */
>  #define IO_TLB_SHIFT 11
>  
> -extern void swiotlb_init(int verbose);
> +void __init swiotlb_init_anywhere(int verbose, bool allocate_anywhere);
> +
> +static inline void swiotlb_init(int verbose)
> +{
> + swiotlb_init_anywhere(verbose, false);
> +}
> +
>  int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>  extern unsigned long swiotlb_nr_tbl(void);
>  unsigned long swiotlb_size_or_default(void);
> diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
> index c19379fabd20..27070aa59e34 100644
> --- a/kernel/dma/swiotlb.c
> +++ b/kernel/dma/swiotlb.c
> @@ -244,7 +244,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long 
> nslabs, int verbose)
>   * structures for the software IO TLB used to implement the DMA API.
>   */
>  void  __init
> -swiotlb_init(int verbose)
> +swiotlb_init_anywhere(int verbose, bool allocate_anywhere)
>  {
>   size_t default_size = IO_TLB_DEFAULT_SIZE;
>   unsigned char *vstart;
> @@ -257,8 +257,12 @@ swiotlb_init(int verbose)
>  
>   bytes = io_tlb_nslabs << IO_TLB_SHIFT;
>  
> - /* Get IO TLB memory from the low pages */
> - vstart = memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE);
> + if (allocate_anywhere)
> + vstart = memblock_alloc(PAGE_ALIGN(bytes), PAGE_SIZE);
> + else
> + /* Get IO TLB memory from the low pages */
> + vstart = memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE);
> +
>   if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
>   return;
>  
---end quoted text---


Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Takashi Iwai
On Mon, 17 Aug 2020 11:18:53 +0200,
Allen Pais wrote:
> 
> >
> > Is this targeted for 5.9 or 5.10?
> 
> This is targeted for 5.9.

Well, then at the next time, please mention it explicitly in the cover
letter.  Usually this kind of API conversion isn't done during rc.  Or
it's done systematically via script or such.  So unless mentioned,
it's not expected to be carried to 5.9.

In anyway, if the final purpose is to drop the old tasklet API and
that's the plan for 5.9, all tree-wide changes have to be done in
5.9 beforehand.  Was that the decision?

> > I have a patch set to drop the whole tasklet usage in sound/*
> > (destined for 5.10, to be submitted soon), so if that's for 5.10,
> > it'll be likely superfluous.
> 
>  I have picked patches from your tree to adapt to this new API.
> Those can be picked in 5.10 I suppose.

Adapting the changes are trivial, don't worry.  It was just a question
of how to organize changes.


thanks,

Takashi


Re: [Virtual ppce500] virtio_gpu virtio0: swiotlb buffer is full

2020-08-17 Thread Christian Zigotzky

Hello

I compiled the RC1 of kernel 5.9 today. Unfortunately the issue with the 
VirtIO-GPU (see below) still exists. Therefore we still need the patch 
(see below) for using the VirtIO-GPU in a virtual e5500 PPC64 QEMU machine.


Could you please check the first bad commit?

Thanks
Christian


On 12 August 2020 at 3:09 pm, Christian Zigotzky wrote:

Hello Daniel,

The VirtIO-GPU doesn't work anymore with the latest Git kernel in a 
virtual e5500 PPC64 QEMU machine [1,2] after the commit "drm/virtio: 
Call the right shmem helpers". [3]

The kernel 5.8 works with the VirtIO-GPU in this virtual machine.

I bisected today [4].

Result: drm/virtio: Call the right shmem helpers ( 
d323bb44e4d23802eb25d13de1f93f2335bd60d0) [3] is the first bad commit.


I was able to revert the first bad commit. [5] After that I compiled a 
new kernel again. Then I was able to boot Linux with this kernel in a 
virtual e5500 PPC64 QEMU machine with the VirtIO-GPU.


I created a patch. [6] With this patch I can use the VirtIO-GPU again.

Could you please check the first bad commit?

Thanks,
Christian

[1] QEMU command: qemu-system-ppc64 -M ppce500 -cpu e5500 -enable-kvm 
-m 1024 -kernel uImage -drive 
format=raw,file=fienix-soar_3.0-2020608-net.img,index=0,if=virtio -nic 
user,model=e1000 -append "rw root=/dev/vda2" -device virtio-vga 
-device virtio-mouse-pci -device virtio-keyboard-pci -device 
pci-ohci,id=newusb -device usb-audio,bus=newusb.0 -smp 4


[2] Error messages:

virtio_gpu virtio0: swiotlb buffer is full (sz: 4096 bytes), total 0 
(slots), used 0 (slots)

BUG: Kernel NULL pointer dereference on read at 0x0010
Faulting instruction address: 0xc00c7324
Oops: Kernel access of bad area, sig: 11 [#1]
BE PAGE_SIZE=4K PREEMPT SMP NR_CPUS=4 QEMU e500
Modules linked in:
CPU: 2 PID: 1678 Comm: kworker/2:2 Not tainted 
5.9-a3_A-EON_X5000-11735-g06a81c1c7db9-dirty #1

Workqueue: events .virtio_gpu_dequeue_ctrl_func
NIP:  c00c7324 LR: c00c72e4 CTR: c0462930
REGS: c0003dba75e0 TRAP: 0300   Not tainted 
(5.9-a3_A-EON_X5000-11735-g06a81c1c7db9-dirty)

MSR:  90029000   CR: 24002288  XER: 
DEAR: 0010 ESR:  IRQMASK: 0
GPR00: c00c6188 c0003dba7870 c17f2300 
c0003d893010
GPR04:  0001  

GPR08:    
7f7f7f7f7f7f7f7f
GPR12: 24002284 c0003fff9200 c008c3a0 
c61566c0
GPR16:    

GPR20:    

GPR24: 0001 0011  

GPR28: c0003d893010   
c0003d893010

NIP [c00c7324] .dma_direct_unmap_sg+0x4c/0xd8
LR [c00c72e4] .dma_direct_unmap_sg+0xc/0xd8
Call Trace:
[c0003dba7870] [c0003dba7950] 0xc0003dba7950 (unreliable)
[c0003dba7920] [c00c6188] .dma_unmap_sg_attrs+0x5c/0x98
[c0003dba79d0] [c05cd438] 
.drm_gem_shmem_free_object+0x98/0xcc
[c0003dba7a50] [c06af5b4] 
.virtio_gpu_cleanup_object+0xc8/0xd4

[c0003dba7ad0] [c06ad3bc] .virtio_gpu_cmd_unref_cb+0x1c/0x30
[c0003dba7b40] [c06adab8] 
.virtio_gpu_dequeue_ctrl_func+0x208/0x28c

[c0003dba7c10] [c0086b70] .process_one_work+0x1a4/0x258
[c0003dba7cb0] [c00870f4] .worker_thread+0x214/0x284
[c0003dba7d70] [c008c4f0] .kthread+0x150/0x158
[c0003dba7e20] [c82c] .ret_from_kernel_thread+0x58/0x60
Instruction dump:
f821ff51 7cb82b78 7cdb3378 4e00 7cfa3b78 3bc0 7f9ec000 41fc0014
382100b0 81810008 7d808120 48bc1ba8  ebfc0248 833d0018 7fff4850
---[ end trace f28d194d9f0955a8 ]---

virtio_gpu virtio0: swiotlb buffer is full (sz: 4096 bytes), total 0 
(slots), used 0 (slots)
virtio_gpu virtio0: swiotlb buffer is full (sz: 16384 bytes), total 0 
(slots), used 0 (slots)


---

[3] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d323bb44e4d23802eb25d13de1f93f2335bd60d0


[4] https://forum.hyperion-entertainment.com/viewtopic.php?p=51377#p51377

[5] git revert d323bb44e4d23802eb25d13de1f93f2335bd60d0 //Output: 
[master 966950f724e4] Revert "drm/virtio: Call the right shmem 
helpers" 1 file changed, 1 insertion(+), 1 deletion(-)


[6]
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c 
b/drivers/gpu/drm/virtio/virtgpu_object.c

index 6ccbd01cd888..346cef5ce251 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -150,7 +150,7 @@ static int virtio_gpu_object_shmem_init(struct 
virtio_gpu_device *vgdev,

 if (ret < 0)
 return -EINVAL;

-    shmem->pages = drm_gem_shmem_get_pages_sgt(>base.base);
+    shmem->pages = drm_gem_shmem_get_sg_table(>base.base);
 if (!shmem->pages) {
 drm_gem_shmem_unpin(>base.base);
 

Re: [PATCH 00/10] sound: convert tasklets to use new tasklet_setup()

2020-08-17 Thread Takashi Iwai
On Mon, 17 Aug 2020 10:56:53 +0200,
Allen Pais wrote:
> 
> From: Allen Pais 
> 
> Commit 12cc923f1ccc ("tasklet: Introduce new initialization API")'
> introduced a new tasklet initialization API. This series converts 
> all the sound drivers to use the new tasklet_setup() API

Is this targeted for 5.9 or 5.10?

I have a patch set to drop the whole tasklet usage in sound/*
(destined for 5.10, to be submitted soon), so if that's for 5.10,
it'll be likely superfluous.


thanks,

Takashi


[PATCH 20/20] ethernet: smsc: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/smsc/smc91x.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/smsc/smc91x.c 
b/drivers/net/ethernet/smsc/smc91x.c
index 1c4fea9c3ec4..7e585aa3031c 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -535,10 +535,10 @@ static inline void  smc_rcv(struct net_device *dev)
 /*
  * This is called to actually send a packet to the chip.
  */
-static void smc_hardware_send_pkt(unsigned long data)
+static void smc_hardware_send_pkt(struct tasklet_struct *t)
 {
-   struct net_device *dev = (struct net_device *)data;
-   struct smc_local *lp = netdev_priv(dev);
+   struct smc_local *lp = from_tasklet(lp, t, tx_task);
+   struct net_device *dev = lp->dev;
void __iomem *ioaddr = lp->base;
struct sk_buff *skb;
unsigned int packet_no, len;
@@ -688,7 +688,7 @@ smc_hard_start_xmit(struct sk_buff *skb, struct net_device 
*dev)
 * Allocation succeeded: push packet to the chip's own memory
 * immediately.
 */
-   smc_hardware_send_pkt((unsigned long)dev);
+   smc_hardware_send_pkt(>tx_task);
}
 
return NETDEV_TX_OK;
@@ -1965,7 +1965,7 @@ static int smc_probe(struct net_device *dev, void __iomem 
*ioaddr,
dev->netdev_ops = _netdev_ops;
dev->ethtool_ops = _ethtool_ops;
 
-   tasklet_init(>tx_task, smc_hardware_send_pkt, (unsigned long)dev);
+   tasklet_setup(>tx_task, smc_hardware_send_pkt);
INIT_WORK(>phy_configure, smc_phy_configure);
lp->dev = dev;
lp->mii.phy_id_mask = 0x1f;
-- 
2.17.1



[PATCH 19/20] ethernet: silan: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/silan/sc92031.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/silan/sc92031.c 
b/drivers/net/ethernet/silan/sc92031.c
index f94078f8ebe5..8d56eca5be17 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -829,10 +829,11 @@ static void _sc92031_link_tasklet(struct net_device *dev)
}
 }
 
-static void sc92031_tasklet(unsigned long data)
+static void sc92031_tasklet(struct tasklet_struct *t)
 {
-   struct net_device *dev = (struct net_device *)data;
-   struct sc92031_priv *priv = netdev_priv(dev);
+   struct  sc92031_priv *priv = from_tasklet(priv, t, tasklet);
+   struct net_device *dev = (struct net_device *)((char *)priv -
+   ALIGN(sizeof(struct net_device), NETDEV_ALIGN));
void __iomem *port_base = priv->port_base;
u32 intr_status, intr_mask;
 
@@ -1108,7 +1109,7 @@ static void sc92031_poll_controller(struct net_device 
*dev)
 
disable_irq(irq);
if (sc92031_interrupt(irq, dev) != IRQ_NONE)
-   sc92031_tasklet((unsigned long)dev);
+   sc92031_tasklet(>tasklet);
enable_irq(irq);
 }
 #endif
@@ -1446,7 +1447,7 @@ static int sc92031_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
spin_lock_init(>lock);
priv->port_base = port_base;
priv->pdev = pdev;
-   tasklet_init(>tasklet, sc92031_tasklet, (unsigned long)dev);
+   tasklet_setup(>tasklet, sc92031_tasklet);
/* Fudge tasklet count so the call to sc92031_enable_interrupts at
 * sc92031_open will work correctly */
tasklet_disable_nosync(>tasklet);
-- 
2.17.1



[PATCH 18/20] ethernet: qlogic: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/qlogic/qed/qed.h  |  2 +-
 drivers/net/ethernet/qlogic/qed/qed_int.c  | 27 +++---
 drivers/net/ethernet/qlogic/qed/qed_int.h  |  2 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c | 14 +--
 4 files changed, 12 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index b2a7b53ee760..22bc4ec7859a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -572,7 +572,7 @@ struct qed_hwfn {
struct qed_consq*p_consq;
 
/* Slow-Path definitions */
-   struct tasklet_struct   *sp_dpc;
+   struct tasklet_struct   sp_dpc;
boolb_sp_dpc_enabled;
 
struct qed_ptt  *p_main_ptt;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c 
b/drivers/net/ethernet/qlogic/qed/qed_int.c
index f8c5a864812d..578935f643b8 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -1216,9 +1216,9 @@ static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn,
barrier();
 }
 
-void qed_int_sp_dpc(unsigned long hwfn_cookie)
+void qed_int_sp_dpc(struct tasklet_struct *t)
 {
-   struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie;
+   struct qed_hwfn *p_hwfn = from_tasklet(p_hwfn, t, sp_dpc);
struct qed_pi_info *pi_info = NULL;
struct qed_sb_attn_info *sb_attn;
struct qed_sb_info *sb_info;
@@ -2285,34 +2285,14 @@ u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn)
 
 static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn)
 {
-   tasklet_init(p_hwfn->sp_dpc,
-qed_int_sp_dpc, (unsigned long)p_hwfn);
+   tasklet_setup(_hwfn->sp_dpc, qed_int_sp_dpc);
p_hwfn->b_sp_dpc_enabled = true;
 }
 
-static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn)
-{
-   p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_KERNEL);
-   if (!p_hwfn->sp_dpc)
-   return -ENOMEM;
-
-   return 0;
-}
-
-static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn)
-{
-   kfree(p_hwfn->sp_dpc);
-   p_hwfn->sp_dpc = NULL;
-}
-
 int qed_int_alloc(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
int rc = 0;
 
-   rc = qed_int_sp_dpc_alloc(p_hwfn);
-   if (rc)
-   return rc;
-
rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt);
if (rc)
return rc;
@@ -2326,7 +2306,6 @@ void qed_int_free(struct qed_hwfn *p_hwfn)
 {
qed_int_sp_sb_free(p_hwfn);
qed_int_sb_attn_free(p_hwfn);
-   qed_int_sp_dpc_free(p_hwfn);
 }
 
 void qed_int_setup(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h 
b/drivers/net/ethernet/qlogic/qed/qed_int.h
index 86809d7bc2de..c5550e96bbe1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_int.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_int.h
@@ -140,7 +140,7 @@ int qed_int_sb_release(struct qed_hwfn *p_hwfn,
  * @param p_hwfn - pointer to hwfn
  *
  */
-void qed_int_sp_dpc(unsigned long hwfn_cookie);
+void qed_int_sp_dpc(struct tasklet_struct *t);
 
 /**
  * @brief qed_int_get_num_sbs - get the number of status
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 2558cb680db3..4c4dd4e88fb1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -841,7 +841,7 @@ static irqreturn_t qed_single_int(int irq, void 
*dev_instance)
 
/* Slowpath interrupt */
if (unlikely(status & 0x1)) {
-   tasklet_schedule(hwfn->sp_dpc);
+   tasklet_schedule(>sp_dpc);
status &= ~0x1;
rc = IRQ_HANDLED;
}
@@ -887,7 +887,7 @@ int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
 id, cdev->pdev->bus->number,
 PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
rc = request_irq(cdev->int_params.msix_table[id].vector,
-qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc);
+qed_msix_sp_int, 0, hwfn->name, >sp_dpc);
} else {
unsigned long flags = 0;
 
@@ -919,8 +919,8 @@ static void qed_slowpath_tasklet_flush(struct qed_hwfn 
*p_hwfn)
 * enable function makes this sequence a flush-like operation.
 */
if (p_hwfn->b_sp_dpc_enabled) {
-   tasklet_disable(p_hwfn->sp_dpc);
-   tasklet_enable(p_hwfn->sp_dpc);
+   tasklet_disable(_hwfn->sp_dpc);
+   

[PATCH 17/20] ethernet: ni: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/ni/nixge.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index 4075f5e59955..a6861df9904f 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -787,9 +787,9 @@ static irqreturn_t nixge_rx_irq(int irq, void *_ndev)
return IRQ_HANDLED;
 }
 
-static void nixge_dma_err_handler(unsigned long data)
+static void nixge_dma_err_handler(struct tasklet_struct *t)
 {
-   struct nixge_priv *lp = (struct nixge_priv *)data;
+   struct nixge_priv *lp = from_tasklet(lp, t, dma_err_tasklet);
struct nixge_hw_dma_bd *cur_p;
struct nixge_tx_skb *tx_skb;
u32 cr, i;
@@ -879,8 +879,7 @@ static int nixge_open(struct net_device *ndev)
phy_start(phy);
 
/* Enable tasklets for Axi DMA error handling */
-   tasklet_init(>dma_err_tasklet, nixge_dma_err_handler,
-(unsigned long)priv);
+   tasklet_setup(>dma_err_tasklet, nixge_dma_err_handler);
 
napi_enable(>napi);
 
-- 
2.17.1



[PATCH 16/20] ethernet: netronome: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c 
b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 39ee23e8c0bf..1dcd24d899f5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2287,9 +2287,9 @@ static bool nfp_ctrl_rx(struct nfp_net_r_vector *r_vec)
return budget;
 }
 
-static void nfp_ctrl_poll(unsigned long arg)
+static void nfp_ctrl_poll(struct tasklet_struct *t)
 {
-   struct nfp_net_r_vector *r_vec = (void *)arg;
+   struct nfp_net_r_vector *r_vec = from_tasklet(r_vec, t, tasklet);
 
spin_lock(_vec->lock);
nfp_net_tx_complete(r_vec->tx_ring, 0);
@@ -2337,8 +2337,7 @@ static void nfp_net_vecs_init(struct nfp_net *nn)
 
__skb_queue_head_init(_vec->queue);
spin_lock_init(_vec->lock);
-   tasklet_init(_vec->tasklet, nfp_ctrl_poll,
-(unsigned long)r_vec);
+   tasklet_setup(_vec->tasklet, nfp_ctrl_poll);
tasklet_disable(_vec->tasklet);
}
 
-- 
2.17.1



[PATCH 15/20] ethernet: natsemi: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/natsemi/ns83820.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/natsemi/ns83820.c 
b/drivers/net/ethernet/natsemi/ns83820.c
index 8e24c7acf79b..9157c1bffc79 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -923,10 +923,10 @@ static void rx_irq(struct net_device *ndev)
spin_unlock_irqrestore(>lock, flags);
 }
 
-static void rx_action(unsigned long _dev)
+static void rx_action(struct tasklet_struct *t)
 {
-   struct net_device *ndev = (void *)_dev;
-   struct ns83820 *dev = PRIV(ndev);
+   struct ns83820 *dev = from_tasklet(dev, t, rx_tasklet);
+   struct net_device *ndev = dev->ndev;
rx_irq(ndev);
writel(ihr, dev->base + IHR);
 
@@ -1927,7 +1927,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev,
SET_NETDEV_DEV(ndev, _dev->dev);
 
INIT_WORK(>tq_refill, queue_refill);
-   tasklet_init(>rx_tasklet, rx_action, (unsigned long)ndev);
+   tasklet_setup(>rx_tasklet, rx_action);
 
err = pci_enable_device(pci_dev);
if (err) {
-- 
2.17.1



[PATCH 14/20] ethernet: micrel: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/micrel/ks8842.c  | 19 ++-
 drivers/net/ethernet/micrel/ksz884x.c | 14 ++
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/micrel/ks8842.c 
b/drivers/net/ethernet/micrel/ks8842.c
index f3f6dfe3eddc..8fd32f98c494 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -587,10 +587,11 @@ static int __ks8842_start_new_rx_dma(struct net_device 
*netdev)
return err;
 }
 
-static void ks8842_rx_frame_dma_tasklet(unsigned long arg)
+static void ks8842_rx_frame_dma_tasklet(struct tasklet_struct *t)
 {
-   struct net_device *netdev = (struct net_device *)arg;
-   struct ks8842_adapter *adapter = netdev_priv(netdev);
+   struct ks8842_adapter *adapter = from_tasklet(adapter, t, 
dma_rx.tasklet);
+   struct net_device *netdev = (struct net_device *)((char *)adapter -
+   ALIGN(sizeof(struct net_device), NETDEV_ALIGN));
struct ks8842_rx_dma_ctl *ctl = >dma_rx;
struct sk_buff *skb = ctl->skb;
dma_addr_t addr = sg_dma_address(>sg);
@@ -720,10 +721,11 @@ static void ks8842_handle_rx_overrun(struct net_device 
*netdev,
netdev->stats.rx_fifo_errors++;
 }
 
-static void ks8842_tasklet(unsigned long arg)
+static void ks8842_tasklet(struct tasklet_struct *t)
 {
-   struct net_device *netdev = (struct net_device *)arg;
-   struct ks8842_adapter *adapter = netdev_priv(netdev);
+   struct ks8842_adapter *adapter = from_tasklet(adapter, t, tasklet);
+   struct net_device *netdev = (struct net_device *)((char *)adapter -
+   ALIGN(sizeof(struct net_device), NETDEV_ALIGN));
u16 isr;
unsigned long flags;
u16 entry_bank;
@@ -953,8 +955,7 @@ static int ks8842_alloc_dma_bufs(struct net_device *netdev)
goto err;
}
 
-   tasklet_init(_ctl->tasklet, ks8842_rx_frame_dma_tasklet,
-   (unsigned long)netdev);
+   tasklet_setup(_ctl->tasklet, ks8842_rx_frame_dma_tasklet);
 
return 0;
 err:
@@ -1173,7 +1174,7 @@ static int ks8842_probe(struct platform_device *pdev)
adapter->dma_tx.channel = -1;
}
 
-   tasklet_init(>tasklet, ks8842_tasklet, (unsigned long)netdev);
+   tasklet_setup(>tasklet, ks8842_tasklet);
spin_lock_init(>lock);
 
netdev->netdev_ops = _netdev_ops;
diff --git a/drivers/net/ethernet/micrel/ksz884x.c 
b/drivers/net/ethernet/micrel/ksz884x.c
index bb646b65cc95..5130507bbf54 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -5159,9 +5159,9 @@ static int dev_rcv_special(struct dev_info *hw_priv)
return received;
 }
 
-static void rx_proc_task(unsigned long data)
+static void rx_proc_task(struct tasklet_struct *t)
 {
-   struct dev_info *hw_priv = (struct dev_info *) data;
+   struct dev_info *hw_priv = from_tasklet(hw_priv, t, rx_tasklet);
struct ksz_hw *hw = _priv->hw;
 
if (!hw->enabled)
@@ -5181,9 +5181,9 @@ static void rx_proc_task(unsigned long data)
}
 }
 
-static void tx_proc_task(unsigned long data)
+static void tx_proc_task(struct tasklet_struct *t)
 {
-   struct dev_info *hw_priv = (struct dev_info *) data;
+   struct dev_info *hw_priv = from_tasklet(hw_priv, t, tx_tasklet);
struct ksz_hw *hw = _priv->hw;
 
hw_ack_intr(hw, KS884X_INT_TX_MASK);
@@ -5436,10 +5436,8 @@ static int prepare_hardware(struct net_device *dev)
rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
if (rc)
return rc;
-   tasklet_init(_priv->rx_tasklet, rx_proc_task,
-(unsigned long) hw_priv);
-   tasklet_init(_priv->tx_tasklet, tx_proc_task,
-(unsigned long) hw_priv);
+   tasklet_setup(_priv->rx_tasklet, rx_proc_task);
+   tasklet_setup(_priv->tx_tasklet, tx_proc_task);
 
hw->promiscuous = 0;
hw->all_multi = 0;
-- 
2.17.1



[PATCH 13/20] ethernet: mellanox: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/mellanox/mlx4/cq.c |  4 ++--
 drivers/net/ethernet/mellanox/mlx4/eq.c |  3 +--
 drivers/net/ethernet/mellanox/mlx4/mlx4.h   |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/cq.c|  4 ++--
 drivers/net/ethernet/mellanox/mlx5/core/eq.c|  3 +--
 drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c |  7 +++
 drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h|  2 +-
 drivers/net/ethernet/mellanox/mlxsw/pci.c   | 12 ++--
 8 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c 
b/drivers/net/ethernet/mellanox/mlx4/cq.c
index 65f8a4b6ed0c..3b8576b9c2f9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -55,11 +55,11 @@
 #define TASKLET_MAX_TIME 2
 #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME)
 
-void mlx4_cq_tasklet_cb(unsigned long data)
+void mlx4_cq_tasklet_cb(struct tasklet_struct *t)
 {
unsigned long flags;
unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES;
-   struct mlx4_eq_tasklet *ctx = (struct mlx4_eq_tasklet *)data;
+   struct mlx4_eq_tasklet *ctx = from_tasklet(ctx, t, task);
struct mlx4_cq *mcq, *temp;
 
spin_lock_irqsave(>lock, flags);
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c 
b/drivers/net/ethernet/mellanox/mlx4/eq.c
index ae305c2e9225..9e48509ed3b2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -1057,8 +1057,7 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
INIT_LIST_HEAD(>tasklet_ctx.list);
INIT_LIST_HEAD(>tasklet_ctx.process_list);
spin_lock_init(>tasklet_ctx.lock);
-   tasklet_init(>tasklet_ctx.task, mlx4_cq_tasklet_cb,
-(unsigned long)>tasklet_ctx);
+   tasklet_setup(>tasklet_ctx.task, mlx4_cq_tasklet_cb);
 
return err;
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h 
b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 527b52e48276..64bed7ac3836 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -1217,7 +1217,7 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev);
 int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param,
  u16 op, unsigned long timeout);
 
-void mlx4_cq_tasklet_cb(unsigned long data);
+void mlx4_cq_tasklet_cb(struct tasklet_struct *t);
 void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn);
 void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type);
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c 
b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
index 8379b24cb838..df3e4938ecdd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c
@@ -42,11 +42,11 @@
 #define TASKLET_MAX_TIME 2
 #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME)
 
-void mlx5_cq_tasklet_cb(unsigned long data)
+void mlx5_cq_tasklet_cb(struct tasklet_struct *t)
 {
unsigned long flags;
unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES;
-   struct mlx5_eq_tasklet *ctx = (struct mlx5_eq_tasklet *)data;
+   struct mlx5_eq_tasklet *ctx = from_tasklet(ctx, t, task);
struct mlx5_core_cq *mcq;
struct mlx5_core_cq *temp;
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 31ef9f8420c8..ec38405d467f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -788,8 +788,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
INIT_LIST_HEAD(>tasklet_ctx.list);
INIT_LIST_HEAD(>tasklet_ctx.process_list);
spin_lock_init(>tasklet_ctx.lock);
-   tasklet_init(>tasklet_ctx.task, mlx5_cq_tasklet_cb,
-(unsigned long)>tasklet_ctx);
+   tasklet_setup(>tasklet_ctx.task, mlx5_cq_tasklet_cb);
 
eq->irq_nb.notifier_call = mlx5_eq_comp_int;
param = (struct mlx5_eq_param) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c 
b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
index 831d2c39e153..9f6d97eae0ae 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
@@ -388,9 +388,9 @@ static inline void mlx5_fpga_conn_cqes(struct 
mlx5_fpga_conn *conn,
mlx5_fpga_conn_arm_cq(conn);
 }
 
-static void mlx5_fpga_conn_cq_tasklet(unsigned long data)
+static void mlx5_fpga_conn_cq_tasklet(struct tasklet_struct *t)
 {
-   struct mlx5_fpga_conn *conn = 

[PATCH 12/20] ethernet: marvell: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/marvell/skge.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/skge.c 
b/drivers/net/ethernet/marvell/skge.c
index b792f6306a64..55fe901d3562 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3338,9 +3338,9 @@ static void skge_error_irq(struct skge_hw *hw)
  * because accessing phy registers requires spin wait which might
  * cause excess interrupt latency.
  */
-static void skge_extirq(unsigned long arg)
+static void skge_extirq(struct tasklet_struct *t)
 {
-   struct skge_hw *hw = (struct skge_hw *) arg;
+   struct skge_hw *hw = from_tasklet(hw, t, phy_task);
int port;
 
for (port = 0; port < hw->ports; port++) {
@@ -3927,7 +3927,7 @@ static int skge_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
hw->pdev = pdev;
spin_lock_init(>hw_lock);
spin_lock_init(>phy_lock);
-   tasklet_init(>phy_task, skge_extirq, (unsigned long) hw);
+   tasklet_setup(>phy_task, skge_extirq);
 
hw->regs = ioremap(pci_resource_start(pdev, 0), 0x4000);
if (!hw->regs) {
-- 
2.17.1



[PATCH 11/20] ethernet: jme: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/jme.c | 40 +++---
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index ddc757680089..e9efe074edc1 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1187,9 +1187,9 @@ jme_shutdown_nic(struct jme_adapter *jme)
 }
 
 static void
-jme_pcc_tasklet(unsigned long arg)
+jme_pcc_tasklet(struct tasklet_struct *t)
 {
-   struct jme_adapter *jme = (struct jme_adapter *)arg;
+   struct jme_adapter *jme = from_tasklet(jme, t, pcc_task);
struct net_device *netdev = jme->dev;
 
if (unlikely(test_bit(JME_FLAG_SHUTDOWN, >flags))) {
@@ -1265,10 +1265,9 @@ jme_stop_shutdown_timer(struct jme_adapter *jme)
jwrite32f(jme, JME_APMC, apmc);
 }
 
-static void
-jme_link_change_tasklet(unsigned long arg)
+static void jme_link_change_tasklet(struct tasklet_struct *t)
 {
-   struct jme_adapter *jme = (struct jme_adapter *)arg;
+   struct jme_adapter *jme = from_tasklet(jme, t, linkch_task);
struct net_device *netdev = jme->dev;
int rc;
 
@@ -1345,9 +1344,9 @@ jme_link_change_tasklet(unsigned long arg)
 }
 
 static void
-jme_rx_clean_tasklet(unsigned long arg)
+jme_rx_clean_tasklet(struct tasklet_struct *t)
 {
-   struct jme_adapter *jme = (struct jme_adapter *)arg;
+   struct jme_adapter *jme = from_tasklet(jme, t, rxclean_task);
struct dynpcc_info *dpi = &(jme->dpi);
 
jme_process_receive(jme, jme->rx_ring_size);
@@ -1380,9 +1379,9 @@ jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget))
 }
 
 static void
-jme_rx_empty_tasklet(unsigned long arg)
+jme_rx_empty_tasklet(struct tasklet_struct *t)
 {
-   struct jme_adapter *jme = (struct jme_adapter *)arg;
+   struct jme_adapter *jme = from_tasklet(jme, t, rxempty_task);
 
if (unlikely(atomic_read(>link_changing) != 1))
return;
@@ -1392,7 +1391,7 @@ jme_rx_empty_tasklet(unsigned long arg)
 
netif_info(jme, rx_status, jme->dev, "RX Queue Full!\n");
 
-   jme_rx_clean_tasklet(arg);
+   jme_rx_clean_tasklet(>rxclean_task);
 
while (atomic_read(>rx_empty) > 0) {
atomic_dec(>rx_empty);
@@ -1416,10 +1415,9 @@ jme_wake_queue_if_stopped(struct jme_adapter *jme)
 
 }
 
-static void
-jme_tx_clean_tasklet(unsigned long arg)
+static void jme_tx_clean_tasklet(struct tasklet_struct *t)
 {
-   struct jme_adapter *jme = (struct jme_adapter *)arg;
+   struct jme_adapter *jme = from_tasklet(jme, t, txclean_task);
struct jme_ring *txring = &(jme->txring[0]);
struct txdesc *txdesc = txring->desc;
struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi;
@@ -1834,14 +1832,10 @@ jme_open(struct net_device *netdev)
jme_clear_pm_disable_wol(jme);
JME_NAPI_ENABLE(jme);
 
-   tasklet_init(>linkch_task, jme_link_change_tasklet,
-(unsigned long) jme);
-   tasklet_init(>txclean_task, jme_tx_clean_tasklet,
-(unsigned long) jme);
-   tasklet_init(>rxclean_task, jme_rx_clean_tasklet,
-(unsigned long) jme);
-   tasklet_init(>rxempty_task, jme_rx_empty_tasklet,
-(unsigned long) jme);
+   tasklet_setup(>linkch_task, jme_link_change_tasklet);
+   tasklet_setup(>txclean_task, jme_tx_clean_tasklet);
+   tasklet_setup(>rxclean_task, jme_rx_clean_tasklet);
+   tasklet_setup(>rxempty_task, jme_rx_empty_tasklet);
 
rc = jme_request_irq(jme);
if (rc)
@@ -3040,9 +3034,7 @@ jme_init_one(struct pci_dev *pdev,
atomic_set(>tx_cleaning, 1);
atomic_set(>rx_empty, 1);
 
-   tasklet_init(>pcc_task,
-jme_pcc_tasklet,
-(unsigned long) jme);
+   tasklet_setup(>pcc_task, jme_pcc_tasklet);
jme->dpi.cur = PCC_P1;
 
jme->reg_ghc = 0;
-- 
2.17.1



[PATCH 10/20] ethernet: ibmvnic: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/ibm/ibmvnic.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
b/drivers/net/ethernet/ibm/ibmvnic.c
index 5afb3c9c52d2..7c565e167521 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -4797,9 +4797,9 @@ static irqreturn_t ibmvnic_interrupt(int irq, void 
*instance)
return IRQ_HANDLED;
 }
 
-static void ibmvnic_tasklet(void *data)
+static void ibmvnic_tasklet(struct tasklet_struct *t)
 {
-   struct ibmvnic_adapter *adapter = data;
+   struct ibmvnic_adapter *adapter = from_tasklet(adapter, t, tasklet);
struct ibmvnic_crq_queue *queue = >crq;
union ibmvnic_crq *crq;
unsigned long flags;
@@ -4934,8 +4934,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter)
 
retrc = 0;
 
-   tasklet_init(>tasklet, (void *)ibmvnic_tasklet,
-(unsigned long)adapter);
+   tasklet_setup(>tasklet, (void *)ibmvnic_tasklet);
 
netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq);
snprintf(crq->name, sizeof(crq->name), "ibmvnic-%x",
-- 
2.17.1



[PATCH 09/20] ethernet: ehea: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/ibm/ehea/ehea_main.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c 
b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 0273fb7a9d01..f3d104fec7e9 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -1212,9 +1212,9 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, 
u64 eqe)
}
 }
 
-static void ehea_neq_tasklet(unsigned long data)
+static void ehea_neq_tasklet(struct tasklet_struct *t)
 {
-   struct ehea_adapter *adapter = (struct ehea_adapter *)data;
+   struct ehea_adapter *adapter = from_tasklet(adapter, t, neq_tasklet);
struct ehea_eqe *eqe;
u64 event_mask;
 
@@ -3417,8 +3417,7 @@ static int ehea_probe_adapter(struct platform_device *dev)
goto out_free_ad;
}
 
-   tasklet_init(>neq_tasklet, ehea_neq_tasklet,
-(unsigned long)adapter);
+   tasklet_setup(>neq_tasklet, ehea_neq_tasklet);
 
ret = ehea_create_device_sysfs(dev);
if (ret)
-- 
2.17.1



[PATCH 08/20] ethernet: hinic: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c 
b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
index ca8cb68a8d20..f304a5b16d75 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
@@ -370,9 +370,9 @@ static void eq_irq_work(struct work_struct *work)
  * ceq_tasklet - the tasklet of the EQ that received the event
  * @ceq_data: the eq
  **/
-static void ceq_tasklet(unsigned long ceq_data)
+static void ceq_tasklet(struct tasklet_struct *t)
 {
-   struct hinic_eq *ceq = (struct hinic_eq *)ceq_data;
+   struct hinic_eq *ceq = from_tasklet(ceq, t, ceq_tasklet);
 
eq_irq_handler(ceq);
 }
@@ -782,8 +782,7 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif 
*hwif,
 
INIT_WORK(_work->work, eq_irq_work);
} else if (type == HINIC_CEQ) {
-   tasklet_init(>ceq_tasklet, ceq_tasklet,
-(unsigned long)eq);
+   tasklet_setup(>ceq_tasklet, ceq_tasklet);
}
 
/* set the attributes of the msix entry */
-- 
2.17.1



[PATCH 07/20] ethernet: dlink: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/dlink/sundance.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/dlink/sundance.c 
b/drivers/net/ethernet/dlink/sundance.c
index b3f8597e77aa..58022396b053 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -429,8 +429,8 @@ static void init_ring(struct net_device *dev);
 static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev);
 static int reset_tx (struct net_device *dev);
 static irqreturn_t intr_handler(int irq, void *dev_instance);
-static void rx_poll(unsigned long data);
-static void tx_poll(unsigned long data);
+static void rx_poll(struct tasklet_struct *t);
+static void tx_poll(struct tasklet_struct *t);
 static void refill_rx (struct net_device *dev);
 static void netdev_error(struct net_device *dev, int intr_status);
 static void netdev_error(struct net_device *dev, int intr_status);
@@ -537,8 +537,8 @@ static int sundance_probe1(struct pci_dev *pdev,
np->msg_enable = (1 << debug) - 1;
spin_lock_init(>lock);
spin_lock_init(>statlock);
-   tasklet_init(>rx_tasklet, rx_poll, (unsigned long)dev);
-   tasklet_init(>tx_tasklet, tx_poll, (unsigned long)dev);
+   tasklet_setup(>rx_tasklet, rx_poll);
+   tasklet_setup(>tx_tasklet, tx_poll);
 
ring_space = dma_alloc_coherent(>dev, TX_TOTAL_SIZE,
_dma, GFP_KERNEL);
@@ -1054,10 +1054,9 @@ static void init_ring(struct net_device *dev)
}
 }
 
-static void tx_poll (unsigned long data)
+static void tx_poll(struct tasklet_struct *t)
 {
-   struct net_device *dev = (struct net_device *)data;
-   struct netdev_private *np = netdev_priv(dev);
+   struct netdev_private *np = from_tasklet(np, t, tx_tasklet);
unsigned head = np->cur_task % TX_RING_SIZE;
struct netdev_desc *txdesc =
>tx_ring[(np->cur_tx - 1) % TX_RING_SIZE];
@@ -1312,10 +1311,11 @@ static irqreturn_t intr_handler(int irq, void 
*dev_instance)
return IRQ_RETVAL(handled);
 }
 
-static void rx_poll(unsigned long data)
+static void rx_poll(struct tasklet_struct *t)
 {
-   struct net_device *dev = (struct net_device *)data;
-   struct netdev_private *np = netdev_priv(dev);
+   struct netdev_private *np = from_tasklet(np, t, rx_tasklet);
+   struct net_device *dev = (struct net_device *)((char *)np -
+ ALIGN(sizeof(struct net_device), 
NETDEV_ALIGN));
int entry = np->cur_rx % RX_RING_SIZE;
int boguscnt = np->budget;
void __iomem *ioaddr = np->base;
-- 
2.17.1



[PATCH 06/20] ethernet: chelsio: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/chelsio/cxgb/sge.c  | 12 
 drivers/net/ethernet/chelsio/cxgb3/sge.c | 14 ++
 drivers/net/ethernet/chelsio/cxgb4/sge.c | 12 ++--
 3 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c 
b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 47b5c8e2104b..5f999187038c 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -239,8 +239,10 @@ struct sched {
unsigned intnum;/* num skbs in per port queues */
struct sched_port p[MAX_NPORTS];
struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */
+   struct sge *sge;
 };
-static void restart_sched(unsigned long);
+
+static void restart_sched(struct tasklet_struct *t);
 
 
 /*
@@ -378,7 +380,8 @@ static int tx_sched_init(struct sge *sge)
return -ENOMEM;
 
pr_debug("tx_sched_init\n");
-   tasklet_init(>sched_tsk, restart_sched, (unsigned long) sge);
+   tasklet_setup(>sched_tsk, restart_sched);
+   s->sge = sge;
sge->tx_sched = s;
 
for (i = 0; i < MAX_NPORTS; i++) {
@@ -1301,9 +1304,10 @@ static inline void reclaim_completed_tx(struct sge *sge, 
struct cmdQ *q)
  * Called from tasklet. Checks the scheduler for any
  * pending skbs that can be sent.
  */
-static void restart_sched(unsigned long arg)
+static void restart_sched(struct tasklet_struct *t)
 {
-   struct sge *sge = (struct sge *) arg;
+   struct sched *s = from_tasklet(s, t, sched_tsk);
+   struct sge *sge = s->sge;
struct adapter *adapter = sge->adapter;
struct cmdQ *q = >cmdQ[0];
struct sk_buff *skb;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c 
b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index 6dabbf1502c7..f2c5da465db5 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -1520,10 +1520,10 @@ static int ctrl_xmit(struct adapter *adap, struct 
sge_txq *q,
  *
  * Resumes transmission on a suspended Tx control queue.
  */
-static void restart_ctrlq(unsigned long data)
+static void restart_ctrlq(struct tasklet_struct *t)
 {
struct sk_buff *skb;
-   struct sge_qset *qs = (struct sge_qset *)data;
+   struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_CTRL].qresume_tsk);
struct sge_txq *q = >txq[TXQ_CTRL];
 
spin_lock(>lock);
@@ -1737,10 +1737,10 @@ again:  reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
  *
  * Resumes transmission on a suspended Tx offload queue.
  */
-static void restart_offloadq(unsigned long data)
+static void restart_offloadq(struct tasklet_struct *t)
 {
struct sk_buff *skb;
-   struct sge_qset *qs = (struct sge_qset *)data;
+   struct sge_qset *qs = from_tasklet(qs, t, txq[TXQ_OFLD].qresume_tsk);
struct sge_txq *q = >txq[TXQ_OFLD];
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
@@ -3084,10 +3084,8 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned 
int id, int nports,
skb_queue_head_init(>txq[i].sendq);
}
 
-   tasklet_init(>txq[TXQ_OFLD].qresume_tsk, restart_offloadq,
-(unsigned long)q);
-   tasklet_init(>txq[TXQ_CTRL].qresume_tsk, restart_ctrlq,
-(unsigned long)q);
+   tasklet_setup(>txq[TXQ_OFLD].qresume_tsk, restart_offloadq);
+   tasklet_setup(>txq[TXQ_CTRL].qresume_tsk, restart_ctrlq);
 
q->fl[0].gen = q->fl[1].gen = 1;
q->fl[0].size = p->fl_size;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c 
b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index d2b587d1670a..e668e17711c8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -2660,11 +2660,11 @@ static int ctrl_xmit(struct sge_ctrl_txq *q, struct 
sk_buff *skb)
  *
  * Resumes transmission on a suspended Tx control queue.
  */
-static void restart_ctrlq(unsigned long data)
+static void restart_ctrlq(struct tasklet_struct *t)
 {
struct sk_buff *skb;
unsigned int written = 0;
-   struct sge_ctrl_txq *q = (struct sge_ctrl_txq *)data;
+   struct sge_ctrl_txq *q = from_tasklet(q, t, qresume_tsk);
 
spin_lock(>sendq.lock);
reclaim_completed_tx_imm(>q);
@@ -2961,9 +2961,9 @@ static int ofld_xmit(struct sge_uld_txq *q, struct 
sk_buff *skb)
  *
  * Resumes transmission on a suspended Tx offload queue.
  */
-static void restart_ofldq(unsigned long data)
+static void restart_ofldq(struct tasklet_struct *t)
 {
-   struct sge_uld_txq *q = (struct sge_uld_txq *)data;
+   struct sge_uld_txq *q = from_tasklet(q, 

[PATCH 05/20] ethernet: cavium: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/cavium/liquidio/lio_main.c| 12 ++--
 drivers/net/ethernet/cavium/liquidio/octeon_main.h |  1 +
 drivers/net/ethernet/cavium/octeon/octeon_mgmt.c   |  8 
 drivers/net/ethernet/cavium/thunder/nicvf_main.c   | 10 --
 drivers/net/ethernet/cavium/thunder/nicvf_queues.c |  4 ++--
 drivers/net/ethernet/cavium/thunder/nicvf_queues.h |  2 +-
 6 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c 
b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index e73bc211779a..41c5f4c6ca22 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -161,13 +161,13 @@ static int liquidio_set_vf_link_state(struct net_device 
*netdev, int vfidx,
 static struct handshake handshake[MAX_OCTEON_DEVICES];
 static struct completion first_stage;
 
-static void octeon_droq_bh(unsigned long pdev)
+static void octeon_droq_bh(struct tasklet_struct *t)
 {
int q_no;
int reschedule = 0;
-   struct octeon_device *oct = (struct octeon_device *)pdev;
-   struct octeon_device_priv *oct_priv =
-   (struct octeon_device_priv *)oct->priv;
+   struct octeon_device_priv *oct_priv = from_tasklet(oct_priv, t,
+ droq_tasklet);
+   struct octeon_device *oct = oct_priv->dev;
 
for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) {
if (!(oct->io_qmask.oq & BIT_ULL(q_no)))
@@ -4194,8 +4194,7 @@ static int octeon_device_init(struct octeon_device 
*octeon_dev)
 
/* Initialize the tasklet that handles output queue packet processing.*/
dev_dbg(_dev->pci_dev->dev, "Initializing droq tasklet\n");
-   tasklet_init(_priv->droq_tasklet, octeon_droq_bh,
-(unsigned long)octeon_dev);
+   tasklet_setup(_priv->droq_tasklet, octeon_droq_bh);
 
/* Setup the interrupt handler and record the INT SUM register address
 */
@@ -4299,6 +4298,7 @@ static int octeon_device_init(struct octeon_device 
*octeon_dev)
complete([octeon_dev->octeon_id].init);
 
atomic_set(_dev->status, OCT_DEV_HOST_OK);
+   oct_priv->dev = octeon_dev;
 
return 0;
 }
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_main.h 
b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
index 073d0647b439..5b4cb725f60f 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_main.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_main.h
@@ -39,6 +39,7 @@ struct octeon_device_priv {
/** Tasklet structures for this device. */
struct tasklet_struct droq_tasklet;
unsigned long napi_mask;
+   struct octeon_device *dev;
 };
 
 /** This structure is used by NIC driver to store information required
diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c 
b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
index 3e17ce0d2314..c745ace07fc3 100644
--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
@@ -315,9 +315,9 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt 
*p)
netif_wake_queue(p->netdev);
 }
 
-static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
+static void octeon_mgmt_clean_tx_tasklet(struct tasklet_struct *t)
 {
-   struct octeon_mgmt *p = (struct octeon_mgmt *)arg;
+   struct octeon_mgmt *p = from_tasklet(p, t, tx_clean_tasklet);
octeon_mgmt_clean_tx_buffers(p);
octeon_mgmt_enable_tx_irq(p);
 }
@@ -1489,8 +1489,8 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
 
skb_queue_head_init(>tx_list);
skb_queue_head_init(>rx_list);
-   tasklet_init(>tx_clean_tasklet,
-octeon_mgmt_clean_tx_tasklet, (unsigned long)p);
+   tasklet_setup(>tx_clean_tasklet,
+octeon_mgmt_clean_tx_tasklet);
 
netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c 
b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index c1378b5c780c..2b58c88f 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -985,9 +985,9 @@ static int nicvf_poll(struct napi_struct *napi, int budget)
  *
  * As of now only CQ errors are handled
  */
-static void nicvf_handle_qs_err(unsigned long data)
+static void nicvf_handle_qs_err(struct tasklet_struct *t)
 {
-   struct nicvf *nic = (struct nicvf *)data;
+   struct nicvf *nic = from_tasklet(nic, t, qs_err_task);
struct queue_set *qs = nic->qs;
int qidx;
u64 status;
@@ -1493,12 +1493,10 @@ int 

[PATCH 04/20] ethernet: cadence: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/cadence/macb_main.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 6761f404b8aa..830c537bc08c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1466,9 +1466,9 @@ static int macb_poll(struct napi_struct *napi, int budget)
return work_done;
 }
 
-static void macb_hresp_error_task(unsigned long data)
+static void macb_hresp_error_task(struct tasklet_struct *t)
 {
-   struct macb *bp = (struct macb *)data;
+   struct macb *bp = from_tasklet(bp, t, hresp_err_tasklet);
struct net_device *dev = bp->dev;
struct macb_queue *queue;
unsigned int q;
@@ -4560,8 +4560,7 @@ static int macb_probe(struct platform_device *pdev)
goto err_out_unregister_mdio;
}
 
-   tasklet_init(>hresp_err_tasklet, macb_hresp_error_task,
-(unsigned long)bp);
+   tasklet_setup(>hresp_err_tasklet, macb_hresp_error_task);
 
netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
-- 
2.17.1



[PATCH 03/20] broadcom: cnic: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/broadcom/cnic.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/cnic.c 
b/drivers/net/ethernet/broadcom/cnic.c
index c5cca63b8571..e1e8c012d501 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -3009,10 +3009,10 @@ static int cnic_service_bnx2(void *data, void 
*status_blk)
return cnic_service_bnx2_queues(dev);
 }
 
-static void cnic_service_bnx2_msix(unsigned long data)
+static void cnic_service_bnx2_msix(struct tasklet_struct *t)
 {
-   struct cnic_dev *dev = (struct cnic_dev *) data;
-   struct cnic_local *cp = dev->cnic_priv;
+   struct cnic_local *cp = from_tasklet(cp, t, cnic_irq_task);
+   struct cnic_dev *dev = cp->dev;
 
cp->last_status_idx = cnic_service_bnx2_queues(dev);
 
@@ -3134,10 +3134,10 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, 
struct kcq_info *info)
return last_status;
 }
 
-static void cnic_service_bnx2x_bh(unsigned long data)
+static void cnic_service_bnx2x_bh(struct tasklet_struct *t)
 {
-   struct cnic_dev *dev = (struct cnic_dev *) data;
-   struct cnic_local *cp = dev->cnic_priv;
+   struct cnic_local *cp = from_tasklet(cp, t, cnic_irq_task);
+   struct cnic_dev *dev = cp->dev;
struct bnx2x *bp = netdev_priv(dev->netdev);
u32 status_idx, new_status_idx;
 
@@ -4458,8 +4458,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev)
CNIC_WR(dev, base + BNX2_HC_CMD_TICKS_OFF, (64 << 16) | 220);
 
cp->last_status_idx = cp->status_blk.bnx2->status_idx;
-   tasklet_init(>cnic_irq_task, cnic_service_bnx2_msix,
-(unsigned long) dev);
+   tasklet_setup(>cnic_irq_task, cnic_service_bnx2_msix);
err = cnic_request_irq(dev);
if (err)
return err;
@@ -4868,8 +4867,7 @@ static int cnic_init_bnx2x_irq(struct cnic_dev *dev)
struct cnic_eth_dev *ethdev = cp->ethdev;
int err = 0;
 
-   tasklet_init(>cnic_irq_task, cnic_service_bnx2x_bh,
-(unsigned long) dev);
+   tasklet_setup(>cnic_irq_task, cnic_service_bnx2x_bh);
if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
err = cnic_request_irq(dev);
 
-- 
2.17.1



[PATCH 02/20] ethernet: amd: convert tasklets to use new tasklet_setup() API

2020-08-17 Thread Allen Pais
In preparation for unconditionally passing the
struct tasklet_struct pointer to all tasklet
callbacks, switch to using the new tasklet_setup()
and from_tasklet() to pass the tasklet pointer explicitly.

Signed-off-by: Romain Perier 
Signed-off-by: Allen Pais 
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c  | 19 +--
 drivers/net/ethernet/amd/xgbe/xgbe-i2c.c  | 11 +--
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 +--
 3 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 43294a148f8a..cc56086b7c51 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -403,9 +403,9 @@ static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, 
unsigned long *period,
return false;
 }
 
-static void xgbe_ecc_isr_task(unsigned long data)
+static void xgbe_ecc_isr_task(struct tasklet_struct *t)
 {
-   struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+   struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_ecc);
unsigned int ecc_isr;
bool stop = false;
 
@@ -468,14 +468,14 @@ static irqreturn_t xgbe_ecc_isr(int irq, void *data)
if (pdata->isr_as_tasklet)
tasklet_schedule(>tasklet_ecc);
else
-   xgbe_ecc_isr_task((unsigned long)pdata);
+   xgbe_ecc_isr_task(>tasklet_ecc);
 
return IRQ_HANDLED;
 }
 
-static void xgbe_isr_task(unsigned long data)
+static void xgbe_isr_task(struct tasklet_struct *t)
 {
-   struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+   struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_dev);
struct xgbe_hw_if *hw_if = >hw_if;
struct xgbe_channel *channel;
unsigned int dma_isr, dma_ch_isr;
@@ -582,7 +582,7 @@ static void xgbe_isr_task(unsigned long data)
 
/* If there is not a separate ECC irq, handle it here */
if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq))
-   xgbe_ecc_isr_task((unsigned long)pdata);
+   xgbe_ecc_isr_task(>tasklet_ecc);
 
/* If there is not a separate I2C irq, handle it here */
if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
@@ -607,7 +607,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
if (pdata->isr_as_tasklet)
tasklet_schedule(>tasklet_dev);
else
-   xgbe_isr_task((unsigned long)pdata);
+   xgbe_isr_task(>tasklet_dev);
 
return IRQ_HANDLED;
 }
@@ -991,9 +991,8 @@ static int xgbe_request_irqs(struct xgbe_prv_data *pdata)
unsigned int i;
int ret;
 
-   tasklet_init(>tasklet_dev, xgbe_isr_task, (unsigned long)pdata);
-   tasklet_init(>tasklet_ecc, xgbe_ecc_isr_task,
-(unsigned long)pdata);
+   tasklet_setup(>tasklet_dev, xgbe_isr_task);
+   tasklet_setup(>tasklet_ecc, xgbe_ecc_isr_task);
 
ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
   netdev_name(netdev), pdata);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c 
b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
index 4d9062d35930..22d4fc547a0a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
@@ -274,9 +274,9 @@ static void xgbe_i2c_clear_isr_interrupts(struct 
xgbe_prv_data *pdata,
XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
 }
 
-static void xgbe_i2c_isr_task(unsigned long data)
+static void xgbe_i2c_isr_task(struct tasklet_struct *t)
 {
-   struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+   struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_i2c);
struct xgbe_i2c_op_state *state = >i2c.op_state;
unsigned int isr;
 
@@ -324,7 +324,7 @@ static irqreturn_t xgbe_i2c_isr(int irq, void *data)
if (pdata->isr_as_tasklet)
tasklet_schedule(>tasklet_i2c);
else
-   xgbe_i2c_isr_task((unsigned long)pdata);
+   xgbe_i2c_isr_task(>tasklet_i2c);
 
return IRQ_HANDLED;
 }
@@ -369,7 +369,7 @@ static void xgbe_i2c_set_target(struct xgbe_prv_data 
*pdata, unsigned int addr)
 
 static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata)
 {
-   xgbe_i2c_isr_task((unsigned long)pdata);
+   xgbe_i2c_isr_task(>tasklet_i2c);
 
return IRQ_HANDLED;
 }
@@ -462,8 +462,7 @@ static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
 
/* If we have a separate I2C irq, enable it */
if (pdata->dev_irq != pdata->i2c_irq) {
-   tasklet_init(>tasklet_i2c, xgbe_i2c_isr_task,
-(unsigned long)pdata);
+   tasklet_setup(>tasklet_i2c, xgbe_i2c_isr_task);
 
ret = devm_request_irq(pdata->dev, pdata->i2c_irq,
   xgbe_i2c_isr, 0, pdata->i2c_name,
diff --git 

  1   2   >