net: brcmfmac: Convey allocation mode as argument
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 29 Sep 2020 20:25:36 +0000 (22:25 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 29 Sep 2020 21:02:55 +0000 (14:02 -0700)
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 seperated or the context be conveyed in an argument passed by the
caller, which usually knows the context.

brcmf_fweh_process_event() uses in_interrupt() to select the allocation
mode GFP_KERNEL/GFP_ATOMIC. Aside of the above reasons this check is
incomplete as it cannot detect contexts which just have preemption or
interrupts disabled.

All callchains leading to brcmf_fweh_process_event() can clearly identify
the calling context. Convey a 'gfp' argument through the callchains and let
the callers hand in the appropriate GFP mode.

This has also the advantage that any change of execution context or
preemption/interrupt state in these callchains will be detected by the
memory allocator for all GFP_KERNEL allocations.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c

index 4b027a2..4ac1e4f 100644 (file)
@@ -513,10 +513,12 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event,
                brcmf_proto_rxreorder(ifp, skb, inirq);
        } else {
                /* Process special event packets */
-               if (handle_event)
-                       brcmf_fweh_process_skb(ifp->drvr, skb,
-                                              BCMILCP_SUBTYPE_VENDOR_LONG);
+               if (handle_event) {
+                       gfp_t gfp = inirq ? GFP_ATOMIC : GFP_KERNEL;
 
+                       brcmf_fweh_process_skb(ifp->drvr, skb,
+                                              BCMILCP_SUBTYPE_VENDOR_LONG, gfp);
+               }
                brcmf_netif_rx(ifp, skb, inirq);
        }
 }
@@ -532,7 +534,7 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
        if (brcmf_rx_hdrpull(drvr, skb, &ifp))
                return;
 
-       brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+       brcmf_fweh_process_skb(ifp->drvr, skb, 0, GFP_KERNEL);
        brcmu_pkt_buf_free_skb(skb);
 }
 
index 3bdbb28..c847062 100644 (file)
@@ -388,12 +388,11 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
  */
 void brcmf_fweh_process_event(struct brcmf_pub *drvr,
                              struct brcmf_event *event_packet,
-                             u32 packet_len)
+                             u32 packet_len, gfp_t gfp)
 {
        enum brcmf_fweh_event_code code;
        struct brcmf_fweh_info *fweh = &drvr->fweh;
        struct brcmf_fweh_queue_item *event;
-       gfp_t alloc_flag = GFP_KERNEL;
        void *data;
        u32 datalen;
 
@@ -412,10 +411,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
            datalen + sizeof(*event_packet) > packet_len)
                return;
 
-       if (in_interrupt())
-               alloc_flag = GFP_ATOMIC;
-
-       event = kzalloc(sizeof(*event) + datalen, alloc_flag);
+       event = kzalloc(sizeof(*event) + datalen, gfp);
        if (!event)
                return;
 
index a82f51b..48414e8 100644 (file)
@@ -319,11 +319,12 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr,
 int brcmf_fweh_activate_events(struct brcmf_if *ifp);
 void brcmf_fweh_process_event(struct brcmf_pub *drvr,
                              struct brcmf_event *event_packet,
-                             u32 packet_len);
+                             u32 packet_len, gfp_t gfp);
 void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
 
 static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
-                                         struct sk_buff *skb, u16 stype)
+                                         struct sk_buff *skb, u16 stype,
+                                         gfp_t gfp)
 {
        struct brcmf_event *event_packet;
        u16 subtype, usr_stype;
@@ -354,7 +355,7 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
        if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
                return;
 
-       brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN);
+       brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN, gfp);
 }
 
 #endif /* FWEH_H_ */
index 69f04bb..7c8e08e 100644 (file)
@@ -1129,7 +1129,7 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
 
        skb->protocol = eth_type_trans(skb, ifp->ndev);
 
-       brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+       brcmf_fweh_process_skb(ifp->drvr, skb, 0, GFP_KERNEL);
 
 exit:
        brcmu_pkt_buf_free_skb(skb);