Re: [PATCH RFC 3/4] mm, slab: add static key for should_failslab()

2024-05-31 Thread Yosry Ahmed
On Fri, May 31, 2024 at 9:44 AM Alexei Starovoitov
 wrote:
>
> On Fri, May 31, 2024 at 2:33 AM Vlastimil Babka  wrote:
> >
> > Since commit 4f6923fbb352 ("mm: make should_failslab always available for
> > fault injection") should_failslab() is unconditionally a noinline
> > function. This adds visible overhead to the slab allocation hotpath,
> > even if the function is empty. With CONFIG_FAILSLAB=y there's additional
> > overhead when the functionality is not enabled by a boot parameter or
> > debugfs.
> >
> > The overhead can be eliminated with a static key around the callsite.
> > Fault injection and error injection frameworks can now be told that the
> > this function has a static key associated, and are able to enable and
> > disable it accordingly.
> >
> > Signed-off-by: Vlastimil Babka 
> > ---
> >  mm/failslab.c |  2 +-
> >  mm/slab.h |  3 +++
> >  mm/slub.c | 10 +++---
> >  3 files changed, 11 insertions(+), 4 deletions(-)
> >
> > diff --git a/mm/failslab.c b/mm/failslab.c
> > index ffc420c0e767..878fd08e5dac 100644
> > --- a/mm/failslab.c
> > +++ b/mm/failslab.c
> > @@ -9,7 +9,7 @@ static struct {
> > bool ignore_gfp_reclaim;
> > bool cache_filter;
> >  } failslab = {
> > -   .attr = FAULT_ATTR_INITIALIZER,
> > +   .attr = FAULT_ATTR_INITIALIZER_KEY(_failslab_active.key),
> > .ignore_gfp_reclaim = true,
> > .cache_filter = false,
> >  };
> > diff --git a/mm/slab.h b/mm/slab.h
> > index 5f8f47c5bee0..792e19cb37b8 100644
> > --- a/mm/slab.h
> > +++ b/mm/slab.h
> > @@ -11,6 +11,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  /*
> >   * Internal slab definitions
> > @@ -160,6 +161,8 @@ static_assert(IS_ALIGNED(offsetof(struct slab, 
> > freelist), sizeof(freelist_aba_t)
> >   */
> >  #define slab_page(s) folio_page(slab_folio(s), 0)
> >
> > +DECLARE_STATIC_KEY_FALSE(should_failslab_active);
> > +
> >  /*
> >   * If network-based swap is enabled, sl*b must keep track of whether pages
> >   * were allocated from pfmemalloc reserves.
> > diff --git a/mm/slub.c b/mm/slub.c
> > index 0809760cf789..3bb579760a37 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -3874,13 +3874,15 @@ static __always_inline void 
> > maybe_wipe_obj_freeptr(struct kmem_cache *s,
> > 0, sizeof(void *));
> >  }
> >
> > +DEFINE_STATIC_KEY_FALSE(should_failslab_active);
> > +
> >  noinline int should_failslab(struct kmem_cache *s, gfp_t gfpflags)
> >  {
> > if (__should_failslab(s, gfpflags))
> > return -ENOMEM;
> > return 0;
> >  }
> > -ALLOW_ERROR_INJECTION(should_failslab, ERRNO);
> > +ALLOW_ERROR_INJECTION_KEY(should_failslab, ERRNO, _failslab_active);
> >
> >  static __fastpath_inline
> >  struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
> > @@ -3889,8 +3891,10 @@ struct kmem_cache *slab_pre_alloc_hook(struct 
> > kmem_cache *s, gfp_t flags)
> >
> > might_alloc(flags);
> >
> > -   if (unlikely(should_failslab(s, flags)))
> > -   return NULL;
> > +   if (static_branch_unlikely(_failslab_active)) {
> > +   if (should_failslab(s, flags))
> > +   return NULL;
> > +   }
>
> makes sense.
> Acked-by: Alexei Starovoitov 
>
> Do you have any microbenchmark numbers before/after this optimization?

There are numbers in the cover letter for the entire series:
https://lore.kernel.org/lkml/20240531-fault-injection-statickeys-v1-0-a513fd0a9...@suse.cz/



Re: [ANNOUNCE] 5.10.30-rt37

2021-04-20 Thread Ahmed S. Darwish
On Tue, Apr 20, 2021, ycollette.nos...@free.fr wrote:
>
> net/xfrm/xfrm_state.c: In function 'xfrm_state_init':
> ./include/linux/seqlock.h:178:36: error: initialization of 
> 'seqcount_spinlock_t *' {aka 'struct seqcount_spinlock *'} from incompatible 
> pointer type 'seqcount_t *' {aka 'struct seqcount *'} 
> [-Werror=incompatible-pointer-types]
>   178 |   seqcount_##lockname##_t *s = (s);   \
>   |^
...
> net/xfrm/xfrm_state.c:2666:2: note: in expansion of macro 
> 'seqcount_spinlock_init'
>  2666 |  seqcount_spinlock_init(>xfrm.xfrm_state_hash_generation,
>   |  ^~

There is a rebase error at:

  247560698349 ("Merge tag 'v5.10.30' into v5.10-rt")

Cherry-pick mainline's commit:

  bc8e0adff343 ("net: xfrm: Use sequence counter with associated spinlock")

and your compilation issue will be fixed.

Good luck,

--
Ahmed S. Darwish


Please respond urgently

2021-04-12 Thread Ahmed Hassan
Greetings,

With due respect to your person, I make this contact with you as I
believe that you can be of great assistance to me. I need your urgent
assistance in transferring the sum of $11.3 million USD to your
private account Where this money can be shared between us.

The money has been here in our Bank lying dormant for years now
without anybody coming for the claim. I want to release the money to
you as the relative to our deceased customer (the account owner) who
died in a plane crash with his family on 16th October 2005.

By indicating your interest I will send you the full details on how
the business will be executed.

Best Regards,
Ahmed Hassan


Compliments of the Season

2021-04-05 Thread ahmed zengo
Compliments of the Season

Greetings from Ahmed Zengo
I have something to discuss with you and it is very important and
urgent. Please contact me by my email: ahmedzengo1...@gmail.com
For further explanation
Sincerely
Ahmed zengo


Compliments of the Season

2021-03-25 Thread ahmed zengo
Compliments of the Season

Greetings from Ahmed Zengo
I have something to discuss with you and it is very important and
urgent. Please contact me by my email:ahmedzengo1...@gmail.com
For further explanation
Sincerely
Ahmed zengo


[PATCH v1 2/2] net: xfrm: Use sequence counter with associated spinlock

2021-03-16 Thread Ahmed S. Darwish
A sequence counter write section must be serialized or its internal
state can get corrupted. A plain seqcount_t does not contain the
information of which lock must be held to guaranteee write side
serialization.

For xfrm_state_hash_generation, use seqcount_spinlock_t instead of plain
seqcount_t.  This allows to associate the spinlock used for write
serialization with the sequence counter. It thus enables lockdep to
verify that the write serialization lock is indeed held before entering
the sequence counter write section.

If lockdep is disabled, this lock association is compiled out and has
neither storage size nor runtime overhead.

Signed-off-by: Ahmed S. Darwish 
---
 include/net/netns/xfrm.h | 2 +-
 net/xfrm/xfrm_state.c| 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index b59d73d529ba..e816b6a3ef2b 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -73,7 +73,7 @@ struct netns_xfrm {
struct dst_ops  xfrm6_dst_ops;
 #endif
spinlock_t  xfrm_state_lock;
-   seqcount_t  xfrm_state_hash_generation;
+   seqcount_spinlock_t xfrm_state_hash_generation;
 
spinlock_t xfrm_policy_lock;
struct mutex xfrm_cfg_mutex;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index ffd315cff984..4496f7efa220 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2665,7 +2665,8 @@ int __net_init xfrm_state_init(struct net *net)
net->xfrm.state_num = 0;
INIT_WORK(>xfrm.state_hash_work, xfrm_hash_resize);
spin_lock_init(>xfrm.xfrm_state_lock);
-   seqcount_init(>xfrm.xfrm_state_hash_generation);
+   seqcount_spinlock_init(>xfrm.xfrm_state_hash_generation,
+  >xfrm.xfrm_state_lock);
return 0;
 
 out_byspi:
-- 
2.30.2



[PATCH v1 1/2] net: xfrm: Localize sequence counter per network namespace

2021-03-16 Thread Ahmed S. Darwish
A sequence counter write section must be serialized or its internal
state can get corrupted. The "xfrm_state_hash_generation" seqcount is
global, but its write serialization lock (net->xfrm.xfrm_state_lock) is
instantiated per network namespace. The write protection is thus
insufficient.

To provide full protection, localize the sequence counter per network
namespace instead. This should be safe as both the seqcount read and
write sections access data exclusively within the network namespace. It
also lays the foundation for transforming "xfrm_state_hash_generation"
data type from seqcount_t to seqcount_LOCKNAME_t in further commits.

Fixes: b65e3d7be06f ("xfrm: state: add sequence count to detect hash resizes")
Signed-off-by: Ahmed S. Darwish 
---
 include/net/netns/xfrm.h |  4 +++-
 net/xfrm/xfrm_state.c| 10 +-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 59f45b1e9dac..b59d73d529ba 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -72,7 +72,9 @@ struct netns_xfrm {
 #if IS_ENABLED(CONFIG_IPV6)
struct dst_ops  xfrm6_dst_ops;
 #endif
-   spinlock_t xfrm_state_lock;
+   spinlock_t  xfrm_state_lock;
+   seqcount_t  xfrm_state_hash_generation;
+
spinlock_t xfrm_policy_lock;
struct mutex xfrm_cfg_mutex;
 };
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d01ca1a18418..ffd315cff984 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -44,7 +44,6 @@ static void xfrm_state_gc_task(struct work_struct *work);
  */
 
 static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
-static __read_mostly seqcount_t xfrm_state_hash_generation = 
SEQCNT_ZERO(xfrm_state_hash_generation);
 static struct kmem_cache *xfrm_state_cache __ro_after_init;
 
 static DECLARE_WORK(xfrm_state_gc_work, xfrm_state_gc_task);
@@ -140,7 +139,7 @@ static void xfrm_hash_resize(struct work_struct *work)
}
 
spin_lock_bh(>xfrm.xfrm_state_lock);
-   write_seqcount_begin(_state_hash_generation);
+   write_seqcount_begin(>xfrm.xfrm_state_hash_generation);
 
nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
odst = xfrm_state_deref_prot(net->xfrm.state_bydst, net);
@@ -156,7 +155,7 @@ static void xfrm_hash_resize(struct work_struct *work)
rcu_assign_pointer(net->xfrm.state_byspi, nspi);
net->xfrm.state_hmask = nhashmask;
 
-   write_seqcount_end(_state_hash_generation);
+   write_seqcount_end(>xfrm.xfrm_state_hash_generation);
spin_unlock_bh(>xfrm.xfrm_state_lock);
 
osize = (ohashmask + 1) * sizeof(struct hlist_head);
@@ -1063,7 +1062,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const 
xfrm_address_t *saddr,
 
to_put = NULL;
 
-   sequence = read_seqcount_begin(_state_hash_generation);
+   sequence = read_seqcount_begin(>xfrm.xfrm_state_hash_generation);
 
rcu_read_lock();
h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
@@ -1176,7 +1175,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const 
xfrm_address_t *saddr,
if (to_put)
xfrm_state_put(to_put);
 
-   if (read_seqcount_retry(_state_hash_generation, sequence)) {
+   if (read_seqcount_retry(>xfrm.xfrm_state_hash_generation, 
sequence)) {
*err = -EAGAIN;
if (x) {
xfrm_state_put(x);
@@ -2666,6 +2665,7 @@ int __net_init xfrm_state_init(struct net *net)
net->xfrm.state_num = 0;
INIT_WORK(>xfrm.state_hash_work, xfrm_hash_resize);
spin_lock_init(>xfrm.xfrm_state_lock);
+   seqcount_init(>xfrm.xfrm_state_hash_generation);
return 0;
 
 out_byspi:
-- 
2.30.2



[PATCH v1 0/2] net: xfrm: Use seqcount_spinlock_t

2021-03-16 Thread Ahmed S. Darwish
Hi,

This is a small series to trasform xfrm_state_hash_generation sequence
counter to seqcount_spinlock_t, instead of plain seqcount_t.

In general, seqcount_LOCKNAME_t sequence counters allows to associate
the lock used for write serialization with the seqcount. This enables
lockdep to verify that the write serialization lock is always held
before entering the seqcount write section.

If lockdep is disabled, this lock association is compiled out and has
neither storage size nor runtime overhead.

The first patch is a general mainline fix, and has a Fixes tag.

Thanks,

8<--

Ahmed S. Darwish (2):
  net: xfrm: Localize sequence counter per network namespace
  net: xfrm: Use sequence counter with associated spinlock

 include/net/netns/xfrm.h |  4 +++-
 net/xfrm/xfrm_state.c| 11 ++-
 2 files changed, 9 insertions(+), 6 deletions(-)

base-commit: 1e28eed17697bcf343c6743f0028cc3b5dd88bf0
--
2.30.2


Re: [RT v5.11-rt7] WARNING at include/linux/seqlock.h:271 nft_counter_eval

2021-02-23 Thread Ahmed S. Darwish
On Tue, Feb 23, 2021 at 02:53:40PM +0100, Juri Lelli wrote:
> On 23/02/21 12:00, Sebastian Andrzej Siewior wrote:
> > On 2021-02-23 11:49:07 [+0100], Juri Lelli wrote:
> > > Hi,
> > Hi,
> >
> > > I'm seeing the following splat right after boot (or during late boot
> > > phases) with v5.11-rt7 (LOCKDEP enabled).
> > …
> > > [   85.273588] WARNING: CPU: 5 PID: 1416 at include/linux/seqlock.h:271 
> > > nft_counter_eval+0x95/0x130 [nft_counter]
> > …
> > > [   85.273713] RIP: 0010:nft_counter_eval+0x95/0x130 [nft_counter]
> >
> > This is a per-CPU seqcount_t in net/netfilter/nft_counter.c which is
> > only protected by local_bh_disabled(). The warning expects preemption
> > to be disabled which is the case on !RT but not on RT.
> >
> > Not sure what to do about this. It is doing anything wrong as of now. It
> > is noisy.
>
> So, I'm a bit confused and I'm very likely missing details (still
> digesting the seqprop_ magic), but write_seqcount_being() has
>
>  if (seqprop_preemptible(s))
>  preempt_disable();
>
> which in this case (no lock associated) is defined to return false,

Preemption is disabled if and only if:

  1. It's a CONFIG_PREEMPT_RT=n system
  2. There's a lock associated with the sequence counter
  3. That lock is also preemptible (e.g., a mutex)

In your case, the 3 condititions are OFF. You're on a PREEMPT_RT=y
kernel and the sequence counter in question has no lock associated.

As Sebastian summarized, the error is just "noisy" at this point.

We will of course need to find a (mainline-friendly) way to let the
lockdep splat go away for -rt kernels. But for now, it's not harmful.

Good luck,

--
Ahmed S. Darwish


Re: [ANNOUNCE] v5.11-rc4-rt1

2021-01-21 Thread Ahmed S. Darwish
On Thu, Jan 21, 2021 at 09:50:08PM +0100, Pavel Machek wrote:
> Hi!
>
> > I'm pleased to announce the v5.11-rc4-rt1 patch set.
> >
> > Changes since v5.10.8-rt24:
> >
> >   - Updated to v5.11-rc4
> >
> > Known issues
> >  - kdb/kgdb can easily deadlock.
> >  - kmsg dumpers expecting not to be called in parallel can clobber
> >their temp buffer.
> >  - netconsole triggers WARN.
>
> I noticed... lot of code using in_interrupt() to decide what to do is
> making it to 5.10-stable at the moment (and I guess that means
> vanilla, too).
>
> I have recollection that that is not okay thing to do. Am I right?
>

Correct. These macros should not be added to new, non-core, kernel code.

There's an on-going effort to clear them already, as in:

  - https://lkml.kernel.org/r/20201019100629.419020...@linutronix.de
(merged)
  - https://lkml.kernel.org/r/20201126132952.2287996-1-bige...@linutronix.de
(merged)
  - https://lkml.kernel.org/r/20210118100955.1761652-1-a.darw...@linutronix.de  
(to be merged)

> Examples: 8abec36d1274bbd5ae8f36f3658b9abb3db56c31,
> d68b29584c25dbacd01ed44a3e45abb35353f1de.
>

That's sad.

Maybe it would be wise to let a bot scan lore regularly, and send an
automatic notification to authors whenever their patches reintroduce
these macros to non-core kernel code.

Thanks,

--
Ahmed S. Darwish


[PATCH v3 05/19] scsi: isci: port: link down: Pass gfp_t flags

2021-01-18 Thread Ahmed S. Darwish
-> enter port state *SCI_PORT_READY*

[1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

[2] Call chains for entering state: *SCI_PHY_STOPPED*
-

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
  -> phy.c: sci_phy_initialize()
-> phy.c: sci_phy_link_layer_initialization()
  -> phy.c: sci_change_state(SCI_PHY_STOPPED)

init.c: PCI ->remove() || PM_OPS ->suspend,  process context(+)
  -> host.c: isci_host_deinit()
-> sci_controller_stop_phys()
  -> phy.c: sci_phy_stop()
-> sci_change_state(SCI_PHY_STOPPED)

phy.c: isci_phy_control()
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_phy_stop(), atomic (*)
-> sci_change_state(SCI_PHY_STOPPED)

[3] Call chains for entering state: *SCI_PHY_STARTING*
--

phy.c: phy_sata_timeout(), atimer, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_change_state(SCI_PHY_STARTING)

host.c: phy_startup_timeout(), atomic, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

host.c: isci_host_start()   (@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_start(), atomic (*)
-> sci_controller_start_next_phy()
  -> sci_phy_start()
-> sci_change_state(SCI_PHY_STARTING)

phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*)
  -> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_phy_starting_final_substate_enter()
  -> sci_change_state(SCI_PHY_READY)
-> Enter SCI state: *SCI_PHY_READY*
  -> sci_phy_ready_state_enter()
-> host.c: sci_controller_link_up()
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

phy.c: sci_phy_event_handler(), atomic, discussed earlier   (*)
  -> sci_change_state(SCI_PHY_STARTING), 11 instances

phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed  (*)
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
phy event notifier.

Note, The now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8d9349738067..a3c58718c260 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -269,8 +269,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
 * isci_port_deformed and isci_dev_gone functions.
 */
sas_phy_disconnected(_phy->sas_phy);
-   sas_notify_phy_event(_phy->sas_phy,
-  PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(_phy->sas_phy,
+PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
 
dev_dbg(_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
-- 
2.30.0



[PATCH v3 03/19] scsi: libsas: Introduce a _gfp() variant of event notifiers

2021-01-18 Thread Ahmed S. Darwish
sas_alloc_event() uses in_interrupt() to decide which allocation should
be used.

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be separated or the context be conveyed in an argument passed by
the caller, which usually knows the context.

The in_interrupt() check is also only partially correct, because it
fails to choose the correct code path when just preemption or interrupts
are disabled. For example, as in the following call chain:

  mvsas/mv_sas.c: mvs_work_queue() [process context]
  spin_lock_irqsave(mvs_info::lock, )
-> libsas/sas_event.c: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> libsas/sas_event.c: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and
sas_notify_phy_event_gfp(), which all behave like the non _gfp()
variants but use a caller-passed GFP mask for allocations.

For bisectability, all callers will be modified first to pass GFP
context, then the non _gfp() libsas API variants will be modified to
take a gfp_t by default.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  2 +
 drivers/scsi/libsas/sas_event.c| 67 --
 drivers/scsi/libsas/sas_init.c | 21 +++---
 drivers/scsi/libsas/sas_internal.h |  4 ++
 include/scsi/libsas.h  |  4 ++
 5 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 6722e352444b..ea63ab3a9216 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -191,6 +191,8 @@ The event interface::
/* LLDD calls these to notify the class of an event. */
void sas_notify_port_event(struct sas_phy *, enum port_event);
void sas_notify_phy_event(struct sas_phy *, enum phy_event);
+   void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
+   void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
 The port notification::
 
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 112a1b76f63b..ba266a17250a 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -131,18 +131,15 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+static int __sas_notify_port_event(struct asd_sas_phy *phy,
+  enum port_event event,
+  struct asd_sas_event *ev)
 {
-   struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -151,20 +148,41 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event)
 
return ret;
 }
+
+int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
+ gfp_t gfp_flags)
+{
+   struct asd_sas_event *ev;
+
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
+EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
+
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+{
+   struct asd_sas_event *ev;
+
+   ev = sas_alloc_event(phy);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
 EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
+enum phy_event event,
+struct asd_sas_event *ev)
 {
-   struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -173,5 +191,28 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event)
 
return ret;
 }
+
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
+

[PATCH v3 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-18 Thread Ahmed S. Darwish
Hi,

Changelog v3


- Include latest version of John's patch. Collect r-b tags.

- Limit all code to 80 columns, even for intermediate patches.

- Rebase over v5.11-rc4

Changelog v2


https://lkml.kernel.org/r/20210112110647.627783-1-a.darw...@linutronix.de

- Rebase on top of John's patch "scsi: libsas and users: Remove notifier
  indirection", as it affects every other patch. Include it in this
  series (patch #2).

- Introduce patches #13 => #19, which modify call sites back to use the
  original libsas notifier function names without _gfp() suffix.

- Rebase over v5.11-rc3

v1 / Cover letter
-

https://lkml.kernel.org/r/20201218204354.586951-1-a.darw...@linutronix.de

In the discussion about preempt count consistency across kernel
configurations:

  https://lkml.kernel.org/r/20200914204209.256266...@linutronix.de

it was concluded that the usage of in_interrupt() and related context
checks should be removed from non-core code.

This includes memory allocation mode decisions (GFP_*). In the long run,
usage of in_interrupt() and its siblings should be banned from driver
code completely.

This series addresses SCSI libsas. Basically, the function:

  => drivers/scsi/libsas/sas_init.c:
  struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
  {
...
gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
event = kmem_cache_zalloc(sas_event_cache, flags);
...
  }

is transformed so that callers explicitly pass the gfp_t memory
allocation flags. Affected libsas clients are modified accordingly.

Patches #1, #2 => #7 have "Fixes: " tags and address bugs the were
noticed during the context analysis.

Thanks!

8<--

Ahmed S. Darwish (18):
  Documentation: scsi: libsas: Remove notify_ha_event()
  scsi: libsas: Introduce a _gfp() variant of event notifiers
  scsi: mvsas: Pass gfp_t flags to libsas event notifiers
  scsi: isci: port: link down: Pass gfp_t flags
  scsi: isci: port: link up: Pass gfp_t flags
  scsi: isci: port: broadcast change: Pass gfp_t flags
  scsi: libsas: Pass gfp_t flags to event notifiers
  scsi: pm80xx: Pass gfp_t flags to libsas event notifiers
  scsi: aic94xx: Pass gfp_t flags to libsas event notifiers
  scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers
  scsi: libsas: event notifiers API: Add gfp_t flags parameter
  scsi: hisi_sas: Switch back to original libsas event notifiers
  scsi: aic94xx: Switch back to original libsas event notifiers
  scsi: pm80xx: Switch back to original libsas event notifiers
  scsi: libsas: Switch back to original event notifiers API
  scsi: isci: Switch back to original libsas event notifiers
  scsi: mvsas: Switch back to original libsas event notifiers
  scsi: libsas: Remove temporarily-added _gfp() API variants

John Garry (1):
  scsi: libsas and users: Remove notifier indirection

 Documentation/scsi/libsas.rst  |  9 +
 drivers/scsi/aic94xx/aic94xx_scb.c | 24 ++--
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 29 +++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  7 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  7 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  7 ++--
 drivers/scsi/isci/port.c   | 11 +++---
 drivers/scsi/libsas/sas_event.c| 27 ++---
 drivers/scsi/libsas/sas_init.c | 19 -
 drivers/scsi/libsas/sas_internal.h |  6 +--
 drivers/scsi/mvsas/mv_sas.c| 25 ++--
 drivers/scsi/pm8001/pm8001_hwi.c   | 54 --
 drivers/scsi/pm8001/pm8001_sas.c   | 12 ++
 drivers/scsi/pm8001/pm80xx_hwi.c   | 46 --
 include/scsi/libsas.h  |  9 +++--
 16 files changed, 149 insertions(+), 146 deletions(-)

base-commit: 19c329f6808995b142b3966301f217c831e7cf31
--
2.30.0


[PATCH v3 04/19] scsi: mvsas: Pass gfp_t flags to libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
mvsas calls the non _gfp version of the libsas event notifiers API,
leading to the buggy call chains below:

  mvsas/mv_sas.c: mvs_work_queue() [process context]
  spin_lock_irqsave(mvs_info::lock, )
-> libsas/sas_event.c: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> libsas/sas_event.c: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Use the new event notifiers API instead, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are context analysis for the modified functions:

=> mvs_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags. Call chains:

  scsi_scan.c: do_scsi_scan_host() [has msleep()]
-> shost->hostt->scan_start()
-> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = 
mvs_scan_start()]
-> mvsas/mv_sas.c: mvs_scan_start()
  -> mvs_bytes_dmaed(..., GFP_KERNEL)

  mvsas/mv_sas.c: mvs_work_queue()
  spin_lock_irqsave(mvs_info::lock,)
-> mvs_bytes_dmaed(..., GFP_ATOMIC)

  mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr()
-> mvsas/mv_chips.h: mvs_int_full()
  -> mvsas/mv_sas.c: mvs_int_port()
-> mvs_bytes_dmaed(..., GFP_ATOMIC);

=> mvs_work_queue():

Invoked from process context, but it calls all the libsas event notifier
APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/mvsas/mv_sas.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index e5e3e95f78b0..484e01428da2 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -216,7 +216,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, 
u32 off_lo,
MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi);
 }
 
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
+static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags)
 {
struct mvs_phy *phy = >phy[i];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -229,7 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
return;
}
 
-   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -261,7 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
 
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 void mvs_scan_start(struct Scsi_Host *shost)
@@ -277,7 +277,7 @@ void mvs_scan_start(struct Scsi_Host *shost)
for (j = 0; j < core_nr; j++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
for (i = 0; i < mvi->chip->n_phy; ++i)
-   mvs_bytes_dmaed(mvi, i);
+   mvs_bytes_dmaed(mvi, i, GFP_KERNEL);
}
mvs_prv->scan_finished = 1;
 }
@@ -1892,20 +1892,21 @@ static void mvs_work_queue(struct work_struct *work)
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
-   sas_notify_phy_event(sas_phy,
-   PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(sas_phy,
+   PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
mvs_update_phyinfo(mvi, phy_no, 1);
-   mvs_bytes_dmaed(mvi, phy_no);
+   mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC);
mvs_port_notify_formed(sas_phy, 0);
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,
+   PORTE_BROADCAST_RCVD, GFP_ATOMIC);
mv_dprintk("phy

[PATCH v3 01/19] Documentation: scsi: libsas: Remove notify_ha_event()

2021-01-18 Thread Ahmed S. Darwish
The ->notify_ha_event() hook has long been removed from the libsas event
interface.

Remove it from documentation.

Fixes: 042ebd293b86 ("scsi: libsas: kill useless ha_event and do some cleanup")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: sta...@vger.kernel.org
---
 Documentation/scsi/libsas.rst | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 7216b5d25800..f9b77c7879db 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,7 +189,6 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);
void (*notify_port_event)(struct sas_phy *, enum port_event);
void (*notify_phy_event)(struct sas_phy *, enum phy_event);
 
-- 
2.30.0



[PATCH v3 02/19] scsi: libsas and users: Remove notifier indirection

2021-01-18 Thread Ahmed S. Darwish
From: John Garry 

LLDDs report events to libsas with .notify_port_event and
.notify_phy_event callbacks.

These callbacks are fixed and so there is no reason why the functions
cannot be called directly, so do that.

This neatens the code slightly, makes it more obvious, and reduces
function pointer usage, which is generally a good thing. Downside is that
there are 2x more symbol exports.

[a.darw...@linutronix.de: Remove the now unused "sas_ha" local variables]
Signed-off-by: John Garry 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Ahmed S. Darwish 
---
 Documentation/scsi/libsas.rst  |  8 ++
 drivers/scsi/aic94xx/aic94xx_scb.c | 20 ++---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 12 +++-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  3 +-
 drivers/scsi/isci/port.c   |  7 ++---
 drivers/scsi/libsas/sas_event.c| 13 +++--
 drivers/scsi/libsas/sas_init.c |  6 
 drivers/scsi/libsas/sas_internal.h |  1 -
 drivers/scsi/mvsas/mv_sas.c| 14 -
 drivers/scsi/pm8001/pm8001_hwi.c   | 40 --
 drivers/scsi/pm8001/pm8001_sas.c   |  7 ++---
 drivers/scsi/pm8001/pm80xx_hwi.c   | 35 ++
 include/scsi/libsas.h  |  7 ++---
 15 files changed, 69 insertions(+), 110 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index f9b77c7879db..6722e352444b 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,12 +189,8 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_port_event)(struct sas_phy *, enum port_event);
