From efa6a370216f1816456b49aac03295071720f7eb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 27 Jun 2006 21:38:40 +0200 Subject: [PATCH] bcm43xx: opencoded locking As many people don't seem to like the locking "obfuscation" in the bcm43xx driver, this patch removes it. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 64 +++---------- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 34 ++++--- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 10 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 64 ++++++------- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 34 ++++--- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 121 ++++++++++++++----------- 7 files changed, 167 insertions(+), 164 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 17a56828e23..ee6571ed706 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -649,6 +649,19 @@ enum { #define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) #define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) +/* *** THEORY OF LOCKING *** + * + * We have two different locks in the bcm43xx driver. + * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private + * and the device registers. This mutex does _not_ protect + * against concurrency from the IRQ handler. + * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. + * + * Please note that, if you only take the irq_lock, you are not protected + * against concurrency from the periodic work handlers. + * Most times you want to take _both_ locks. + */ + struct bcm43xx_private { struct ieee80211_device *ieee; struct ieee80211softmac_device *softmac; @@ -659,7 +672,6 @@ struct bcm43xx_private { void __iomem *mmio_addr; - /* Locking, see "theory of locking" text below. */ spinlock_t irq_lock; struct mutex mutex; @@ -691,6 +703,7 @@ struct bcm43xx_private { struct bcm43xx_sprominfo sprom; #define BCM43xx_NR_LEDS 4 struct bcm43xx_led leds[BCM43xx_NR_LEDS]; + spinlock_t leds_lock; /* The currently active core. */ struct bcm43xx_coreinfo *current_core; @@ -763,55 +776,6 @@ struct bcm43xx_private { }; -/* *** THEORY OF LOCKING *** - * - * We have two different locks in the bcm43xx driver. - * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private - * and the device registers. - * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. - * - * We have three types of helper function pairs to utilize these locks. - * (Always use the helper functions.) - * 1) bcm43xx_{un}lock_noirq(): - * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, - * so it is almost always unsafe, if device IRQs are enabled. - * So only use this, if device IRQs are masked. - * Locking may sleep. - * You can sleep within the critical section. - * 2) bcm43xx_{un}lock_irqonly(): - * Takes bcm->irq_lock. Does _not_ protect against - * bcm43xx_lock_noirq() critical sections. - * Does only protect against the IRQ handler path and other - * irqonly() critical sections. - * Locking does not sleep. - * You must not sleep within the critical section. - * 3) bcm43xx_{un}lock_irqsafe(): - * This is the cummulative lock and takes both, mutex and irq_lock. - * Protects against noirq() and irqonly() critical sections (and - * the IRQ handler path). - * Locking may sleep. - * You must not sleep within the critical section. - */ - -/* Lock type 1 */ -#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) -#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) -/* Lock type 2 */ -#define bcm43xx_lock_irqonly(bcm, flags) \ - spin_lock_irqsave(&(bcm)->irq_lock, flags) -#define bcm43xx_unlock_irqonly(bcm, flags) \ - spin_unlock_irqrestore(&(bcm)->irq_lock, flags) -/* Lock type 3 */ -#define bcm43xx_lock_irqsafe(bcm, flags) do { \ - bcm43xx_lock_noirq(bcm); \ - bcm43xx_lock_irqonly(bcm, flags); \ - } while (0) -#define bcm43xx_unlock_irqsafe(bcm, flags) do { \ - bcm43xx_unlock_irqonly(bcm, flags); \ - bcm43xx_unlock_noirq(bcm); \ - } while (0) - - static inline struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index ce2e40b29b4..2600ee4b803 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; @@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\n"); out: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, unsigned long flags; down(&big_buffer_sem); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; @@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); out: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, u64 tsf; down(&big_buffer_sem); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; @@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, (unsigned int)(tsf & 0xFFFFFFFFULL)); out: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = -EFAULT; goto out_up; } - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT; @@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = buf_size; out_unlock: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); out_up: up(&big_buffer_sem); return res; @@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, int i, cnt, j = 0; down(&big_buffer_sem); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", BCM43xx_NR_LOGGED_XMITSTATUS); @@ -294,14 +303,15 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - bcm43xx_lock_irqsafe(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); if (*ppos == pos) { /* Done. Drop the copied data. */ e->xmitstatus_printing = 0; } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); up(&big_buffer_sem); return res; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index ec80692d638..c3f90c8563d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) struct bcm43xx_private *bcm = led->bcm; unsigned long flags; - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->leds_lock, flags); if (led->blink_interval) { bcm43xx_led_changestate(led); mod_timer(&led->blink_timer, jiffies + led->blink_interval); } - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->leds_lock, flags); } static void bcm43xx_led_blink_start(struct bcm43xx_led *led, @@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) int i, turn_on; unsigned long interval = 0; u16 ledctl; + unsigned long flags; + spin_lock_irqsave(&bcm->leds_lock, flags); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); @@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ledctl &= ~(1 << i); } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); + spin_unlock_irqrestore(&bcm->leds_lock, flags); } void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) @@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) u16 ledctl; int i; int bit_on; + unsigned long flags; + spin_lock_irqsave(&bcm->leds_lock, flags); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); @@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) ledctl &= ~(1 << i); } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); + spin_unlock_irqrestore(&bcm->leds_lock, flags); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3889f79e712..ef9bc80bee0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -514,13 +514,13 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old unsigned long flags; u32 old; - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); bcm43xx_synchronize_irq(bcm); if (oldstate) @@ -1720,7 +1720,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) # define bcmirq_handled(irq) do { /* nothing */ } while (0) #endif /* CONFIG_BCM43XX_DEBUG*/ - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); reason = bcm->irq_reason; dma_reason[0] = bcm->dma_reason[0]; dma_reason[1] = bcm->dma_reason[1]; @@ -1746,7 +1746,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) dma_reason[2], dma_reason[3]); bcm43xx_controller_restart(bcm, "DMA error"); mmiowb(); - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); return; } if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | @@ -1834,7 +1834,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_leds_update(bcm, activity); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); mmiowb(); - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); } static void pio_irq_workaround(struct bcm43xx_private *bcm, @@ -3182,25 +3182,26 @@ static void bcm43xx_periodic_work_handler(void *d) /* Periodic work will take a long time, so we want it to * be preemtible. */ - bcm43xx_lock_irqonly(bcm, flags); netif_stop_queue(bcm->net_dev); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_using_pio(bcm)) bcm43xx_pio_freeze_txqueues(bcm); savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_unlock_irqonly(bcm, flags); - bcm43xx_lock_noirq(bcm); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_lock(&bcm->mutex); bcm43xx_synchronize_irq(bcm); } else { /* Periodic work should take short time, so we want low * locking overhead. */ - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); } do_periodic_work(bcm); if (badness > BADNESS_LIMIT) { - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { tasklet_enable(&bcm->isr_tasklet); bcm43xx_interrupt_enable(bcm, savedirqs); @@ -3208,13 +3209,10 @@ static void bcm43xx_periodic_work_handler(void *d) bcm43xx_pio_thaw_txqueues(bcm); } netif_wake_queue(bcm->net_dev); - mmiowb(); - bcm43xx_unlock_irqonly(bcm, flags); - bcm43xx_unlock_noirq(bcm); - } else { - mmiowb(); - bcm43xx_unlock_irqsafe(bcm, flags); } + mmiowb(); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) @@ -3276,7 +3274,7 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) { int i, err; - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); bcm43xx_sysfs_unregister(bcm); bcm43xx_periodic_tasks_delete(bcm); @@ -3297,7 +3295,7 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); } static int bcm43xx_init_board(struct bcm43xx_private *bcm) @@ -3307,7 +3305,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) might_sleep(); - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); err = bcm43xx_pctl_set_crystal(bcm, 1); @@ -3389,7 +3387,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) assert(err == 0); out: - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); return err; @@ -3647,7 +3645,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, struct bcm43xx_radioinfo *radio; unsigned long flags; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, channel, 0); @@ -3656,7 +3655,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, radio = bcm43xx_current_radio(bcm); radio->initial_channel = channel; } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); } /* set_security() callback in struct ieee80211_device */ @@ -3670,7 +3670,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, dprintk(KERN_INFO PFX "set security called"); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); for (keyidx = 0; keyidxflags & (1<irq_lock, flags); + mutex_unlock(&bcm->mutex); } /* hard_start_xmit() callback in struct ieee80211_device */ @@ -3751,10 +3753,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, int err = -ENODEV; unsigned long flags; - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) err = bcm43xx_tx(bcm, txb); - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); return err; } @@ -3769,9 +3771,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev) struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); bcm43xx_controller_restart(bcm, "TX timeout"); - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -3822,6 +3824,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->net_dev = net_dev; bcm->bad_frames_preempt = modparam_bad_frames_preempt; spin_lock_init(&bcm->irq_lock); + spin_lock_init(&bcm->leds_lock); mutex_init(&bcm->mutex); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, @@ -4002,16 +4005,13 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *net_dev = pci_get_drvdata(pdev); struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int try_to_shutdown = 0, err; dprintk(KERN_INFO PFX "Suspending...\n"); - bcm43xx_lock_irqsafe(bcm, flags); bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); if (bcm->was_initialized) try_to_shutdown = 1; - bcm43xx_unlock_irqsafe(bcm, flags); netif_device_detach(net_dev); if (try_to_shutdown) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 574085c4615..c60c1743ea0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d) int err; u16 txctl; - bcm43xx_lock_irqonly(bcm, flags); + spin_lock_irqsave(&bcm->irq_lock, flags); if (queue->tx_frozen) goto out_unlock; @@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d) continue; } out_unlock: - bcm43xx_unlock_irqonly(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 6a23bdc7541..cc1ff3c6f14 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, GFP_KERNEL); if (!sprom) return -ENOMEM; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); err = bcm43xx_sprom_read(bcm, sprom); if (!err) err = sprom2hex(sprom, buf, PAGE_SIZE); mmiowb(); - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); kfree(sprom); return err; @@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, err = hex2sprom(sprom, buf, count); if (err) goto out_kfree; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); + spin_lock(&bcm->leds_lock); err = bcm43xx_sprom_write(bcm, sprom); mmiowb(); - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock(&bcm->leds_lock); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); out_kfree: kfree(sprom); @@ -176,7 +182,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); switch (bcm43xx_current_radio(bcm)->interfmode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -193,7 +199,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, } err = 0; - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); return err ? err : count; @@ -229,7 +235,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, return -EINVAL; } - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { @@ -237,7 +244,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, "supported by device\n"); } mmiowb(); - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err ? err : count; } @@ -257,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); if (bcm->short_preamble) count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); @@ -265,7 +273,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); err = 0; - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); return err ? err : count; } @@ -285,12 +293,14 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, value = get_boolean(buf, count); if (value < 0) return value; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); bcm->short_preamble = !!value; err = 0; - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err ? err : count; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 5c36e29efff..ebe2a8469a7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -56,12 +56,11 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int i; - unsigned long flags; struct bcm43xx_phyinfo *phy; char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); for (i = 0; i < bcm->nr_80211_available; i++) { phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { @@ -77,7 +76,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, assert(0); } } - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); i = 0; if (have_a) { @@ -111,7 +110,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = -EINVAL; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); + if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -131,7 +132,8 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = 0; } out_unlock: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -143,11 +145,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); struct bcm43xx_radioinfo *radio; - unsigned long flags; int err = -ENODEV; u16 channel; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); radio = bcm43xx_current_radio(bcm); channel = radio->channel; if (channel == 0xFF) { @@ -162,7 +163,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -180,13 +181,15 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { if (bcm->ieee->iw_mode != mode) bcm43xx_set_iwmode(bcm, mode); } else bcm->ieee->iw_mode = mode; - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -197,11 +200,10 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); data->mode = bcm->ieee->iw_mode; - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -214,7 +216,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); struct iw_range *range = (struct iw_range *)extra; const struct ieee80211_geo *geo; - unsigned long flags; int i, j; struct bcm43xx_phyinfo *phy; @@ -254,7 +255,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); phy = bcm43xx_current_phy(bcm); range->num_bitrates = 0; @@ -301,7 +302,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, } range->num_frequency = j; - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -314,11 +315,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); size_t len; - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); bcm->nick[len] = '\0'; - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); return 0; } @@ -331,12 +332,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); size_t len; - bcm43xx_lock_noirq(bcm); + mutex_lock(&bcm->mutex); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); data->data.length = (__u16)len; data->data.flags = 1; - bcm43xx_unlock_noirq(bcm); + mutex_unlock(&bcm->mutex); return 0; } @@ -350,7 +351,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; err = 0; @@ -361,7 +363,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, err = 0; } } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -372,13 +375,12 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -392,7 +394,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; err = 0; @@ -403,7 +406,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, err = 0; } } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -414,13 +418,12 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -442,7 +445,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, return -EOPNOTSUPP; } - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); @@ -466,7 +470,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -478,10 +483,9 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); struct bcm43xx_radioinfo *radio; - unsigned long flags; int err = -ENODEV; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); @@ -493,7 +497,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -580,7 +584,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, return -EINVAL; } - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { @@ -595,7 +600,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, } else bcm43xx_current_radio(bcm)->interfmode = mode; } - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return err; } @@ -606,12 +612,11 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int mode; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); mode = bcm43xx_current_radio(bcm)->interfmode; - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -641,9 +646,11 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, int on; on = *((int *)extra); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); bcm->short_preamble = !!on; - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -654,12 +661,11 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int on; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); on = bcm->short_preamble; - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); if (on) strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); @@ -681,11 +687,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, on = *((int *)extra); - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); return 0; } @@ -696,12 +704,11 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int on; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); on = bcm->ieee->host_encrypt; - bcm43xx_unlock_irqsafe(bcm, flags); + mutex_unlock(&bcm->mutex); if (on) strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); @@ -764,11 +771,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, if (!sprom) goto out; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); err = -ENODEV; if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_read(bcm, sprom); - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); if (!err) data->data.length = sprom2hex(sprom, extra); kfree(sprom); @@ -809,11 +818,15 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, if (err) goto out_kfree; - bcm43xx_lock_irqsafe(bcm, flags); + mutex_lock(&bcm->mutex); + spin_lock_irqsave(&bcm->irq_lock, flags); + spin_lock(&bcm->leds_lock); err = -ENODEV; if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_write(bcm, sprom); - bcm43xx_unlock_irqsafe(bcm, flags); + spin_unlock(&bcm->leds_lock); + spin_unlock_irqrestore(&bcm->irq_lock, flags); + mutex_unlock(&bcm->mutex); out_kfree: kfree(sprom); out: -- cgit v1.2.3-18-g5258 From 2087da5dc12c497123d5fb8949ceed9021b673ec Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 28 Jun 2006 20:17:57 +0200 Subject: [PATCH] bcm43xx: voluntary preemtion in the calibration loops This patch adds voluntary preemption points into the PHY calibration loops to allow non-CONFIG_PREEMPT machines to not suffer from huge delays. CONFIG_PREEMPT machines are already fine, because all this code is run in non-atomic process context. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index f8200deecc8..eafd0f66268 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = { static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); +static inline +void bcm43xx_voluntary_preempt(void) +{ + assert(!in_atomic() && !in_irq() && + !in_interrupt() && !irqs_disabled()); +#ifndef CONFIG_PREEMPT + cond_resched(); +#endif /* CONFIG_PREEMPT */ +} + void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); @@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - unsigned long flags; bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ if (phy->calibrated) return; if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { - /* We do not want to be preempted while calibrating - * the hardware. - */ - local_irq_save(flags); - bcm43xx_wireless_core_reset(bcm, 0); bcm43xx_phy_initg(bcm); bcm43xx_wireless_core_reset(bcm, 1); - - local_irq_restore(flags); } phy->calibrated = 1; } @@ -1299,7 +1301,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) { int i; u16 ret = 0; + unsigned long flags; + local_irq_save(flags); for (i = 0; i < 10; i++){ bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); udelay(1); @@ -1309,6 +1313,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) udelay(40); ret += bcm43xx_phy_read(bcm, 0x002C); } + local_irq_restore(flags); + bcm43xx_voluntary_preempt(); return ret; } @@ -1435,6 +1441,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) } ret = bcm43xx_phy_read(bcm, 0x002D); local_irq_restore(flags); + bcm43xx_voluntary_preempt(); return ret; } @@ -1760,6 +1767,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x43, i); bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); udelay(10); + bcm43xx_voluntary_preempt(); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); @@ -1803,6 +1811,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) radio->txctl2 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? udelay(10); + bcm43xx_voluntary_preempt(); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); @@ -1824,6 +1833,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); udelay(2); bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); + bcm43xx_voluntary_preempt(); } else bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); bcm43xx_phy_lo_adjust(bcm, is_initializing); @@ -2188,12 +2198,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err = -ENODEV; - unsigned long flags; - - /* We do not want to be preempted while calibrating - * the hardware. - */ - local_irq_save(flags); switch (phy->type) { case BCM43xx_PHYTYPE_A: @@ -2227,7 +2231,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) err = 0; break; } - local_irq_restore(flags); if (err) printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); -- cgit v1.2.3-18-g5258 From 4221f980a4931364be7ffd81c4f16784990f6f8b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 29 Jun 2006 22:48:59 -0500 Subject: [PATCH] bcm43xx: improved statistics This patch improves the statistics returned from bcm43xx_get_wireless_stats. The signal level comes from smoothing the "rssi" value returned by the firmware after it is converted into a dBm value by the driver. The quality value is a hack derived from the smoothed level and an assumed RX_POWER_MAX of -10 dBM. The noise value is still the one calculated from the clean-room formula. On my system, this is roughly -65 dBm, which seems too high. The revised version uses the ieee80211 spinlock to protect traversing of the network list. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 41 +++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index ebe2a8469a7..8ffd760dc83 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -47,6 +47,9 @@ #define BCM43xx_WX_VERSION 18 #define MAX_WX_STRING 80 +/* FIXME: the next line is a guess as to what the maximum value of RX power + (in dBm) might be */ +#define RX_POWER_MAX -10 static int bcm43xx_wx_get_name(struct net_device *net_dev, @@ -228,14 +231,14 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->max_qual.qual = 100; /* TODO: Real max RSSI */ - range->max_qual.level = 3; - range->max_qual.noise = 100; - range->max_qual.updated = 7; + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->max_qual.updated = IW_QUAL_ALL_UPDATED; - range->avg_qual.qual = 70; - range->avg_qual.level = 2; - range->avg_qual.noise = 40; - range->avg_qual.updated = 7; + range->avg_qual.qual = 50; + range->avg_qual.level = 0; + range->avg_qual.noise = 0; + range->avg_qual.updated = IW_QUAL_ALL_UPDATED; range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; @@ -840,6 +843,9 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); struct iw_statistics *wstats; + struct ieee80211_network *network = NULL; + static int tmp_level = 0; + unsigned long flags; wstats = &bcm->stats.wstats; if (!mac->associated) { @@ -857,16 +863,25 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d wstats->qual.level = 0; wstats->qual.noise = 0; wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_NOISE_INVALID | - IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; + wstats->qual.updated |= IW_QUAL_ALL_UPDATED; return wstats; } /* fill in the real statistics when iface associated */ - wstats->qual.qual = 100; // TODO: get the real signal quality - wstats->qual.level = 3 - bcm->stats.link_quality; + spin_lock_irqsave(&mac->ieee->lock, flags); + list_for_each_entry(network, &mac->ieee->network_list, list) { + if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) { + if (!tmp_level) /* get initial value */ + tmp_level = network->stats.rssi; + else /* smooth results */ + tmp_level = (7 * tmp_level + network->stats.rssi)/8; + break; + } + } + spin_unlock_irqrestore(&mac->ieee->lock, flags); + wstats->qual.level = tmp_level; + wstats->qual.qual = 100 + tmp_level - RX_POWER_MAX; // TODO: get the real signal quality wstats->qual.noise = bcm->stats.noise; - wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED; + wstats->qual.updated = IW_QUAL_ALL_UPDATED; wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; -- cgit v1.2.3-18-g5258 From dd2f5538a157bda68bfa8efb39feaaccdda9e74e Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 5 Jul 2006 15:57:31 +0100 Subject: [PATCH] zd1211rw: Add Sagem device ID's Based on a patch by Matthieu CASTET. zd1211 chip 079b:004a v4330 high 00-60-b3 AL2230_RF pa0 g-- zd1211b chip 079b:0062 v4810 high 00-60-b3 AL2230_RF pa0 g-- Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 72f90525bf6..c68b9f8995c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -39,9 +39,11 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, {} }; -- cgit v1.2.3-18-g5258 From 5f5d83fdbfb50ffb6f5fbf5fd69bc791d9d5cd20 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jul 2006 15:38:32 -0400 Subject: [PATCH] sky2: add another PCI ID Yet another PCI ID for 88E8056 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index de91609ca11..8f8799c3f9d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -121,6 +121,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, { 0 } }; -- cgit v1.2.3-18-g5258 From b6e37e55c250f5233401b2566b1a4b512a98bc7b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 14 Jul 2006 12:15:40 +0100 Subject: [PATCH] Cleanup SLHC configuration Convert selection of serial line header compression to use CONFIG_SLHC rather than makefile ifeq uglyness. This makes it easier to select the SLHC module from other code. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/isdn/i4l/Kconfig | 1 + drivers/net/Kconfig | 8 ++++++++ drivers/net/Makefile | 10 ++-------- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index a4f7288a1fc..3ef567b99c7 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -5,6 +5,7 @@ config ISDN_PPP bool "Support synchronous PPP" depends on INET + select SLHC help Over digital connections such as ISDN, there is no need to synchronize sender and recipient's clocks with start and stop bits diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 39189903e35..7c826db8460 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2509,6 +2509,7 @@ config PLIP config PPP tristate "PPP (point-to-point protocol) support" + select SLHC ---help--- PPP (Point to Point Protocol) is a newer and better SLIP. It serves the same purpose: sending Internet traffic over telephone (and other @@ -2689,6 +2690,7 @@ config SLIP config SLIP_COMPRESSED bool "CSLIP compressed headers" depends on SLIP + select SLHC ---help--- This protocol is faster than SLIP because it uses compression on the TCP/IP headers (not on the data itself), but it has to be supported @@ -2701,6 +2703,12 @@ config SLIP_COMPRESSED , explains how to configure CSLIP. This won't enlarge your kernel. +config SLHC + tristate + help + This option enables Van Jacobsen serial line header compression + routines. + config SLIP_SMART bool "Keepalive and linefill" depends on SLIP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c91e95126f7..038a8e02f64 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -2,10 +2,6 @@ # Makefile for the Linux network (ethercard) device drivers. # -ifeq ($(CONFIG_ISDN_PPP),y) - obj-$(CONFIG_ISDN) += slhc.o -endif - obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_IBM_EMAC) += ibm_emac/ obj-$(CONFIG_IXGB) += ixgb/ @@ -111,7 +107,7 @@ obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o -obj-$(CONFIG_PPP) += ppp_generic.o slhc.o +obj-$(CONFIG_PPP) += ppp_generic.o obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o @@ -120,9 +116,7 @@ obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o -ifeq ($(CONFIG_SLIP_COMPRESSED),y) - obj-$(CONFIG_SLIP) += slhc.o -endif +obj-$(CONFIG_SLHC) += slhc.o obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_IFB) += ifb.o -- cgit v1.2.3-18-g5258 From 15880352659a363209c5ad9cfc796a9c8a7f5196 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jul 2006 12:10:48 +0100 Subject: [PATCH] Convert to kzalloc Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/slhc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index 3a1b7131681..f0adad520af 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -94,27 +94,24 @@ slhc_init(int rslots, int tslots) register struct cstate *ts; struct slcompress *comp; - comp = (struct slcompress *)kmalloc(sizeof(struct slcompress), + comp = (struct slcompress *)kzalloc(sizeof(struct slcompress), GFP_KERNEL); if (! comp) goto out_fail; - memset(comp, 0, sizeof(struct slcompress)); if ( rslots > 0 && rslots < 256 ) { size_t rsize = rslots * sizeof(struct cstate); - comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL); + comp->rstate = (struct cstate *) kzalloc(rsize, GFP_KERNEL); if (! comp->rstate) goto out_free; - memset(comp->rstate, 0, rsize); comp->rslot_limit = rslots - 1; } if ( tslots > 0 && tslots < 256 ) { size_t tsize = tslots * sizeof(struct cstate); - comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL); + comp->tstate = (struct cstate *) kzalloc(tsize, GFP_KERNEL); if (! comp->tstate) goto out_free2; - memset(comp->tstate, 0, tsize); comp->tslot_limit = tslots - 1; } -- cgit v1.2.3-18-g5258 From 79690602adc5b52ce224df6ac67bde0074b2aede Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jul 2006 12:12:53 +0100 Subject: [PATCH] Remove useless casts Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/slhc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index f0adad520af..24bbe00852b 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -94,14 +94,13 @@ slhc_init(int rslots, int tslots) register struct cstate *ts; struct slcompress *comp; - comp = (struct slcompress *)kzalloc(sizeof(struct slcompress), - GFP_KERNEL); + comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL); if (! comp) goto out_fail; if ( rslots > 0 && rslots < 256 ) { size_t rsize = rslots * sizeof(struct cstate); - comp->rstate = (struct cstate *) kzalloc(rsize, GFP_KERNEL); + comp->rstate = kzalloc(rsize, GFP_KERNEL); if (! comp->rstate) goto out_free; comp->rslot_limit = rslots - 1; @@ -109,7 +108,7 @@ slhc_init(int rslots, int tslots) if ( tslots > 0 && tslots < 256 ) { size_t tsize = tslots * sizeof(struct cstate); - comp->tstate = (struct cstate *) kzalloc(tsize, GFP_KERNEL); + comp->tstate = kzalloc(tsize, GFP_KERNEL); if (! comp->tstate) goto out_free2; comp->tslot_limit = tslots - 1; @@ -138,9 +137,9 @@ slhc_init(int rslots, int tslots) return comp; out_free2: - kfree((unsigned char *)comp->rstate); + kfree(comp->rstate); out_free: - kfree((unsigned char *)comp); + kfree(comp); out_fail: return NULL; } -- cgit v1.2.3-18-g5258 From 3fac0613937dff488141c8ade3320fd815c38ed7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jul 2006 12:14:55 +0100 Subject: [PATCH] Remove useless #ifdef MODULE stuff and printout Get rid of the MODULE stuff. Could have rewritten to use modern interfaces but the copyright message of this BSD licensed code isn't interesting enough to be watched on every bootup, in every syslog. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/slhc.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index 24bbe00852b..9a540e2092b 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -696,20 +696,6 @@ EXPORT_SYMBOL(slhc_compress); EXPORT_SYMBOL(slhc_uncompress); EXPORT_SYMBOL(slhc_toss); -#ifdef MODULE - -int init_module(void) -{ - printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n"); - return 0; -} - -void cleanup_module(void) -{ - return; -} - -#endif /* MODULE */ #else /* CONFIG_INET */ -- cgit v1.2.3-18-g5258 From 22ad852b8297e5063fc50f54a77e13f6d9b16a6f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 5 Jul 2006 20:36:40 +0200 Subject: [PATCH] resend of 8390 patch for lockdep The 8390 drivers use disable_irq() as a locking primitive, which means these uses need lockdep specific annotation that they are used as such. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Jeff Garzik --- drivers/net/8390.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/8390.c b/drivers/net/8390.c index d2935ae3981..3eb7048684a 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -299,7 +299,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) * Slow phase with lock held. */ - disable_irq_nosync(dev->irq); + disable_irq_nosync_lockdep(dev->irq); spin_lock(&ei_local->page_lock); @@ -338,7 +338,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); outb_p(ENISR_ALL, e8390_base + EN0_IMR); spin_unlock(&ei_local->page_lock); - enable_irq(dev->irq); + enable_irq_lockdep(dev->irq); ei_local->stat.tx_errors++; return 1; } @@ -379,7 +379,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) outb_p(ENISR_ALL, e8390_base + EN0_IMR); spin_unlock(&ei_local->page_lock); - enable_irq(dev->irq); + enable_irq_lockdep(dev->irq); dev_kfree_skb (skb); ei_local->stat.tx_bytes += send_length; @@ -505,9 +505,9 @@ irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) #ifdef CONFIG_NET_POLL_CONTROLLER void ei_poll(struct net_device *dev) { - disable_irq(dev->irq); + disable_irq_lockdep(dev->irq); ei_interrupt(dev->irq, dev, NULL); - enable_irq(dev->irq); + enable_irq_lockdep(dev->irq); } #endif -- cgit v1.2.3-18-g5258 From a2b98a697fa4e7564f78905b83db122824916cf9 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 14 May 2006 12:18:44 +0200 Subject: r8169: mac address change support Fix for http://bugzilla.kernel.org/show_bug.cgi?id=6032. Cc: Tim Mattox Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4c2f575faad..e8786c4fcac 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1382,6 +1382,41 @@ static void rtl8169_netpoll(struct net_device *dev) } #endif +static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem *ioaddr) +{ + unsigned int i, j; + + RTL_W8(Cfg9346, Cfg9346_Unlock); + for (i = 0; i < 2; i++) { + __le32 l = 0; + + for (j = 0; j < 4; j++) { + l <<= 8; + l |= dev->dev_addr[4*i + j]; + } + RTL_W32(MAC0 + 4*i, cpu_to_be32(l)); + } + RTL_W8(Cfg9346, Cfg9346_Lock); +} + +static int rtl8169_set_mac_addr(struct net_device *dev, void *p) +{ + struct rtl8169_private *tp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + if (netif_running(dev)) { + spin_lock_irq(&tp->lock); + __rtl8169_set_mac_addr(dev, tp->mmio_addr); + spin_unlock_irq(&tp->lock); + } + return 0; +} + static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, void __iomem *ioaddr) { @@ -1609,6 +1644,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; + dev->set_mac_address = rtl8169_set_mac_addr; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; @@ -1842,6 +1878,8 @@ rtl8169_hw_start(struct net_device *dev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16(IntrMask, rtl8169_intr_mask); + __rtl8169_set_mac_addr(dev, ioaddr); + netif_start_queue(dev); } -- cgit v1.2.3-18-g5258 From 9dccf61112e6755f4e6f154c1794bab3c509bc71 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 14 May 2006 12:31:17 +0200 Subject: r8169: RX fifo overflow recovery Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index e8786c4fcac..ea4f9f7bd07 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -257,10 +257,11 @@ enum RTL8169_register_content { RxOK = 0x01, /* RxStatusDesc */ - RxRES = 0x00200000, - RxCRC = 0x00080000, - RxRUNT = 0x00100000, - RxRWT = 0x00400000, + RxFOVF = (1 << 23), + RxRWT = (1 << 22), + RxRES = (1 << 21), + RxRUNT = (1 << 20), + RxCRC = (1 << 19), /* ChipCmdBits */ CmdReset = 0x10, @@ -2465,6 +2466,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, tp->stats.rx_length_errors++; if (status & RxCRC) tp->stats.rx_crc_errors++; + if (status & RxFOVF) { + rtl8169_schedule_work(dev, rtl8169_reset_task); + tp->stats.rx_fifo_errors++; + } rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { struct sk_buff *skb = tp->Rx_skbuff[entry]; -- cgit v1.2.3-18-g5258 From 623a1593c84afb86b2f496a56fb4ec37f82b5c78 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 14 May 2006 12:42:14 +0200 Subject: r8169: hardware flow control The datasheet suggests that the device handles the hardware flow control almost automagically. User report a different story, so let's try to twiddle the mii registers. Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index ea4f9f7bd07..3424b3c1083 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -771,6 +771,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half); } + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + tp->phy_auto_nego_reg = auto_nego; tp->phy_1000_ctrl_reg = giga_ctrl; @@ -962,6 +964,11 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) else if (status & _10bps) cmd->speed = SPEED_10; + if (status & TxFlowCtrl) + cmd->advertising |= ADVERTISED_Asym_Pause; + if (status & RxFlowCtrl) + cmd->advertising |= ADVERTISED_Pause; + cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? DUPLEX_FULL : DUPLEX_HALF; } -- cgit v1.2.3-18-g5258 From 4ff96fa67379c31ced69f193c7ffba17051f38e8 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 26 Jul 2006 22:05:06 +0200 Subject: r8169: remove rtl8169_init_board Rationale: - its signature is not exactly pretty; - it has no knowledge of pci_device_id; - kiss 23 lines good bye. Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 191 +++++++++++++++++++++++----------------------------- 1 file changed, 86 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 3424b3c1083..ca0f303a6b5 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1434,23 +1434,60 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, free_netdev(dev); } +static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + static int board_idx = -1; + u8 autoneg, duplex; + u16 speed; + + board_idx++; + + rtl8169_hw_phy_config(dev); + + dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); + RTL_W8(0x82, 0x01); + + if (tp->mac_version < RTL_GIGA_MAC_VER_E) { + dprintk("Set PCI Latency=0x40\n"); + pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); + } + + if (tp->mac_version == RTL_GIGA_MAC_VER_D) { + dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); + RTL_W8(0x82, 0x01); + dprintk("Set PHY Reg 0x0bh = 0x00h\n"); + mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 + } + + rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); + + rtl8169_set_speed(dev, autoneg, speed, duplex); + + if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) + printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); +} + static int __devinit -rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, - void __iomem **ioaddr_out) +rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - void __iomem *ioaddr; - struct net_device *dev; struct rtl8169_private *tp; - int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap; + struct net_device *dev; + void __iomem *ioaddr; + unsigned int i, pm_cap; + int rc; - assert(ioaddr_out != NULL); + if (netif_msg_drv(&debug)) { + printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", + MODULENAME, RTL8169_VERSION); + } - /* dev zeroed in alloc_etherdev */ dev = alloc_etherdev(sizeof (*tp)); - if (dev == NULL) { + if (!dev) { if (netif_msg_drv(&debug)) dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - goto err_out; + rc = -ENOMEM; + goto out; } SET_MODULE_OWNER(dev); @@ -1463,48 +1500,52 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, if (rc < 0) { if (netif_msg_probe(tp)) dev_err(&pdev->dev, "enable failure\n"); - goto err_out_free_dev; + goto err_out_free_dev_1; } rc = pci_set_mwi(pdev); if (rc < 0) - goto err_out_disable; + goto err_out_disable_2; /* save power state before pci_enable_device overwrites it */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap) { - u16 pwr_command; + u16 pwr_command, acpi_idle_state; pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - if (netif_msg_probe(tp)) + if (netif_msg_probe(tp)) { dev_err(&pdev->dev, - "PowerManagement capability not found.\n"); + "PowerManagement capability not found.\n"); + } } /* make sure PCI base addr 1 is MMIO */ if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) + if (netif_msg_probe(tp)) { dev_err(&pdev->dev, - "region #1 not an MMIO resource, aborting\n"); + "region #1 not an MMIO resource, aborting\n"); + } rc = -ENODEV; - goto err_out_mwi; + goto err_out_mwi_3; } + /* check for weird/broken PCI region reporting */ if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) + if (netif_msg_probe(tp)) { dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); + "Invalid PCI region size(s), aborting\n"); + } rc = -ENODEV; - goto err_out_mwi; + goto err_out_mwi_3; } rc = pci_request_regions(pdev, MODULENAME); if (rc < 0) { if (netif_msg_probe(tp)) dev_err(&pdev->dev, "could not request regions.\n"); - goto err_out_mwi; + goto err_out_mwi_3; } tp->cp_cmd = PCIMulRW | RxChkSum; @@ -1516,10 +1557,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { - if (netif_msg_probe(tp)) + if (netif_msg_probe(tp)) { dev_err(&pdev->dev, - "DMA configuration failed.\n"); - goto err_out_free_res; + "DMA configuration failed.\n"); + } + goto err_out_free_res_4; } } @@ -1527,11 +1569,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, /* ioremap MMIO region */ ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE); - if (ioaddr == NULL) { + if (!ioaddr) { if (netif_msg_probe(tp)) dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); rc = -EIO; - goto err_out_free_res; + goto err_out_free_res_4; } /* Unneeded ? Don't mess with Mrs. Murphy. */ @@ -1562,8 +1604,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, /* Unknown chip: assume array element #0, original RTL-8169 */ if (netif_msg_probe(tp)) { dev_printk(KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming %s\n", - rtl_chip_info[0].name); + "unknown chip version, assuming %s\n", + rtl_chip_info[0].name); } i++; } @@ -1574,56 +1616,6 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); RTL_W8(Cfg9346, Cfg9346_Lock); - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); - -err_out_mwi: - pci_clear_mwi(pdev); - -err_out_disable: - pci_disable_device(pdev); - -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static int __devinit -rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8169_p