aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch')
-rw-r--r--package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch485
1 files changed, 485 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch b/package/kernel/mac80211/patches/315-ssb-pick-PCMCIA-host-code-support-from-b43-driver.patch
new file mode 100644
index 0000000000..64601ddf45
--- /dev/null
+++ b/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?= <zajec5@gmail.com>
+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 <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ 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 <m@bues.ch>
++ *
++ * 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 <m@bues.ch>
+-
+- 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);
+-}