-   void (*notify_phy_event)(struct sas_phy *, enum phy_event);
-
-When sas_register_ha() returns, those are set and can be
-called by the LLDD to notify the SAS layer of such events
-the SAS layer.
+   void sas_notify_port_event(struct sas_phy *, enum port_event);
+   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
 
 The port notification::
 
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 13677973da5c..770546177ca4 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -68,7 +68,6 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
 struct done_list_struct *dl)
 {
struct asd_ha_struct *asd_ha = ascb->ha;
-   struct sas_ha_struct *sas_ha = _ha->sas_ha;
int phy_id = dl->status_block[0] & DL_PHY_MASK;
struct asd_phy *phy = _ha->phys[phy_id];
 
@@ -81,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -102,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
break;
}
 }
@@ -222,7 +221,6 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
int edb_el = edb_id + ascb->edb_index;
struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
struct asd_phy *phy = >ha->phys[phy_id];
-   struct sas_ha_struct *sas_ha = phy->sas_phy.ha;
u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
 
size = min(size, (u16) sizeof(phy->frame_rcvd));
@@ -234

[PATCH v3 06/19] scsi: isci: port: link up: Pass gfp_t flags

2021-01-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

libsas sas_notify_port_event() is called from isci_port_link_up().
Below is the context analysis for all of its call chains:

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
-> port_config.c: sci_port_configuration_agent_initialize()
  -> sci_mpc_agent_validate_phy_configuration()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

port_config.c: apc_agent_timeout(), atomic, timer callback  (*)
  -> sci_apc_agent_configure_ports()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1]
  -> phy.c: sci_phy_starting_final_substate_enter()
-> phy.c: sci_change_state(SCI_PHY_READY)
  -> enter SCI state: *SCI_PHY_READY*
-> phy.c: sci_phy_ready_state_enter()
  -> host.c: sci_controller_link_up()
-> .link_up_handler()
== port_config.c: sci_apc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])
== port_config.c: sci_mpc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])

port_config.c: mpc_agent_timeout(), atomic, timer callback  (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> ->link_up_handler()
  == port_config.c: sci_apc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])
  == port_config.c: sci_mpc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])

[A] port.c: sci_port_link_up()
  -> sci_port_activate_phy()
-> isci_port_link_up()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

[1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*
---

host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, all the call-chains are
atomic.  Pass GFP_ATOMIC to libsas port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index a3c58718c260..10136ae466e2 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -223,7 +223,8 @@ static void isci_port_link_up(struct isci_host *isci_host,
/* Notify libsas that we have an address frame, if indeed
 * we've found an SSP, SMP, or STP target */
if (success)
-   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(>sas_phy,
+ PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 
-- 
2.30.0



[PATCH v3 14/19] scsi: aic94xx: Switch back to original libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
---
 drivers/scsi/aic94xx/aic94xx_scb.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 76a4c21144d8..68214a58b160 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -80,8 +80,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL,
-GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL,
+GFP_ATOMIC);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,14 +89,13 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE,
-GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD,
-GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD,
+GFP_ATOMIC);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -104,8 +103,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR,
-GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);
break;
}
 }
@@ -236,7 +234,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_notify_port_event_gfp(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -272,7 +270,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb 
*ascb,
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
 
if (retries_left == 0) {
int num = 1;
@@ -317,8 +315,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
- GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
+ GFP_ATOMIC);
break;
 
case LmUNKNOWNP:
@@ -339,8 +337,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
/* The sequencer disables all phys on that port.
 * We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET,
- GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_HARD_RESET,
+ GFP_ATO

[PATCH v3 08/19] scsi: libsas: Pass gfp_t flags to event notifiers

2021-01-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  - sas_enable_revalidation(): process, acquires mutex
  - sas_resume_ha(): process, calls wait_event_timeout()

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/libsas/sas_event.c | 3 ++-
 drivers/scsi/libsas/sas_init.c  | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index ba266a17250a..25f3aaea8142 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,8 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
 
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,
+   PORTE_BROADCAST_RCVD, GFP_KERNEL);
}
mutex_unlock(>disco_mutex);
 }
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index f8ae1f0f17d3..9ce0cd214eb9 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -404,7 +404,8 @@ void sas_resume_ha(struct sas_ha_struct *ha)
 
if (phy->suspended) {
dev_warn(>phy->dev, "resume timeout\n");
-   sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT);
+   sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT,
+GFP_KERNEL);
}
}
 
-- 
2.30.0



[PATCH v3 16/19] scsi: libsas: Switch back to original event notifiers API

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original event notifiers API, while still passing GFP
context.  The _gfp() notifier variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/libsas/sas_event.c | 6 +++---
 drivers/scsi/libsas/sas_init.c  | 8 
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 3d0cc407b33f..542831887769 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
 
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
-   sas_notify_port_event_gfp(sas_phy,
+   sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD, GFP_KERNEL);
}
mutex_unlock(>disco_mutex);
@@ -141,7 +141,7 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   ev = sas_alloc_event(phy, gfp_flags);
if (!ev)
return -ENOMEM;
 
@@ -171,7 +171,7 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event,
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   ev = sas_alloc_event(phy, gfp_flags);
if (!ev)
return -ENOMEM;
 
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index f06b83211e3b..62260e84ca2d 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -404,8 +404,8 @@ void sas_resume_ha(struct sas_ha_struct *ha)
 
if (phy->suspended) {
dev_warn(>phy->dev, "resume timeout\n");
-   sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT,
-GFP_KERNEL);
+   sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT,
+GFP_KERNEL);
}
}
 
@@ -604,8 +604,8 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy 
*phy,
if (cmpxchg(>in_shutdown, 0, 1) == 0) {
pr_notice("The phy%d bursting events, shut it 
down.\n",
  phy->id);
-   sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN,
-gfp_flags);
+   sas_notify_phy_event(phy, PHYE_SHUTDOWN,
+gfp_flags);
}
} else {
/* Do not support PHY control, stop allocating events */
-- 
2.30.0



[PATCH v3 07/19] scsi: isci: port: broadcast change: Pass gfp_t flags

2021-01-18 Thread Ahmed S. Darwish
G)
-> enter SCI PHY state: *SCI_PHY_RESETTING*
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

[2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 10136ae466e2..e50c3b0deeb3 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,7 +164,8 @@ static void isci_port_bc_change_received(struct isci_host 
*ihost,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, >sas_phy);
 
-   sas_notify_port_event(>sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(>sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
sci_port_bcn_enable(iport);
 }
 
-- 
2.30.0



[PATCH v3 10/19] scsi: aic94xx: Pass gfp_t flags to libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  aic94xx_hwi.c: asd_dl_tasklet_handler()
-> asd_ascb::tasklet_complete()
== escb_tasklet_complete()
  -> aic94xx_scb.c: asd_phy_event_tasklet()
  -> aic94xx_scb.c: asd_bytes_dmaed_tasklet()
  -> aic94xx_scb.c: asd_link_reset_err_tasklet()
  -> aic94xx_scb.c: asd_primitive_rcvd_tasklet()

All functions are invoked by escb_tasklet_complete(), which is invoked
by the tasklet handler. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
---
 drivers/scsi/aic94xx/aic94xx_scb.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 770546177ca4..76a4c21144d8 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -80,7 +80,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL,
+GFP_ATOMIC);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -88,12 +89,14 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE,
+GFP_ATOMIC);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD,
+GFP_ATOMIC);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -101,7 +104,8 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR,
+GFP_ATOMIC);
break;
}
 }
@@ -232,7 +236,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -268,7 +272,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb 
*ascb,
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
 
if (retries_left == 0) {
int num = 1;
@@ -313,7 +317,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
+ GFP_ATOMIC);
break;
 
case LmUNKNOWNP:
@@ -334,7 +339,8 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
/* The sequencer disables all phys on that port.
 * We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
+   sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET,
+ GFP_ATOMIC);
break;
 
default:
@@ -565,7 +571,8 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
/* the device is gon

[PATCH v3 12/19] scsi: libsas: event notifiers API: Add gfp_t flags parameter

2021-01-18 Thread Ahmed S. Darwish
All call-sites of below libsas APIs:

  - sas_alloc_event()
  - sas_notify_port_event()
  - sas_notify_phy_event()

have been converted to use the _gfp()-suffixed version.  Modify the
original APIs above to take a gfp_t flags parameter by default.

For bisectability, call-sites will be modified again to use the original
libsas APIs (while passing gfp_t). The temporary _gfp()-suffixed
versions can then be removed.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  4 +-
 drivers/scsi/libsas/sas_event.c| 62 +-
 drivers/scsi/libsas/sas_init.c | 12 ++
 drivers/scsi/libsas/sas_internal.h |  5 ++-
 include/scsi/libsas.h  |  6 ++-
 5 files changed, 31 insertions(+), 58 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index ea63ab3a9216..c65086470a15 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,8 +189,8 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void sas_notify_port_event(struct sas_phy *, enum port_event);
-   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
+   void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t);
+   void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t);
void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 25f3aaea8142..3d0cc407b33f 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -132,15 +132,19 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-static int __sas_notify_port_event(struct asd_sas_phy *phy,
-  enum port_event event,
-  struct asd_sas_event *ev)
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event,
+ gfp_t gfp_flags)
 {
struct sas_ha_struct *ha = phy->ha;
+   struct asd_sas_event *ev;
int ret;
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -149,41 +153,28 @@ static int __sas_notify_port_event(struct asd_sas_phy 
*phy,
 
return ret;
 }
+EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
 int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
  gfp_t gfp_flags)
 {
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
+   return sas_notify_port_event(phy, event, gfp_flags);
 }
 EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
 
-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
-}
-EXPORT_SYMBOL_GPL(sas_notify_port_event);
-
-static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
-enum phy_event event,
-struct asd_sas_event *ev)
+int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
+gfp_t gfp_flags)
 {
struct sas_ha_struct *ha = phy->ha;
+   struct asd_sas_event *ev;
int ret;
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -192,28 +183,11 @@ static inline int __sas_notify_phy_event(struct 
asd_sas_phy *phy,
 
return ret;
 }
+EXPORT_SYMBOL_GPL(sas_notify_phy_event);
 
 int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags)
 {
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_phy_event(phy, event, ev);
+   return sas_notify_phy_event(phy, event, gfp_flags);
 }
 EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp);
-
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_phy_event(phy, event, ev);
-}
-EXPORT_SYMBOL_GPL(sas_notify_phy_event);
di

[PATCH v3 09/19] scsi: pm80xx: Pass gfp_t flags to libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Call chain analysis, pm8001_hwi.c:

  pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || 
pm8001_tasklet()
-> PM8001_CHIP_DISP->isr() = pm80xx_chip_isr()
  -> process_oq [spin_lock_irqsave(_ha->lock, ...)]
-> process_one_iomb()
  -> mpi_hw_event()
-> hw_event_sas_phy_up()
  -> pm8001_bytes_dmaed()
-> hw_event_sata_phy_up
  -> pm8001_bytes_dmaed()

All functions are invoked by process_one_iomb(), which is invoked by the
interrupt service routine and the tasklet handler. A similar call chain
is also found at pm80xx_hwi.c. Pass GFP_ATOMIC.

For pm8001_sas.c, pm8001_phy_control() runs in task context as it calls
wait_for_completion() and msleep().  Pass GFP_KERNEL.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jack Wang 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 54 +---
 drivers/scsi/pm8001/pm8001_sas.c |  8 ++---
 drivers/scsi/pm8001/pm80xx_hwi.c | 41 +++-
 3 files changed, 65 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index dd15246d5b03..c8bfa8e6f211 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3179,7 +3179,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info 
*pm8001_ha, int i)
pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 /* Get the link rate speed  */
@@ -3336,7 +3336,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, >sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3379,7 +3379,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)>sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3726,11 +3726,13 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
-   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD,
+   GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
-   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL,
+   GFP_ATOMIC);
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
@@ -3739,7 +3741,8 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
-   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR,
+   GFP_ATOMIC);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
@@ -3750,20 +3753,23 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
+   GFP_ATOMIC);
break;
case HW_EVENT_PHY_ERROR:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_

[PATCH v3 15/19] scsi: pm80xx: Switch back to original libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jack Wang 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 40 +++-
 drivers/scsi/pm8001/pm8001_sas.c |  5 ++--
 drivers/scsi/pm8001/pm80xx_hwi.c | 32 -
 3 files changed, 36 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index c8bfa8e6f211..b3f136998025 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3179,7 +3179,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info 
*pm8001_ha, int i)
pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 /* Get the link rate speed  */
@@ -3336,7 +3336,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, >sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3379,7 +3379,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)>sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3726,12 +3726,12 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD,
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD,
GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL,
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL,
GFP_ATOMIC);
phy->phy_attached = 0;
phy->phy_state = 0;
@@ -3741,7 +3741,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
-   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR,
+   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,
GFP_ATOMIC);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
@@ -3753,22 +3753,21 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
GFP_ATOMIC);
break;
case HW_EVENT_PHY_ERROR:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
sas_phy_disconnected(>sas_phy);
phy->phy_attached = 0;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR,
-   GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);
break;
case HW_EVENT_BROADCAST_EXP:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");
spin_lock_irqsav

[PATCH v3 11/19] scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are the context analysis for modified functions:

=> hisi_sas_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags:

  * hisi_sas_main.c:
  --

hisi_sas_phyup_work(): workqueue context
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_controller_reset_done(): has an msleep()
  -> hisi_sas_rescan_topology()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_debug_I_T_nexus_reset(): calls wait_for_completion_timeout()
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

  * hisi_sas_v1_hw.c:
  ---

int_abnormal_v1_hw(): irq handler
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

  * hisi_sas_v[23]_hw.c:
  --

int_phy_updown_v[23]_hw(): irq handler
  -> phy_down_v[23]_hw()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

=> int_bcast_v1_hw() and phy_bcast_v3_hw():

Both are invoked exclusively from irq handlers. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 26 +++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  6 --
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  6 --
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  6 --
 5 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e821dd32dd28..873bfffa626d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -637,7 +637,8 @@ extern void hisi_sas_scan_start(struct Scsi_Host *shost);
 extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
 extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
int enable);
-extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
+extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy,
+ gfp_t gfp_flags);
 extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 76f8fc3fad59..54acaeab5bb7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -612,7 +612,8 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t 
gfp_flags,
return rc;
 }
 
-static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
+static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no,
+gfp_t gfp_flags)
 {
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -626,7 +627,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
return;
}
 
-   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -654,7 +655,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
}
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
@@ -860,7 +861,7 @@ static void hisi_sas_phyup_work(struct work_struct *work)
 
if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP)
hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no);
-   hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+   hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL);
 }
 
 static void hisi_sas_linkreset_work(struct work_struct *work)
@@ -1429,11 +1430,12 @@ static void hisi_sas_rescan_topology(struct hisi_hba 
*hisi_hba, u32 state)
_sas_port = sas_port;
 
if (dev_is_expander(dev->dev_type))
-   sas_notify_port_event(sas_phy,
-   PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,
+   PORTE_BROADCAST_RCVD,
+   GFP_KERNEL);
}
} else {
-   hisi_sas_phy_down(his

Re: [RFC PATCH 0/1] net: arcnet: Fix RESET sequence

2021-01-18 Thread Ahmed S. Darwish
On Mon, Jan 11, 2021 at 02:54:06PM +0100, Ahmed S. Darwish wrote:
> Hi,
>
> On Tue, Dec 22, 2020 at 10:03:37AM +0100, Ahmed S. Darwish wrote:
> ...
> >
> > Included is an RFC patch to fix the points above: if the RESET flag is
> > encountered, a workqueue is scheduled to run the generic reset sequence.
> >
> ...
>
> Kind reminder.

Ping. Will anyone look at this?

Thanks,

--
Ahmed S. Darwish


[PATCH v3 19/19] scsi: libsas: Remove temporarily-added _gfp() API variants

2021-01-18 Thread Ahmed S. Darwish
These variants were added for bisectability. Remove them, as all call
sites have now been convertd to use the original API.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  2 --
 drivers/scsi/libsas/sas_event.c| 14 --
 drivers/scsi/libsas/sas_init.c |  7 ---
 drivers/scsi/libsas/sas_internal.h |  4 
 include/scsi/libsas.h  |  4 
 5 files changed, 31 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index c65086470a15..6589dfefbc02 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -191,8 +191,6 @@ The event interface::
/* LLDD calls these to notify the class of an event. */
void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t);
void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t);
-   void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
-   void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
 The port notification::
 
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 542831887769..f703115e7a25 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -155,13 +155,6 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
 }
 EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
- gfp_t gfp_flags)
-{
-   return sas_notify_port_event(phy, event, gfp_flags);
-}
-EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
-
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags)
 {
@@ -184,10 +177,3 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event,
return ret;
 }
 EXPORT_SYMBOL_GPL(sas_notify_phy_event);
-
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
-gfp_t gfp_flags)
-{
-   return sas_notify_phy_event(phy, event, gfp_flags);
-}
-EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp);
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 62260e84ca2d..2b0f98ca6ec3 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -619,13 +619,6 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy 
*phy,
return event;
 }
 
-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy,
- gfp_t gfp_flags)
-{
-
-   return sas_alloc_event(phy, gfp_flags);
-}
-
 void sas_free_event(struct asd_sas_event *event)
 {
struct asd_sas_phy *phy = event->phy;
diff --git a/drivers/scsi/libsas/sas_internal.h 
b/drivers/scsi/libsas/sas_internal.h
index 294cdcb4ce42..d7a1fb5c10c6 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -49,8 +49,6 @@ int  sas_register_phys(struct sas_ha_struct *sas_ha);
 void sas_unregister_phys(struct sas_ha_struct *sas_ha);
 
 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t 
gfp_flags);
-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy,
- gfp_t gfp_flags);
 void sas_free_event(struct asd_sas_event *event);
 
 int  sas_register_ports(struct sas_ha_struct *sas_ha);
@@ -80,8 +78,6 @@ int sas_smp_get_phy_events(struct sas_phy *phy);
 
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t flags);
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
-gfp_t flags);
 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
 struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
 struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index fda56e151695..9271d7a49b90 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -706,9 +706,5 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
  gfp_t gfp_flags);
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags);
-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
- gfp_t gfp_flags);
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
-gfp_t gfp_flags);
 
 #endif /* _SASLIB_H_ */
-- 
2.30.0



[PATCH v3 18/19] scsi: mvsas: Switch back to original libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
---
 drivers/scsi/mvsas/mv_sas.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 484e01428da2..1acea528f27f 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -229,7 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, 
gfp_t gfp_flags)
return;
}
 
