staging: brcm80211: move dpc code to dhd_sdio.c
authorFranky Lin <frankyl@broadcom.com>
Wed, 29 Jun 2011 23:47:45 +0000 (16:47 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 5 Jul 2011 16:57:22 +0000 (09:57 -0700)
Dpc thread handles data transaction which should be placed in
bus interface layer. Move related code to dhd_sdio.c for clean up.

Signed-off-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/brcm80211/brcmfmac/dhd_bus.h
drivers/staging/brcm80211/brcmfmac/dhd_linux.c
drivers/staging/brcm80211/brcmfmac/dhd_sdio.c

index eab5cdd2343aeb3b50c58a7f3559273d970ade9e..1038ddb3b80d372ac477df3485e68d252b6fa93f 100644 (file)
@@ -58,8 +58,6 @@ brcmf_sdbrcm_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
 extern int
 brcmf_sdbrcm_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
 
-/* Deferred processing for the bus, return true requests reschedule */
-extern bool dhd_bus_dpc(struct dhd_bus *bus);
 extern void dhd_bus_isr(bool *InterruptRecognized,
                        bool *QueueMiniportHandleInterrupt, void *arg);
 
index 8491b4e58f462df53f1bb073cf6f2d6694f8a50d..fac8302301dd144785b24afe71aaed44fd3f5c88 100644 (file)
@@ -82,13 +82,10 @@ typedef struct dhd_info {
 
        struct semaphore proto_sem;
        wait_queue_head_t ioctl_resp_wait;
-       struct tasklet_struct tasklet;
        spinlock_t sdlock;
        /* Thread based operation */
        bool threads_only;
        struct semaphore sdsem;
-       struct task_struct *dpc_tsk;
-       struct semaphore dpc_sem;
 
        /* Thread to issue ioctl for multicast */
        struct task_struct *sysioc_tsk;
@@ -145,11 +142,6 @@ module_param(brcmf_pkt_filter_init, uint, 0);
 uint brcmf_master_mode = true;
 module_param(brcmf_master_mode, uint, 1);
 
-/* DPC thread priority, -1 to use tasklet */
-int brcmf_dpc_prio = 98;
-module_param(brcmf_dpc_prio, int, 0);
-
-/* DPC thread priority, -1 to use tasklet */
 extern int brcmf_dongle_memsize;
 module_param(brcmf_dongle_memsize, int, 0);
 
@@ -190,10 +182,6 @@ extern uint brcmf_rxbound;
 module_param(brcmf_txbound, uint, 0);
 module_param(brcmf_rxbound, uint, 0);
 
-/* Deferred transmits */
-extern uint brcmf_deferred_tx;
-module_param(brcmf_deferred_tx, uint, 0);
-
 #ifdef SDTEST
 /* Echo packet generator (pkts/s) */
 uint brcmf_pktgen;
@@ -211,7 +199,6 @@ module_param(brcmf_pktgen_len, uint, 0);
 #define DHD_COMPILED
 #endif
 
-static void brcmf_dpc(unsigned long data);
 static int brcmf_toe_get(dhd_info_t *dhd, int idx, u32 *toe_ol);
 static int brcmf_toe_set(dhd_info_t *dhd, int idx, u32 toe_ol);
 static int brcmf_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
@@ -1012,69 +999,6 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
        return &ifp->stats;
 }
 
-static int brcmf_dpc_thread(void *data)
-{
-       dhd_info_t *dhd = (dhd_info_t *) data;
-
-       /* This thread doesn't need any user-level access,
-        * so get rid of all our resources
-        */
-       if (brcmf_dpc_prio > 0) {
-               struct sched_param param;
-               param.sched_priority =
-                   (brcmf_dpc_prio <
-                    MAX_RT_PRIO) ? brcmf_dpc_prio : (MAX_RT_PRIO - 1);
-               sched_setscheduler(current, SCHED_FIFO, &param);
-       }
-
-       allow_signal(SIGTERM);
-       /* Run until signal received */
-       while (1) {
-               if (kthread_should_stop())
-                       break;
-               if (down_interruptible(&dhd->dpc_sem) == 0) {
-                       /* Call bus dpc unless it indicated down
-                                (then clean stop) */
-                       if (dhd->pub.busstate != DHD_BUS_DOWN) {
-                               if (dhd_bus_dpc(dhd->pub.bus)) {
-                                       up(&dhd->dpc_sem);
-                               }
-                       } else {
-                               brcmf_sdbrcm_bus_stop(dhd->pub.bus, true);
-                       }
-               } else
-                       break;
-       }
-       return 0;
-}
-
-static void brcmf_dpc(unsigned long data)
-{
-       dhd_info_t *dhd;
-
-       dhd = (dhd_info_t *) data;
-
-       /* Call bus dpc unless it indicated down (then clean stop) */
-       if (dhd->pub.busstate != DHD_BUS_DOWN) {
-               if (dhd_bus_dpc(dhd->pub.bus))
-                       tasklet_schedule(&dhd->tasklet);
-       } else {
-               brcmf_sdbrcm_bus_stop(dhd->pub.bus, true);
-       }
-}
-
-void brcmf_sched_dpc(dhd_pub_t *dhdp)
-{
-       dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-
-       if (dhd->dpc_tsk) {
-               up(&dhd->dpc_sem);
-               return;
-       }
-
-       tasklet_schedule(&dhd->tasklet);
-}
-
 /* Retrieve current toe component enables, which are kept
         as a bitmap in toe_ol iovar */
 static int brcmf_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
@@ -1598,21 +1522,6 @@ dhd_pub_t *brcmf_attach(struct dhd_bus *bus, uint bus_hdrlen)
        else
                dhd->threads_only = false;
 
-       /* Set up the bottom half handler */
-       if (brcmf_dpc_prio >= 0) {
-               /* Initialize DPC thread */
-               sema_init(&dhd->dpc_sem, 0);
-               dhd->dpc_tsk = kthread_run(brcmf_dpc_thread, dhd, "dhd_dpc");
-               if (IS_ERR(dhd->dpc_tsk)) {
-                       printk(KERN_WARNING
-                               "dhd_dpc thread failed to start\n");
-                       dhd->dpc_tsk = NULL;
-               }
-       } else {
-               tasklet_init(&dhd->tasklet, brcmf_dpc, (unsigned long) dhd);
-               dhd->dpc_tsk = NULL;
-       }
-
        if (brcmf_sysioc) {
                sema_init(&dhd->sysioc_sem, 0);
                dhd->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, dhd,
@@ -1866,13 +1775,6 @@ void brcmf_detach(dhd_pub_t *dhdp)
                                unregister_netdev(ifp->net);
                        }
 
-                       if (dhd->dpc_tsk) {
-                               send_sig(SIGTERM, dhd->dpc_tsk, 1);
-                               kthread_stop(dhd->dpc_tsk);
-                               dhd->dpc_tsk = NULL;
-                       } else
-                               tasklet_kill(&dhd->tasklet);
-
                        if (dhd->sysioc_tsk) {
                                send_sig(SIGTERM, dhd->sysioc_tsk, 1);
                                kthread_stop(dhd->sysioc_tsk);
@@ -1907,21 +1809,6 @@ static int __init brcmf_module_init(void)
 
        DHD_TRACE(("%s: Enter\n", __func__));
 
-       /* Sanity check on the module parameters */
-       do {
-               /* Both watchdog and DPC as tasklets are ok */
-               if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
-                       break;
-
-               /* If both watchdog and DPC are threads, TX must be deferred */
-               if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
-                   && brcmf_deferred_tx)
-                       break;
-
-               DHD_ERROR(("Invalid module parameters.\n"));
-               return -EINVAL;
-       } while (0);
-
        error = dhd_bus_register();
 
        if (error) {
index b79e5cdad6c5e2da4dc9dfd9f90a40f96a44272f..6f69413279944234f44748b638a4c2929df17709 100644 (file)
@@ -593,6 +593,10 @@ typedef struct dhd_bus {
        struct completion watchdog_wait;
        struct task_struct *watchdog_tsk;
        bool wd_timer_valid;
+
+       struct tasklet_struct tasklet;
+       struct task_struct *dpc_tsk;
+       struct completion dpc_wait;
 } dhd_bus_t;
 
 typedef volatile struct _sbconfig {
@@ -649,7 +653,8 @@ static int tx_packets[NUMPRIO];
 #endif                         /* BCMDBG */
 
 /* Deferred transmit */
-const uint brcmf_deferred_tx = 1;
+uint brcmf_deferred_tx = 1;
+module_param(brcmf_deferred_tx, uint, 0);
 
 /* Watchdog thread priority, -1 to use kernel timer */
 int brcmf_watchdog_prio = 97;
@@ -659,6 +664,10 @@ module_param(brcmf_watchdog_prio, int, 0);
 uint brcmf_watchdog_ms = 10;
 module_param(brcmf_watchdog_ms, uint, 0);
 
+/* DPC thread priority, -1 to use tasklet */
+int brcmf_dpc_prio = 98;
+module_param(brcmf_dpc_prio, int, 0);
+
 #ifdef BCMDBG
 /* Console poll interval */
 uint brcmf_console_ms;
@@ -804,6 +813,9 @@ static void brcmf_sdbrcm_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
 static void brcmf_sdbrcm_wait_event_wakeup(dhd_bus_t *bus);
 static void brcmf_sdbrcm_watchdog(unsigned long data);
 static int brcmf_sdbrcm_watchdog_thread(void *data);
+static int brcmf_sdbrcm_dpc_thread(void *data);
+static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
+static void brcmf_sdbrcm_sched_dpc(dhd_bus_t *bus);
 
 /* Packet free applicable unconditionally for sdio and sdspi.
  * Conditional if bufpool was present for gspi bus.
@@ -1355,7 +1367,7 @@ int brcmf_sdbrcm_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
                /* Schedule DPC if needed to send queued packet(s) */
                if (brcmf_deferred_tx && !bus->dpc_sched) {
                        bus->dpc_sched = true;
-                       brcmf_sched_dpc(bus->dhd);
+                       brcmf_sdbrcm_sched_dpc(bus);
                }
        } else {
                /* Lock: we're about to use shared data/code (and SDIO) */
@@ -3033,6 +3045,13 @@ void brcmf_sdbrcm_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
                bus->watchdog_tsk = NULL;
        }
 
+       if (bus->dpc_tsk) {
+               send_sig(SIGTERM, bus->dpc_tsk, 1);
+               kthread_stop(bus->dpc_tsk);
+               bus->dpc_tsk = NULL;
+       } else
+               tasklet_kill(&bus->tasklet);
+
        /* Disable and clear interrupts at the chip level also */
        W_SDREG(0, &bus->regs->hostintmask, retries);
        local_hostintmask = bus->hostintmask;
@@ -4459,7 +4478,7 @@ static u32 brcmf_sdbrcm_hostmail(dhd_bus_t *bus)
        return intstatus;
 }
 
-bool brcmf_sdbrcm_dpc(dhd_bus_t *bus)
+static bool brcmf_sdbrcm_dpc(dhd_bus_t *bus)
 {
        struct brcmf_sdio *sdh = bus->sdh;
        struct sdpcmd_regs *regs = bus->regs;
@@ -4711,17 +4730,6 @@ clkwait:
        return resched;
 }
 
-bool dhd_bus_dpc(struct dhd_bus *bus)
-{
-       bool resched;
-
-       /* Call the DPC directly. */
-       DHD_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
-       resched = brcmf_sdbrcm_dpc(bus);
-
-       return resched;
-}
-
 void brcmf_sdbrcm_isr(void *arg)
 {
        dhd_bus_t *bus = (dhd_bus_t *) arg;
@@ -4765,7 +4773,7 @@ void brcmf_sdbrcm_isr(void *arg)
                ;
 #else
        bus->dpc_sched = true;
-       brcmf_sched_dpc(bus->dhd);
+       brcmf_sdbrcm_sched_dpc(bus);
 #endif
 
 }
@@ -5077,7 +5085,7 @@ extern bool brcmf_sdbrcm_bus_watchdog(dhd_pub_t *dhdp)
                                        brcmf_sdcard_intr_disable(bus->sdh);
 
                                bus->dpc_sched = true;
-                               brcmf_sched_dpc(bus->dhd);
+                               brcmf_sdbrcm_sched_dpc(bus);
 
                        }
                }
