pull request: wireless 2013-09-10
Subsystems (4)
Dave,
This is a pull request for a few early fixes for the 3.12 stream.
Alexey Khoroshilov corrects a use-after-free issue on rtl8187 found by the Linux Driver Verification project.
Arend van Spriel provides a brcmfmac patch to fix a build issue reported by Randy Dunlap.
Hauke Mehrtens offers a bcma fix to properly account for the storage width of error code values before checking them.
Solomon Peachy brings a pair of cw1200 fixes to avoid hangs in that driver with SPI devices. One avoids transfers in interrupt context, the other fixes a locking issue.
Stanislaw Gruszka changes the initialization of the rt2800 driver to avoid a freeze, addressing a bug in the Red Hat bugzilla.
Please let me know if there are problems!
Thanks,
John
---
The following changes since commit e7d33bb5ea82922e6ddcfc6b28a630b1a4ced071:
lockref: add ability to mark lockrefs "dead" (2013-09-07 15:49:18 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git tags/master-2013-09-09
for you to fetch changes up to f4e1a4d3ecbb9e42bdf8e7869ee8a4ebfa27fb20:
rt2800: change initialization sequence to fix system freeze (2013-09-09 14:44:34 -0400)
----------------------------------------------------------------
Alexey Khoroshilov (1):
rtl8187: fix use after free on failure path in rtl8187_init_urbs()
Arend van Spriel (1):
brcmfmac: fix bus interface selection in Kconfig
Hauke Mehrtens (1):
bcma: fix error code handling on 64 Bit systems
Solomon Peachy (2):
cw1200: Don't perform SPI transfers in interrupt context
cw1200: Prevent a lock-related hang in the cw1200_spi driver
Stanislaw Gruszka (1):
rt2800: change initialization sequence to fix system freeze
drivers/bcma/scan.c | 12 +++++++----- drivers/net/wireless/brcm80211/Kconfig | 4 ++-- drivers/net/wireless/cw1200/cw1200_spi.c | 28 +++++++++++++++++++++++++--- drivers/net/wireless/cw1200/fwio.c | 2 +- drivers/net/wireless/cw1200/hwbus.h | 1 + drivers/net/wireless/cw1200/hwio.c | 15 +++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 11 ++++++----- drivers/net/wireless/rtl818x/rtl8187/dev.c | 15 ++++++++++----- 8 files changed, 67 insertions(+), 21 deletions(-)
drivers/bcma/scan.c +7 -5
@@ -269,6 +269,8 @@ static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 corereturn NULL ; } +#define IS_ERR_VALUE_U32 (x) ((x) >= (u32)-MAX_ERRNO) +static int bcma_get_next_core (struct bcma_bus *bus,u32 __iomem **eromptr,struct bcma_device_id *match,int core_num,struct bcma_device *core)
@@ -351,11 +353,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,* the main register space for the core */ tmp =bcma_erom_get_addr_desc (bus, eromptr,SCAN_ADDR_TYPE_SLAVE ,0 ); -if (tmp ==0 ||IS_ERR_VALUE (tmp)) { +if (tmp ==0 ||IS_ERR_VALUE_U32 (tmp)) {/* Try again to see if it is a bridge */ tmp =bcma_erom_get_addr_desc (bus, eromptr,SCAN_ADDR_TYPE_BRIDGE ,0 ); -if (tmp ==0 ||IS_ERR_VALUE (tmp)) { +if (tmp ==0 ||IS_ERR_VALUE_U32 (tmp)) {return -EILSEQ ; }else {bcma_info (bus,"Bridge found\n" );
@@ -369,7 +371,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,for (j =0 ; ; j++) { tmp =bcma_erom_get_addr_desc (bus, eromptr,SCAN_ADDR_TYPE_SLAVE , i); -if (IS_ERR_VALUE (tmp)) { +if (IS_ERR_VALUE_U32 (tmp)) {/* no more entries for port _i_ */ /* pr_debug("erom: slave port %d " * "has %d descriptors\n", i, j); */
@@ -386,7 +388,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,for (j =0 ; ; j++) { tmp =bcma_erom_get_addr_desc (bus, eromptr,SCAN_ADDR_TYPE_MWRAP , i); -if (IS_ERR_VALUE (tmp)) { +if (IS_ERR_VALUE_U32 (tmp)) {/* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * "has %d descriptors\n", i, j); */
@@ -404,7 +406,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,for (j =0 ; ; j++) { tmp =bcma_erom_get_addr_desc (bus, eromptr,SCAN_ADDR_TYPE_SWRAP , i + hack); -if (IS_ERR_VALUE (tmp)) { +if (IS_ERR_VALUE_U32 (tmp)) {/* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * has %d descriptors\n", i, j); */
drivers/net/wireless/brcm80211/Kconfig +2 -2
@@ -28,7 +28,7 @@ config BRCMFMAC config BRCMFMAC_SDIO bool "SDIO bus interface support for FullMAC driver" - depends on MMC + depends on (MMC = y || MMC = BRCMFMAC) depends on BRCMFMAC select FW_LOADER default y
@@ -39,7 +39,7 @@ config BRCMFMAC_SDIO config BRCMFMAC_USB bool "USB bus interface support for FullMAC driver" - depends on USB + depends on (USB = y || USB = BRCMFMAC) depends on BRCMFMAC select FW_LOADER ---help---
drivers/net/wireless/cw1200/cw1200_spi.c +25 -3
@@ -40,7 +40,9 @@ struct hwbus_priv {struct cw1200_common *core;const struct cw1200_platform_data_spi *pdata;spinlock_t lock;/* Serialize all bus operations */ +wait_queue_head_t wq;int claimed; +int irq_disabled; };#define SDIO_TO_SPI_ADDR (addr) ((addr & 0x1f)>>2)
@@ -197,8 +199,11 @@ static void cw1200_spi_lock(struct hwbus_priv *self) {unsigned long flags; +DECLARE_WAITQUEUE (wait, current); +might_sleep (); +add_wait_queue (&self->wq, &wait);spin_lock_irqsave (&self->lock, flags);while (1 ) {set_current_state (TASK_UNINTERRUPTIBLE );
@@ -211,6 +216,7 @@ static void cw1200_spi_lock(struct hwbus_priv *self)set_current_state (TASK_RUNNING ); self->claimed =1 ;spin_unlock_irqrestore (&self->lock, flags); +remove_wait_queue (&self->wq, &wait);return ; }
@@ -222,6 +228,8 @@ static void cw1200_spi_unlock(struct hwbus_priv *self)spin_lock_irqsave (&self->lock, flags); self->claimed =0 ;spin_unlock_irqrestore (&self->lock, flags); +wake_up (&self->wq); +return ; }
@@ -230,6 +238,8 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)struct hwbus_priv *self = dev_id;if (self->core) { +disable_irq_nosync (self->func->irq); + self->irq_disabled =1 ;cw1200_irq_handler (self->core);return IRQ_HANDLED ; }else {
@@ -263,13 +273,22 @@ exit:static int cw1200_spi_irq_unsubscribe (struct hwbus_priv *self) { -int ret =0 ; -pr_debug ("SW IRQ unsubscribe\n" );disable_irq_wake (self->func->irq);free_irq (self->func->irq, self); -return ret; +return 0 ; +} + +static int cw1200_spi_irq_enable (struct hwbus_priv *self,int enable) +{ +/* Disables are handled by the interrupt handler */ +if (enable && self->irq_disabled) { +enable_irq (self->func->irq); + self->irq_disabled =0 ; + } + +return 0 ; }static int cw1200_spi_off (const struct cw1200_platform_data_spi *pdata)
@@ -349,6 +368,7 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = { .unlock = cw1200_spi_unlock, .align_size = cw1200_spi_align_size, .power_mgmt = cw1200_spi_pm, + .irq_enable = cw1200_spi_irq_enable, };/* Probe Function to be called by SPI stack when device is discovered */
@@ -400,6 +420,8 @@ static int cw1200_spi_probe(struct spi_device *func)spi_set_drvdata (func, self); +init_waitqueue_head (&self->wq); + status =cw1200_spi_irq_subscribe (self); status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
drivers/net/wireless/cw1200/fwio.c +1 -1
@@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_common *priv)/* Enable interrupt signalling */ priv->hwbus_ops->lock (priv->hwbus_priv); - ret =__cw1200_irq_enable (priv,1 ); + ret =__cw1200_irq_enable (priv,2 ); priv->hwbus_ops->unlock (priv->hwbus_priv);if (ret <0 ) goto unsubscribe;
drivers/net/wireless/cw1200/hwbus.h +1 -0
@@ -28,6 +28,7 @@ struct hwbus_ops {void (*unlock)(struct hwbus_priv *self);size_t (*align_size)(struct hwbus_priv *self,size_t size);int (*power_mgmt)(struct hwbus_priv *self,bool suspend); + int (*irq_enable)(struct hwbus_priv *self, int enable); };#endif /* CW1200_HWBUS_H */
drivers/net/wireless/cw1200/hwio.c +15 -0
@@ -273,6 +273,21 @@ int __cw1200_irq_enable(struct cw1200_common *priv, int enable)u16 val16;int ret; +/* We need to do this hack because the SPI layer can sleep on I/O +and the general path involves I/O to the device in interrupt +context. + +However, the initial enable call needs to go to the hardware. + +We don't worry about shutdown because we do a full reset which +clears the interrupt enabled bits. +*/ +if (priv->hwbus_ops->irq_enable) { + ret = priv->hwbus_ops->irq_enable (priv->hwbus_priv, enable); +if (ret || enable <2 ) +return ret; + } +if (HIF_8601_SILICON == priv->hw_type) { ret =__cw1200_reg_read_32 (priv,ST90TDS_CONFIG_REG_ID , &val32);if (ret <0 ) {
drivers/net/wireless/rt2x00/rt2800lib.c +6 -5
@@ -6659,19 +6659,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) rt2800_init_registers(rt2x00dev)))return -EIO ; +if (unlikely (rt2800_wait_bbp_rf_ready (rt2x00dev))) +return -EIO ; +/* * Send signal to firmware during boot time. */ rt2800_register_write (rt2x00dev,H2M_BBP_AGENT ,0 );rt2800_register_write (rt2x00dev,H2M_MAILBOX_CSR ,0 ); -if (rt2x00_is_usb (rt2x00dev)) { +if (rt2x00_is_usb (rt2x00dev))rt2800_register_write (rt2x00dev,H2M_INT_SRC ,0 ); -rt2800_mcu_request (rt2x00dev,MCU_BOOT_SIGNAL ,0 ,0 ,0 ); - } +rt2800_mcu_request (rt2x00dev,MCU_BOOT_SIGNAL ,0 ,0 ,0 );msleep (1 ); -if (unlikely (rt2800_wait_bbp_rf_ready (rt2x00dev) || -rt2800_wait_bbp_ready (rt2x00dev))) +if (unlikely (rt2800_wait_bbp_ready (rt2x00dev)))return -EIO ;rt2800_init_bbp (rt2x00dev);
drivers/net/wireless/rtl818x/rtl8187/dev.c +10 -5
@@ -438,17 +438,16 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)skb_queue_tail (&priv->rx_queue, skb);usb_anchor_urb (entry, &priv->anchored); ret =usb_submit_urb (entry,GFP_KERNEL ); +usb_put_urb (entry);if (ret) {skb_unlink (skb, &priv->rx_queue);usb_unanchor_urb (entry); goto err; } -usb_free_urb (entry); }return ret; err: -usb_free_urb (entry);kfree_skb (skb);usb_kill_anchored_urbs (&priv->anchored);return ret;
@@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev) (RETRY_COUNT <<8 /* short retry limit */ ) | (RETRY_COUNT <<0 /* long retry limit */ ) | (7 << 21 /* MAX TX DMA */)); -rtl8187_init_urbs (dev); -rtl8187b_init_status_urb (dev); + ret =rtl8187_init_urbs (dev); +if (ret) + goto rtl8187_start_exit; + ret =rtl8187b_init_status_urb (dev); +if (ret) +usb_kill_anchored_urbs (&priv->anchored); goto rtl8187_start_exit; }
@@ -966,7 +969,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)rtl818x_iowrite32 (priv, &priv->map->MAR[0 ], ~0 );rtl818x_iowrite32 (priv, &priv->map->MAR[1 ], ~0 ); -rtl8187_init_urbs (dev); + ret =rtl8187_init_urbs (dev); +if (ret) + goto rtl8187_start_exit; reg =RTL818X_RX_CONF_ONLYERLPKT | RTL818X_RX_CONF_RX_AUTORESETPHY |
Signature · 2 lines
John W. Linville Someday the world will need a hero, and you [email protected] might be all we have. Be ready.
David Miller
maintainerFrom: "John W. Linville" <[email protected]>
Date: Tue, 10 Sep 2013 15:38:45 -0400
Quoted 1 line
This is a pull request for a few early fixes for the 3.12 stream.
Looks good, pulled, thanks John.