-   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -261,7 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, 
gfp_t gfp_flags)
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
 
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 void mvs_scan_start(struct Scsi_Host *shost)
@@ -1892,7 +1892,7 @@ static void mvs_work_queue(struct work_struct *work)
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
-   sas_notify_phy_event_gfp(sas_phy,
+   sas_notify_phy_event(sas_phy,
PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
@@ -1905,7 +1905,7 @@ static void mvs_work_queue(struct work_struct *work)
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
-   sas_notify_port_event_gfp(sas_phy,
+   sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD, GFP_ATOMIC);
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
}
-- 
2.30.0



[PATCH v3 17/19] scsi: isci: Switch back to original libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index e50c3b0deeb3..448a8c31ba35 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,8 +164,8 @@ static void isci_port_bc_change_received(struct isci_host 
*ihost,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, >sas_phy);
 
-   sas_notify_port_event_gfp(>sas_phy,
- PORTE_BROADCAST_RCVD, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
sci_port_bcn_enable(iport);
 }
 
@@ -224,8 +224,8 @@ static void isci_port_link_up(struct isci_host *isci_host,
/* Notify libsas that we have an address frame, if indeed
 * we've found an SSP, SMP, or STP target */
if (success)
-   sas_notify_port_event_gfp(>sas_phy,
- PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy,
+ PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 
@@ -271,8 +271,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
 * isci_port_deformed and isci_dev_gone functions.
 */
sas_phy_disconnected(_phy->sas_phy);
-   sas_notify_phy_event_gfp(_phy->sas_phy,
-PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
+   sas_notify_phy_event(_phy->sas_phy,
+PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
 
dev_dbg(_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
-- 
2.30.0



[PATCH v3 13/19] scsi: hisi_sas: Switch back to original libsas event notifiers

2021-01-18 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 9 -
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 ++--
 4 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 54acaeab5bb7..625327e99b06 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -627,7 +627,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no,
return;
}
 
-   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -655,7 +655,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no,
}
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
@@ -1430,7 +1430,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba 
*hisi_hba, u32 state)
_sas_port = sas_port;
 
if (dev_is_expander(dev->dev_type))
-   sas_notify_port_event_gfp(sas_phy,
+   sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD,
GFP_KERNEL);
}
@@ -2209,8 +2209,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int 
phy_no, int rdy,
return;
}
/* Phy down and not ready */
-   sas_notify_phy_event_gfp(sas_phy,
-PHYE_LOSS_OF_SIGNAL, gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL, gfp_flags);
sas_phy_disconnected(sas_phy);
 
if (port) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 2e660c0476f1..7451377c4cb6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1423,8 +1423,8 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p)
}
 
if (!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
- GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
+ GFP_ATOMIC);
 
 end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index da62dfdb724d..502ad3e4f7cd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2825,8 +2825,8 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD,
- GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,
+ GFP_ATOMIC);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 CHL_INT0_SL_RX_BCST_ACK_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 0307248fd973..28edf76e0f47 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1607,8 +1607,8 @@ static irqreturn_t phy_bcast_v3_hw(int phy_no, struct 
hisi_hba *hisi_hba)
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_not

Re: [PATCH v2 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-15 Thread Ahmed S. Darwish
On Fri, Jan 15, 2021 at 04:29:51PM +, John Garry wrote:
> On 15/01/2021 16:27, Ahmed S. Darwish wrote:
> > Thanks!
> >
> > Shall I add you r-b tag to the whole series then, or only to the ones
> > which directly touch libsas (#3, #12, #16, and #19)?
>
> The whole series, if you like. But there was a nit about fitting some code
> on a single line still, and I think Christoph also had some issue on that
> related topic.
>

Nice. Then I'll send a v3 to fixing these 80 col issues -- including in
the intermediate patches.

> >
> > > As an aside, your analysis showed some quite poor usage of spinlocks in 
> > > some
> > > drivers, specifically grabbing a lock and then calling into a depth of 3 
> > > or
> > > 4 functions.
> > >
> > Correct.
>
> BTW, testing report looked all good.
>

Oh, that's good to hear :)

Have a nice weekend,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH v2 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-15 Thread Ahmed S. Darwish
On Thu, Jan 14, 2021 at 09:51:35AM +, John Garry wrote:
...
>
> To me, the series looks fine. Well, the end result - I didn't go through
> patch by patch. So:
>
> Reviewed-by: John Garry 
>

Thanks!

Shall I add you r-b tag to the whole series then, or only to the ones
which directly touch libsas (#3, #12, #16, and #19)?

>
> As an aside, your analysis showed some quite poor usage of spinlocks in some
> drivers, specifically grabbing a lock and then calling into a depth of 3 or
> 4 functions.
>

Correct.

Kind regards,

--
Ahmed S. Darwish


Re: [PATCH v2 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-12 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 04:00:57PM +, John Garry wrote:
...
>
> I boot-tested on my machines which have hisi_sas v2 and v3 hw, and it's ok.
> I will ask some guys to test a bit more.
>

Thanks a lot!

> And generally the changes look ok. But I just have a slight concern that we
> don't pass the gfp_flags all the way from the origin caller.
>
> So we have some really long callchains, for example:
>
> host.c: sci_controller_error_handler(): atomic, irq handler (*)
> OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
>   -> sci_controller_process_completions()
> -> sci_controller_unsolicited_frame()
>   -> phy.c: sci_phy_frame_handler()
> -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
>   -> sci_phy_starting_await_sas_power_substate_enter()
> -> host.c: sci_controller_power_control_queue_insert()
>   -> phy.c: sci_phy_consume_power_handler()
> -> sci_change_state(SCI_PHY_SUB_FINAL)
> -> sci_change_state(SCI_PHY_SUB_FINAL)
> -> sci_controller_event_completion()
>   -> phy.c: sci_phy_event_handler()
> -> sci_phy_start_sata_link_training()
>   -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
> -> sci_phy_starting_await_sata_power_substate_enter
>   -> host.c: sci_controller_power_control_queue_insert()
> -> phy.c: sci_phy_consume_power_handler()
>   -> sci_change_state(SCI_PHY_SUB_FINAL)
>
> So if someone rearranges the code later, adds new callchains, etc., it could
> be missed that the context may have changed than what we assume at the
> bottom. But then passing the flags everywhere is cumbersome, and all the
> libsas users see little or no significant changes anyway, apart from a
> couple.
>

The deep call chains like the one you've quoted are all within the isci
Intel driver (patches #5 => #7), due to the *massive* state transitions
that driver has. But as the commit logs of these three patches show,
almost all of such transitions happened under atomic context anyway and
GFP_ATOMIC was thus used.

The GFP_KERNEL call-chains were all very simple: a workqueue, functions
already calling msleep() or wait_event_timeout() two or three lines
nearby, and so on.

All the other libsas clients (that is, except isci) also had normal call
chains that were IMHO easy to follow.

Thanks,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH v2 04/19] scsi: mvsas: Pass gfp_t flags to libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 03:46:42PM +, Christoph Hellwig wrote:
> > } else if (mwq->handler & EXP_BRCT_CHG) {
> > phy->phy_event &= ~EXP_BRCT_CHG;
> > -   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
> > +   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
> > GFP_ATOMIC);
>
> Please don't add pointless lines > 80 chars.  This seems to happen a lot
> more in the series.

I didn't break the lines because they will be modified at the end of the
series anway.

When the _gfp() suffix is removed (patches #13 => #19), the lines get
within the 80 cols range.

Thanks,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH v2 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-12 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 11:53:50AM +, John Garry wrote:
> On 12/01/2021 11:06, Ahmed S. Darwish wrote:
> > Hi,
> >
> > Changelog v2
> > 
...
>
> I'll give this a spin today and help review also then.
>
> There's 18 patches here - it would be very convenient if they were on a
> public branch :)
>

Konstantin's "b4" is your friend:

  https://people.kernel.org/monsieuricon/introducing-b4-and-patch-attestation

It boils down to:

  $ pip install b4
  $ b4 am -v2 20210112110647.627783-1-a.darw...@linutronix.de

Kind regards,

--
Ahmed S. Darwish
Linutronix GmbH


[PATCH v3 02/19] scsi: libsas and users: Remove notifier indirection

2021-01-12 Thread Ahmed S. Darwish
From: John Garry 

LLDDs report events to libsas with .notify_port_event and
.notify_phy_event callbacks.

These callbacks are fixed and so there is no reason why the functions
cannot be called directly, so do that.

This neatens the code slightly, makes it more obvious, and reduces
function pointer usage, which is generally a good thing. Downside is that
there are 2x more symbol exports.

[a.darw...@linutronix.de: Remove the now unused "sas_ha" local variables]
Signed-off-by: John Garry 
Signed-off-by: Ahmed S. Darwish 
---
 Documentation/scsi/libsas.rst  |  8 ++
 drivers/scsi/aic94xx/aic94xx_scb.c | 20 ++---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 12 +++-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  3 +-
 drivers/scsi/isci/port.c   |  7 ++---
 drivers/scsi/libsas/sas_event.c| 13 +++--
 drivers/scsi/libsas/sas_init.c |  6 
 drivers/scsi/libsas/sas_internal.h |  1 -
 drivers/scsi/mvsas/mv_sas.c| 14 -
 drivers/scsi/pm8001/pm8001_hwi.c   | 40 --
 drivers/scsi/pm8001/pm8001_sas.c   |  7 ++---
 drivers/scsi/pm8001/pm80xx_hwi.c   | 35 ++
 include/scsi/libsas.h  |  7 ++---
 15 files changed, 69 insertions(+), 110 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index f9b77c7879db..6722e352444b 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,12 +189,8 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_port_event)(struct sas_phy *, enum port_event);
-   void (*notify_phy_event)(struct sas_phy *, enum phy_event);
-
-When sas_register_ha() returns, those are set and can be
-called by the LLDD to notify the SAS layer of such events
-the SAS layer.
+   void sas_notify_port_event(struct sas_phy *, enum port_event);
+   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
 
 The port notification::
 
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 13677973da5c..4a4e8aa227c5 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -68,7 +68,6 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
 struct done_list_struct *dl)
 {
struct asd_ha_struct *asd_ha = ascb->ha;
-   struct sas_ha_struct *sas_ha = _ha->sas_ha;
int phy_id = dl->status_block[0] & DL_PHY_MASK;
struct asd_phy *phy = _ha->phys[phy_id];
 
@@ -81,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -102,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
break;
}
 }
@@ -222,7 +221,6 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
int edb_el = edb_id + ascb->edb_index;
struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
struct asd_phy *phy = >ha->phys[phy_id];
-   struct sas_ha_struct *sas_ha = phy->sas_phy.ha;
u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
 
size = min(size, (u16) sizeof(phy->frame_rcvd));
@@ -234,7 +232,7 @@ static void asd_bytes_dma

Re: [PATCH v2 02/19] scsi: libsas and users: Remove notifier indirection

2021-01-12 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 11:36:21AM +, John Garry wrote:
> On 12/01/2021 11:06, Ahmed S. Darwish wrote:
> > From: John Garry
> >
> > The LLDDs report events to libsas with .notify_port_event and
> > .notify_phy_event callbacks.
> >
> > These callbacks are fixed and so there is no reason why we cannot call the
> > functions directly, so do that.
> >
> > This neatens the code slightly.
> >
> > [a.darw...@linutronix.de: Remove the now unused "sas_ha" local variables]
> > Signed-off-by: John Garry
>
> Don't forget your signed-off-by :)
>

Oh, yes.

> >
> > diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
> > index f9b77c7879db..a183b1d84713 100644
> > --- a/Documentation/scsi/libsas.rst
> > +++ b/Documentation/scsi/libsas.rst
> > @@ -189,8 +189,8 @@ num_phys
> >   The event interface::
> > /* LLDD calls these to notify the class of an event. */
> > -   void (*notify_port_event)(struct sas_phy *, enum port_event);
> > -   void (*notify_phy_event)(struct sas_phy *, enum phy_event);
> > +   void sas_notify_port_event(struct sas_phy *, enum port_event);
> > +   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
> >   When sas_register_ha() returns, those are set and can be
> >   called by the LLDD to notify the SAS layer of such events
>
> Maybe this was missed in the rebase, but I think that this comment can go/be
> changed at some stage.
>

Yeah, I pulled the patch yesterday from:

  
https://github.com/hisilicon/kernel-dev/commit/87fcd7e113dc05b7933260e7fa4588dc3730cc2a

Lemme check if there are any other differences.

Thanks,
--
Ahmed S. Darwish


Re: [PATCH] MAINTAINERS: Remove intel-linux-...@intel.com for INTEL C600 SAS DRIVER

2021-01-12 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 07:11:30PM +0800, John Garry wrote:
> The mail address intel-linux-...@intel.com bounces for Ahmed and I, so
> just remove it.
>
> Cc: Ahmed S. Darwish 
> Cc: Artur Paszkiewicz 
> Signed-off-by: John Garry 
>

Acked-by: Ahmed S. Darwish 


Re: [PATCH] scsi: libsas and users: Remove notifier indirection

2021-01-12 Thread Ahmed S. Darwish
Hi John,

On Tue, Jan 12, 2021 at 01:28:32AM +0800, John Garry wrote:
> LLDDs report events to libsas with .notify_port_event and
> .notify_phy_event callbacks.
>
> These callbacks are fixed and so there is no reason why the functions
> cannot be called directly, so do that.
>
> This neatens the code slightly, makes it more obvious, and reduces
> function pointer usage, which is generally a good thing. Downside is that
> there are 2x more symbol exports.
>
> Signed-off-by: John Garry 
>

Since this patch necessitates a careful manual rebase of _every_ patch
in my series, I've included it at the top of my v2 submission and
rebased everything on top:

https://lkml.kernel.org/r/20210112110647.627783-1-a.darw...@linutronix.de

Some left-over 'sas_ha' local variables were removed, and I've mentioned
that in the commit log of course.

Thanks!

--
Ahmed S. Darwish
Linutronix GmbH


[PATCH v2 18/19] scsi: mvsas: Switch back to original libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/scsi/mvsas/mv_sas.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index e80f760f8abd..9336e2987879 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -229,7 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, 
gfp_t gfp_flags)
return;
}
 
-   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -261,7 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, 
gfp_t gfp_flags)
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
 
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 void mvs_scan_start(struct Scsi_Host *shost)
@@ -1892,7 +1892,7 @@ static void mvs_work_queue(struct work_struct *work)
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
-   sas_notify_phy_event_gfp(sas_phy,
+   sas_notify_phy_event(sas_phy,
PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
@@ -1905,7 +1905,7 @@ static void mvs_work_queue(struct work_struct *work)
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
}
list_del(>entry);
-- 
2.30.0



[PATCH v2 19/19] scsi: libsas: Remove temporarily-added _gfp() API variants

2021-01-12 Thread Ahmed S. Darwish
These variants were added for bisectability. Remove them, as all call
sites have now been convertd to use the original API.

Signed-off-by: Ahmed S. Darwish 
---
 Documentation/scsi/libsas.rst  |  2 --
 drivers/scsi/libsas/sas_event.c| 14 --
 drivers/scsi/libsas/sas_init.c |  7 ---
 drivers/scsi/libsas/sas_internal.h |  2 --
 include/scsi/libsas.h  |  4 
 5 files changed, 29 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 73020c1cb019..e31800d9a1ac 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -191,8 +191,6 @@ The event interface::
/* LLDD calls these to notify the class of an event. */
void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t);
void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t);
-   void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
-   void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
 When sas_register_ha() returns, those are set and can be
 called by the LLDD to notify the SAS layer of such events
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 542831887769..f703115e7a25 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -155,13 +155,6 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
 }
 EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
- gfp_t gfp_flags)
-{
-   return sas_notify_port_event(phy, event, gfp_flags);
-}
-EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
-
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags)
 {
@@ -184,10 +177,3 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event,
return ret;
 }
 EXPORT_SYMBOL_GPL(sas_notify_phy_event);
-
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
-gfp_t gfp_flags)
-{
-   return sas_notify_phy_event(phy, event, gfp_flags);
-}
-EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp);
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 30dd35eb9449..6bfbf5fbd989 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -617,13 +617,6 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy 
*phy,
return event;
 }
 
-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy,
- gfp_t gfp_flags)
-{
-
-   return sas_alloc_event(phy, gfp_flags);
-}
-
 void sas_free_event(struct asd_sas_event *event)
 {
struct asd_sas_phy *phy = event->phy;
diff --git a/drivers/scsi/libsas/sas_internal.h 
b/drivers/scsi/libsas/sas_internal.h
index 9b39fd478328..5eef5a1c1997 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -49,7 +49,6 @@ int  sas_register_phys(struct sas_ha_struct *sas_ha);
 void sas_unregister_phys(struct sas_ha_struct *sas_ha);
 
 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t 
gfp_flags);
-struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, gfp_t 
gfp_flags);
 void sas_free_event(struct asd_sas_event *event);
 
 int  sas_register_ports(struct sas_ha_struct *sas_ha);
@@ -78,7 +77,6 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id,
 int sas_smp_get_phy_events(struct sas_phy *phy);
 
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, gfp_t 
flags);
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, 
gfp_t flags);
 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
 struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
 struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index fda56e151695..9271d7a49b90 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -706,9 +706,5 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
  gfp_t gfp_flags);
 int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags);
-int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
- gfp_t gfp_flags);
-int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
-gfp_t gfp_flags);
 
 #endif /* _SASLIB_H_ */
-- 
2.30.0



[PATCH v2 16/19] scsi: libsas: Switch back to original event notifiers API

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original event notifiers API, while still passing GFP
context.  The _gfp() notifier variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/libsas/sas_event.c | 6 +++---
 drivers/scsi/libsas/sas_init.c  | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 3d0cc407b33f..542831887769 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
 
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
-   sas_notify_port_event_gfp(sas_phy,
+   sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD, GFP_KERNEL);
}
mutex_unlock(>disco_mutex);
@@ -141,7 +141,7 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event,
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   ev = sas_alloc_event(phy, gfp_flags);
if (!ev)
return -ENOMEM;
 
@@ -171,7 +171,7 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event,
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   ev = sas_alloc_event(phy, gfp_flags);
if (!ev)
return -ENOMEM;
 
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 0dc38385ecbd..30dd35eb9449 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -404,7 +404,7 @@ void sas_resume_ha(struct sas_ha_struct *ha)
 
if (phy->suspended) {
dev_warn(>phy->dev, "resume timeout\n");
-   sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT, 
GFP_KERNEL);
+   sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT, 
GFP_KERNEL);
}
}
 
@@ -603,7 +603,7 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy 
*phy,
if (cmpxchg(>in_shutdown, 0, 1) == 0) {
pr_notice("The phy%d bursting events, shut it 
down.\n",
  phy->id);
-   sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN, 
gfp_flags);
+   sas_notify_phy_event(phy, PHYE_SHUTDOWN, 
gfp_flags);
}
} else {
/* Do not support PHY control, stop allocating events */
-- 
2.30.0



[PATCH v2 14/19] scsi: aic94xx: Switch back to original libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/scsi/aic94xx/aic94xx_scb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 18422a3f9ff0..5e19efb38e36 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -80,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -88,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -101,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);
break;
}
 }
@@ -232,7 +232,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_notify_port_event_gfp(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -268,7 +268,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb 
*ascb,
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
 
if (retries_left == 0) {
int num = 1;
@@ -313,7 +313,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event_gfp(sas_phy,PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy,PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
break;
 
case LmUNKNOWNP:
@@ -334,7 +334,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
/* The sequencer disables all phys on that port.
 * We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_HARD_RESET, 
GFP_ATOMIC);
break;
 
default:
@@ -565,7 +565,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
/* the device is gone */
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event_gfp(sas_phy, PORTE_TIMER_EVENT, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT, GFP_ATOMIC);
brea

[PATCH v2 11/19] scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are the context analysis for modified functions:

=> hisi_sas_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags:

  * hisi_sas_main.c:
  --

hisi_sas_phyup_work(): workqueue context
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_controller_reset_done(): has an msleep()
  -> hisi_sas_rescan_topology()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_debug_I_T_nexus_reset(): calls wait_for_completion_timeout()
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

  * hisi_sas_v1_hw.c:
  ---

int_abnormal_v1_hw(): irq handler
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

  * hisi_sas_v[23]_hw.c:
  --

int_phy_updown_v[23]_hw(): irq handler
  -> phy_down_v[23]_hw()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

=> int_bcast_v1_hw() and phy_bcast_v3_hw():

Both are invoked exclusively from irq handlers. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 25 ++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  5 +++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  5 +++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  5 +++--
 5 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e821dd32dd28..873bfffa626d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -637,7 +637,8 @@ extern void hisi_sas_scan_start(struct Scsi_Host *shost);
 extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
 extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
int enable);
-extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
+extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy,
+ gfp_t gfp_flags);
 extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 76f8fc3fad59..f781b52c6441 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -612,7 +612,8 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t 
gfp_flags,
return rc;
 }
 
-static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
+static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no,
+gfp_t gfp_flags)
 {
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -626,7 +627,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
return;
}
 
-   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -654,7 +655,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
}
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
@@ -860,7 +861,7 @@ static void hisi_sas_phyup_work(struct work_struct *work)
 
if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP)
hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no);
-   hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+   hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL);
 }
 
 static void hisi_sas_linkreset_work(struct work_struct *work)
@@ -1429,11 +1430,12 @@ static void hisi_sas_rescan_topology(struct hisi_hba 
*hisi_hba, u32 state)
_sas_port = sas_port;
 
if (dev_is_expander(dev->dev_type))
-   sas_notify_port_event(sas_phy,
-   PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,
+   PORTE_BROADCAST_RCVD,
+   GFP_KERNEL);
}
} else {
-   hisi_sas_phy_down(hisi_hba, phy_

[PATCH v2 07/19] scsi: isci: port: broadcast change: Pass gfp_t flags

2021-01-12 Thread Ahmed S. Darwish
G)
-> enter SCI PHY state: *SCI_PHY_RESETTING*
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

[2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 10136ae466e2..e50c3b0deeb3 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,7 +164,8 @@ static void isci_port_bc_change_received(struct isci_host 
*ihost,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, >sas_phy);
 
-   sas_notify_port_event(>sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(>sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
sci_port_bcn_enable(iport);
 }
 
-- 
2.30.0



[PATCH v2 17/19] scsi: isci: Switch back to original libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index e50c3b0deeb3..448a8c31ba35 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,8 +164,8 @@ static void isci_port_bc_change_received(struct isci_host 
*ihost,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, >sas_phy);
 
-   sas_notify_port_event_gfp(>sas_phy,
- PORTE_BROADCAST_RCVD, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
sci_port_bcn_enable(iport);
 }
 
@@ -224,8 +224,8 @@ static void isci_port_link_up(struct isci_host *isci_host,
/* Notify libsas that we have an address frame, if indeed
 * we've found an SSP, SMP, or STP target */
if (success)
-   sas_notify_port_event_gfp(>sas_phy,
- PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(>sas_phy,
+ PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 
@@ -271,8 +271,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
 * isci_port_deformed and isci_dev_gone functions.
 */
sas_phy_disconnected(_phy->sas_phy);
-   sas_notify_phy_event_gfp(_phy->sas_phy,
-PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
+   sas_notify_phy_event(_phy->sas_phy,
+PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
 
dev_dbg(_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
-- 
2.30.0



[PATCH v2 12/19] scsi: libsas: event notifiers API: Add gfp_t flags parameter

2021-01-12 Thread Ahmed S. Darwish
All call-sites of below libsas APIs:

  - sas_alloc_event()
  - sas_notify_port_event()
  - sas_notify_phy_event()

have been converted to use the _gfp()-suffixed version.  Modify the
original APIs above to take a gfp_t flags parameter by default.

For bisectability, call-sites will be modified again to use the original
libsas APIs (while passing gfp_t). The temporary _gfp()-suffixed
versions can then be removed.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  4 +-
 drivers/scsi/libsas/sas_event.c| 61 +-
 drivers/scsi/libsas/sas_init.c | 12 ++
 drivers/scsi/libsas/sas_internal.h |  4 +-
 include/scsi/libsas.h  |  6 ++-
 5 files changed, 30 insertions(+), 57 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 0cb0f9ce5e23..73020c1cb019 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,8 +189,8 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void sas_notify_port_event(struct sas_phy *, enum port_event);
-   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
+   void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t);
+   void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t);
void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 922056644da5..3d0cc407b33f 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -132,14 +132,19 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-static int __sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event,
-  struct asd_sas_event *ev)
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event,
+ gfp_t gfp_flags)
 {
struct sas_ha_struct *ha = phy->ha;
+   struct asd_sas_event *ev;
int ret;
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -148,41 +153,28 @@ static int __sas_notify_port_event(struct asd_sas_phy 
*phy, enum port_event even
 
return ret;
 }
+EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
 int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
  gfp_t gfp_flags)
 {
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
+   return sas_notify_port_event(phy, event, gfp_flags);
 }
 EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
 
-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
-}
-EXPORT_SYMBOL_GPL(sas_notify_port_event);
-
-static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
-enum phy_event event,
-struct asd_sas_event *ev)
+int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
+gfp_t gfp_flags)
 {
struct sas_ha_struct *ha = phy->ha;
+   struct asd_sas_event *ev;
int ret;
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -191,28 +183,11 @@ static inline int __sas_notify_phy_event(struct 
asd_sas_phy *phy,
 
return ret;
 }
+EXPORT_SYMBOL_GPL(sas_notify_phy_event);
 
 int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags)
 {
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_phy_event(phy, event, ev);
+   return sas_notify_phy_event(phy, event, gfp_flags);
 }
 EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp);
-
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_phy_event(phy, event, ev);
-}
-EXPORT_SYMBOL_GPL(sas_notify_phy_event);
diff --git a/drivers/scsi

