Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 732bf15e authored by David S. Miller's avatar David S. Miller
Browse files


John W. Linville says:

====================
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.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3ced8c95 f4e1a4d3
Loading
Loading
Loading
Loading
+7 −5
Original line number Original line Diff line number Diff line
@@ -269,6 +269,8 @@ static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 core
	return NULL;
	return NULL;
}
}


#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO)

static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
			      struct bcma_device_id *match, int core_num,
			      struct bcma_device_id *match, int core_num,
			      struct bcma_device *core)
			      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
	 * the main register space for the core
	 */
	 */
	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
	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 */
		/* Try again to see if it is a bridge */
		tmp = bcma_erom_get_addr_desc(bus, eromptr,
		tmp = bcma_erom_get_addr_desc(bus, eromptr,
					      SCAN_ADDR_TYPE_BRIDGE, 0);
					      SCAN_ADDR_TYPE_BRIDGE, 0);
		if (tmp == 0 || IS_ERR_VALUE(tmp)) {
		if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
			return -EILSEQ;
			return -EILSEQ;
		} else {
		} else {
			bcma_info(bus, "Bridge found\n");
			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++) {
		for (j = 0; ; j++) {
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
				SCAN_ADDR_TYPE_SLAVE, i);
				SCAN_ADDR_TYPE_SLAVE, i);
			if (IS_ERR_VALUE(tmp)) {
			if (IS_ERR_VALUE_U32(tmp)) {
				/* no more entries for port _i_ */
				/* no more entries for port _i_ */
				/* pr_debug("erom: slave port %d "
				/* pr_debug("erom: slave port %d "
				 * "has %d descriptors\n", i, j); */
				 * "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++) {
		for (j = 0; ; j++) {
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
				SCAN_ADDR_TYPE_MWRAP, i);
				SCAN_ADDR_TYPE_MWRAP, i);
			if (IS_ERR_VALUE(tmp)) {
			if (IS_ERR_VALUE_U32(tmp)) {
				/* no more entries for port _i_ */
				/* no more entries for port _i_ */
				/* pr_debug("erom: master wrapper %d "
				/* pr_debug("erom: master wrapper %d "
				 * "has %d descriptors\n", i, j); */
				 * "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++) {
		for (j = 0; ; j++) {
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
			tmp = bcma_erom_get_addr_desc(bus, eromptr,
				SCAN_ADDR_TYPE_SWRAP, i + hack);
				SCAN_ADDR_TYPE_SWRAP, i + hack);
			if (IS_ERR_VALUE(tmp)) {
			if (IS_ERR_VALUE_U32(tmp)) {
				/* no more entries for port _i_ */
				/* no more entries for port _i_ */
				/* pr_debug("erom: master wrapper %d "
				/* pr_debug("erom: master wrapper %d "
				 * has %d descriptors\n", i, j); */
				 * has %d descriptors\n", i, j); */
+2 −2
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ config BRCMFMAC


config BRCMFMAC_SDIO
config BRCMFMAC_SDIO
	bool "SDIO bus interface support for FullMAC driver"
	bool "SDIO bus interface support for FullMAC driver"
	depends on MMC
	depends on (MMC = y || MMC = BRCMFMAC)
	depends on BRCMFMAC
	depends on BRCMFMAC
	select FW_LOADER
	select FW_LOADER
	default y
	default y
@@ -39,7 +39,7 @@ config BRCMFMAC_SDIO


config BRCMFMAC_USB
config BRCMFMAC_USB
	bool "USB bus interface support for FullMAC driver"
	bool "USB bus interface support for FullMAC driver"
	depends on USB
	depends on (USB = y || USB = BRCMFMAC)
	depends on BRCMFMAC
	depends on BRCMFMAC
	select FW_LOADER
	select FW_LOADER
	---help---
	---help---
+25 −3
Original line number Original line Diff line number Diff line
@@ -40,7 +40,9 @@ struct hwbus_priv {
	struct cw1200_common	*core;
	struct cw1200_common	*core;
	const struct cw1200_platform_data_spi *pdata;
	const struct cw1200_platform_data_spi *pdata;
	spinlock_t		lock; /* Serialize all bus operations */
	spinlock_t		lock; /* Serialize all bus operations */
	wait_queue_head_t       wq;
	int claimed;
	int claimed;
	int irq_disabled;
};
};


#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
#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;
	unsigned long flags;


	DECLARE_WAITQUEUE(wait, current);

	might_sleep();
	might_sleep();


	add_wait_queue(&self->wq, &wait);
	spin_lock_irqsave(&self->lock, flags);
	spin_lock_irqsave(&self->lock, flags);
	while (1) {
	while (1) {
		set_current_state(TASK_UNINTERRUPTIBLE);
		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -211,6 +216,7 @@ static void cw1200_spi_lock(struct hwbus_priv *self)
	set_current_state(TASK_RUNNING);
	set_current_state(TASK_RUNNING);
	self->claimed = 1;
	self->claimed = 1;
	spin_unlock_irqrestore(&self->lock, flags);
	spin_unlock_irqrestore(&self->lock, flags);
	remove_wait_queue(&self->wq, &wait);


	return;
	return;
}
}
@@ -222,6 +228,8 @@ static void cw1200_spi_unlock(struct hwbus_priv *self)
	spin_lock_irqsave(&self->lock, flags);
	spin_lock_irqsave(&self->lock, flags);
	self->claimed = 0;
	self->claimed = 0;
	spin_unlock_irqrestore(&self->lock, flags);
	spin_unlock_irqrestore(&self->lock, flags);
	wake_up(&self->wq);

	return;
	return;
}
}


@@ -230,6 +238,8 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
	struct hwbus_priv *self = dev_id;
	struct hwbus_priv *self = dev_id;


	if (self->core) {
	if (self->core) {
		disable_irq_nosync(self->func->irq);
		self->irq_disabled = 1;
		cw1200_irq_handler(self->core);
		cw1200_irq_handler(self->core);
		return IRQ_HANDLED;
		return IRQ_HANDLED;
	} else {
	} else {
@@ -263,13 +273,22 @@ exit:


static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
{
{
	int ret = 0;

	pr_debug("SW IRQ unsubscribe\n");
	pr_debug("SW IRQ unsubscribe\n");
	disable_irq_wake(self->func->irq);
	disable_irq_wake(self->func->irq);
	free_irq(self->func->irq, self);
	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)
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,
	.unlock			= cw1200_spi_unlock,
	.align_size		= cw1200_spi_align_size,
	.align_size		= cw1200_spi_align_size,
	.power_mgmt		= cw1200_spi_pm,
	.power_mgmt		= cw1200_spi_pm,
	.irq_enable             = cw1200_spi_irq_enable,
};
};


/* Probe Function to be called by SPI stack when device is discovered */
/* 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);
	spi_set_drvdata(func, self);


	init_waitqueue_head(&self->wq);

	status = cw1200_spi_irq_subscribe(self);
	status = cw1200_spi_irq_subscribe(self);


	status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
	status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
+1 −1
Original line number Original line Diff line number Diff line
@@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_common *priv)


	/* Enable interrupt signalling */
	/* Enable interrupt signalling */
	priv->hwbus_ops->lock(priv->hwbus_priv);
	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);
	priv->hwbus_ops->unlock(priv->hwbus_priv);
	if (ret < 0)
	if (ret < 0)
		goto unsubscribe;
		goto unsubscribe;
+1 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ struct hwbus_ops {
	void (*unlock)(struct hwbus_priv *self);
	void (*unlock)(struct hwbus_priv *self);
	size_t (*align_size)(struct hwbus_priv *self, size_t size);
	size_t (*align_size)(struct hwbus_priv *self, size_t size);
	int (*power_mgmt)(struct hwbus_priv *self, bool suspend);
	int (*power_mgmt)(struct hwbus_priv *self, bool suspend);
	int (*irq_enable)(struct hwbus_priv *self, int enable);
};
};


#endif /* CW1200_HWBUS_H */
#endif /* CW1200_HWBUS_H */
Loading