@@ -5323,6 +5331,23 @@ static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
        } else
                bus->watchdog_tsk = NULL;
 
+       /* Set up the bottom half handler */
+       if (brcmf_dpc_prio >= 0) {
+               /* Initialize DPC thread */
+               init_completion(&bus->dpc_wait);
+               bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
+                                          bus, "dhd_dpc");
+               if (IS_ERR(bus->dpc_tsk)) {
+                       printk(KERN_WARNING
+                              "dhd_dpc thread failed to start\n");
+                       bus->dpc_tsk = NULL;
+               }
+       } else {
+               tasklet_init(&bus->tasklet, brcmf_sdbrcm_dpc_tasklet,
+                            (unsigned long)bus);
+               bus->dpc_tsk = NULL;
+       }
+
        /* Attach to the dhd/OS/network interface */
        bus->dhd = brcmf_attach(bus, SDPCM_RESERVE);
        if (!bus->dhd) {
@@ -5679,6 +5704,21 @@ int dhd_bus_register(void)
 {
        DHD_TRACE(("%s: Enter\n", __func__));
 
+       /* Sanity check on the module parameters */
+       do {
+               /* Both watchdog and DPC as tasklets are ok */
+               if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
+                       break;
+
+               /* If both watchdog and DPC are threads, TX must be deferred */
+               if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
+                   && brcmf_deferred_tx)
+                       break;
+
+               DHD_ERROR(("Invalid module parameters.\n"));
+               return -EINVAL;
+       } while (0);
+
        return brcmf_sdio_register(&dhd_sdio);
 }
 