[PATCH v2 15/19] scsi: pm80xx: Switch back to original libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Cc: Jack Wang 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 38 
 drivers/scsi/pm8001/pm8001_sas.c |  4 ++--
 drivers/scsi/pm8001/pm80xx_hwi.c | 28 +++
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 85b9a168794e..a7dcfa68ea83 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3179,7 +3179,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info 
*pm8001_ha, int i)
pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 /* Get the link rate speed  */
@@ -3336,7 +3336,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, >sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3379,7 +3379,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)>sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3726,11 +3726,11 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
@@ -3739,7 +3739,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
-   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR, 
GFP_ATOMIC);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
@@ -3750,20 +3750,20 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
break;
case HW_EVENT_PHY_ERROR:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
sas_phy_disconnected(>sas_phy);
phy->phy_attached = 0;
-   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR, 
GFP_ATOMIC);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);
break;
case HW_EVENT_BROADCAST_EXP:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");
spin_lock_irqsav

[PATCH v2 13/19] scsi: hisi_sas: Switch back to original libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
libsas event notifiers required an extension where gfp_t flags must be
explicitly passed. For bisectability, a temporary _gfp() variant of such
functions were added. All call sites then got converted use the _gfp()
variants and explicitly pass GFP context. Having no callers left, the
original libsas notifiers were then modified to accept gfp_t flags by
default.

Switch back to the original libas API, while still passing GFP context.
The libsas _gfp() variants will be removed afterwards.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 8 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f781b52c6441..625327e99b06 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -627,7 +627,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no,
return;
}
 
-   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -655,7 +655,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no,
}
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
+   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
@@ -1430,7 +1430,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba 
*hisi_hba, u32 state)
_sas_port = sas_port;
 
if (dev_is_expander(dev->dev_type))
-   sas_notify_port_event_gfp(sas_phy,
+   sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD,
GFP_KERNEL);
}
@@ -2209,7 +2209,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int 
phy_no, int rdy,
return;
}
/* Phy down and not ready */
-   sas_notify_phy_event_gfp(sas_phy, PHYE_LOSS_OF_SIGNAL, 
gfp_flags);
+   sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL, gfp_flags);
sas_phy_disconnected(sas_phy);
 
if (port) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index b0a72ffce4f0..c33f2881d3c4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1423,7 +1423,7 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p)
}
 
if (!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
 
 end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index d8f8fb2ed63b..a9de1939c426 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2825,7 +2825,7 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 CHL_INT0_SL_RX_BCST_ACK_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 87392de60e9d..9ffc429c8d42 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1607,7 +1607,7 @@ static irqreturn_t phy_bcast_v3_hw(int phy_no, struct 
hisi_hba *hisi_hba)
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, _hba->flags))
-   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
+   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 CHL_INT0_S

[PATCH v2 00/19] scsi: libsas: Remove in_interrupt() check

2021-01-12 Thread Ahmed S. Darwish
Hi,

Changelog v2


- Rebase on top of v5.11-rc3

- Rebase on top of John's patch "scsi: libsas and users: Remove notifier
  indirection", as it affects every other patch. Include it in this
  series (patch #2).

- Introduce patches #13 => #19, which modify call sites back to use the
  original libsas notifier function names without _gfp() suffix.

- Collect r-b tags

v1 Submission
-

  https://lkml.kernel.org/r/20201218204354.586951-1-a.darw...@linutronix.de

Cover letter


In the discussion about preempt count consistency across kernel
configurations:

  https://lkml.kernel.org/r/20200914204209.256266...@linutronix.de

it was concluded that the usage of in_interrupt() and related context
checks should be removed from non-core code.

This includes memory allocation mode decisions (GFP_*). In the long run,
usage of in_interrupt() and its siblings should be banned from driver
code completely.

This series addresses SCSI libsas. Basically, the function:

  => drivers/scsi/libsas/sas_init.c:
  struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
  {
...
gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
event = kmem_cache_zalloc(sas_event_cache, flags);
...
  }

is transformed so that callers explicitly pass the gfp_t memory
allocation flags. Affected libsas clients are modified accordingly.

Patches #1, #2 => #7 have "Fixes: " tags and address bugs the were
noticed during the context analysis.

Thanks!

8<--

Ahmed S. Darwish (18):
  Documentation: scsi: libsas: Remove notify_ha_event()
  scsi: libsas: Introduce a _gfp() variant of event notifiers
  scsi: mvsas: Pass gfp_t flags to libsas event notifiers
  scsi: isci: port: link down: Pass gfp_t flags
  scsi: isci: port: link up: Pass gfp_t flags
  scsi: isci: port: broadcast change: Pass gfp_t flags
  scsi: libsas: Pass gfp_t flags to event notifiers
  scsi: pm80xx: Pass gfp_t flags to libsas event notifiers
  scsi: aic94xx: Pass gfp_t flags to libsas event notifiers
  scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers
  scsi: libsas: event notifiers API: Add gfp_t flags parameter
  scsi: hisi_sas: Switch back to original libsas event notifiers
  scsi: aic94xx: Switch back to original libsas event notifiers
  scsi: pm80xx: Switch back to original libsas event notifiers
  scsi: libsas: Switch back to original event notifiers API
  scsi: isci: Switch back to original libsas event notifiers
  scsi: mvsas: Switch back to original libsas event notifiers
  scsi: libsas: Remove temporarily-added _gfp() API variants

John Garry (1):
  scsi: libsas and users: Remove notifier indirection

 Documentation/scsi/libsas.rst  |  5 ++--
 drivers/scsi/aic94xx/aic94xx_scb.c | 20 ++---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 29 +--
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  6 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  6 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  6 ++--
 drivers/scsi/isci/port.c   | 11 +++
 drivers/scsi/libsas/sas_event.c| 27 -
 drivers/scsi/libsas/sas_init.c | 17 ---
 drivers/scsi/libsas/sas_internal.h |  5 ++--
 drivers/scsi/mvsas/mv_sas.c| 24 +++-
 drivers/scsi/pm8001/pm8001_hwi.c   | 40 --
 drivers/scsi/pm8001/pm8001_sas.c   | 12 +++-
 drivers/scsi/pm8001/pm80xx_hwi.c   | 37 +++-
 include/scsi/libsas.h  |  9 +++---
 16 files changed, 115 insertions(+), 142 deletions(-)

base-commit: 7c53f6b671f4aba70ff15e1b05148b10d58c2837
--
2.30.0


[PATCH v2 10/19] scsi: aic94xx: Pass gfp_t flags to libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  aic94xx_hwi.c: asd_dl_tasklet_handler()
-> asd_ascb::tasklet_complete()
== escb_tasklet_complete()
  -> aic94xx_scb.c: asd_phy_event_tasklet()
  -> aic94xx_scb.c: asd_bytes_dmaed_tasklet()
  -> aic94xx_scb.c: asd_link_reset_err_tasklet()
  -> aic94xx_scb.c: asd_primitive_rcvd_tasklet()

All functions are invoked by escb_tasklet_complete(), which is invoked
by the tasklet handler. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/scsi/aic94xx/aic94xx_scb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 4a4e8aa227c5..18422a3f9ff0 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -80,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -88,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, 
GFP_ATOMIC);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -101,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR, 
GFP_ATOMIC);
break;
}
 }
@@ -232,7 +232,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(>sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -268,7 +268,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb 
*ascb,
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, GFP_ATOMIC);
 
if (retries_left == 0) {
int num = 1;
@@ -313,7 +313,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event(sas_phy,PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
break;
 
case LmUNKNOWNP:
@@ -334,7 +334,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
/* The sequencer disables all phys on that port.
 * We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
+   sas_notify_port_event_gfp(sas_phy, PORTE_HARD_RESET, 
GFP_ATOMIC);
break;
 
default:
@@ -565,7 +565,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
/* the device is gone */
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT);
+   sas_notify_port_event_gfp(sas_phy, PORTE_TIMER_EVENT, 
GFP_ATOMIC);
break;
default:
ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
-- 
2.30.0



[PATCH v2 08/19] scsi: libsas: Pass gfp_t flags to event notifiers

2021-01-12 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  - sas_enable_revalidation(): process, acquires mutex
  - sas_resume_ha(): process, calls wait_event_timeout()

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/libsas/sas_event.c | 3 ++-
 drivers/scsi/libsas/sas_init.c  | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 31fc32b9bb4e..922056644da5 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,8 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
 
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy,
+   PORTE_BROADCAST_RCVD, GFP_KERNEL);
}
mutex_unlock(>disco_mutex);
 }
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 1c78347fbcc6..b8567902f0ce 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -404,7 +404,7 @@ void sas_resume_ha(struct sas_ha_struct *ha)
 
if (phy->suspended) {
dev_warn(>phy->dev, "resume timeout\n");
-   sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT);
+   sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT, 
GFP_KERNEL);
}
}
 
-- 
2.30.0



[PATCH v2 09/19] scsi: pm80xx: Pass gfp_t flags to libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Call chain analysis, pm8001_hwi.c:

  pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || 
pm8001_tasklet()
-> PM8001_CHIP_DISP->isr() = pm80xx_chip_isr()
  -> process_oq [spin_lock_irqsave(_ha->lock, ...)]
-> process_one_iomb()
  -> mpi_hw_event()
-> hw_event_sas_phy_up()
  -> pm8001_bytes_dmaed()
-> hw_event_sata_phy_up
  -> pm8001_bytes_dmaed()

All functions are invoked by process_one_iomb(), which is invoked by the
interrupt service routine and the tasklet handler. A similar call chain
is also found at pm80xx_hwi.c. Pass GFP_ATOMIC.

For pm8001_sas.c, pm8001_phy_control() runs in task context as it calls
wait_for_completion() and msleep().  Pass GFP_KERNEL.

Signed-off-by: Ahmed S. Darwish 
Cc: Jack Wang 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 38 
 drivers/scsi/pm8001/pm8001_sas.c |  9 
 drivers/scsi/pm8001/pm80xx_hwi.c | 30 -
 3 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index dd15246d5b03..85b9a168794e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3179,7 +3179,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info 
*pm8001_ha, int i)
pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 /* Get the link rate speed  */
@@ -3336,7 +3336,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, >sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3379,7 +3379,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
-   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)>sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3726,11 +3726,11 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
break;
case HW_EVENT_SATA_SPINUP_HOLD:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
-   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
-   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(>sas_phy, PHYE_LOSS_OF_SIGNAL, 
GFP_ATOMIC);
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
@@ -3739,7 +3739,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
-   sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, 
GFP_ATOMIC);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
@@ -3750,20 +3750,20 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
break;
case HW_EVENT_PHY_ERROR:
pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
sas_phy_disconnected(>sas_phy);
phy->phy_attached = 0;
- 

[PATCH v2 06/19] scsi: isci: port: link up: Pass gfp_t flags

2021-01-12 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

libsas sas_notify_port_event() is called from isci_port_link_up().
Below is the context analysis for all of its call chains:

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
-> port_config.c: sci_port_configuration_agent_initialize()
  -> sci_mpc_agent_validate_phy_configuration()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

port_config.c: apc_agent_timeout(), atomic, timer callback  (*)
  -> sci_apc_agent_configure_ports()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1]
  -> phy.c: sci_phy_starting_final_substate_enter()
-> phy.c: sci_change_state(SCI_PHY_READY)
  -> enter SCI state: *SCI_PHY_READY*
-> phy.c: sci_phy_ready_state_enter()
  -> host.c: sci_controller_link_up()
-> .link_up_handler()
== port_config.c: sci_apc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])
== port_config.c: sci_mpc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])

port_config.c: mpc_agent_timeout(), atomic, timer callback  (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> ->link_up_handler()
  == port_config.c: sci_apc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])
  == port_config.c: sci_mpc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])

[A] port.c: sci_port_link_up()
  -> sci_port_activate_phy()
-> isci_port_link_up()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

[1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*
---

host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, all the call-chains are
atomic.  Pass GFP_ATOMIC to libsas port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index a3c58718c260..10136ae466e2 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -223,7 +223,8 @@ static void isci_port_link_up(struct isci_host *isci_host,
/* Notify libsas that we have an address frame, if indeed
 * we've found an SSP, SMP, or STP target */
if (success)
-   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(>sas_phy,
+ PORTE_BYTES_DMAED, GFP_ATOMIC);
 }
 
 
-- 
2.30.0



[PATCH v2 05/19] scsi: isci: port: link down: Pass gfp_t flags

2021-01-12 Thread Ahmed S. Darwish
-> enter port state *SCI_PORT_READY*

[1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

[2] Call chains for entering state: *SCI_PHY_STOPPED*
-

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
  -> phy.c: sci_phy_initialize()
-> phy.c: sci_phy_link_layer_initialization()
  -> phy.c: sci_change_state(SCI_PHY_STOPPED)

init.c: PCI ->remove() || PM_OPS ->suspend,  process context(+)
  -> host.c: isci_host_deinit()
-> sci_controller_stop_phys()
  -> phy.c: sci_phy_stop()
-> sci_change_state(SCI_PHY_STOPPED)

phy.c: isci_phy_control()
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_phy_stop(), atomic (*)
-> sci_change_state(SCI_PHY_STOPPED)

[3] Call chains for entering state: *SCI_PHY_STARTING*
--

phy.c: phy_sata_timeout(), atimer, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_change_state(SCI_PHY_STARTING)

host.c: phy_startup_timeout(), atomic, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

host.c: isci_host_start()   (@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_start(), atomic (*)
-> sci_controller_start_next_phy()
  -> sci_phy_start()
-> sci_change_state(SCI_PHY_STARTING)

phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*)
  -> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_phy_starting_final_substate_enter()
  -> sci_change_state(SCI_PHY_READY)
-> Enter SCI state: *SCI_PHY_READY*
  -> sci_phy_ready_state_enter()
-> host.c: sci_controller_link_up()
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

phy.c: sci_phy_event_handler(), atomic, discussed earlier   (*)
  -> sci_change_state(SCI_PHY_STARTING), 11 instances

phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed  (*)
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
phy event notifier.

Note, The now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8d9349738067..a3c58718c260 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -269,8 +269,8 @@ static void isci_port_link_down(struct isci_host *isci_host,
 * isci_port_deformed and isci_dev_gone functions.
 */
sas_phy_disconnected(_phy->sas_phy);
-   sas_notify_phy_event(_phy->sas_phy,
-  PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(_phy->sas_phy,
+PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
 
dev_dbg(_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
-- 
2.30.0



[PATCH v2 04/19] scsi: mvsas: Pass gfp_t flags to libsas event notifiers

2021-01-12 Thread Ahmed S. Darwish
mvsas calls the non _gfp version of the libsas event notifiers API,
leading to the buggy call chains below:

  mvsas/mv_sas.c: mvs_work_queue() [process context]
  spin_lock_irqsave(mvs_info::lock, )
-> libsas/sas_event.c: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> libsas/sas_event.c: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Use the new event notifiers API instead, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are context analysis for the modified functions:

=> mvs_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags. Call chains:

  scsi_scan.c: do_scsi_scan_host() [has msleep()]
-> shost->hostt->scan_start()
-> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = 
mvs_scan_start()]
-> mvsas/mv_sas.c: mvs_scan_start()
  -> mvs_bytes_dmaed(..., GFP_KERNEL)

  mvsas/mv_sas.c: mvs_work_queue()
  spin_lock_irqsave(mvs_info::lock,)
-> mvs_bytes_dmaed(..., GFP_ATOMIC)

  mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr()
-> mvsas/mv_chips.h: mvs_int_full()
  -> mvsas/mv_sas.c: mvs_int_port()
-> mvs_bytes_dmaed(..., GFP_ATOMIC);

=> mvs_work_queue():

Invoked from process context, but it calls all the libsas event notifier
APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/mvsas/mv_sas.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index e5e3e95f78b0..e80f760f8abd 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -216,7 +216,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, 
u32 off_lo,
MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi);
 }
 
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
+static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags)
 {
struct mvs_phy *phy = >phy[i];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -229,7 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
return;
}
 
-   sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -261,7 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
 
-   sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 void mvs_scan_start(struct Scsi_Host *shost)
@@ -277,7 +277,7 @@ void mvs_scan_start(struct Scsi_Host *shost)
for (j = 0; j < core_nr; j++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
for (i = 0; i < mvi->chip->n_phy; ++i)
-   mvs_bytes_dmaed(mvi, i);
+   mvs_bytes_dmaed(mvi, i, GFP_KERNEL);
}
mvs_prv->scan_finished = 1;
 }
@@ -1892,20 +1892,20 @@ static void mvs_work_queue(struct work_struct *work)
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
-   sas_notify_phy_event(sas_phy,
-   PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event_gfp(sas_phy,
+   PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
mvs_update_phyinfo(mvi, phy_no, 1);
-   mvs_bytes_dmaed(mvi, phy_no);
+   mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC);
mvs_port_notify_formed(sas_phy, 0);
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
-   sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
 

[PATCH v2 03/19] scsi: libsas: Introduce a _gfp() variant of event notifiers

2021-01-12 Thread Ahmed S. Darwish
sas_alloc_event() uses in_interrupt() to decide which allocation should
be used.

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be separated or the context be conveyed in an argument passed by
the caller, which usually knows the context.

The in_interrupt() check is also only partially correct, because it
fails to choose the correct code path when just preemption or interrupts
are disabled. For example, as in the following call chain:

  mvsas/mv_sas.c: mvs_work_queue() [process context]
  spin_lock_irqsave(mvs_info::lock, )
-> libsas/sas_event.c: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> libsas/sas_event.c: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and
sas_notify_phy_event_gfp(), which all behave like the non _gfp()
variants but use a caller-passed GFP mask for allocations.

For bisectability, all callers will be modified first to pass GFP
context, then the non _gfp() libsas API variants will be modified to
take a gfp_t by default.

Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event 
lost")
Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  2 +
 drivers/scsi/libsas/sas_event.c| 66 --
 drivers/scsi/libsas/sas_init.c | 20 ++---
 drivers/scsi/libsas/sas_internal.h |  2 +
 include/scsi/libsas.h  |  4 ++
 5 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index a183b1d84713..0cb0f9ce5e23 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -191,6 +191,8 @@ The event interface::
/* LLDD calls these to notify the class of an event. */
void sas_notify_port_event(struct sas_phy *, enum port_event);
void sas_notify_phy_event(struct sas_phy *, enum phy_event);
+   void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, 
gfp_t);
+   void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
 
 When sas_register_ha() returns, those are set and can be
 called by the LLDD to notify the SAS layer of such events
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 112a1b76f63b..31fc32b9bb4e 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -131,18 +131,14 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+static int __sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event,
+  struct asd_sas_event *ev)
 {
-   struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -151,20 +147,41 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum 
port_event event)
 
return ret;
 }
+
+int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
+ gfp_t gfp_flags)
+{
+   struct asd_sas_event *ev;
+
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
+EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
+
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+{
+   struct asd_sas_event *ev;
+
+   ev = sas_alloc_event(phy);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
 EXPORT_SYMBOL_GPL(sas_notify_port_event);
 
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
+enum phy_event event,
+struct asd_sas_event *ev)
 {
-   struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -173,5 +190,28 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event)
 
return ret;
 }
+
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum

[PATCH v2 02/19] scsi: libsas and users: Remove notifier indirection

2021-01-12 Thread Ahmed S. Darwish
From: John Garry 

The LLDDs report events to libsas with .notify_port_event and
.notify_phy_event callbacks.

These callbacks are fixed and so there is no reason why we cannot call the
functions directly, so do that.

This neatens the code slightly.

[a.darw...@linutronix.de: Remove the now unused "sas_ha" local variables]
Signed-off-by: John Garry 
---
 Documentation/scsi/libsas.rst  |  4 +--
 drivers/scsi/aic94xx/aic94xx_scb.c | 20 ++---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 12 +++-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  3 +-
 drivers/scsi/isci/port.c   |  7 ++---
 drivers/scsi/libsas/sas_event.c| 13 +++--
 drivers/scsi/libsas/sas_init.c |  6 
 drivers/scsi/libsas/sas_internal.h |  1 -
 drivers/scsi/mvsas/mv_sas.c| 14 -
 drivers/scsi/pm8001/pm8001_hwi.c   | 40 --
 drivers/scsi/pm8001/pm8001_sas.c   |  7 ++---
 drivers/scsi/pm8001/pm80xx_hwi.c   | 35 ++
 include/scsi/libsas.h  |  7 ++---
 15 files changed, 69 insertions(+), 106 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index f9b77c7879db..a183b1d84713 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,8 +189,8 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_port_event)(struct sas_phy *, enum port_event);
-   void (*notify_phy_event)(struct sas_phy *, enum phy_event);
+   void sas_notify_port_event(struct sas_phy *, enum port_event);
+   void sas_notify_phy_event(struct sas_phy *, enum phy_event);
 
 When sas_register_ha() returns, those are set and can be
 called by the LLDD to notify the SAS layer of such events
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index 13677973da5c..4a4e8aa227c5 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -68,7 +68,6 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
 struct done_list_struct *dl)
 {
struct asd_ha_struct *asd_ha = ascb->ha;
-   struct sas_ha_struct *sas_ha = _ha->sas_ha;
int phy_id = dl->status_block[0] & DL_PHY_MASK;
struct asd_phy *phy = _ha->phys[phy_id];
 
@@ -81,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_DONE);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -102,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
break;
}
 }
@@ -222,7 +221,6 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
int edb_el = edb_id + ascb->edb_index;
struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
struct asd_phy *phy = >ha->phys[phy_id];
-   struct sas_ha_struct *sas_ha = phy->sas_phy.ha;
u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
 
size = min(size, (u16) sizeof(phy->frame_rcvd));
@@ -234,7 +232,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_ha->notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ 

[PATCH v2 01/19] Documentation: scsi: libsas: Remove notify_ha_event()

2021-01-12 Thread Ahmed S. Darwish
The ->notify_ha_event() hook has long been removed from the libsas event
interface.

Remove it from documentation.

Fixes: 042ebd293b86 ("scsi: libsas: kill useless ha_event and do some cleanup")
Signed-off-by: Ahmed S. Darwish 
Reviewed-by: John Garry 
Cc: sta...@vger.kernel.org
---
 Documentation/scsi/libsas.rst | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 7216b5d25800..f9b77c7879db 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,7 +189,6 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);
void (*notify_port_event)(struct sas_phy *, enum port_event);
void (*notify_phy_event)(struct sas_phy *, enum phy_event);
 
-- 
2.30.0



Re: [PATCH] scsi: libsas and users: Remove notifier indirection

2021-01-11 Thread Ahmed S. Darwish
On Mon, Jan 11, 2021 at 05:44:17PM +, John Garry wrote:
> On 11/01/2021 17:41, Ahmed S. Darwish wrote:
> > On Tue, Jan 12, 2021 at 01:28:32AM +0800, John Garry wrote:
> > ...
> > > index a920eced92ec..6a51abdc59ae 100644
> > > --- a/drivers/scsi/mvsas/mv_sas.c
> > > +++ b/drivers/scsi/mvsas/mv_sas.c
> > > @@ -230,7 +230,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int 
> > > i)
> > >   }
> > >
> > >   sas_ha = mvi->sas;
> > > - sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
> > > + sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
> > >
> >
> > Minor point: "sas_ha" is now not used anywhere; it should be removed.
> > .
> >
>
> ah, yes, it can be removed.
>

Similarly for drivers/scsi/pm8001/pm8001_sas.c.

(Just discovering these while integrating your patch at the top of my
 series).

> BTW, on separate topic, did intel-linux-...@intel.com bounce for you?
>

Yup :)

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH] scsi: libsas and users: Remove notifier indirection

