Просмотр исходного кода

kernel: backport ssb changes from 4.4-rc1

Signed-off-by: Rafał Miłecki <[email protected]>

SVN-Revision: 47483
Rafał Miłecki 10 лет назад
Родитель
Сommit
b2dab45aa7

+ 485 - 0
package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch

@@ -0,0 +1,485 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
+Date: Thu, 15 Oct 2015 07:23:25 +0200
+Subject: [PATCH] ssb: pick PCMCIA host code support from b43 driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+ssb bus can be found on various "host" devices like PCI/PCMCIA/SDIO.
+Every ssb bus contains cores AKA devices.
+The main idea is to have ssb driver scan/initialize bus and register
+ready-to-use cores. This way ssb drivers can operate on a single core
+mostly ignoring underlaying details.
+
+For some reason PCMCIA support was split between ssb and b43. We got
+PCMCIA host device probing in b43, then bus scanning in ssb and then
+wireless core probing back in b43. The truth is it's very unlikely we
+will ever see PCMCIA ssb device with no 802.11 core but I still don't
+see any advantage of the current architecture.
+
+With proposed change we get the same functionality with a simpler
+architecture, less Kconfig symbols, one killed EXPORT and hopefully
+cleaner b43. Since b43 supports both: ssb & bcma I prefer to keep ssb
+specific code in ssb driver.
+
+This mostly moves code from b43's pcmcia.c to bridge_pcmcia_80211.c. We
+already use similar solution with b43_pci_bridge.c. I didn't use "b43"
+in name of this new file as in theory any driver can operate on wireless
+core.
+
+Signed-off-by: Rafał Miłecki <[email protected]>
+Signed-off-by: Kalle Valo <[email protected]>
+---
+ delete mode 100644 drivers/net/wireless/b43/pcmcia.c
+ delete mode 100644 drivers/net/wireless/b43/pcmcia.h
+ create mode 100644 drivers/ssb/bridge_pcmcia_80211.c
+
+--- a/drivers/net/wireless/b43/Kconfig
++++ b/drivers/net/wireless/b43/Kconfig
+@@ -72,26 +72,6 @@ config B43_PCICORE_AUTOSELECT
+ 	select SSB_DRIVER_PCICORE
+ 	default y
+ 
+-config B43_PCMCIA
+-	bool "Broadcom 43xx PCMCIA device support"
+-	depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
+-	select SSB_PCMCIAHOST
+-	---help---
+-	  Broadcom 43xx PCMCIA device support.
+-
+-	  Support for 16bit PCMCIA devices.
+-	  Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA
+-	  devices, but 32bit CardBUS devices. CardBUS devices are supported
+-	  out of the box by b43.
+-
+-	  With this config option you can drive b43 cards in
+-	  CompactFlash formfactor in a PCMCIA adaptor.
+-	  CF b43 cards can sometimes be found in handheld PCs.
+-
+-	  It's safe to select Y here, even if you don't have a B43 PCMCIA device.
+-
+-	  If unsure, say N.
+-
+ config B43_SDIO
+ 	bool "Broadcom 43xx SDIO device support"
+ 	depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
+--- a/drivers/net/wireless/b43/Makefile
++++ b/drivers/net/wireless/b43/Makefile
+@@ -21,7 +21,6 @@ b43-y				+= pio.o
+ b43-y				+= rfkill.o
+ b43-y				+= ppr.o
+ b43-$(CPTCFG_B43_LEDS)		+= leds.o
+-b43-$(CPTCFG_B43_PCMCIA)	+= pcmcia.o
+ b43-$(CPTCFG_B43_SDIO)		+= sdio.o
+ b43-$(CPTCFG_B43_DEBUG)		+= debugfs.o
+ 
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -56,7 +56,6 @@
+ #include "sysfs.h"
+ #include "xmit.h"
+ #include "lo.h"
+-#include "pcmcia.h"
+ #include "sdio.h"
+ #include <linux/mmc/sdio_func.h>
+ 
+@@ -5850,12 +5849,9 @@ static int __init b43_init(void)
+ 	int err;
+ 
+ 	b43_debugfs_init();
+-	err = b43_pcmcia_init();
+-	if (err)
+-		goto err_dfs_exit;
+ 	err = b43_sdio_init();
+ 	if (err)
+-		goto err_pcmcia_exit;
++		goto err_dfs_exit;
+ #ifdef CPTCFG_B43_BCMA
+ 	err = bcma_driver_register(&b43_bcma_driver);
+ 	if (err)
+@@ -5878,8 +5874,6 @@ err_bcma_driver_exit:
+ err_sdio_exit:
+ #endif
+ 	b43_sdio_exit();
+-err_pcmcia_exit:
+-	b43_pcmcia_exit();
+ err_dfs_exit:
+ 	b43_debugfs_exit();
+ 	return err;
+@@ -5894,7 +5888,6 @@ static void __exit b43_exit(void)
+ 	bcma_driver_unregister(&b43_bcma_driver);
+ #endif
+ 	b43_sdio_exit();
+-	b43_pcmcia_exit();
+ 	b43_debugfs_exit();
+ }
+ 
+--- a/drivers/net/wireless/b43/pcmcia.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#ifndef B43_PCMCIA_H_
+-#define B43_PCMCIA_H_
+-
+-#ifdef CPTCFG_B43_PCMCIA
+-
+-int b43_pcmcia_init(void);
+-void b43_pcmcia_exit(void);
+-
+-#else /* CPTCFG_B43_PCMCIA */
+-
+-static inline int b43_pcmcia_init(void)
+-{
+-	return 0;
+-}
+-static inline void b43_pcmcia_exit(void)
+-{
+-}
+-
+-#endif /* CPTCFG_B43_PCMCIA */
+-#endif /* B43_PCMCIA_H_ */
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -5,7 +5,7 @@ ssb-$(CPTCFG_SSB_SPROM)			+= sprom.o
+ 
+ # host support
+ ssb-$(CPTCFG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o
+-ssb-$(CPTCFG_SSB_PCMCIAHOST)		+= pcmcia.o
++ssb-$(CPTCFG_SSB_PCMCIAHOST)		+= pcmcia.o bridge_pcmcia_80211.o
+ ssb-$(CPTCFG_SSB_SDIOHOST)		+= sdio.o
+ 
+ # built-in drivers
+--- /dev/null
++++ b/drivers/ssb/bridge_pcmcia_80211.c
+@@ -0,0 +1,128 @@
++/*
++ * Broadcom 43xx PCMCIA-SSB bridge module
++ *
++ * Copyright (c) 2007 Michael Buesch <[email protected]>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include <pcmcia/cistpl.h>
++#include <pcmcia/ciscode.h>
++#include <pcmcia/ds.h>
++#include <pcmcia/cisreg.h>
++
++#include "ssb_private.h"
++
++static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
++	PCMCIA_DEVICE_NULL,
++};
++
++MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
++
++static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb;
++	int err = -ENOMEM;
++	int res = 0;
++
++	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
++	if (!ssb)
++		goto out_error;
++
++	err = -ENODEV;
++
++	dev->config_flags |= CONF_ENABLE_IRQ;
++
++	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
++			 WIN_USE_WAIT;
++	dev->resource[2]->start = 0;
++	dev->resource[2]->end = SSB_CORE_SIZE;
++	res = pcmcia_request_window(dev, dev->resource[2], 250);
++	if (res != 0)
++		goto err_kfree_ssb;
++
++	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
++	if (res != 0)
++		goto err_disable;
++
++	if (!dev->irq)
++		goto err_disable;
++
++	res = pcmcia_enable_device(dev);
++	if (res != 0)
++		goto err_disable;
++
++	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
++	if (err)
++		goto err_disable;
++	dev->priv = ssb;
++
++	return 0;
++
++err_disable:
++	pcmcia_disable_device(dev);
++err_kfree_ssb:
++	kfree(ssb);
++out_error:
++	ssb_err("Initialization failed (%d, %d)\n", res, err);
++	return err;
++}
++
++static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	ssb_bus_unregister(ssb);
++	pcmcia_disable_device(dev);
++	kfree(ssb);
++	dev->priv = NULL;
++}
++
++#ifdef CPTCFG_PM
++static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_suspend(ssb);
++}
++
++static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_resume(ssb);
++}
++#else /* CPTCFG_PM */
++# define ssb_host_pcmcia_suspend		NULL
++# define ssb_host_pcmcia_resume		NULL
++#endif /* CPTCFG_PM */
++
++static struct pcmcia_driver ssb_host_pcmcia_driver = {
++	.owner		= THIS_MODULE,
++	.name		= "ssb-pcmcia",
++	.id_table	= ssb_host_pcmcia_tbl,
++	.probe		= ssb_host_pcmcia_probe,
++	.remove		= ssb_host_pcmcia_remove,
++	.suspend	= ssb_host_pcmcia_suspend,
++	.resume		= ssb_host_pcmcia_resume,
++};
++
++/*
++ * These are not module init/exit functions!
++ * The module_pcmcia_driver() helper cannot be used here.
++ */
++int ssb_host_pcmcia_init(void)
++{
++	return pcmcia_register_driver(&ssb_host_pcmcia_driver);
++}
++
++void ssb_host_pcmcia_exit(void)
++{
++	pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
++}
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -906,7 +906,6 @@ int ssb_bus_pcmciabus_register(struct ss
+ 
+ 	return err;
+ }
+-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
+ #endif /* CPTCFG_SSB_PCMCIAHOST */
+ 
+ #ifdef CPTCFG_SSB_SDIOHOST
+@@ -1474,6 +1473,12 @@ static int __init ssb_modinit(void)
+ 		/* don't fail SSB init because of this */
+ 		err = 0;
+ 	}
++	err = ssb_host_pcmcia_init();
++	if (err) {
++		ssb_err("PCMCIA host initialization failed\n");
++		/* don't fail SSB init because of this */
++		err = 0;
++	}
+ 	err = ssb_gige_init();
+ 	if (err) {
+ 		ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
+@@ -1491,6 +1496,7 @@ fs_initcall(ssb_modinit);
+ static void __exit ssb_modexit(void)
+ {
+ 	ssb_gige_exit();
++	ssb_host_pcmcia_exit();
+ 	b43_pci_ssb_bridge_exit();
+ 	bus_unregister(&ssb_bustype);
+ }
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -94,6 +94,8 @@ extern int ssb_pcmcia_get_invariants(str
+ extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
+ extern void ssb_pcmcia_exit(struct ssb_bus *bus);
+ extern int ssb_pcmcia_init(struct ssb_bus *bus);
++extern int ssb_host_pcmcia_init(void);
++extern void ssb_host_pcmcia_exit(void);
+ extern const struct ssb_bus_ops ssb_pcmcia_ops;
+ #else /* CPTCFG_SSB_PCMCIAHOST */
+ static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+@@ -117,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
+ {
+ 	return 0;
+ }
++static inline int ssb_host_pcmcia_init(void)
++{
++	return 0;
++}
++static inline void ssb_host_pcmcia_exit(void)
++{
++}
+ #endif /* CPTCFG_SSB_PCMCIAHOST */
+ 
+ /* sdio.c */
+--- a/drivers/net/wireless/b43/pcmcia.c
++++ /dev/null
+@@ -1,145 +0,0 @@
+-/*
+-
+-  Broadcom B43 wireless driver
+-
+-  Copyright (c) 2007 Michael Buesch <[email protected]>
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "pcmcia.h"
+-
+-#include <linux/ssb/ssb.h>
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-
+-#include <pcmcia/cistpl.h>
+-#include <pcmcia/ciscode.h>
+-#include <pcmcia/ds.h>
+-#include <pcmcia/cisreg.h>
+-
+-
+-static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
+-	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
+-	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
+-	PCMCIA_DEVICE_NULL,
+-};
+-
+-MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
+-
+-#ifdef CONFIG_PM
+-static int b43_pcmcia_suspend(struct pcmcia_device *dev)
+-{
+-	struct ssb_bus *ssb = dev->priv;
+-
+-	return ssb_bus_suspend(ssb);
+-}
+-
+-static int b43_pcmcia_resume(struct pcmcia_device *dev)
+-{
+-	struct ssb_bus *ssb = dev->priv;
+-
+-	return ssb_bus_resume(ssb);
+-}
+-#else /* CONFIG_PM */
+-# define b43_pcmcia_suspend		NULL
+-# define b43_pcmcia_resume		NULL
+-#endif /* CONFIG_PM */
+-
+-static int b43_pcmcia_probe(struct pcmcia_device *dev)
+-{
+-	struct ssb_bus *ssb;
+-	int err = -ENOMEM;
+-	int res = 0;
+-
+-	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
+-	if (!ssb)
+-		goto out_error;
+-
+-	err = -ENODEV;
+-
+-	dev->config_flags |= CONF_ENABLE_IRQ;
+-
+-	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
+-			 WIN_USE_WAIT;
+-	dev->resource[2]->start = 0;
+-	dev->resource[2]->end = SSB_CORE_SIZE;
+-	res = pcmcia_request_window(dev, dev->resource[2], 250);
+-	if (res != 0)
+-		goto err_kfree_ssb;
+-
+-	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
+-	if (res != 0)
+-		goto err_disable;
+-
+-	if (!dev->irq)
+-		goto err_disable;
+-
+-	res = pcmcia_enable_device(dev);
+-	if (res != 0)
+-		goto err_disable;
+-
+-	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
+-	if (err)
+-		goto err_disable;
+-	dev->priv = ssb;
+-
+-	return 0;
+-
+-err_disable:
+-	pcmcia_disable_device(dev);
+-err_kfree_ssb:
+-	kfree(ssb);
+-out_error:
+-	printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
+-	       res, err);
+-	return err;
+-}
+-
+-static void b43_pcmcia_remove(struct pcmcia_device *dev)
+-{
+-	struct ssb_bus *ssb = dev->priv;
+-
+-	ssb_bus_unregister(ssb);
+-	pcmcia_disable_device(dev);
+-	kfree(ssb);
+-	dev->priv = NULL;
+-}
+-
+-static struct pcmcia_driver b43_pcmcia_driver = {
+-	.owner		= THIS_MODULE,
+-	.name		= "b43-pcmcia",
+-	.id_table	= b43_pcmcia_tbl,
+-	.probe		= b43_pcmcia_probe,
+-	.remove		= b43_pcmcia_remove,
+-	.suspend	= b43_pcmcia_suspend,
+-	.resume		= b43_pcmcia_resume,
+-};
+-
+-/*
+- * These are not module init/exit functions!
+- * The module_pcmcia_driver() helper cannot be used here.
+- */
+-int b43_pcmcia_init(void)
+-{
+-	return pcmcia_register_driver(&b43_pcmcia_driver);
+-}
+-
+-void b43_pcmcia_exit(void)
+-{
+-	pcmcia_unregister_driver(&b43_pcmcia_driver);
+-}

+ 2 - 2
package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch

@@ -10,7 +10,7 @@
  	struct b43_phy phy;
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+@@ -75,6 +75,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
  MODULE_FIRMWARE("b43/ucode5.fw");
  MODULE_FIRMWARE("b43/ucode9.fw");
  
@@ -22,7 +22,7 @@
  static int modparam_bad_frames_preempt;
  module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
  MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2883,10 +2888,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2882,10 +2887,10 @@ static int b43_gpio_init(struct b43_wlde
  	u32 mask, set;
  
  	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);

+ 2 - 2
package/kernel/mac80211/patches/810-b43_no_pio.patch

@@ -11,7 +11,7 @@
  b43-$(CPTCFG_B43_LEDS)		+= leds.o
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -2009,10 +2009,12 @@ static void b43_do_interrupt_thread(stru
+@@ -2008,10 +2008,12 @@ static void b43_do_interrupt_thread(stru
  			dma_reason[0], dma_reason[1],
  			dma_reason[2], dma_reason[3],
  			dma_reason[4], dma_reason[5]);
@@ -75,7 +75,7 @@
  #endif /* B43_PIO_H_ */
 --- a/drivers/net/wireless/b43/Kconfig
 +++ b/drivers/net/wireless/b43/Kconfig
-@@ -118,7 +118,7 @@ config B43_BCMA_PIO
+@@ -98,7 +98,7 @@ config B43_BCMA_PIO
  	default y
  
  config B43_PIO

+ 8 - 8
package/kernel/mac80211/patches/820-b43-add-antenna-control.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -1649,7 +1649,7 @@ static void b43_write_beacon_template(st
+@@ -1648,7 +1648,7 @@ static void b43_write_beacon_template(st
  				  len, ram_offset, shm_size_offset, rate);
  
  	/* Write the PHY TX control parameters. */
@@ -9,7 +9,7 @@
  	antenna = b43_antenna_to_phyctl(antenna);
  	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
  	/* We can't send beacons with short preamble. Would get PHY errors. */
-@@ -3301,8 +3301,8 @@ static int b43_chip_init(struct b43_wlde
+@@ -3300,8 +3300,8 @@ static int b43_chip_init(struct b43_wlde
  
  	/* Select the antennae */
  	if (phy->ops->set_rx_antenna)
@@ -20,7 +20,7 @@
  
  	if (phy->type == B43_PHYTYPE_B) {
  		value16 = b43_read16(dev, 0x005E);
-@@ -4002,7 +4002,6 @@ static int b43_op_config(struct ieee8021
+@@ -4001,7 +4001,6 @@ static int b43_op_config(struct ieee8021
  	struct b43_wldev *dev = wl->current_dev;
  	struct b43_phy *phy = &dev->phy;
  	struct ieee80211_conf *conf = &hw->conf;
@@ -28,7 +28,7 @@
  	int err = 0;
  
  	mutex_lock(&wl->mutex);
-@@ -4045,11 +4044,9 @@ static int b43_op_config(struct ieee8021
+@@ -4044,11 +4043,9 @@ static int b43_op_config(struct ieee8021
  	}
  
  	/* Antennas for RX and management frame TX. */
@@ -42,7 +42,7 @@
  
  	if (wl->radio_enabled != phy->radio_on) {
  		if (wl->radio_enabled) {
-@@ -5210,6 +5207,47 @@ static int b43_op_get_survey(struct ieee
+@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee
  	return 0;
  }
  
@@ -90,7 +90,7 @@
  static const struct ieee80211_ops b43_hw_ops = {
  	.tx			= b43_op_tx,
  	.conf_tx		= b43_op_conf_tx,
-@@ -5231,6 +5269,8 @@ static const struct ieee80211_ops b43_hw
+@@ -5230,6 +5268,8 @@ static const struct ieee80211_ops b43_hw
  	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
  	.get_survey		= b43_op_get_survey,
  	.rfkill_poll		= b43_rfkill_poll,
@@ -99,7 +99,7 @@
  };
  
  /* Hard-reset the chip. Do not call this directly.
-@@ -5539,6 +5579,8 @@ static int b43_one_core_attach(struct b4
+@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4
  	if (!wldev)
  		goto out;
  
@@ -108,7 +108,7 @@
  	wldev->use_pio = b43_modparam_pio;
  	wldev->dev = dev;
  	wldev->wl = wl;
-@@ -5629,6 +5671,9 @@ static struct b43_wl *b43_wireless_init(
+@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init(
  
  	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
  

+ 1 - 1
package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -2900,6 +2900,14 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2899,6 +2899,14 @@ static int b43_gpio_init(struct b43_wlde
  	} else if (dev->dev->chip_id == 0x5354) {
  		/* Don't allow overtaking buttons GPIOs */
  		set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */

+ 1 - 1
package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -118,7 +118,7 @@ static int b43_modparam_pio = 0;
+@@ -117,7 +117,7 @@ static int b43_modparam_pio = 0;
  module_param_named(pio, b43_modparam_pio, int, 0644);
  MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
  

+ 686 - 0
target/linux/generic/patches-4.1/020-ssb-backport.patch

@@ -0,0 +1,686 @@
+--- a/arch/mips/bcm47xx/Kconfig
++++ b/arch/mips/bcm47xx/Kconfig
+@@ -4,6 +4,7 @@ config BCM47XX_SSB
+ 	bool "SSB Support for Broadcom BCM47XX"
+ 	select SYS_HAS_CPU_BMIPS32_3300
+ 	select SSB
++	select SSB_HOST_SOC
+ 	select SSB_DRIVER_MIPS
+ 	select SSB_DRIVER_EXTIF
+ 	select SSB_EMBEDDED
+--- a/drivers/ssb/Kconfig
++++ b/drivers/ssb/Kconfig
+@@ -80,6 +80,15 @@ config SSB_SDIOHOST
+ 
+ 	  If unsure, say N
+ 
++config SSB_HOST_SOC
++	bool "Support for SSB bus on SoC"
++	depends on SSB
++	help
++	  Host interface for a SSB directly mapped into memory. This is
++	  for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
++
++	  If unsure, say N
++
+ config SSB_SILENT
+ 	bool "No SSB kernel messages"
+ 	depends on SSB && EXPERT
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM)			+= sprom.o
+ 
+ # host support
+ ssb-$(CONFIG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o
+-ssb-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o
++ssb-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o bridge_pcmcia_80211.o
+ ssb-$(CONFIG_SSB_SDIOHOST)		+= sdio.o
++ssb-$(CONFIG_SSB_HOST_SOC)		+= host_soc.o
+ 
+ # built-in drivers
+ ssb-y					+= driver_chipcommon.o
+--- /dev/null
++++ b/drivers/ssb/bridge_pcmcia_80211.c
+@@ -0,0 +1,128 @@
++/*
++ * Broadcom 43xx PCMCIA-SSB bridge module
++ *
++ * Copyright (c) 2007 Michael Buesch <[email protected]>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include <pcmcia/cistpl.h>
++#include <pcmcia/ciscode.h>
++#include <pcmcia/ds.h>
++#include <pcmcia/cisreg.h>
++
++#include "ssb_private.h"
++
++static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
++	PCMCIA_DEVICE_NULL,
++};
++
++MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
++
++static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb;
++	int err = -ENOMEM;
++	int res = 0;
++
++	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
++	if (!ssb)
++		goto out_error;
++
++	err = -ENODEV;
++
++	dev->config_flags |= CONF_ENABLE_IRQ;
++
++	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
++			 WIN_USE_WAIT;
++	dev->resource[2]->start = 0;
++	dev->resource[2]->end = SSB_CORE_SIZE;
++	res = pcmcia_request_window(dev, dev->resource[2], 250);
++	if (res != 0)
++		goto err_kfree_ssb;
++
++	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
++	if (res != 0)
++		goto err_disable;
++
++	if (!dev->irq)
++		goto err_disable;
++
++	res = pcmcia_enable_device(dev);
++	if (res != 0)
++		goto err_disable;
++
++	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
++	if (err)
++		goto err_disable;
++	dev->priv = ssb;
++
++	return 0;
++
++err_disable:
++	pcmcia_disable_device(dev);
++err_kfree_ssb:
++	kfree(ssb);
++out_error:
++	ssb_err("Initialization failed (%d, %d)\n", res, err);
++	return err;
++}
++
++static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	ssb_bus_unregister(ssb);
++	pcmcia_disable_device(dev);
++	kfree(ssb);
++	dev->priv = NULL;
++}
++
++#ifdef CONFIG_PM
++static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_suspend(ssb);
++}
++
++static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_resume(ssb);
++}
++#else /* CONFIG_PM */
++# define ssb_host_pcmcia_suspend		NULL
++# define ssb_host_pcmcia_resume		NULL
++#endif /* CONFIG_PM */
++
++static struct pcmcia_driver ssb_host_pcmcia_driver = {
++	.owner		= THIS_MODULE,
++	.name		= "ssb-pcmcia",
++	.id_table	= ssb_host_pcmcia_tbl,
++	.probe		= ssb_host_pcmcia_probe,
++	.remove		= ssb_host_pcmcia_remove,
++	.suspend	= ssb_host_pcmcia_suspend,
++	.resume		= ssb_host_pcmcia_resume,
++};
++
++/*
++ * These are not module init/exit functions!
++ * The module_pcmcia_driver() helper cannot be used here.
++ */
++int ssb_host_pcmcia_init(void)
++{
++	return pcmcia_register_driver(&ssb_host_pcmcia_driver);
++}
++
++void ssb_host_pcmcia_exit(void)
++{
++	pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
++}
+--- /dev/null
++++ b/drivers/ssb/host_soc.c
+@@ -0,0 +1,173 @@
++/*
++ * Sonics Silicon Backplane SoC host related functions.
++ * Subsystem core
++ *
++ * Copyright 2005, Broadcom Corporation
++ * Copyright 2006, 2007, Michael Buesch <[email protected]>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++
++#include "ssb_private.h"
++
++static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readb(bus->mmio + offset);
++}
++
++static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readw(bus->mmio + offset);
++}
++
++static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readl(bus->mmio + offset);
++}
++
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
++				    size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		u8 *buf = buffer;
++
++		while (count) {
++			*buf = __raw_readb(addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		__le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		__le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			*buf = (__force __le32)__raw_readl(addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writeb(value, bus->mmio + offset);
++}
++
++static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writew(value, bus->mmio + offset);
++}
++
++static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writel(value, bus->mmio + offset);
++}
++
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
++				     size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		const u8 *buf = buffer;
++
++		while (count) {
++			__raw_writeb(*buf, addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		const __le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		const __le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			__raw_writel((__force u32)(*buf), addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
++const struct ssb_bus_ops ssb_host_soc_ops = {
++	.read8		= ssb_host_soc_read8,
++	.read16		= ssb_host_soc_read16,
++	.read32		= ssb_host_soc_read32,
++	.write8		= ssb_host_soc_write8,
++	.write16	= ssb_host_soc_write16,
++	.write32	= ssb_host_soc_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++	.block_read	= ssb_host_soc_block_read,
++	.block_write	= ssb_host_soc_block_write,
++#endif
++};
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -596,166 +596,6 @@ error:
+ 	return err;
+ }
+ 
+-static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readb(bus->mmio + offset);
+-}
+-
+-static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readw(bus->mmio + offset);
+-}
+-
+-static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readl(bus->mmio + offset);
+-}
+-
+-#ifdef CONFIG_SSB_BLOCKIO
+-static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
+-			       size_t count, u16 offset, u8 reg_width)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-	void __iomem *addr;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	addr = bus->mmio + offset;
+-
+-	switch (reg_width) {
+-	case sizeof(u8): {
+-		u8 *buf = buffer;
+-
+-		while (count) {
+-			*buf = __raw_readb(addr);
+-			buf++;
+-			count--;
+-		}
+-		break;
+-	}
+-	case sizeof(u16): {
+-		__le16 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 1);
+-		while (count) {
+-			*buf = (__force __le16)__raw_readw(addr);
+-			buf++;
+-			count -= 2;
+-		}
+-		break;
+-	}
+-	case sizeof(u32): {
+-		__le32 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 3);
+-		while (count) {
+-			*buf = (__force __le32)__raw_readl(addr);
+-			buf++;
+-			count -= 4;
+-		}
+-		break;
+-	}
+-	default:
+-		SSB_WARN_ON(1);
+-	}
+-}
+-#endif /* CONFIG_SSB_BLOCKIO */
+-
+-static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writeb(value, bus->mmio + offset);
+-}
+-
+-static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writew(value, bus->mmio + offset);
+-}
+-
+-static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writel(value, bus->mmio + offset);
+-}
+-
+-#ifdef CONFIG_SSB_BLOCKIO
+-static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
+-				size_t count, u16 offset, u8 reg_width)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-	void __iomem *addr;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	addr = bus->mmio + offset;
+-
+-	switch (reg_width) {
+-	case sizeof(u8): {
+-		const u8 *buf = buffer;
+-
+-		while (count) {
+-			__raw_writeb(*buf, addr);
+-			buf++;
+-			count--;
+-		}
+-		break;
+-	}
+-	case sizeof(u16): {
+-		const __le16 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 1);
+-		while (count) {
+-			__raw_writew((__force u16)(*buf), addr);
+-			buf++;
+-			count -= 2;
+-		}
+-		break;
+-	}
+-	case sizeof(u32): {
+-		const __le32 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 3);
+-		while (count) {
+-			__raw_writel((__force u32)(*buf), addr);
+-			buf++;
+-			count -= 4;
+-		}
+-		break;
+-	}
+-	default:
+-		SSB_WARN_ON(1);
+-	}
+-}
+-#endif /* CONFIG_SSB_BLOCKIO */
+-
+-/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+-static const struct ssb_bus_ops ssb_ssb_ops = {
+-	.read8		= ssb_ssb_read8,
+-	.read16		= ssb_ssb_read16,
+-	.read32		= ssb_ssb_read32,
+-	.write8		= ssb_ssb_write8,
+-	.write16	= ssb_ssb_write16,
+-	.write32	= ssb_ssb_write32,
+-#ifdef CONFIG_SSB_BLOCKIO
+-	.block_read	= ssb_ssb_block_read,
+-	.block_write	= ssb_ssb_block_write,
+-#endif
+-};
+-
+ static int ssb_fetch_invariants(struct ssb_bus *bus,
+ 				ssb_invariants_func_t get_invariants)
+ {
+@@ -876,7 +716,6 @@ int ssb_bus_pcibus_register(struct ssb_b
+ 
+ 	return err;
+ }
+-EXPORT_SYMBOL(ssb_bus_pcibus_register);
+ #endif /* CONFIG_SSB_PCIHOST */
+ 
+ #ifdef CONFIG_SSB_PCMCIAHOST
+@@ -898,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ss
+ 
+ 	return err;
+ }
+-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
+ #ifdef CONFIG_SSB_SDIOHOST
+@@ -923,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_
+ EXPORT_SYMBOL(ssb_bus_sdiobus_register);
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
++#ifdef CONFIG_SSB_HOST_SOC
+ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
+ 			    ssb_invariants_func_t get_invariants)
+ {
+ 	int err;
+ 
+ 	bus->bustype = SSB_BUSTYPE_SSB;
+-	bus->ops = &ssb_ssb_ops;
++	bus->ops = &ssb_host_soc_ops;
+ 
+ 	err = ssb_bus_register(bus, get_invariants, baseaddr);
+ 	if (!err) {
+@@ -939,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_b
+ 
+ 	return err;
+ }
++#endif
+ 
+ int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
+ {
+@@ -1465,6 +1305,12 @@ static int __init ssb_modinit(void)
+ 		/* don't fail SSB init because of this */
+ 		err = 0;
+ 	}
++	err = ssb_host_pcmcia_init();
++	if (err) {
++		ssb_err("PCMCIA host initialization failed\n");
++		/* don't fail SSB init because of this */
++		err = 0;
++	}
+ 	err = ssb_gige_init();
+ 	if (err) {
+ 		ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
+@@ -1482,6 +1328,7 @@ fs_initcall(ssb_modinit);
+ static void __exit ssb_modexit(void)
+ {
+ 	ssb_gige_exit();
++	ssb_host_pcmcia_exit();
+ 	b43_pci_ssb_bridge_exit();
+ 	bus_unregister(&ssb_bustype);
+ }
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -147,8 +147,7 @@ error:
+ 	return err;
+ }
+ 
+-int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-			   struct ssb_device *dev)
++static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+ {
+ 	int err;
+ 
+--- a/drivers/ssb/sdio.c
++++ b/drivers/ssb/sdio.c
+@@ -200,7 +200,7 @@ out:
+ }
+ 
+ /* host must be already claimed */
+-int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
++static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+ {
+ 	u8 coreidx = dev->core_index;
+ 	u32 sbaddr;
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -85,8 +85,6 @@ static inline int ssb_pci_init(struct ss
+ 
+ /* pcmcia.c */
+ #ifdef CONFIG_SSB_PCMCIAHOST
+-extern int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-				  struct ssb_device *dev);
+ extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 				     u8 coreidx);
+ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+@@ -96,13 +94,10 @@ extern int ssb_pcmcia_get_invariants(str
+ extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
+ extern void ssb_pcmcia_exit(struct ssb_bus *bus);
+ extern int ssb_pcmcia_init(struct ssb_bus *bus);
++extern int ssb_host_pcmcia_init(void);
++extern void ssb_host_pcmcia_exit(void);
+ extern const struct ssb_bus_ops ssb_pcmcia_ops;
+ #else /* CONFIG_SSB_PCMCIAHOST */
+-static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-					 struct ssb_device *dev)
+-{
+-	return 0;
+-}
+ static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 					    u8 coreidx)
+ {
+@@ -124,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
+ {
+ 	return 0;
+ }
++static inline int ssb_host_pcmcia_init(void)
++{
++	return 0;
++}
++static inline void ssb_host_pcmcia_exit(void)
++{
++}
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
+ /* sdio.c */
+@@ -132,9 +134,7 @@ extern int ssb_sdio_get_invariants(struc
+ 				     struct ssb_init_invariants *iv);
+ 
+ extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
+-extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
+ extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
+-extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
+ extern void ssb_sdio_exit(struct ssb_bus *bus);
+ extern int ssb_sdio_init(struct ssb_bus *bus);
+ 
+@@ -144,19 +144,10 @@ static inline u32 ssb_sdio_scan_read32(s
+ {
+ 	return 0;
+ }
+-static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
+-					 struct ssb_device *dev)
+-{
+-	return 0;
+-}
+ static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
+ {
+ 	return 0;
+ }
+-static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
+-{
+-	return 0;
+-}
+ static inline void ssb_sdio_exit(struct ssb_bus *bus)
+ {
+ }
+@@ -166,6 +157,13 @@ static inline int ssb_sdio_init(struct s
+ }
+ #endif /* CONFIG_SSB_SDIOHOST */
+ 
++/**************************************************
++ * host_soc.c
++ **************************************************/
++
++#ifdef CONFIG_SSB_HOST_SOC
++extern const struct ssb_bus_ops ssb_host_soc_ops;
++#endif
+ 
+ /* scan.c */
+ extern const char *ssb_core_name(u16 coreid);

+ 686 - 0
target/linux/generic/patches-4.3/020-ssb-backport.patch

@@ -0,0 +1,686 @@
+--- a/arch/mips/bcm47xx/Kconfig
++++ b/arch/mips/bcm47xx/Kconfig
+@@ -4,6 +4,7 @@ config BCM47XX_SSB
+ 	bool "SSB Support for Broadcom BCM47XX"
+ 	select SYS_HAS_CPU_BMIPS32_3300
+ 	select SSB
++	select SSB_HOST_SOC
+ 	select SSB_DRIVER_MIPS
+ 	select SSB_DRIVER_EXTIF
+ 	select SSB_EMBEDDED
+--- a/drivers/ssb/Kconfig
++++ b/drivers/ssb/Kconfig
+@@ -80,6 +80,15 @@ config SSB_SDIOHOST
+ 
+ 	  If unsure, say N
+ 
++config SSB_HOST_SOC
++	bool "Support for SSB bus on SoC"
++	depends on SSB
++	help
++	  Host interface for a SSB directly mapped into memory. This is
++	  for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
++
++	  If unsure, say N
++
+ config SSB_SILENT
+ 	bool "No SSB kernel messages"
+ 	depends on SSB && EXPERT
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM)			+= sprom.o
+ 
+ # host support
+ ssb-$(CONFIG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o
+-ssb-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o
++ssb-$(CONFIG_SSB_PCMCIAHOST)		+= pcmcia.o bridge_pcmcia_80211.o
+ ssb-$(CONFIG_SSB_SDIOHOST)		+= sdio.o
++ssb-$(CONFIG_SSB_HOST_SOC)		+= host_soc.o
+ 
+ # built-in drivers
+ ssb-y					+= driver_chipcommon.o
+--- /dev/null
++++ b/drivers/ssb/bridge_pcmcia_80211.c
+@@ -0,0 +1,128 @@
++/*
++ * Broadcom 43xx PCMCIA-SSB bridge module
++ *
++ * Copyright (c) 2007 Michael Buesch <[email protected]>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include <pcmcia/cistpl.h>
++#include <pcmcia/ciscode.h>
++#include <pcmcia/ds.h>
++#include <pcmcia/cisreg.h>
++
++#include "ssb_private.h"
++
++static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
++	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
++	PCMCIA_DEVICE_NULL,
++};
++
++MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
++
++static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb;
++	int err = -ENOMEM;
++	int res = 0;
++
++	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
++	if (!ssb)
++		goto out_error;
++
++	err = -ENODEV;
++
++	dev->config_flags |= CONF_ENABLE_IRQ;
++
++	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
++			 WIN_USE_WAIT;
++	dev->resource[2]->start = 0;
++	dev->resource[2]->end = SSB_CORE_SIZE;
++	res = pcmcia_request_window(dev, dev->resource[2], 250);
++	if (res != 0)
++		goto err_kfree_ssb;
++
++	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
++	if (res != 0)
++		goto err_disable;
++
++	if (!dev->irq)
++		goto err_disable;
++
++	res = pcmcia_enable_device(dev);
++	if (res != 0)
++		goto err_disable;
++
++	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
++	if (err)
++		goto err_disable;
++	dev->priv = ssb;
++
++	return 0;
++
++err_disable:
++	pcmcia_disable_device(dev);
++err_kfree_ssb:
++	kfree(ssb);
++out_error:
++	ssb_err("Initialization failed (%d, %d)\n", res, err);
++	return err;
++}
++
++static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	ssb_bus_unregister(ssb);
++	pcmcia_disable_device(dev);
++	kfree(ssb);
++	dev->priv = NULL;
++}
++
++#ifdef CONFIG_PM
++static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_suspend(ssb);
++}
++
++static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
++{
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_resume(ssb);
++}
++#else /* CONFIG_PM */
++# define ssb_host_pcmcia_suspend		NULL
++# define ssb_host_pcmcia_resume		NULL
++#endif /* CONFIG_PM */
++
++static struct pcmcia_driver ssb_host_pcmcia_driver = {
++	.owner		= THIS_MODULE,
++	.name		= "ssb-pcmcia",
++	.id_table	= ssb_host_pcmcia_tbl,
++	.probe		= ssb_host_pcmcia_probe,
++	.remove		= ssb_host_pcmcia_remove,
++	.suspend	= ssb_host_pcmcia_suspend,
++	.resume		= ssb_host_pcmcia_resume,
++};
++
++/*
++ * These are not module init/exit functions!
++ * The module_pcmcia_driver() helper cannot be used here.
++ */
++int ssb_host_pcmcia_init(void)
++{
++	return pcmcia_register_driver(&ssb_host_pcmcia_driver);
++}
++
++void ssb_host_pcmcia_exit(void)
++{
++	pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
++}
+--- /dev/null
++++ b/drivers/ssb/host_soc.c
+@@ -0,0 +1,173 @@
++/*
++ * Sonics Silicon Backplane SoC host related functions.
++ * Subsystem core
++ *
++ * Copyright 2005, Broadcom Corporation
++ * Copyright 2006, 2007, Michael Buesch <[email protected]>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++
++#include "ssb_private.h"
++
++static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readb(bus->mmio + offset);
++}
++
++static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readw(bus->mmio + offset);
++}
++
++static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readl(bus->mmio + offset);
++}
++
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
++				    size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		u8 *buf = buffer;
++
++		while (count) {
++			*buf = __raw_readb(addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		__le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		__le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			*buf = (__force __le32)__raw_readl(addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writeb(value, bus->mmio + offset);
++}
++
++static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writew(value, bus->mmio + offset);
++}
++
++static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writel(value, bus->mmio + offset);
++}
++
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
++				     size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		const u8 *buf = buffer;
++
++		while (count) {
++			__raw_writeb(*buf, addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		const __le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		const __le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			__raw_writel((__force u32)(*buf), addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
++const struct ssb_bus_ops ssb_host_soc_ops = {
++	.read8		= ssb_host_soc_read8,
++	.read16		= ssb_host_soc_read16,
++	.read32		= ssb_host_soc_read32,
++	.write8		= ssb_host_soc_write8,
++	.write16	= ssb_host_soc_write16,
++	.write32	= ssb_host_soc_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++	.block_read	= ssb_host_soc_block_read,
++	.block_write	= ssb_host_soc_block_write,
++#endif
++};
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -596,166 +596,6 @@ error:
+ 	return err;
+ }
+ 
+-static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readb(bus->mmio + offset);
+-}
+-
+-static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readw(bus->mmio + offset);
+-}
+-
+-static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	return readl(bus->mmio + offset);
+-}
+-
+-#ifdef CONFIG_SSB_BLOCKIO
+-static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
+-			       size_t count, u16 offset, u8 reg_width)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-	void __iomem *addr;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	addr = bus->mmio + offset;
+-
+-	switch (reg_width) {
+-	case sizeof(u8): {
+-		u8 *buf = buffer;
+-
+-		while (count) {
+-			*buf = __raw_readb(addr);
+-			buf++;
+-			count--;
+-		}
+-		break;
+-	}
+-	case sizeof(u16): {
+-		__le16 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 1);
+-		while (count) {
+-			*buf = (__force __le16)__raw_readw(addr);
+-			buf++;
+-			count -= 2;
+-		}
+-		break;
+-	}
+-	case sizeof(u32): {
+-		__le32 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 3);
+-		while (count) {
+-			*buf = (__force __le32)__raw_readl(addr);
+-			buf++;
+-			count -= 4;
+-		}
+-		break;
+-	}
+-	default:
+-		SSB_WARN_ON(1);
+-	}
+-}
+-#endif /* CONFIG_SSB_BLOCKIO */
+-
+-static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writeb(value, bus->mmio + offset);
+-}
+-
+-static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writew(value, bus->mmio + offset);
+-}
+-
+-static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	writel(value, bus->mmio + offset);
+-}
+-
+-#ifdef CONFIG_SSB_BLOCKIO
+-static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
+-				size_t count, u16 offset, u8 reg_width)
+-{
+-	struct ssb_bus *bus = dev->bus;
+-	void __iomem *addr;
+-
+-	offset += dev->core_index * SSB_CORE_SIZE;
+-	addr = bus->mmio + offset;
+-
+-	switch (reg_width) {
+-	case sizeof(u8): {
+-		const u8 *buf = buffer;
+-
+-		while (count) {
+-			__raw_writeb(*buf, addr);
+-			buf++;
+-			count--;
+-		}
+-		break;
+-	}
+-	case sizeof(u16): {
+-		const __le16 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 1);
+-		while (count) {
+-			__raw_writew((__force u16)(*buf), addr);
+-			buf++;
+-			count -= 2;
+-		}
+-		break;
+-	}
+-	case sizeof(u32): {
+-		const __le32 *buf = buffer;
+-
+-		SSB_WARN_ON(count & 3);
+-		while (count) {
+-			__raw_writel((__force u32)(*buf), addr);
+-			buf++;
+-			count -= 4;
+-		}
+-		break;
+-	}
+-	default:
+-		SSB_WARN_ON(1);
+-	}
+-}
+-#endif /* CONFIG_SSB_BLOCKIO */
+-
+-/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+-static const struct ssb_bus_ops ssb_ssb_ops = {
+-	.read8		= ssb_ssb_read8,
+-	.read16		= ssb_ssb_read16,
+-	.read32		= ssb_ssb_read32,
+-	.write8		= ssb_ssb_write8,
+-	.write16	= ssb_ssb_write16,
+-	.write32	= ssb_ssb_write32,
+-#ifdef CONFIG_SSB_BLOCKIO
+-	.block_read	= ssb_ssb_block_read,
+-	.block_write	= ssb_ssb_block_write,
+-#endif
+-};
+-
+ static int ssb_fetch_invariants(struct ssb_bus *bus,
+ 				ssb_invariants_func_t get_invariants)
+ {
+@@ -876,7 +716,6 @@ int ssb_bus_pcibus_register(struct ssb_b
+ 
+ 	return err;
+ }
+-EXPORT_SYMBOL(ssb_bus_pcibus_register);
+ #endif /* CONFIG_SSB_PCIHOST */
+ 
+ #ifdef CONFIG_SSB_PCMCIAHOST
+@@ -898,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ss
+ 
+ 	return err;
+ }
+-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
+ #ifdef CONFIG_SSB_SDIOHOST
+@@ -923,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_
+ EXPORT_SYMBOL(ssb_bus_sdiobus_register);
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
++#ifdef CONFIG_SSB_HOST_SOC
+ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
+ 			    ssb_invariants_func_t get_invariants)
+ {
+ 	int err;
+ 
+ 	bus->bustype = SSB_BUSTYPE_SSB;
+-	bus->ops = &ssb_ssb_ops;
++	bus->ops = &ssb_host_soc_ops;
+ 
+ 	err = ssb_bus_register(bus, get_invariants, baseaddr);
+ 	if (!err) {
+@@ -939,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_b
+ 
+ 	return err;
+ }
++#endif
+ 
+ int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
+ {
+@@ -1465,6 +1305,12 @@ static int __init ssb_modinit(void)
+ 		/* don't fail SSB init because of this */
+ 		err = 0;
+ 	}
++	err = ssb_host_pcmcia_init();
++	if (err) {
++		ssb_err("PCMCIA host initialization failed\n");
++		/* don't fail SSB init because of this */
++		err = 0;
++	}
+ 	err = ssb_gige_init();
+ 	if (err) {
+ 		ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
+@@ -1482,6 +1328,7 @@ fs_initcall(ssb_modinit);
+ static void __exit ssb_modexit(void)
+ {
+ 	ssb_gige_exit();
++	ssb_host_pcmcia_exit();
+ 	b43_pci_ssb_bridge_exit();
+ 	bus_unregister(&ssb_bustype);
+ }
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -147,8 +147,7 @@ error:
+ 	return err;
+ }
+ 
+-int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-			   struct ssb_device *dev)
++static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+ {
+ 	int err;
+ 
+--- a/drivers/ssb/sdio.c
++++ b/drivers/ssb/sdio.c
+@@ -200,7 +200,7 @@ out:
+ }
+ 
+ /* host must be already claimed */
+-int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
++static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+ {
+ 	u8 coreidx = dev->core_index;
+ 	u32 sbaddr;
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -85,8 +85,6 @@ static inline int ssb_pci_init(struct ss
+ 
+ /* pcmcia.c */
+ #ifdef CONFIG_SSB_PCMCIAHOST
+-extern int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-				  struct ssb_device *dev);
+ extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 				     u8 coreidx);
+ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+@@ -96,13 +94,10 @@ extern int ssb_pcmcia_get_invariants(str
+ extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
+ extern void ssb_pcmcia_exit(struct ssb_bus *bus);
+ extern int ssb_pcmcia_init(struct ssb_bus *bus);
++extern int ssb_host_pcmcia_init(void);
++extern void ssb_host_pcmcia_exit(void);
+ extern const struct ssb_bus_ops ssb_pcmcia_ops;
+ #else /* CONFIG_SSB_PCMCIAHOST */
+-static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+-					 struct ssb_device *dev)
+-{
+-	return 0;
+-}
+ static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 					    u8 coreidx)
+ {
+@@ -124,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
+ {
+ 	return 0;
+ }
++static inline int ssb_host_pcmcia_init(void)
++{
++	return 0;
++}
++static inline void ssb_host_pcmcia_exit(void)
++{
++}
+ #endif /* CONFIG_SSB_PCMCIAHOST */
+ 
+ /* sdio.c */
+@@ -132,9 +134,7 @@ extern int ssb_sdio_get_invariants(struc
+ 				     struct ssb_init_invariants *iv);
+ 
+ extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
+-extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
+ extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
+-extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
+ extern void ssb_sdio_exit(struct ssb_bus *bus);
+ extern int ssb_sdio_init(struct ssb_bus *bus);
+ 
+@@ -144,19 +144,10 @@ static inline u32 ssb_sdio_scan_read32(s
+ {
+ 	return 0;
+ }
+-static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
+-					 struct ssb_device *dev)
+-{
+-	return 0;
+-}
+ static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
+ {
+ 	return 0;
+ }
+-static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
+-{
+-	return 0;
+-}
+ static inline void ssb_sdio_exit(struct ssb_bus *bus)
+ {
+ }
+@@ -166,6 +157,13 @@ static inline int ssb_sdio_init(struct s
+ }
+ #endif /* CONFIG_SSB_SDIOHOST */
+ 
++/**************************************************
++ * host_soc.c
++ **************************************************/
++
++#ifdef CONFIG_SSB_HOST_SOC
++extern const struct ssb_bus_ops ssb_host_soc_ops;
++#endif
+ 
+ /* scan.c */
+ extern const char *ssb_core_name(u16 coreid);