@@ -6542,3 +6582,59 @@ brcmf_sdbrcm_wd_timer(struct dhd_bus *bus, uint wdtick)
                save_ms = wdtick;
        }
 }
+
+static int brcmf_sdbrcm_dpc_thread(void *data)
+{
+       dhd_bus_t *bus = (dhd_bus_t *) data;
+
+       /* This thread doesn't need any user-level access,
+        * so get rid of all our resources
+        */
+       if (brcmf_dpc_prio > 0) {
+               struct sched_param param;
+               param.sched_priority = (brcmf_dpc_prio < MAX_RT_PRIO) ?
+                                      brcmf_dpc_prio : (MAX_RT_PRIO - 1);
+               sched_setscheduler(current, SCHED_FIFO, &param);
+       }
+
+       allow_signal(SIGTERM);
+       /* Run until signal received */
+       while (1) {
+               if (kthread_should_stop())
+                       break;
+               if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
+                       /* Call bus dpc unless it indicated down
+                       (then clean stop) */
+                       if (bus->dhd->busstate != DHD_BUS_DOWN) {
+                               if (brcmf_sdbrcm_dpc(bus))
+                                       complete(&bus->dpc_wait);
+                       } else {
+                               brcmf_sdbrcm_bus_stop(bus, true);
+                       }
+               } else
+                       break;
+       }
+       return 0;
+}
+
+static void brcmf_sdbrcm_dpc_tasklet(unsigned long data)
+{
+       dhd_bus_t *bus = (dhd_bus_t *) data;
+
+       /* Call bus dpc unless it indicated down (then clean stop) */
+       if (bus->dhd->busstate != DHD_BUS_DOWN) {
+               if (brcmf_sdbrcm_dpc(bus))
+                       tasklet_schedule(&bus->tasklet);
+       } else
+               brcmf_sdbrcm_bus_stop(bus, true);
+}
+
+static void brcmf_sdbrcm_sched_dpc(dhd_bus_t *bus)
+{
+       if (bus->dpc_tsk) {
+               complete(&bus->dpc_wait);
+               return;
+       }
+
+       tasklet_schedule(&bus->tasklet);
+}