2021-01-11 Thread Ahmed S. Darwish
On Tue, Jan 12, 2021 at 01:28:32AM +0800, John Garry wrote:
...
> index a920eced92ec..6a51abdc59ae 100644
> --- a/drivers/scsi/mvsas/mv_sas.c
> +++ b/drivers/scsi/mvsas/mv_sas.c
> @@ -230,7 +230,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
>   }
>
>   sas_ha = mvi->sas;
> - sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
> + sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
>

Minor point: "sas_ha" is now not used anywhere; it should be removed.


Re: [PATCH 00/11] scsi: libsas: Remove in_interrupt() check

2021-01-11 Thread Ahmed S. Darwish
On Mon, Jan 11, 2021 at 01:59:25PM +, John Garry wrote:
...
> To me, what you're doing seems fine.
>
...
>
> Just one other thing to mention:
> I have a patch to remove the indirection in libsas notifiers:
> https://github.com/hisilicon/kernel-dev/commit/87fcd7e113dc05b7933260e7fa4588dc3730cc2a
>
> I was going to send it today. Hopefully, if community has no problem with
> it, you can make your changes with that in mind.
>

Perfect. I'll rebase on top of it if everything is OK there.

I'll also append some patches to the series, removing the _gfp() suffix,
per your request earlier:

  https://lkml.kernel.org/r/68957d37-c789-0f0e-f5d1-85fef7f39...@huawei.com

Thanks!

--
Ahmed S. Darwish
Linutronix GmbH


Re: [RFC PATCH 0/1] net: arcnet: Fix RESET sequence

2021-01-11 Thread Ahmed S. Darwish
Hi,

On Tue, Dec 22, 2020 at 10:03:37AM +0100, Ahmed S. Darwish wrote:
...
>
> Included is an RFC patch to fix the points above: if the RESET flag is
> encountered, a workqueue is scheduled to run the generic reset sequence.
>
...

Kind reminder.


Re: [PATCH 00/11] scsi: libsas: Remove in_interrupt() check

2021-01-11 Thread Ahmed S. Darwish
Hi John, Jason,

On Tue, Dec 22, 2020 at 12:54:58PM +, John Garry wrote:
> On 22/12/2020 12:30, Jason Yan wrote:
> > >  return event;
> > >
> > >
> > > So default for phy->ha->event_thres is 32, and I can't imagine that
> >
> > The default value is 1024.
>
> Ah, 32 is the minimum allowed set via sysfs.
>
> >
> > > anyone has ever reconfigured this via sysfs or even required a value
> > > that large. Maybe Jason (cc'ed) knows better. It's an arbitrary
> > > value to say that the PHY is malfunctioning. I do note that there is
> > > the circular path sas_alloc_event() -> sas_notify_phy_event() ->
> > > sas_alloc_event() there also.
> > >
> > > Anyway, if the 32x event memories were per-allocated, maybe there is
> > > a clean method to manage this memory, which even works in atomic
> > > context, so we could avoid this rework (ignoring the context bugs
> > > you reported for a moment). I do also note that the sas_event_cache
> > > size is not huge.
> > >
> >
> > Pre-allocated memory is an option.(Which we have tried at the very
> > beginnig by Wang Yijing.)
>
> Right, I remember this, but I think the concern was having a proper method
> to manage this pre-allocated memory then. And same problem now.
>
> >
> > Or directly use GFP_ATOMIC is maybe better than passing flags from lldds.
> >
>
> I think that if we don't really need this, then should not use it.
>

Kind reminder. Do we have any consensus here?

Thanks,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [RFC PATCH 1/3] chelsio: cxgb: Remove ndo_poll_controller()

2020-12-24 Thread Ahmed S. Darwish
[[ Actually adding Eric to Cc ]]

On Thu, Dec 24, 2020 at 02:11:46PM +0100, Ahmed S. Darwish wrote:
> Since commit ac3d9dd034e5 ("netpoll: make ndo_poll_controller()
> optional"), networking drivers which use NAPI for clearing their TX
> completions should not provide an ndo_poll_controller(). Netpoll simply
> triggers the necessary TX queues cleanup by synchronously calling the
> driver's NAPI poll handler -- with irqs off and a zero budget.
>
> Modify the cxgb's poll method to clear the TX queues upon zero budget.
> Per API requirements, make sure to never consume any RX packet in that
> case (budget=0), and thus also not to increment the budget upon return.
>
> Afterwards, remove ndo_poll_controller().
>
> Link: https://lkml.kernel.org/r/20180921222752.101307-1-eduma...@google.com
> Link: https://lkml.kernel.org/r/a782704a-df97-4e85-b10a-d2268a67d...@fb.com
> References: 822d54b9c2c1 ("netpoll: Drop budget parameter from NAPI polling 
> call hierarchy")
> Signed-off-by: Ahmed S. Darwish 
> Cc: Eric Dumazet 
> ---
>  drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 14 --
>  drivers/net/ethernet/chelsio/cxgb/sge.c   |  9 -
>  2 files changed, 8 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c 
> b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> index 0e4a0f413960..7b5a98330ef7 100644
> --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
> @@ -878,17 +878,6 @@ static int t1_set_features(struct net_device *dev, 
> netdev_features_t features)
>
>   return 0;
>  }
> -#ifdef CONFIG_NET_POLL_CONTROLLER
> -static void t1_netpoll(struct net_device *dev)
> -{
> - unsigned long flags;
> - struct adapter *adapter = dev->ml_priv;
> -
> - local_irq_save(flags);
> - t1_interrupt(adapter->pdev->irq, adapter);
> - local_irq_restore(flags);
> -}
> -#endif
>
>  /*
>   * Periodic accumulation of MAC statistics.  This is used only if the MAC
> @@ -973,9 +962,6 @@ static const struct net_device_ops cxgb_netdev_ops = {
>   .ndo_set_mac_address= t1_set_mac_addr,
>   .ndo_fix_features   = t1_fix_features,
>   .ndo_set_features   = t1_set_features,
> -#ifdef CONFIG_NET_POLL_CONTROLLER
> - .ndo_poll_controller= t1_netpoll,
> -#endif
>  };
>
>  static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
> diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c 
> b/drivers/net/ethernet/chelsio/cxgb/sge.c
> index 2d9c2b5a690a..d6df1a87db0b 100644
> --- a/drivers/net/ethernet/chelsio/cxgb/sge.c
> +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
> @@ -1609,7 +1609,14 @@ static int process_pure_responses(struct adapter 
> *adapter)
>  int t1_poll(struct napi_struct *napi, int budget)
>  {
>   struct adapter *adapter = container_of(napi, struct adapter, napi);
> - int work_done = process_responses(adapter, budget);
> + int work_done = 0;
> +
> + if (budget)
> + work_done = process_responses(adapter, budget);
> + else {
> + /* budget=0 means: don't poll rx data */
> + process_pure_responses(adapter);
> + }
>
>   if (likely(work_done < budget)) {
>   napi_complete_done(napi, work_done);
> --
> 2.29.2
>


[RFC PATCH 3/3] chelsio: cxgb: Do not schedule a workqueue for external interrupts

2020-12-24 Thread Ahmed S. Darwish
cxgb's "elmer0" external interrupt handling code requires task context,
so originally a workqueue was scheduled for it from the hardirq handler.

Now that all of the external interrupt handling, elmer0 included, is run
from a threaded-irq context, just directly call the real handler.

Remove all the workqueue code that is now no longer needed, including
the spinlock used for synchronizing the workqueue's NIC regsiters access
against the irq handler.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/net/ethernet/chelsio/cxgb/common.h |  2 --
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c  | 38 --
 drivers/net/ethernet/chelsio/cxgb/sge.c|  3 --
 drivers/net/ethernet/chelsio/cxgb/subr.c   |  2 +-
 4 files changed, 1 insertion(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb/common.h 
b/drivers/net/ethernet/chelsio/cxgb/common.h
index 6475060649e9..504882e66831 100644
--- a/drivers/net/ethernet/chelsio/cxgb/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb/common.h
@@ -238,7 +238,6 @@ struct adapter {
int msg_enable;
u32 mmio_len;
 
-   struct work_struct ext_intr_handler_task;
struct adapter_params params;
 
/* Terminator modules. */
@@ -256,7 +255,6 @@ struct adapter {
spinlock_t mac_lock;
 
/* guards async operations */
-   spinlock_t async_lock cacheline_aligned;
u32 slow_intr_mask;
int t1powersave;
 };
diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c 
b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index c96bdca4f270..b93e86d4d079 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -905,41 +905,6 @@ static void mac_stats_task(struct work_struct *work)
spin_unlock(>work_lock);
 }
 
-/*
- * Processes elmer0 external interrupts in process context.
- */
-static void ext_intr_task(struct work_struct *work)
-{
-   struct adapter *adapter =
-   container_of(work, struct adapter, ext_intr_handler_task);
-
-   t1_elmer0_ext_intr_handler(adapter);
-
-   /* Now reenable external interrupts */
-   spin_lock_irq(>async_lock);
-   adapter->slow_intr_mask |= F_PL_INTR_EXT;
-   writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
-   writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
-  adapter->regs + A_PL_ENABLE);
-   spin_unlock_irq(>async_lock);
-}
-
-/*
- * Interrupt-context handler for elmer0 external interrupts.
- */
-void t1_elmer0_ext_intr(struct adapter *adapter)
-{
-   /*
-* Schedule a task to handle external interrupts as we require
-* a process context.  We disable EXT interrupts in the interim
-* and let the task reenable them when it's done.
-*/
-   adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
-   writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
-  adapter->regs + A_PL_ENABLE);
-   schedule_work(>ext_intr_handler_task);
-}
-
 void t1_fatal_err(struct adapter *adapter)
 {
if (adapter->flags & FULL_INIT_DONE) {
@@ -1045,11 +1010,8 @@ static int init_one(struct pci_dev *pdev, const struct 
pci_device_id *ent)
 
spin_lock_init(>tpi_lock);
spin_lock_init(>work_lock);
-   spin_lock_init(>async_lock);
spin_lock_init(>mac_lock);
 
-   INIT_WORK(>ext_intr_handler_task,
- ext_intr_task);
INIT_DELAYED_WORK(>stats_update_task,
  mac_stats_task);
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c 
b/drivers/net/ethernet/chelsio/cxgb/sge.c
index f1c402f6b889..9b4ffddbbc05 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -1657,10 +1657,7 @@ irqreturn_t t1_irq_thread(int irq, void *data)
struct sge *sge = adapter->sge;
int handled;
 
-   spin_lock(>async_lock);
handled = t1_slow_intr_handler(adapter);
-   spin_unlock(>async_lock);
-
if (!handled)
sge->stats.unhandled_irqs++;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c 
b/drivers/net/ethernet/chelsio/cxgb/subr.c
index ea0f8741d7cf..197d3bb924ca 100644
--- a/drivers/net/ethernet/chelsio/cxgb/subr.c
+++ b/drivers/net/ethernet/chelsio/cxgb/subr.c
@@ -858,7 +858,7 @@ static int asic_slow_intr(adapter_t *adapter)
if (cause & F_PL_INTR_PCIX)
t1_pci_intr_handler(adapter);
if (cause & F_PL_INTR_EXT)
-   t1_elmer0_ext_intr(adapter);
+   t1_elmer0_ext_intr_handler(adapter);
 
/* Clear the interrupts just processed. */
writel(cause, adapter->regs + A_PL_CAUSE);
-- 
2.29.2



[RFC PATCH 2/3] chelsio: cxgb: Move slow interrupt handling to threaded irqs

2020-12-24 Thread Ahmed S. Darwish
The t1_interrupt() irq handler calls del_timer_sync() down the chain:

   sge.c: t1_interrupt()
 -> subr.c: t1_slow_intr_handler()
   -> asic_slow_intr() || fpga_slow_intr()
 -> t1_pci_intr_handler()
   -> cxgb2.c: t1_fatal_err()   # Cont. at [*]
   -> fpga_slow_intr()
 -> sge.c: t1_sge_intr_error_handler()
   -> cxgb2.c: t1_fatal_err()   # Cont. at [*]

[*] cxgb2.c: t1_fatal_err()
  -> sge.c: t1_sge_stop()
-> timer.c: del_timer_sync()

This is invalid: if an irq handler calls del_timer_sync() on a timer it
has already interrupted, it will loop forever.

Move the slow t1 interrupt handling path, t1_slow_intr_handler(), to a
threaded-irq task context.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c |  6 +++---
 drivers/net/ethernet/chelsio/cxgb/sge.c   | 13 +++--
 drivers/net/ethernet/chelsio/cxgb/sge.h   |  3 ++-
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c 
b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 7b5a98330ef7..c96bdca4f270 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -211,9 +211,9 @@ static int cxgb_up(struct adapter *adapter)
t1_interrupts_clear(adapter);
 
adapter->params.has_msi = !disable_msi && 
!pci_enable_msi(adapter->pdev);
-   err = request_irq(adapter->pdev->irq, t1_interrupt,
- adapter->params.has_msi ? 0 : IRQF_SHARED,
- adapter->name, adapter);
+   err = request_threaded_irq(adapter->pdev->irq, t1_irq, t1_irq_thread,
+  adapter->params.has_msi ? 0 : IRQF_SHARED,
+  adapter->name, adapter);
if (err) {
if (adapter->params.has_msi)
pci_disable_msi(adapter->pdev);
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c 
b/drivers/net/ethernet/chelsio/cxgb/sge.c
index d6df1a87db0b..f1c402f6b889 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -1626,11 +1626,10 @@ int t1_poll(struct napi_struct *napi, int budget)
return work_done;
 }
 
-irqreturn_t t1_interrupt(int irq, void *data)
+irqreturn_t t1_irq(int irq, void *data)
 {
struct adapter *adapter = data;
struct sge *sge = adapter->sge;
-   int handled;
 
if (likely(responses_pending(adapter))) {
writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
@@ -1645,9 +1644,19 @@ irqreturn_t t1_interrupt(int irq, void *data)
napi_enable(>napi);
}
}
+
return IRQ_HANDLED;
}
 
+   return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t t1_irq_thread(int irq, void *data)
+{
+   struct adapter *adapter = data;
+   struct sge *sge = adapter->sge;
+   int handled;
+
spin_lock(>async_lock);
handled = t1_slow_intr_handler(adapter);
spin_unlock(>async_lock);
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.h 
b/drivers/net/ethernet/chelsio/cxgb/sge.h
index a1ba591b3431..4072b3fb312b 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.h
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.h
@@ -74,7 +74,8 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params 
*);
 int t1_sge_configure(struct sge *, struct sge_params *);
 int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
 void t1_sge_destroy(struct sge *);
-irqreturn_t t1_interrupt(int irq, void *cookie);
+irqreturn_t t1_irq(int irq, void *cookie);
+irqreturn_t t1_irq_thread(int irq, void *cookie);
 int t1_poll(struct napi_struct *, int);
 
 netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
-- 
2.29.2



[RFC PATCH 1/3] chelsio: cxgb: Remove ndo_poll_controller()

2020-12-24 Thread Ahmed S. Darwish
Since commit ac3d9dd034e5 ("netpoll: make ndo_poll_controller()
optional"), networking drivers which use NAPI for clearing their TX
completions should not provide an ndo_poll_controller(). Netpoll simply
triggers the necessary TX queues cleanup by synchronously calling the
driver's NAPI poll handler -- with irqs off and a zero budget.

Modify the cxgb's poll method to clear the TX queues upon zero budget.
Per API requirements, make sure to never consume any RX packet in that
case (budget=0), and thus also not to increment the budget upon return.

Afterwards, remove ndo_poll_controller().

Link: https://lkml.kernel.org/r/20180921222752.101307-1-eduma...@google.com
Link: https://lkml.kernel.org/r/a782704a-df97-4e85-b10a-d2268a67d...@fb.com
References: 822d54b9c2c1 ("netpoll: Drop budget parameter from NAPI polling 
call hierarchy")
Signed-off-by: Ahmed S. Darwish 
Cc: Eric Dumazet 
---
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 14 --
 drivers/net/ethernet/chelsio/cxgb/sge.c   |  9 -
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c 
b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
index 0e4a0f413960..7b5a98330ef7 100644
--- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -878,17 +878,6 @@ static int t1_set_features(struct net_device *dev, 
netdev_features_t features)
 
return 0;
 }
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void t1_netpoll(struct net_device *dev)
-{
-   unsigned long flags;
-   struct adapter *adapter = dev->ml_priv;
-
-   local_irq_save(flags);
-   t1_interrupt(adapter->pdev->irq, adapter);
-   local_irq_restore(flags);
-}
-#endif
 
 /*
  * Periodic accumulation of MAC statistics.  This is used only if the MAC
@@ -973,9 +962,6 @@ static const struct net_device_ops cxgb_netdev_ops = {
.ndo_set_mac_address= t1_set_mac_addr,
.ndo_fix_features   = t1_fix_features,
.ndo_set_features   = t1_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-   .ndo_poll_controller= t1_netpoll,
-#endif
 };
 
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c 
b/drivers/net/ethernet/chelsio/cxgb/sge.c
index 2d9c2b5a690a..d6df1a87db0b 100644
--- a/drivers/net/ethernet/chelsio/cxgb/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -1609,7 +1609,14 @@ static int process_pure_responses(struct adapter 
*adapter)
 int t1_poll(struct napi_struct *napi, int budget)
 {
struct adapter *adapter = container_of(napi, struct adapter, napi);
-   int work_done = process_responses(adapter, budget);
+   int work_done = 0;
+
+   if (budget)
+   work_done = process_responses(adapter, budget);
+   else {
+   /* budget=0 means: don't poll rx data */
+   process_pure_responses(adapter);
+   }
 
if (likely(work_done < budget)) {
napi_complete_done(napi, work_done);
-- 
2.29.2



[RFC PATCH 0/3] chelsio: cxgb: Use threaded irqs

2020-12-24 Thread Ahmed S. Darwish
Folks,

The t1_interrupt() irq handler calls del_timer_sync() down the chain:

   sge.c: t1_interrupt()
 -> subr.c: t1_slow_intr_handler()
   -> asic_slow_intr() || fpga_slow_intr()
 -> t1_pci_intr_handler()
  -> cxgb2.c: t1_fatal_err()# Cont. at [*]
   -> fpga_slow_intr()
 -> sge.c: t1_sge_intr_error_handler()
  -> cxgb2.c: t1_fatal_err()# Cont. at [*]

[*] cxgb2.c: t1_fatal_err()
  -> sge.c: t1_sge_stop()
-> timer.c: del_timer_sync()

This is invalid: if an irq handler calls del_timer_sync() on a timer
it has already interrupted, it will just loop forever.  That's why
del_timer_sync() also has a WARN_ON(in_irq()).

Included is an RFC patch series that runs the interrupt handler slow
path, t1_slow_intr_handler(), in a threaded-irq context.

This also leads to nice code savings across the driver, as some
workqueues and spinlocks are no longer needed.

Note: Only compile-tested. I do not have the hardware in question.

Thanks,

8<--

Ahmed S. Darwish (3):
  chelsio: cxgb: Remove ndo_poll_controller()
  chelsio: cxgb: Move slow interrupt handling to threaded irqs
  chelsio: cxgb: Do not schedule a workqueue for external interrupts

 drivers/net/ethernet/chelsio/cxgb/common.h |  2 -
 drivers/net/ethernet/chelsio/cxgb/cxgb2.c  | 58 ++
 drivers/net/ethernet/chelsio/cxgb/sge.c| 25 +++---
 drivers/net/ethernet/chelsio/cxgb/sge.h|  3 +-
 drivers/net/ethernet/chelsio/cxgb/subr.c   |  2 +-
 5 files changed, 25 insertions(+), 65 deletions(-)

base-commit: 2c85ebc57b3e1817b6ce1a6b703928e113a90442
-- 
2.29.2



[RFC PATCH 0/1] net: arcnet: Fix RESET sequence

2020-12-22 Thread Ahmed S. Darwish
Folks,

At drivers/net/arcnet/arcnet.c, there is:

  irqreturn_t arcnet_interrupt(int irq, void *dev_id)
  {
...
if (status & RESETflag) {
arcnet_close(dev);
arcnet_open(dev);
}
...
  }

  struct net_device_ops arcnet_netdev_ops = {
.ndo_open = arcnet_open,
.ndo_stop = arcnet_close,
...
  };

which is wrong, in many ways:

  1) In general, interrupt handlers should never call ->ndo_stop() and
 ->ndo_open() functions. They are usually full of blocking calls and
 other methods that are expected to be called only from drivers
 init/exit code paths.

  2) arcnet_close() contains a del_timer_sync(). If the irq handler
 interrupts the to-be-deleted timer then call del_timer_sync(), it
 will just loop forever.

  3) arcnet_close() also calls tasklet_kill(), which has a warning if
 called from irq context.

  4) For device reset, the sequence "arcnet_close(); arcnet_open();" is
 not complete.  Some children arcnet drivers have special init/exit
 code sequences, which then embed a call to arcnet_open() and
 arcnet_close() accordingly. Check drivers/net/arcnet/com20020.c.

Included is an RFC patch to fix the points above: if the RESET flag is
encountered, a workqueue is scheduled to run the generic reset sequence.

Note: Only compile-tested, as I do not have the hardware in question.

Thanks,

8<--

Ahmed S. Darwish (1):
  net: arcnet: Fix RESET flag handling

 drivers/net/arcnet/arc-rimi.c |  4 +-
 drivers/net/arcnet/arcdevice.h|  6 +++
 drivers/net/arcnet/arcnet.c   | 69 +--
 drivers/net/arcnet/com20020-isa.c |  4 +-
 drivers/net/arcnet/com20020-pci.c |  2 +-
 drivers/net/arcnet/com20020_cs.c  |  2 +-
 drivers/net/arcnet/com90io.c  |  4 +-
 drivers/net/arcnet/com90xx.c  |  4 +-
 8 files changed, 81 insertions(+), 14 deletions(-)

base-commit: 2c85ebc57b3e1817b6ce1a6b703928e113a90442
--
2.29.2


[RFC PATCH 1/1] net: arcnet: Fix RESET flag handling

2020-12-22 Thread Ahmed S. Darwish
The main arcnet interrupt handler calls arcnet_close() then
arcnet_open(), if the RESET status flag is encountered.

This is invalid:

  1) In general, interrupt handlers should never call ->ndo_stop() and
 ->ndo_open() functions. They are usually full of blocking calls and
 other methods that are expected to be called only from drivers
 init and exit code paths.

  2) arcnet_close() contains a del_timer_sync(). If the irq handler
 interrupts the to-be-deleted timer, del_timer_sync() will just loop
 forever.

  3) arcnet_close() also calls tasklet_kill(), which has a warning if
 called from irq context.

  4) For device reset, the sequence "arcnet_close(); arcnet_open();" is
 not complete.  Some children arcnet drivers have special init/exit
 code sequences, which then embed a call to arcnet_open() and
 arcnet_close() accordingly. Check drivers/net/arcnet/com20020.c.

Run the device RESET sequence from a scheduled workqueue instead.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/net/arcnet/arc-rimi.c |  4 +-
 drivers/net/arcnet/arcdevice.h|  6 +++
 drivers/net/arcnet/arcnet.c   | 69 +--
 drivers/net/arcnet/com20020-isa.c |  4 +-
 drivers/net/arcnet/com20020-pci.c |  2 +-
 drivers/net/arcnet/com20020_cs.c  |  2 +-
 drivers/net/arcnet/com90io.c  |  4 +-
 drivers/net/arcnet/com90xx.c  |  4 +-
 8 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 98df38fe553c..12d085405bd0 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -332,7 +332,7 @@ static int __init arc_rimi_init(void)
dev->irq = 9;
 
if (arcrimi_probe(dev)) {
-   free_netdev(dev);
+   free_arcdev(dev);
return -EIO;
}
 
@@ -349,7 +349,7 @@ static void __exit arc_rimi_exit(void)
iounmap(lp->mem_start);
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
free_irq(dev->irq, dev);
-   free_netdev(dev);
+   free_arcdev(dev);
 }
 
 #ifndef MODULE
diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h
index 22a49c6d7ae6..5d4a4c7efbbf 100644
--- a/drivers/net/arcnet/arcdevice.h
+++ b/drivers/net/arcnet/arcdevice.h
@@ -298,6 +298,10 @@ struct arcnet_local {
 
int excnak_pending;/* We just got an excesive nak interrupt */
 
+   /* RESET flag handling */
+   int reset_in_progress;
+   struct work_struct reset_work;
+
struct {
uint16_t sequence;  /* sequence number (incs with each 
packet) */
__be16 aborted_seq;
@@ -350,7 +354,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff 
*skb, char *desc)
 
 void arcnet_unregister_proto(struct ArcProto *proto);
 irqreturn_t arcnet_interrupt(int irq, void *dev_id);
+
 struct net_device *alloc_arcdev(const char *name);
+void free_arcdev(struct net_device *dev);
 
 int arcnet_open(struct net_device *dev);
 int arcnet_close(struct net_device *dev);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index e04efc0a5c97..563c43ae5cce 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -387,10 +387,46 @@ static void arcnet_timer(struct timer_list *t)
struct arcnet_local *lp = from_timer(lp, t, timer);
struct net_device *dev = lp->dev;
 
-   if (!netif_carrier_ok(dev)) {
+   spin_lock_irq(>lock);
+
+   if (!lp->reset_in_progress && !netif_carrier_ok(dev)) {
netif_carrier_on(dev);
netdev_info(dev, "link up\n");
}
+
+   spin_unlock_irq(>lock);
+}
+
+static void reset_device_work(struct work_struct *work)
+{
+   struct arcnet_local *lp;
+   struct net_device *dev;
+
+   lp = container_of(work, struct arcnet_local, reset_work);
+   dev = lp->dev;
+
+   /*
+* Do not bring the network interface back up if an ifdown
+* was already done.
+*/
+   if (!netif_running(dev) || !lp->reset_in_progress)
+   return;
+
+   rtnl_lock();
+
+   /*
+* Do another check, in case of an ifdown that was triggered in
+* the small race window between the exit condition above and
+* acquiring RTNL.
+*/
+   if (!netif_running(dev) || !lp->reset_in_progress)
+   goto out;
+
+   dev_close(dev);
+   dev_open(dev, NULL);
+
+out:
+   rtnl_unlock();
 }
 
 static void arcnet_reply_tasklet(unsigned long data)
@@ -452,12 +488,26 @@ struct net_device *alloc_arcdev(const char *name)
lp->dev = dev;
spin_lock_init(>lock);
timer_setup(>timer, arcnet_timer, 0);
+   INIT_WORK(>reset_work, reset_device_work);
}
 
return dev;
 }
 EXPORT_SYMBOL(alloc_arcdev);
 
+void

Re: [PATCH 11/11] scsi: libsas: event notifiers: Remove non _gfp() variants

2020-12-21 Thread Ahmed S. Darwish
On Mon, Dec 21, 2020 at 05:17:13PM +, John Garry wrote:
> On 18/12/2020 20:43, Ahmed S. Darwish wrote:
> > All call-sites of below libsas APIs:
> >
> >- sas_alloc_event()
> >- sas_ha_struct::notify_port_event()
> >- sas_ha_struct::notify_phy_event()
> >
> > have been converted to use the new _gfp()-suffixed version.
> >
>
> nit: Is it possible to have non- _gfp()-suffixed symbols at the end, i.e.
> have same as original?
>

Yes, of course. I just did not want to double-fold the patch series size
from first submission ;-)

If the overall outlook of this series is OK, in v2 I'll append patches
#12 => #20 restoring call sites to the original names without _gfp(),
then keep only the original libsas names.

Thanks,

--
Ahmed S. Darwish
Linutronix GmbH


[PATCH 09/11] scsi: aic94xx: Pass gfp_t flags to libsas event notifiers

2020-12-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  aic94xx_hwi.c: asd_dl_tasklet_handler()
-> asd_ascb::tasklet_complete()
== escb_tasklet_complete()
  -> aic94xx_scb.c: asd_phy_event_tasklet()
  -> aic94xx_scb.c: asd_bytes_dmaed_tasklet()
  -> aic94xx_scb.c: asd_link_reset_err_tasklet()
  -> aic94xx_scb.c: asd_primitive_rcvd_tasklet()

All functions are invoked by escb_tasklet_complete(), which is invoked
by the tasklet handler. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
---
 drivers/scsi/aic94xx/aic94xx_scb.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c 
b/drivers/scsi/aic94xx/aic94xx_scb.c
index e2d880a5f391..9ca60da59865 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -81,7 +81,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_ha->notify_phy_event_gfp(>sas_phy, 
PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,12 +89,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, 
GFP_ATOMIC);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -102,7 +102,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb,
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(>sas_phy);
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_ERROR);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_OOB_ERROR, 
GFP_ATOMIC);
break;
}
 }
@@ -234,7 +234,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
spin_unlock_irqrestore(>sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
-   sas_ha->notify_port_event(>sas_phy, PORTE_BYTES_DMAED);
+   sas_ha->notify_port_event_gfp(>sas_phy, PORTE_BYTES_DMAED, 
GFP_ATOMIC);
 }
 
 static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -270,7 +270,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb 
*ascb,
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_ha->notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, 
GFP_ATOMIC);
 
if (retries_left == 0) {
int num = 1;
@@ -315,7 +315,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_ha->notify_port_event(sas_phy,PORTE_BROADCAST_RCVD);
+   
sas_ha->notify_port_event_gfp(sas_phy,PORTE_BROADCAST_RCVD, GFP_ATOMIC);
break;
 
case LmUNKNOWNP:
@@ -336,7 +336,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb 
*ascb,
/* The sequencer disables all phys on that port.
 * We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
-   sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+   sas_ha->notify_port_event_gfp(sas_phy, 
PORTE_HARD_RESET, GFP_ATOMIC);
break;
 
default:
@@ -567,7 +567,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
/* the device is gone */
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
-   sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
+

[PATCH 08/11] scsi: pm80xx: Pass gfp_t flags to libsas event notifiers

2020-12-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Call chain analysis, pm8001_hwi.c:

  pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || 
pm8001_tasklet()
-> PM8001_CHIP_DISP->isr() = pm80xx_chip_isr()
  -> process_oq [spin_lock_irqsave(_ha->lock, ...)]
-> process_one_iomb()
  -> mpi_hw_event()
-> hw_event_sas_phy_up()
  -> pm8001_bytes_dmaed()
-> hw_event_sata_phy_up
  -> pm8001_bytes_dmaed()

All functions are invoked by process_one_iomb(), which is invoked by the
interrupt service routine and the tasklet handler. A similar call chain
is also found at pm80xx_hwi.c. Pass GFP_ATOMIC.

For pm8001_sas.c, pm8001_phy_control() runs in task context as it calls
wait_for_completion() and msleep().  Pass GFP_KERNEL.

Signed-off-by: Ahmed S. Darwish 
Cc: Jack Wang 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 38 
 drivers/scsi/pm8001/pm8001_sas.c |  8 +++
 drivers/scsi/pm8001/pm80xx_hwi.c | 30 -
 3 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2b7b2954ec31..36eb5cc6f2fa 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3306,7 +3306,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info 
*pm8001_ha, int i)
PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy %d byte dmaded.\n", i));
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   pm8001_ha->sas->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   pm8001_ha->sas->notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, 
GFP_ATOMIC);
 }
 
 /* Get the link rate speed  */
@@ -3467,7 +3467,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, >sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3512,7 +3512,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
-   sas_ha->notify_phy_event(>sas_phy, PHYE_OOB_DONE);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);
spin_lock_irqsave(>sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)>sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3879,12 +3879,12 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
case HW_EVENT_SATA_SPINUP_HOLD:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
-   sas_ha->notify_phy_event(>sas_phy, PHYE_SPINUP_HOLD);
+   sas_ha->notify_phy_event_gfp(>sas_phy, PHYE_SPINUP_HOLD, 
GFP_ATOMIC);
break;
case HW_EVENT_PHY_DOWN:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_PHY_DOWN\n"));
-   sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
+   sas_ha->notify_phy_event_gfp(>sas_phy, 
PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
@@ -3894,7 +3894,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_printk("HW_EVENT_PORT_INVALID\n"));
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
-   sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+   sas_ha->notify_port_event_gfp(sas_phy, PORTE_LINK_RESET_ERR, 
GFP_ATOMIC);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
@@ -3906,14 +3906,14 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
spin_lock_irqsave(_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(_phy->sas_prim_lock, flags);
-   sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   sas_ha->notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_ATOMIC);
break;
case HW_EVENT_

[PATCH 06/11] scsi: isci: port: broadcast change: Pass gfp_t flags

2020-12-18 Thread Ahmed S. Darwish
TING)
-> enter SCI PHY state: *SCI_PHY_RESETTING*
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

[2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 69684c80c407..6244981a3ebf 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,7 +164,9 @@ static void isci_port_bc_change_received(struct isci_host 
*ihost,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, >sas_phy);
 
-   ihost->sas_ha.notify_port_event(>sas_phy, PORTE_BROADCAST_RCVD);
+   ihost->sas_ha.notify_port_event_gfp(>sas_phy,
+   PORTE_BROADCAST_RCVD,
+   GFP_ATOMIC);
sci_port_bcn_enable(iport);
 }
 
-- 
2.29.2



[PATCH 11/11] scsi: libsas: event notifiers: Remove non _gfp() variants

2020-12-18 Thread Ahmed S. Darwish
All call-sites of below libsas APIs:

  - sas_alloc_event()
  - sas_ha_struct::notify_port_event()
  - sas_ha_struct::notify_phy_event()

have been converted to use the new _gfp()-suffixed version.

Remove the old APIs from libsas code, headers, and documentation.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  2 -
 drivers/scsi/libsas/sas_event.c| 72 +++---
 drivers/scsi/libsas/sas_init.c | 15 +--
 drivers/scsi/libsas/sas_internal.h |  2 -
 include/scsi/libsas.h  |  2 -
 5 files changed, 18 insertions(+), 75 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index dc85d0e4c107..7e1bf710760b 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,8 +189,6 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_port_event)(struct sas_phy *, enum port_event);
-   void (*notify_phy_event)(struct sas_phy *, enum phy_event);
void (*notify_port_event_gfp)(struct sas_phy *, enum port_event, gfp_t);
void (*notify_phy_event_gfp)(struct sas_phy *, enum phy_event, gfp_t);
 
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 31b733eeabf6..23aeb67f6381 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -131,57 +131,21 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-static int __sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event,
-  struct asd_sas_event *ev)
-{
-   struct sas_ha_struct *ha = phy->ha;
-   int ret;
-
-   BUG_ON(event >= PORT_NUM_EVENTS);
-
-   INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
-
-   ret = sas_queue_event(event, >work, ha);
-   if (ret != 1)
-   sas_free_event(ev);
-
-   return ret;
-}
-
 static int sas_notify_port_event_gfp(struct asd_sas_phy *phy,
 enum port_event event,
 gfp_t gfp_flags)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event_gfp(phy, gfp_flags);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
-}
-
-static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event)
-{
-   struct asd_sas_event *ev;
-
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_port_event(phy, event, ev);
-}
-
-static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
-enum phy_event event,
-struct asd_sas_event *ev)
 {
struct sas_ha_struct *ha = phy->ha;
+   struct asd_sas_event *ev;
int ret;
 
-   BUG_ON(event >= PHY_NUM_EVENTS);
+   BUG_ON(event >= PORT_NUM_EVENTS);
 
-   INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
+   INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
if (ret != 1)
@@ -193,31 +157,27 @@ static inline int __sas_notify_phy_event(struct 
asd_sas_phy *phy,
 int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
 gfp_t gfp_flags)
 {
+   struct sas_ha_struct *ha = phy->ha;
struct asd_sas_event *ev;
+   int ret;
+
+   BUG_ON(event >= PHY_NUM_EVENTS);
 
ev = sas_alloc_event_gfp(phy, gfp_flags);
if (!ev)
return -ENOMEM;
 
-   return __sas_notify_phy_event(phy, event, ev);
-}
+   INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
-{
-   struct asd_sas_event *ev;
+   ret = sas_queue_event(event, >work, ha);
+   if (ret != 1)
+   sas_free_event(ev);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
-   return __sas_notify_phy_event(phy, event, ev);
+   return ret;
 }
 
 int sas_init_events(struct sas_ha_struct *sas_ha)
 {
-   sas_ha->notify_port_event = sas_notify_port_event;
-   sas_ha->notify_phy_event = sas_notify_phy_event;
-
sas_ha->notify_port_event_gfp = sas_notify_port_event_gfp;
sas_ha->notify_phy_event_gfp = sas_notify_phy_event_gfp;
 
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2d2116f827c6..e08351f909fb 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -590,8 +590,8 @@ sas_domain_attach_transport(struct 
sas_domain_function_template *dft)
 }
 EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
 
-static struc

[PATCH 10/11] scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers

2020-12-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are the context analysis for modified functions:

=> hisi_sas_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags:

  * hisi_sas_main.c:
  --

hisi_sas_phyup_work(): workqueue context
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_controller_reset_done(): has an msleep()
  -> hisi_sas_rescan_topology()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

hisi_sas_debug_I_T_nexus_reset(): calls wait_for_completion_timeout()
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_KERNEL)

  * hisi_sas_v1_hw.c:
  ---

int_abnormal_v1_hw(): irq handler
  -> hisi_sas_phy_down()
-> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

  * hisi_sas_v[23]_hw.c:
  --

int_phy_updown_v[23]_hw(): irq handler
  -> phy_down_v[23]_hw()
-> hisi_sas_phy_down()
  -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC)

=> int_bcast_v1_hw() and phy_bcast_v3_hw():

Both are invoked exclusively from irq handlers. Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 26 +++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  5 +++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  5 +++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  5 +++--
 5 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index a25cfc11c96d..e08c71bf607d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -658,7 +658,8 @@ extern void hisi_sas_scan_start(struct Scsi_Host *shost);
 extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
 extern void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no,
int enable);
-extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
+extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy,
+ gfp_t gfp_flags);
 extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 274ccf18ce2d..f9332f62739b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -618,7 +618,8 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t 
gfp_flags,
return rc;
 }
 
-static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
+static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no,
+gfp_t gfp_flags)
 {
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -634,7 +635,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
}
 
sas_ha = _hba->sha;
-   sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_ha->notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -662,7 +663,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, 
int phy_no)
}
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
-   sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+   sas_ha->notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
 }
 
 static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
@@ -868,7 +869,7 @@ static void hisi_sas_phyup_work(struct work_struct *work)
 
if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP)
hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no);
-   hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+   hisi_sas_bytes_dmaed(hisi_hba, phy_no, GFP_KERNEL);
 }
 
 static void hisi_sas_linkreset_work(struct work_struct *work)
@@ -1438,11 +1439,12 @@ static void hisi_sas_rescan_topology(struct hisi_hba 
*hisi_hba, u32 state)
_sas_port = sas_port;
 
if (dev_is_expander(dev->dev_type))
-   sas_ha->notify_port_event(sas_phy,
-   PORTE_BROADCAST_RCVD);
+   sas_ha->notify_port_event_gfp(sas_phy,
+ 
PORTE_BROADCAST_RCVD,
+ 
GFP_KERNEL);
  

[PATCH 07/11] scsi: libsas: Pass gfp_t flags to event notifiers

2020-12-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Context analysis:

  - sas_enable_revalidation(): process, acquires mutex
  - sas_resume_ha(): process, calls wait_event_timeout()

Signed-off-by: Ahmed S. Darwish 
Cc: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/libsas/sas_event.c | 2 +-
 drivers/scsi/libsas/sas_init.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index ed5a8325dca7..31b733eeabf6 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
 
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
-   ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   ha->notify_port_event_gfp(sas_phy, PORTE_BROADCAST_RCVD, 
GFP_KERNEL);
}
mutex_unlock(>disco_mutex);
 }
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 9269d524158f..2d2116f827c6 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -410,7 +410,7 @@ void sas_resume_ha(struct sas_ha_struct *ha)
 
if (phy->suspended) {
dev_warn(>phy->dev, "resume timeout\n");
-   sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT);
+   sas_notify_phy_event_gfp(phy, PHYE_RESUME_TIMEOUT, 
GFP_KERNEL);
}
}
 
-- 
2.29.2



[PATCH 05/11] scsi: isci: port: link up: Pass gfp_t flags

2020-12-18 Thread Ahmed S. Darwish
Use the new libsas event notifiers API, which requires callers to
explicitly pass the gfp_t memory allocation flags.

The libsas ->notify_port_event() hook is called from
isci_port_link_up().  Below is the context analysis for all of its call
chains:

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
-> port_config.c: sci_port_configuration_agent_initialize()
  -> sci_mpc_agent_validate_phy_configuration()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

port_config.c: apc_agent_timeout(), atomic, timer callback  (*)
  -> sci_apc_agent_configure_ports()
-> port.c: sci_port_add_phy()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1]
  -> phy.c: sci_phy_starting_final_substate_enter()
-> phy.c: sci_change_state(SCI_PHY_READY)
  -> enter SCI state: *SCI_PHY_READY*
-> phy.c: sci_phy_ready_state_enter()
  -> host.c: sci_controller_link_up()
-> .link_up_handler()
== port_config.c: sci_apc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])
== port_config.c: sci_mpc_agent_link_up()
  -> port.c: sci_port_link_up()
-> (continue at [A])

port_config.c: mpc_agent_timeout(), atomic, timer callback  (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> ->link_up_handler()
  == port_config.c: sci_apc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])
  == port_config.c: sci_mpc_agent_link_up()
-> port.c: sci_port_link_up()
  -> (continue at [A])

[A] port.c: sci_port_link_up()
  -> sci_port_activate_phy()
-> isci_port_link_up()
  -> sci_port_general_link_up_handler()
-> sci_port_activate_phy()
  -> isci_port_link_up()

[1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*
---

host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

As can be seen from the "(*)" markers above, all the call-chains are
atomic.  Pass GFP_ATOMIC to libsas port event notifier.

Note, the now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index c3a8c84b19a2..69684c80c407 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -223,8 +223,9 @@ static void isci_port_link_up(struct isci_host *isci_host,
/* Notify libsas that we have an address frame, if indeed
 * we've found an SSP, SMP, or STP target */
if (success)
-   isci_host->sas_ha.notify_port_event(>sas_phy,
-   PORTE_BYTES_DMAED);
+   isci_host->sas_ha.notify_port_event_gfp(>sas_phy,
+   PORTE_BYTES_DMAED,
+   GFP_ATOMIC);
 }
 
 
-- 
2.29.2



[PATCH 04/11] scsi: isci: port: link down: Pass gfp_t flags

2020-12-18 Thread Ahmed S. Darwish
 sci_port_link_up()
-> sci_port_general_link_up_handler()
  -> port_state_machine_change(, SCI_PORT_READY)
-> enter port state *SCI_PORT_READY*

[1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL*


host.c: power_control_timeout(), atomic, timer callback (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> phy.c: sci_phy_consume_power_handler()
-> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)

host.c: sci_controller_error_handler(): atomic, irq handler (*)
OR host.c: sci_controller_completion_handler(), atomic, tasklet (*)
  -> sci_controller_process_completions()
-> sci_controller_unsolicited_frame()
  -> phy.c: sci_phy_frame_handler()
-> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER)
  -> sci_phy_starting_await_sas_power_substate_enter()
-> host.c: sci_controller_power_control_queue_insert()
  -> phy.c: sci_phy_consume_power_handler()
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_controller_event_completion()
  -> phy.c: sci_phy_event_handler()
-> sci_phy_start_sata_link_training()
  -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER)
-> sci_phy_starting_await_sata_power_substate_enter
  -> host.c: sci_controller_power_control_queue_insert()
-> phy.c: sci_phy_consume_power_handler()
  -> sci_change_state(SCI_PHY_SUB_FINAL)

[2] Call chains for entering state: *SCI_PHY_STOPPED*
-

host.c: isci_host_init()(@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_initialize(), atomic(*)
  -> phy.c: sci_phy_initialize()
-> phy.c: sci_phy_link_layer_initialization()
  -> phy.c: sci_change_state(SCI_PHY_STOPPED)

init.c: PCI ->remove() || PM_OPS ->suspend,  process context(+)
  -> host.c: isci_host_deinit()
-> sci_controller_stop_phys()
  -> phy.c: sci_phy_stop()
-> sci_change_state(SCI_PHY_STOPPED)

phy.c: isci_phy_control()
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_phy_stop(), atomic (*)
-> sci_change_state(SCI_PHY_STOPPED)

[3] Call chains for entering state: *SCI_PHY_STARTING*
--

phy.c: phy_sata_timeout(), atimer, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_change_state(SCI_PHY_STARTING)

host.c: phy_startup_timeout(), atomic, timer callback   (*)
spin_lock_irqsave(isci_host::scic_lock, )
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

host.c: isci_host_start()   (@)
spin_lock_irq(isci_host::scic_lock)
  -> sci_controller_start(), atomic (*)
-> sci_controller_start_next_phy()
  -> sci_phy_start()
-> sci_change_state(SCI_PHY_STARTING)

phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*)
  -> sci_change_state(SCI_PHY_SUB_FINAL)
-> sci_phy_starting_final_substate_enter()
  -> sci_change_state(SCI_PHY_READY)
-> Enter SCI state: *SCI_PHY_READY*
  -> sci_phy_ready_state_enter()
-> host.c: sci_controller_link_up()
  -> sci_controller_start_next_phy()
-> sci_phy_start()
  -> sci_change_state(SCI_PHY_STARTING)

phy.c: sci_phy_event_handler(), atomic, discussed earlier   (*)
  -> sci_change_state(SCI_PHY_STARTING), 11 instances

phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed  (*)
  -> sci_phy_resetting_state_enter()
-> sci_change_state(SCI_PHY_STARTING)

As can be seen from the "(*)" markers above, almost all the call-chains
are atomic. The only exception, marked with "(+)", is a PCI ->remove()
and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas
phy event notifier.

Note, The now-replaced libsas APIs used in_interrupt() to implicitly
decide which memory allocation type to use.  This was only partially
correct, as it fails to choose the correct GFP flags when just
preemption or interrupts are disabled. Such buggy code paths are marked
with "(@)" in the call chains above.

Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: Artur Paszkiewicz 
---
 drivers/scsi/isci/port.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 1df45f028ea7..c3a8c84b19a2 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -270,8 +270,9 @@ stati

[PATCH 02/11] scsi: libsas: Introduce a _gfp() variant of event notifiers

2020-12-18 Thread Ahmed S. Darwish
sas_alloc_event() uses in_interrupt() to decide which allocation should
be used.

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be separated or the context be conveyed in an argument passed by
the caller, which usually knows the context.

The in_interrupt() check is also only partially correct, because it
fails to choose the correct code path when just preemption or interrupts
are disabled. For example, as in the following call chain:

  drivers/scsi/mvsas/mv_sas.c :: mvs_work_queue() [process context]
  spin_lock_irqsave()
-> sas_ha->notify_phy_event()
== drivers/scsi/libsas/sas_event.c :: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> sas_ha->notify_port_event()
== drivers/scsi/libsas/sas_event.c :: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Introduce sas_alloc_event_gfp(), sas_ha_struct::notify_port_event_gfp(),
and sas_ha_struct::notify_phy_event_gfp(), which all behave like the non
_gfp() variants but use a caller passed GFP mask for allocations.

After all callers are converted to pass the GFP context, the non _gfp()
variants will be removed.

Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst  |  2 +
 drivers/scsi/libsas/sas_event.c| 65 +-
 drivers/scsi/libsas/sas_init.c | 20 ++---
 drivers/scsi/libsas/sas_internal.h |  2 +
 include/scsi/libsas.h  |  2 +
 5 files changed, 75 insertions(+), 16 deletions(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index f9b77c7879db..dc85d0e4c107 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -191,6 +191,8 @@ The event interface::
/* LLDD calls these to notify the class of an event. */
void (*notify_port_event)(struct sas_phy *, enum port_event);
void (*notify_phy_event)(struct sas_phy *, enum phy_event);
+   void (*notify_port_event_gfp)(struct sas_phy *, enum port_event, gfp_t);
+   void (*notify_phy_event_gfp)(struct sas_phy *, enum phy_event, gfp_t);
 
 When sas_register_ha() returns, those are set and can be
 called by the LLDD to notify the SAS layer of such events
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index a1852f6c042b..ed5a8325dca7 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -131,18 +131,14 @@ static void sas_phy_event_worker(struct work_struct *work)
sas_free_event(ev);
 }
 
-static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event)
+static int __sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event,
+  struct asd_sas_event *ev)
 {
-   struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PORT_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -152,18 +148,39 @@ static int sas_notify_port_event(struct asd_sas_phy *phy, 
enum port_event event)
return ret;
 }
 
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+static int sas_notify_port_event_gfp(struct asd_sas_phy *phy,
+enum port_event event,
+gfp_t gfp_flags)
 {
struct asd_sas_event *ev;
+
+   ev = sas_alloc_event_gfp(phy, gfp_flags);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
+
+static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event 
event)
+{
+   struct asd_sas_event *ev;
+
+   ev = sas_alloc_event(phy);
+   if (!ev)
+   return -ENOMEM;
+
+   return __sas_notify_port_event(phy, event, ev);
+}
+
+static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
+enum phy_event event,
+struct asd_sas_event *ev)
+{
struct sas_ha_struct *ha = phy->ha;
int ret;
 
BUG_ON(event >= PHY_NUM_EVENTS);
 
-   ev = sas_alloc_event(phy);
-   if (!ev)
-   return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
 
ret = sas_queue_event(event, >work, ha);
@@ -173,10 +190,36 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum 
phy_event event)
return ret;
 }
 
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
+gfp_t gfp_flags)
+

[PATCH 03/11] scsi: mvsas: Pass gfp_t flags to libsas event notifiers

2020-12-18 Thread Ahmed S. Darwish
mvsas calls the non _gfp version of the libsas event notifiers API,
leading to the buggy call chains below:

  mvsas/mv_sas.c :: mvs_work_queue() [process context]
  spin_lock_irqsave(mvs_info::lock, )
-> sas_ha->notify_phy_event()
== libsas/sas_event.c :: sas_notify_phy_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation
-> sas_ha->notify_port_event()
== libsas/sas_event.c :: sas_notify_port_event()
  -> sas_alloc_event()
-> in_interrupt() = false
  -> invalid GFP_KERNEL allocation

Use the new event notifiers API instead, which requires callers to
explicitly pass the gfp_t memory allocation flags.

Below are context analysis for the modified functions:

=> mvs_bytes_dmaed():

Since it is invoked from both process and atomic contexts, let its
callers pass the gfp_t flags. Call chains:

  scsi_scan.c: do_scsi_scan_host() [has msleep()]
-> shost->hostt->scan_start()
-> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = 
mvs_scan_start()]
-> mvsas/mv_sas.c: mvs_scan_start()
  -> mvs_bytes_dmaed(..., GFP_KERNEL)

  mvsas/mv_sas.c: mvs_work_queue()
  spin_lock_irqsave(mvs_info::lock,)
-> mvs_bytes_dmaed(..., GFP_ATOMIC)

  mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr()
-> mvsas/mv_chips.h: mvs_int_full()
  -> mvsas/mv_sas.c: mvs_int_port()
-> mvs_bytes_dmaed(..., GFP_ATOMIC);

=> mvs_work_queue():

Invoked from process context, but it calls all the libsas event notifier
APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC.

Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: John Garry 
Cc: Jason Yan 
---
 drivers/scsi/mvsas/mv_sas.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index a920eced92ec..30a34c5bdf6b 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -216,7 +216,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, 
u32 off_lo,
MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi);
 }
 
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
+static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags)
 {
struct mvs_phy *phy = >phy[i];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -230,7 +230,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
}
 
sas_ha = mvi->sas;
-   sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+   sas_ha->notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
 
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -262,8 +262,8 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
 
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
 
-   mvi->sas->notify_port_event(sas_phy,
-  PORTE_BYTES_DMAED);
+   mvi->sas->notify_port_event_gfp(sas_phy,
+   PORTE_BYTES_DMAED, gfp_flags);
 }
 
 void mvs_scan_start(struct Scsi_Host *shost)
@@ -279,7 +279,7 @@ void mvs_scan_start(struct Scsi_Host *shost)
for (j = 0; j < core_nr; j++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
for (i = 0; i < mvi->chip->n_phy; ++i)
-   mvs_bytes_dmaed(mvi, i);
+   mvs_bytes_dmaed(mvi, i, GFP_KERNEL);
}
mvs_prv->scan_finished = 1;
 }
@@ -1895,21 +1895,21 @@ static void mvs_work_queue(struct work_struct *work)
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
-   sas_ha->notify_phy_event(sas_phy,
-   PHYE_LOSS_OF_SIGNAL);
+   sas_ha->notify_phy_event_gfp(sas_phy,
+
PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
mvs_update_phyinfo(mvi, phy_no, 1);
-   mvs_bytes_dmaed(mvi, phy_no);
+   mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC);
mvs_port_notify_formed(sas_phy, 0);
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
-   sas_ha->notify_port_event(sas_phy,
-   PORTE_BROAD

[PATCH 01/11] Documentation: scsi: libsas: Remove notify_ha_event()

2020-12-18 Thread Ahmed S. Darwish
The ->notify_ha_event() hook has long been removed from the libsas event
interface.

Remove it from documentation.

Fixes: 042ebd293b86 ("scsi: libsas: kill useless ha_event and do some cleanup")
Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: John Garry 
Cc: Jason Yan 
---
 Documentation/scsi/libsas.rst | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst
index 7216b5d25800..f9b77c7879db 100644
--- a/Documentation/scsi/libsas.rst
+++ b/Documentation/scsi/libsas.rst
@@ -189,7 +189,6 @@ num_phys
 The event interface::
 
/* LLDD calls these to notify the class of an event. */
-   void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);
void (*notify_port_event)(struct sas_phy *, enum port_event);
void (*notify_phy_event)(struct sas_phy *, enum phy_event);
 
-- 
2.29.2



[PATCH 00/11] scsi: libsas: Remove in_interrupt() check

2020-12-18 Thread Ahmed S. Darwish
Folks,

In the discussion about preempt count consistency across kernel
configurations:

  https://lkml.kernel.org/r/20200914204209.256266...@linutronix.de

it was concluded that the usage of in_interrupt() and related context
checks should be removed from non-core code.

This includes memory allocation mode decisions (GFP_*). In the long run,
usage of in_interrupt() and its siblings should be banned from driver
code completely.

This series addresses SCSI libsas. Basically, the function:

  => drivers/scsi/libsas/sas_init.c:
  struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
  {
...
gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
event = kmem_cache_zalloc(sas_event_cache, flags);
...
  }

is transformed so that callers explicitly pass the gfp_t memory
allocation flags. Affected libsas clients are modified accordingly.

The first six patches have "Fixes: " tags and address bugs the were
noticed during the context analysis.

Thanks!

8<--

Ahmed S. Darwish (11):
  Documentation: scsi: libsas: Remove notify_ha_event()
  scsi: libsas: Introduce a _gfp() variant of event notifiers
  scsi: mvsas: Pass gfp_t flags to libsas event notifiers
  scsi: isci: port: link down: Pass gfp_t flags
  scsi: isci: port: link up: Pass gfp_t flags
  scsi: isci: port: broadcast change: Pass gfp_t flags
  scsi: libsas: Pass gfp_t flags to event notifiers
  scsi: pm80xx: Pass gfp_t flags to libsas event notifiers
  scsi: aic94xx: Pass gfp_t flags to libsas event notifiers
  scsi: hisi_sas: Pass gfp_t flags to libsas event notifiers
  scsi: libsas: event notifiers: Remove non _gfp() variants

 Documentation/scsi/libsas.rst  |  5 ++--
 drivers/scsi/aic94xx/aic94xx_scb.c | 18 ++--
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 26 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  5 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  5 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  5 ++--
 drivers/scsi/isci/port.c   | 14 ++
 drivers/scsi/libsas/sas_event.c| 21 --
 drivers/scsi/libsas/sas_init.c | 11 
 drivers/scsi/libsas/sas_internal.h |  4 +--
 drivers/scsi/mvsas/mv_sas.c| 22 +++
 drivers/scsi/pm8001/pm8001_hwi.c   | 38 +-
 drivers/scsi/pm8001/pm8001_sas.c   |  8 +++---
 drivers/scsi/pm8001/pm80xx_hwi.c   | 30 ++--
 include/scsi/libsas.h  |  4 +--
 16 files changed, 116 insertions(+), 103 deletions(-)

base-commit: 2c85ebc57b3e1817b6ce1a6b703928e113a90442
--
2.29.2


[tip: locking/core] seqlock: kernel-doc: Specify when preemption is automatically altered

2020-12-09 Thread tip-bot2 for Ahmed S. Darwish
The following commit has been merged into the locking/core branch of tip:

Commit-ID: cb262935a166bdef0ccfe6e2adffa00c0f2d038a
Gitweb:
https://git.kernel.org/tip/cb262935a166bdef0ccfe6e2adffa00c0f2d038a
Author:Ahmed S. Darwish 
AuthorDate:Sun, 06 Dec 2020 17:21:43 +01:00
Committer: Peter Zijlstra 
CommitterDate: Wed, 09 Dec 2020 17:08:49 +01:00

seqlock: kernel-doc: Specify when preemption is automatically altered

The kernel-doc annotations for sequence counters write side functions
are incomplete: they do not specify when preemption is automatically
disabled and re-enabled.

This has confused a number of call-site developers. Fix it.

Signed-off-by: Ahmed S. Darwish 
Signed-off-by: Peter Zijlstra (Intel) 
Link: 
https://lkml.kernel.org/r/CAHk-=wikhgexmprxgaw+mvxg1zsgpztbbvwob23vetk41et...@mail.gmail.com
---
 include/linux/seqlock.h | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 235cbc6..2f7bb92 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -456,6 +456,8 @@ static inline int do_read_seqcount_retry(const seqcount_t 
*s, unsigned start)
 /**
  * raw_write_seqcount_begin() - start a seqcount_t write section w/o lockdep
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
+ *
+ * Context: check write_seqcount_begin()
  */
 #define raw_write_seqcount_begin(s)\
 do {   \
@@ -475,6 +477,8 @@ static inline void do_raw_write_seqcount_begin(seqcount_t 
*s)
 /**
  * raw_write_seqcount_end() - end a seqcount_t write section w/o lockdep
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
+ *
+ * Context: check write_seqcount_end()
  */
 #define raw_write_seqcount_end(s)  \
 do {   \
@@ -498,6 +502,7 @@ static inline void do_raw_write_seqcount_end(seqcount_t *s)
  * @subclass: lockdep nesting level
  *
  * See Documentation/locking/lockdep-design.rst
+ * Context: check write_seqcount_begin()
  */
 #define write_seqcount_begin_nested(s, subclass)   \
 do {   \
@@ -519,11 +524,10 @@ static inline void 
do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
  * write_seqcount_begin() - start a seqcount_t write side critical section
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
  *
- * write_seqcount_begin opens a write side critical section of the given
- * seqcount_t.
- *
- * Context: seqcount_t write side critical sections must be serialized and
- * non-preemptible. If readers can be invoked from hardirq or softirq
+ * Context: sequence counter write side sections must be serialized and
+ * non-preemptible. Preemption will be automatically disabled if and
+ * only if the seqcount write serialization lock is associated, and
+ * preemptible.  If readers can be invoked from hardirq or softirq
  * context, interrupts or bottom halves must be respectively disabled.
  */
 #define write_seqcount_begin(s)
\
@@ -545,7 +549,8 @@ static inline void do_write_seqcount_begin(seqcount_t *s)
  * write_seqcount_end() - end a seqcount_t write side critical section
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
  *
- * The write section must've been opened with write_seqcount_begin().
+ * Context: Preemption will be automatically re-enabled if and only if
+ * the seqcount write serialization lock is associated, and preemptible.
  */
 #define write_seqcount_end(s)  \
 do {   \


[tip: locking/core] seqlock: Prefix internal seqcount_t-only macros with a "do_"

2020-12-09 Thread tip-bot2 for Ahmed S. Darwish
The following commit has been merged into the locking/core branch of tip:

Commit-ID: 66bcfcdf89d00f2409f4b5da0f8c20c08318dc72
Gitweb:
https://git.kernel.org/tip/66bcfcdf89d00f2409f4b5da0f8c20c08318dc72
Author:Ahmed S. Darwish 
AuthorDate:Sun, 06 Dec 2020 17:21:42 +01:00
Committer: Peter Zijlstra 
CommitterDate: Wed, 09 Dec 2020 17:08:49 +01:00

seqlock: Prefix internal seqcount_t-only macros with a "do_"

When the seqcount_LOCKNAME_t group of data types were introduced, two
classes of seqlock.h sequence counter macros were added:

  - An external public API which can either take a plain seqcount_t or
any of the seqcount_LOCKNAME_t variants.

  - An internal API which takes only a plain seqcount_t.

To distinguish between the two groups, the "*_seqcount_t_*" pattern was
used for the latter. This confused a number of mm/ call-site developers,
and Linus also commented that it was not a standard practice for marking
seqlock.h internal APIs.

Distinguish the latter group of macros by prefixing a "do_".

Signed-off-by: Ahmed S. Darwish 
Signed-off-by: Peter Zijlstra (Intel) 
Link: 
https://lkml.kernel.org/r/CAHk-=wikhgexmprxgaw+mvxg1zsgpztbbvwob23vetk41et...@mail.gmail.com
---
 include/linux/seqlock.h | 66 
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index d89134c..235cbc6 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -425,9 +425,9 @@ SEQCOUNT_LOCKNAME(ww_mutex, struct ww_mutex, true, 
>lock->base, ww_mu
  * Return: true if a read section retry is required, else false
  */
 #define __read_seqcount_retry(s, start)
\
-   __read_seqcount_t_retry(seqprop_ptr(s), start)
+   do___read_seqcount_retry(seqprop_ptr(s), start)
 
-static inline int __read_seqcount_t_retry(const seqcount_t *s, unsigned start)
+static inline int do___read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
kcsan_atomic_next(0);
return unlikely(READ_ONCE(s->sequence) != start);
@@ -445,12 +445,12 @@ static inline int __read_seqcount_t_retry(const 
seqcount_t *s, unsigned start)
  * Return: true if a read section retry is required, else false
  */
 #define read_seqcount_retry(s, start)  \
-   read_seqcount_t_retry(seqprop_ptr(s), start)
+   do_read_seqcount_retry(seqprop_ptr(s), start)
 
-static inline int read_seqcount_t_retry(const seqcount_t *s, unsigned start)
+static inline int do_read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
smp_rmb();
-   return __read_seqcount_t_retry(s, start);
+   return do___read_seqcount_retry(s, start);
 }
 
 /**
@@ -462,10 +462,10 @@ do {  
\
if (seqprop_preemptible(s)) \
preempt_disable();  \
\
-   raw_write_seqcount_t_begin(seqprop_ptr(s)); \
+   do_raw_write_seqcount_begin(seqprop_ptr(s));\
 } while (0)
 
-static inline void raw_write_seqcount_t_begin(seqcount_t *s)
+static inline void do_raw_write_seqcount_begin(seqcount_t *s)
 {
kcsan_nestable_atomic_begin();
s->sequence++;
@@ -478,13 +478,13 @@ static inline void raw_write_seqcount_t_begin(seqcount_t 
*s)
  */
 #define raw_write_seqcount_end(s)  \
 do {   \
-   raw_write_seqcount_t_end(seqprop_ptr(s));   \
+   do_raw_write_seqcount_end(seqprop_ptr(s));  \
\
if (seqprop_preemptible(s)) \
preempt_enable();   \
 } while (0)
 
-static inline void raw_write_seqcount_t_end(seqcount_t *s)
+static inline void do_raw_write_seqcount_end(seqcount_t *s)
 {
smp_wmb();
s->sequence++;
@@ -506,12 +506,12 @@ do {  
\
if (seqprop_preemptible(s)) \
preempt_disable();  \
\
-   write_seqcount_t_begin_nested(seqprop_ptr(s), subclass);\
+   do_write_seqcount_begin_nested(seqprop_ptr(s), subclass);   \
 } while (0)
 
-static inline void write_seqcount_t_begin_nested(seqcount_t *s, int subclass)
+static inline void do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-   raw_write_seqcount_t_begin(s);
+   do_raw_write_seqcount_begin(s);
 

[tip: locking/core] Documentation: seqlock: s/LOCKTYPE/LOCKNAME/g

2020-12-09 Thread tip-bot2 for Ahmed S. Darwish
The following commit has been merged into the locking/core branch of tip:

Commit-ID: cf48647243cc28d15280600292db5777592606c5
Gitweb:
https://git.kernel.org/tip/cf48647243cc28d15280600292db5777592606c5
Author:Ahmed S. Darwish 
AuthorDate:Sun, 06 Dec 2020 17:21:41 +01:00
Committer: Peter Zijlstra 
CommitterDate: Wed, 09 Dec 2020 17:08:49 +01:00

Documentation: seqlock: s/LOCKTYPE/LOCKNAME/g

Sequence counters with an associated write serialization lock are called
seqcount_LOCKNAME_t. Fix the documentation accordingly.

While at it, remove a paragraph that inappropriately discussed a
seqlock.h implementation detail.

Fixes: 6dd699b13d53 ("seqlock: seqcount_LOCKNAME_t: Standardize naming 
convention")
Signed-off-by: Ahmed S. Darwish 
Signed-off-by: Peter Zijlstra (Intel) 
Cc: sta...@vger.kernel.org
Link: https://lkml.kernel.org/r/20201206162143.14387-2-a.darw...@linutronix.de
---
 Documentation/locking/seqlock.rst | 21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/Documentation/locking/seqlock.rst 
b/Documentation/locking/seqlock.rst
index a334b58..64405e5 100644
--- a/Documentation/locking/seqlock.rst
+++ b/Documentation/locking/seqlock.rst
@@ -89,7 +89,7 @@ Read path::
 
 .. _seqcount_locktype_t:
 
-Sequence counters with associated locks (``seqcount_LOCKTYPE_t``)
+Sequence counters with associated locks (``seqcount_LOCKNAME_t``)
 -
 
 As discussed at :ref:`seqcount_t`, sequence count write side critical
@@ -115,27 +115,26 @@ The following sequence counters with associated locks are 
defined:
   - ``seqcount_mutex_t``
   - ``seqcount_ww_mutex_t``
 
-The plain seqcount read and write APIs branch out to the specific
-seqcount_LOCKTYPE_t implementation at compile-time. This avoids kernel
-API explosion per each new seqcount LOCKTYPE.
+The sequence counter read and write APIs can take either a plain
+seqcount_t or any of the seqcount_LOCKNAME_t variants above.
 
-Initialization (replace "LOCKTYPE" with one of the supported locks)::
+Initialization (replace "LOCKNAME" with one of the supported locks)::
 
/* dynamic */
-   seqcount_LOCKTYPE_t foo_seqcount;
-   seqcount_LOCKTYPE_init(_seqcount, );
+   seqcount_LOCKNAME_t foo_seqcount;
+   seqcount_LOCKNAME_init(_seqcount, );
 
/* static */
-   static seqcount_LOCKTYPE_t foo_seqcount =
-   SEQCNT_LOCKTYPE_ZERO(foo_seqcount, );
+   static seqcount_LOCKNAME_t foo_seqcount =
+   SEQCNT_LOCKNAME_ZERO(foo_seqcount, );
 
/* C99 struct init */
struct {
-   .seq   = SEQCNT_LOCKTYPE_ZERO(foo.seq, ),
+   .seq   = SEQCNT_LOCKNAME_ZERO(foo.seq, ),
} foo;
 
 Write path: same as in :ref:`seqcount_t`, while running from a context
-with the associated LOCKTYPE lock acquired.
+with the associated write serialization lock acquired.
 
 Read path: same as in :ref:`seqcount_t`.
 


Re: [PATCH -tip v1 3/3] seqlock: kernel-doc: Specify when preemption is automatically altered

2020-12-08 Thread Ahmed S. Darwish
Hi Jason,

On Mon, Dec 07, 2020 at 04:43:16PM -0400, Jason Gunthorpe wrote:
...
>
> The thing that was confusing is if it was appropriate to use a
> seqcount in case where write side preemption was not disabled - which
> is safe only if the read side doesn't spin.
>

No, that's not correct.

What was confusing was that *everyone* in that mm/ thread, including
yourself, thought that write_seqcount_begin() will automatically disable
preemption for plain seqcount_t:

  https://lkml.kernel.org/r/20201030235121.gq2620...@nvidia.com

Quoting Peter Xu: "My understanding is that we used
raw_write_seqcount_t_begin() because we're with spin lock so assuming we
disabled preemption already."

Quoting you: "write_seqcount_begin - Enforces preemption off".

And that's why this patch explicitly adds to the kernel-doc: "Preemption
will be automatically disabled if and only if the seqcount write
serialization lock is associated, and preemptible."

Honestly, I should've added that statement anyway in my original
"sequence counters with associated locks" submission. I take the blame
for the resulting confusion, and I'm sorry...



Now regarding the other point, where the seqcount_t write side does not
need to disable preemption if the reader does not spin. We've already
discussed that (at length) last time.

There comes a point where you decide what level of documentation to add,
and what level to skip.

Because in the end, you don't want to confuse "Joe, the generic driver
developer" with too much details that's not relevant to their task at
hand.

You want to keep the general case simple, but the special case do-able.
And you also want to encourage people to use the standard write side
critical section entry and exit functions, as much as possible.

Because, oh, look at that:

  [PATCH v2 0/6] seqlock: seqcount_t call sites bugfixes
  https://lkml.kernel.org/r/20200603144949.1122421-1-a.darw...@linutronix.de

Sequence counters are already hard to get right. And driver developers
get things wrong, a lot -- you don't want to confuse them even further.

For developers who're advanced enough to know the difference, they don't
need the kernel-doc anyway. And that's why I've kindly asked to add the
following to your mm/ patch (which you did, thanks):

/*
 * Disabling preemption is not needed for the write side, as
 * the read side does not spin, but goes to mmap_lock.
 * ...
 */

And IMHO, that should be enough. Developers of such special cases are
already assumed to know what they're doing.

Thanks a lot,

--
Ahmed S. Darwish
Linutronix GmbH


[PATCH -tip v1 1/3] Documentation: seqlock: s/LOCKTYPE/LOCKNAME/g

2020-12-06 Thread Ahmed S. Darwish
Sequence counters with an associated write serialization lock are called
seqcount_LOCKNAME_t. Fix the documentation accordingly.

While at it, remove a paragraph that inappropriately discussed a
seqlock.h implementation detail.

Fixes: 6dd699b13d53 ("seqlock: seqcount_LOCKNAME_t: Standardize naming 
convention")
Signed-off-by: Ahmed S. Darwish 
Cc: sta...@vger.kernel.org
Cc: Jonathan Corbet 
---
 Documentation/locking/seqlock.rst | 21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/Documentation/locking/seqlock.rst 
b/Documentation/locking/seqlock.rst
index a334b584f2b3..64405e5da63e 100644
--- a/Documentation/locking/seqlock.rst
+++ b/Documentation/locking/seqlock.rst
@@ -89,7 +89,7 @@ Read path::
 
 .. _seqcount_locktype_t:
 
-Sequence counters with associated locks (``seqcount_LOCKTYPE_t``)
+Sequence counters with associated locks (``seqcount_LOCKNAME_t``)
 -
 
 As discussed at :ref:`seqcount_t`, sequence count write side critical
@@ -115,27 +115,26 @@ The following sequence counters with associated locks are 
defined:
   - ``seqcount_mutex_t``
   - ``seqcount_ww_mutex_t``
 
-The plain seqcount read and write APIs branch out to the specific
-seqcount_LOCKTYPE_t implementation at compile-time. This avoids kernel
-API explosion per each new seqcount LOCKTYPE.
+The sequence counter read and write APIs can take either a plain
+seqcount_t or any of the seqcount_LOCKNAME_t variants above.
 
-Initialization (replace "LOCKTYPE" with one of the supported locks)::
+Initialization (replace "LOCKNAME" with one of the supported locks)::
 
/* dynamic */
-   seqcount_LOCKTYPE_t foo_seqcount;
-   seqcount_LOCKTYPE_init(_seqcount, );
+   seqcount_LOCKNAME_t foo_seqcount;
+   seqcount_LOCKNAME_init(_seqcount, );
 
/* static */
-   static seqcount_LOCKTYPE_t foo_seqcount =
-   SEQCNT_LOCKTYPE_ZERO(foo_seqcount, );
+   static seqcount_LOCKNAME_t foo_seqcount =
+   SEQCNT_LOCKNAME_ZERO(foo_seqcount, );
 
/* C99 struct init */
struct {
-   .seq   = SEQCNT_LOCKTYPE_ZERO(foo.seq, ),
+   .seq   = SEQCNT_LOCKNAME_ZERO(foo.seq, ),
} foo;
 
 Write path: same as in :ref:`seqcount_t`, while running from a context
-with the associated LOCKTYPE lock acquired.
+with the associated write serialization lock acquired.
 
 Read path: same as in :ref:`seqcount_t`.
 
-- 
2.29.2



[PATCH -tip v1 2/3] seqlock: Prefix internal seqcount_t-only macros with a "do_"

2020-12-06 Thread Ahmed S. Darwish
When the seqcount_LOCKNAME_t group of data types were introduced, two
classes of seqlock.h sequence counter macros were added:

  - An external public API which can either take a plain seqcount_t or
any of the seqcount_LOCKNAME_t variants.

  - An internal API which takes only a plain seqcount_t.

To distinguish between the two groups, the "*_seqcount_t_*" pattern was
used for the latter. This confused a number of mm/ call-site developers,
and Linus also commented that it was not a standard practice for marking
seqlock.h internal APIs.

Distinguish the latter group of macros by prefixing a "do_".

Link: 
https://lkml.kernel.org/r/CAHk-=wgb8nyoqufpn0o6a5bpjcjpnxvh+krxapujhsgg+7q...@mail.gmail.com
Link: 
https://lkml.kernel.org/r/CAHk-=wikhgexmprxgaw+mvxg1zsgpztbbvwob23vetk41et...@mail.gmail.com
Signed-off-by: Ahmed S. Darwish 
---
 include/linux/seqlock.h | 66 -
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index d89134c74fba..235cbc65fd71 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -425,9 +425,9 @@ SEQCOUNT_LOCKNAME(ww_mutex, struct ww_mutex, true, 
>lock->base, ww_mu
  * Return: true if a read section retry is required, else false
  */
 #define __read_seqcount_retry(s, start)
\
-   __read_seqcount_t_retry(seqprop_ptr(s), start)
+   do___read_seqcount_retry(seqprop_ptr(s), start)
 
-static inline int __read_seqcount_t_retry(const seqcount_t *s, unsigned start)
+static inline int do___read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
kcsan_atomic_next(0);
return unlikely(READ_ONCE(s->sequence) != start);
@@ -445,12 +445,12 @@ static inline int __read_seqcount_t_retry(const 
seqcount_t *s, unsigned start)
  * Return: true if a read section retry is required, else false
  */
 #define read_seqcount_retry(s, start)  \
-   read_seqcount_t_retry(seqprop_ptr(s), start)
+   do_read_seqcount_retry(seqprop_ptr(s), start)
 
-static inline int read_seqcount_t_retry(const seqcount_t *s, unsigned start)
+static inline int do_read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
smp_rmb();
-   return __read_seqcount_t_retry(s, start);
+   return do___read_seqcount_retry(s, start);
 }
 
 /**
@@ -462,10 +462,10 @@ do {  
\
if (seqprop_preemptible(s)) \
preempt_disable();  \
\
-   raw_write_seqcount_t_begin(seqprop_ptr(s)); \
+   do_raw_write_seqcount_begin(seqprop_ptr(s));\
 } while (0)
 
-static inline void raw_write_seqcount_t_begin(seqcount_t *s)
+static inline void do_raw_write_seqcount_begin(seqcount_t *s)
 {
kcsan_nestable_atomic_begin();
s->sequence++;
@@ -478,13 +478,13 @@ static inline void raw_write_seqcount_t_begin(seqcount_t 
*s)
  */
 #define raw_write_seqcount_end(s)  \
 do {   \
-   raw_write_seqcount_t_end(seqprop_ptr(s));   \
+   do_raw_write_seqcount_end(seqprop_ptr(s));  \
\
if (seqprop_preemptible(s)) \
preempt_enable();   \
 } while (0)
 
-static inline void raw_write_seqcount_t_end(seqcount_t *s)
+static inline void do_raw_write_seqcount_end(seqcount_t *s)
 {
smp_wmb();
s->sequence++;
@@ -506,12 +506,12 @@ do {  
\
if (seqprop_preemptible(s)) \
preempt_disable();  \
\
-   write_seqcount_t_begin_nested(seqprop_ptr(s), subclass);\
+   do_write_seqcount_begin_nested(seqprop_ptr(s), subclass);   \
 } while (0)
 
-static inline void write_seqcount_t_begin_nested(seqcount_t *s, int subclass)
+static inline void do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-   raw_write_seqcount_t_begin(s);
+   do_raw_write_seqcount_begin(s);
seqcount_acquire(>dep_map, subclass, 0, _RET_IP_);
 }
 
@@ -533,12 +533,12 @@ do {  
\
if (seqprop_preemptible(s)) \
preempt_disable();  \
  

[PATCH -tip v1 3/3] seqlock: kernel-doc: Specify when preemption is automatically altered

2020-12-06 Thread Ahmed S. Darwish
The kernel-doc annotations for sequence counters write side functions
are incomplete: they do not specify when preemption is automatically
disabled and re-enabled.

This has confused a number of call-site developers. Fix it.

Link: https://lkml.kernel.org/r/20201030235121.gq2620...@nvidia.com
Link: 
https://lkml.kernel.org/r/CAHk-=wikhgexmprxgaw+mvxg1zsgpztbbvwob23vetk41et...@mail.gmail.com
Signed-off-by: Ahmed S. Darwish 
Cc: Jonathan Corbet 
---
 include/linux/seqlock.h | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 235cbc65fd71..2f7bb92b4c9e 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -456,6 +456,8 @@ static inline int do_read_seqcount_retry(const seqcount_t 
*s, unsigned start)
 /**
  * raw_write_seqcount_begin() - start a seqcount_t write section w/o lockdep
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
+ *
+ * Context: check write_seqcount_begin()
  */
 #define raw_write_seqcount_begin(s)\
 do {   \
@@ -475,6 +477,8 @@ static inline void do_raw_write_seqcount_begin(seqcount_t 
*s)
 /**
  * raw_write_seqcount_end() - end a seqcount_t write section w/o lockdep
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
+ *
+ * Context: check write_seqcount_end()
  */
 #define raw_write_seqcount_end(s)  \
 do {   \
@@ -498,6 +502,7 @@ static inline void do_raw_write_seqcount_end(seqcount_t *s)
  * @subclass: lockdep nesting level
  *
  * See Documentation/locking/lockdep-design.rst
+ * Context: check write_seqcount_begin()
  */
 #define write_seqcount_begin_nested(s, subclass)   \
 do {   \
@@ -519,11 +524,10 @@ static inline void 
do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
  * write_seqcount_begin() - start a seqcount_t write side critical section
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
  *
- * write_seqcount_begin opens a write side critical section of the given
- * seqcount_t.
- *
- * Context: seqcount_t write side critical sections must be serialized and
- * non-preemptible. If readers can be invoked from hardirq or softirq
+ * Context: sequence counter write side sections must be serialized and
+ * non-preemptible. Preemption will be automatically disabled if and
+ * only if the seqcount write serialization lock is associated, and
+ * preemptible.  If readers can be invoked from hardirq or softirq
  * context, interrupts or bottom halves must be respectively disabled.
  */
 #define write_seqcount_begin(s)
\
@@ -545,7 +549,8 @@ static inline void do_write_seqcount_begin(seqcount_t *s)
  * write_seqcount_end() - end a seqcount_t write side critical section
  * @s: Pointer to seqcount_t or any of the seqcount_LOCKNAME_t variants
  *
- * The write section must've been opened with write_seqcount_begin().
+ * Context: Preemption will be automatically re-enabled if and only if
+ * the seqcount write serialization lock is associated, and preemptible.
  */
 #define write_seqcount_end(s)  \
 do {   \
-- 
2.29.2



[PATCH -tip v1 0/3] seqlock: assorted cleanups

2020-12-06 Thread Ahmed S. Darwish
Hi,

When the seqcount_LOCKNAME_t group of data types were introduced, two
classes of seqlock.h sequence counter macros were added:

  - An external public API which can either take a plain seqcount_t or
any of the seqcount_LOCKNAME_t variants.

  - An internal API which takes only a plain seqcount_t.

To distinguish between the two groups, the "*_seqcount_t_*" pattern was
used for the latter. This confused a number of mm/ call-site developers,
and Linus also commented that this was not the standard practice for
marking kernel internal APIs. [1]

Distinguish the latter group of macros by prefixing a "do_".

A number of call-site developers also complained that the automatic
preemption disable/enable for the write side macros was not obvious, or
documented. [2] Linus also suggested adding few comments explaining that
behavior. [3] Fix it by completing the seqcount write side kernel-doc
annotations.

Finally, fix a minor naming inconsistency w.r.t. seqlock.h
vs. Documentation/locking/seqlock.rst.

This series does not change the output "allyesconfig" kernel binary:

text databss  ...filename
  247616963289662125   81498728   ...  ../build-x86-64/vmlinux.old
  247616963289662125   81498728   ...  ../build-x86-64/vmlinux
  1450540287827027318435468   ...  ../build-arm/vmlinux.old
  1450540287827027318435468   ...  ../build-arm/vmlinux

Note: based over -tip locking/core, instead of latest -rc, due to -tip
  ab440b2c604b ("seqlock: Rename __seqprop() users").

References:

[1] 
https://lkml.kernel.org/r/CAHk-=wgb8nyoqufpn0o6a5bpjcjpnxvh+krxapujhsgg+7q...@mail.gmail.com
[2] https://lkml.kernel.org/r/20201030235121.gq2620...@nvidia.com
[3] 
https://lkml.kernel.org/r/CAHk-=wikhgexmprxgaw+mvxg1zsgpztbbvwob23vetk41et...@mail.gmail.com

8<--

Ahmed S. Darwish (3):
  Documentation: seqlock: s/LOCKTYPE/LOCKNAME/g
  seqlock: Prefix internal seqcount_t-only macros with a "do_"
  seqlock: kernel-doc: Specify when preemption is automatically altered

 Documentation/locking/seqlock.rst | 21 
 include/linux/seqlock.h   | 83 ---
 2 files changed, 54 insertions(+), 50 deletions(-)

base-commit: 97d62caa32d6d79dadae3f8d19af5c92ea9a589a
--
2.29.2


[PATCH v3] scsi: NCR5380: Remove context check

2020-12-05 Thread Ahmed S. Darwish
NCR5380_poll_politely2() uses in_interrupt() and irqs_disabled() to
check if it is safe to sleep.

Such usage in drivers is phased out and Linus clearly requested that
code which changes behaviour depending on context should either be
separated, or the context be explicitly conveyed in an argument passed
by the caller.

Below is a context analysis of NCR5380_poll_politely2() uppermost
callers:

  - NCR5380_maybe_reset_bus(), task, invoked during device probe.
-> NCR5380_poll_politely()
-> do_abort()

  - NCR5380_select(), task, but can only sleep in the "release, then
re-acquire" regions of the spinlock held by its caller.
Sleeping invocations (lock released):
-> NCR5380_poll_politely2()

Atomic invocations (lock acquired):
-> NCR5380_reselect()
   -> NCR5380_poll_politely()
   -> do_abort()
   -> NCR5380_transfer_pio()

  - NCR5380_intr(), interrupt handler
-> NCR5380_dma_complete()
   -> NCR5380_transfer_pio()
  -> NCR5380_poll_politely()
-> NCR5380_reselect() (see above)

  - NCR5380_information_transfer(), task, but can only sleep in the
"release, then re-acquire" regions of the caller-held spinlock.
Sleeping invocations (lock released):
  - NCR5380_transfer_pio() -> NCR5380_poll_politely()
  - NCR5380_poll_politely()

Atomic invocations (lock acquired):
  - NCR5380_transfer_dma()
-> NCR5380_dma_recv_setup()
   => generic_NCR5380_precv() -> NCR5380_poll_politely()
   => macscsi_pread() -> NCR5380_poll_politely()

-> NCR5380_dma_send_setup()
   => generic_NCR5380_psend -> NCR5380_poll_politely2()
   => macscsi_pwrite() -> NCR5380_poll_politely()

-> NCR5380_poll_politely2()
-> NCR5380_dma_complete()
   -> NCR5380_transfer_pio()
  -> NCR5380_poll_politely()
  - NCR5380_transfer_pio() -> NCR5380_poll_politely

  - NCR5380_reselect(), atomic, always called with hostdata spinlock
held.

Since NCR5380_poll_politely2() already takes a "wait" argument in
jiffies, use it to determine if the function can sleep. Modify atomic
callers, which passed an unused wait value in terms of HZ, to pass zero.

Suggested-by: Finn Thain 
Co-developed-by: Sebastian Andrzej Siewior 
Signed-off-by: Ahmed S. Darwish 
Cc: Michael Schmitz 
Cc: 
---
 drivers/scsi/NCR5380.c   | 74 ++--
 drivers/scsi/NCR5380.h   |  3 +-
 drivers/scsi/g_NCR5380.c | 12 +++
 drivers/scsi/mac_scsi.c  | 10 +++---
 4 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index d654a6cc4162..448cd22214c0 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -132,7 +132,7 @@
 static unsigned int disconnect_mask = ~0;
 module_param(disconnect_mask, int, 0444);
 
-static int do_abort(struct Scsi_Host *);
+static int do_abort(struct Scsi_Host *, unsigned int);
 static void do_reset(struct Scsi_Host *);
 static void bus_reset_cleanup(struct Scsi_Host *);
 
@@ -197,7 +197,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
  * @reg2: Second 5380 register to poll
  * @bit2: Second bitmask to check
  * @val2: Second expected value
- * @wait: Time-out in jiffies
+ * @wait: Time-out in jiffies, 0 if sleeping is not allowed
  *
  * Polls the chip in a reasonably efficient manner waiting for an
  * event to occur. After a short quick poll we begin to yield the CPU
@@ -223,7 +223,7 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata 
*hostdata,
cpu_relax();
} while (n--);
 
-   if (irqs_disabled() || in_interrupt())
+   if (!wait)
return -ETIMEDOUT;
 
/* Repeatedly sleep for 1 ms until deadline */
@@ -486,7 +486,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host 
*instance)
break;
case 2:
shost_printk(KERN_ERR, instance, "bus busy, attempting 
abort\n");
-   do_abort(instance);
+   do_abort(instance, 1);
break;
case 4:
shost_printk(KERN_ERR, instance, "bus busy, attempting 
reset\n");
@@ -818,7 +818,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
if (toPIO > 0) {
dsprintk(NDEBUG_DMA, instance,
 "Doing %d byte PIO to 0x%p\n", cnt, 
*data);
-   NCR5380_transfer_pio(instance, , , data);
+   NCR5380_transfer_pio(instance, , , data, 
0);
*count -= toPIO - cnt;
}
}
@@ -1185,7 +1185,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, 
struct scsi_cmnd *cmd)

Re: [PATCH] scsi/NCR5380: Remove in_interrupt() test

2020-12-04 Thread Ahmed S. Darwish
On Fri, Dec 04, 2020 at 10:08:08AM +1100, Finn Thain wrote:
...
>
> You've put your finger on a known problem with certain
> NCR5380_poll_politely() call sites. That is, the nominal timeout, HZ / 64,
> is meaningless because it is ignored in atomic context. So you may as well
> specify 0 jiffies at these call sites. (There will be a 1 jiffy timeout
> applied regardless.)
...
>
> However, I can see the value in your approach, i.e. passing a zero timeout
> to NCR5380_poll_politely() whenever that argument is unused. And I agree
> that this could then be used to inhibit sleeping, rather than testing
> irqs_disabled().
>
> So if you really don't like irqs_disabled(), perhaps you can just keep the
> better parts of your two attempts, i.e. passing 0 to
> NCR5380_poll_politely() where appropriate and facilitating that by adding
> a new can_sleep parameter to do_abort() and NCR5380_transfer_pio(), as in,
...
>
> Does that sound like a reasonable compromise?
>

Yes, of course. Thanks a lot.

I've sent a v2.

--
Ahmed S. Darwish
Linutronix GmbH


[PATCH v2] scsi: NCR5380: Remove context check

2020-12-04 Thread Ahmed S. Darwish
NCR5380_poll_politely2() uses in_interrupt() and irqs_disabled() to
check if it is safe to sleep.

Such usage in drivers is phased out and Linus clearly requested that
code which changes behaviour depending on context should either be
separated, or the context be explicitly conveyed in an argument passed
by the caller.

Below is a context analysis of NCR5380_poll_politely2() uppermost
callers:

  - NCR5380_maybe_reset_bus(), task, invoked during device probe.
-> NCR5380_poll_politely()
-> do_abort()

  - NCR5380_select(), task, but can only sleep in the "release, then
re-acquire" regions of the spinlock held by its caller.
Sleeping invocations (lock released):
-> NCR5380_poll_politely2()

Atomic invocations (lock acquired):
-> NCR5380_reselect()
   -> NCR5380_poll_politely()
   -> do_abort()
   -> NCR5380_transfer_pio()

  - NCR5380_intr(), interrupt handler
-> NCR5380_dma_complete()
   -> NCR5380_transfer_pio()
  -> NCR5380_poll_politely()
-> NCR5380_reselect() (see above)

  - NCR5380_information_transfer(), task, but can only sleep in the
"release, then re-acquire" regions of the caller-held spinlock.
Sleeping invocations (lock released):
  - NCR5380_transfer_pio() -> NCR5380_poll_politely()
  - NCR5380_poll_politely()

Atomic invocations (lock acquired):
  - NCR5380_transfer_dma()
-> NCR5380_dma_recv_setup()
   => generic_NCR5380_precv() -> NCR5380_poll_politely()
   => macscsi_pread() -> NCR5380_poll_politely()

-> NCR5380_dma_send_setup()
   => generic_NCR5380_psend -> NCR5380_poll_politely2()
   => macscsi_pwrite() -> NCR5380_poll_politely()

-> NCR5380_poll_politely2()
-> NCR5380_dma_complete()
   -> NCR5380_transfer_pio()
  -> NCR5380_poll_politely()
  - NCR5380_transfer_pio() -> NCR5380_poll_politely

  - NCR5380_reselect(), atomic, always called with hostdata spinlock
held.

Since NCR5380_poll_politely2() already takes a "wait" argument in
jiffies, use it to determine if the function can sleep. Modify atomic
callers, which passed an unused wait value in terms of HZ, to pass zero.

Suggested-by: Finn Thain 
Co-developed-by: Sebastian Andrzej Siewior 
Signed-off-by: Ahmed S. Darwish 
Cc: Michael Schmitz 
Cc: 
---
 drivers/scsi/NCR5380.c   | 77 ++--
 drivers/scsi/NCR5380.h   |  3 +-
 drivers/scsi/g_NCR5380.c | 12 +++
 drivers/scsi/mac_scsi.c  | 10 +++---
 4 files changed, 55 insertions(+), 47 deletions(-)

diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index d654a6cc4162..60200f61592e 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -132,7 +132,7 @@
 static unsigned int disconnect_mask = ~0;
 module_param(disconnect_mask, int, 0444);
 
-static int do_abort(struct Scsi_Host *);
+static int do_abort(struct Scsi_Host *, unsigned int);
 static void do_reset(struct Scsi_Host *);
 static void bus_reset_cleanup(struct Scsi_Host *);
 
@@ -197,7 +197,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
  * @reg2: Second 5380 register to poll
  * @bit2: Second bitmask to check
  * @val2: Second expected value
- * @wait: Time-out in jiffies
+ * @wait: Time-out in jiffies, 0 if sleeping is not allowed
  *
  * Polls the chip in a reasonably efficient manner waiting for an
  * event to occur. After a short quick poll we begin to yield the CPU
@@ -213,7 +213,7 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata 
*hostdata,
   unsigned long wait)
 {
unsigned long n = hostdata->poll_loops;
-   unsigned long deadline = jiffies + wait;
+   unsigned long deadline;
 
do {
if ((NCR5380_read(reg1) & bit1) == val1)
@@ -223,10 +223,11 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata 
*hostdata,
cpu_relax();
} while (n--);
 
-   if (irqs_disabled() || in_interrupt())
+   if (!wait)
return -ETIMEDOUT;
 
/* Repeatedly sleep for 1 ms until deadline */
+   deadline = jiffies + wait;
while (time_is_after_jiffies(deadline)) {
schedule_timeout_uninterruptible(1);
if ((NCR5380_read(reg1) & bit1) == val1)
@@ -486,7 +487,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host 
*instance)
break;
case 2:
shost_printk(KERN_ERR, instance, "bus busy, attempting 
abort\n");
-   do_abort(instance);
+   do_abort(instance, 1);
break;
case 4:
shost_printk(KERN_ERR, instance, "bus busy, attempting 
reset\n");
@@ -818,7 +819,7 @@ static void NCR5380_d

Re: [PATCH v4 2/2] mm: prevent gup_fast from racing with COW during fork

2020-11-11 Thread Ahmed S. Darwish
On Tue, Nov 10, 2020 at 07:44:09PM -0400, Jason Gunthorpe wrote:
...
>
> Fixes: f3c64eda3e50 ("mm: avoid early COW write protect games during fork()")
> Suggested-by: Linus Torvalds 
> Link: 
> https://lore.kernel.org/r/CAHk-=wi=icnycarbpgjkvju9eyyez13n64tzyldob8cp5q_...@mail.gmail.com
> Reviewed-by: John Hubbard 
> Reviewed-by: Jan Kara 
> Signed-off-by: Jason Gunthorpe 
> ---

Thanks for the v3 and v4 updates.

For the seqcount_t parts:

  Acked-by: "Ahmed S. Darwish" 


Re: [PATCH v3 0/2] Add a seqcount between gup_fast and copy_page_range()

2020-11-06 Thread Ahmed S. Darwish
On Fri, Nov 06, 2020 at 11:55:12AM -0400, Jason Gunthorpe wrote:
...
>
>  arch/x86/kernel/tboot.c|   1 +
>  drivers/firmware/efi/efi.c |   1 +
>  include/linux/mm_types.h   |   8 +++
>  kernel/fork.c  |   1 +
>  mm/gup.c   | 118 +++--
>  mm/init-mm.c   |   1 +
>  mm/memory.c|  13 +++-
>  7 files changed, 97 insertions(+), 46 deletions(-)
>

Nitpick: Please also use the "--base" option of git format-patch. This
will produce a nice "base-commit: " tag behind the diffstat.

Konstantin's amazing "b4" tool gets much happier with that ;-)

All the best,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH v3 2/2] mm: prevent gup_fast from racing with COW during fork

2020-11-06 Thread Ahmed S. Darwish
Hi Jason,

On Fri, Nov 06, 2020 at 11:55:14AM -0400, Jason Gunthorpe wrote:
...
> + if (gup_flags & FOLL_PIN) {
> + seq = raw_read_seqcount(>mm->write_protect_seq);
> + if (seq & 1)
> + return 0;
> + }
> +
...
> + if (gup_flags & FOLL_PIN) {
> + if (read_seqcount_t_retry(>mm->write_protect_seq,
> +   seq)) {
> + unpin_user_pages(pages, nr_pinned);
> + return 0;
> + }
> + }

>From seqlock.h:

/**
 * raw_read_seqcount() - read the raw seqcount_t counter value
 * ...
 * Return: count to be passed to read_seqcount_retry()
 */
#define raw_read_seqcount(s)

Please avoid using the internal API (read_seqcount_*t*_retry) and just
use read_seqcount_retry() as the documentation suggests.

(I guess you just missed changing that last one... I'm in process of
 changing all these "*_seqcount_t_*" stuff to "do_*" as we talked on the
 v2 thread. Hopefully there will be no more confusion after that.)

Kind regards,

--
Ahmed S. Darwish
Linutronix GmbH


Re: [PATCH v2 2/2] mm: prevent gup_fast from racing with COW during fork

2020-11-04 Thread Ahmed S. Darwish
On Wed, Nov 04, 2020 at 10:38:57AM -0800, Linus Torvalds wrote:
...
>
> Looks reasonable to me.
>
> And can you add a few comments to the magic type macros, so that it's
> a lot more obvious what the end result was.
...
>
> I can see it when I really look, but when looking at the actual use,
> it's very non-obvious indeed.
>

ACK, will do.

>      Linus

Thanks,

--
Ahmed S. Darwish
Linutronix GmbH


  1   2   3   4   5   6   7   8   9   10   >