L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.mcuos.com
S: Maintained
++F: arch/arm/mach-w90x900/
++F: arch/arm/mach-nuc93x/
++F: drivers/input/keyboard/w90p910_keypad.c
++F: drivers/input/touchscreen/w90p910_ts.c
++F: drivers/watchdog/nuc900_wdt.c
++F: drivers/net/arm/w90p910_ether.c
++F: drivers/mtd/nand/w90p910_nand.c
++F: drivers/rtc/rtc-nuc900.c
++F: drivers/spi/spi_nuc900.c
++F: drivers/usb/host/ehci-w90x900.c
++F: drivers/video/nuc900fb.c
++F: drivers/sound/soc/nuc900/
+
+ARM/U300 MACHINE SUPPORT
+M: Linus Walleij <linus.walleij@stericsson.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: arch/arm/mach-u300/
+F: drivers/i2c/busses/i2c-stu300.c
+F: drivers/rtc/rtc-coh901331.c
+F: drivers/watchdog/coh901327_wdt.c
+F: drivers/dma/coh901318*
ARM/U8500 ARM ARCHITECTURE
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
S: Maintained
F: arch/arm/vfp/
++ARM/VOIPAC PXA270 SUPPORT
++M: Marek Vasut <marek.vasut@gmail.com>
++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
++S: Maintained
++F: arch/arm/mach-pxa/vpac270.c
++F: arch/arm/mach-pxa/include/mach-pxa/vpac270.h
++
++ARM/ZIPIT Z2 SUPPORT
++M: Marek Vasut <marek.vasut@gmail.com>
++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
++S: Maintained
++F: arch/arm/mach-pxa/z2.c
++F: arch/arm/mach-pxa/include/mach-pxa/z2.h
++
+ASC7621 HARDWARE MONITOR DRIVER
+M: George Joseph <george.joseph@fairview5.com>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/asc7621
+F: drivers/hwmon/asc7621.c
+
ASUS ACPI EXTRAS DRIVER
M: Corentin Chary <corentincj@iksaif.net>
M: Karol Kozimor <sziwan@users.sourceforge.net>
COMMON INTERNET FILE SYSTEM (CIFS)
M: Steve French <sfrench@samba.org>
--L: linux-cifs-client@lists.samba.org (moderated for non-subscribers)
++L: linux-cifs@vger.kernel.org
L: samba-technical@lists.samba.org (moderated for non-subscribers)
W: http://linux-cifs.samba.org/
+Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
S: Supported
F: Documentation/filesystems/cifs.txt
S: Maintained
F: drivers/input/
++INPUT MULTITOUCH (MT) PROTOCOL
++M: Henrik Rydberg <rydberg@euromail.se>
++L: linux-input@vger.kernel.org
++S: Maintained
++F: Documentation/input/multi-touch-protocol.txt
++K: \b(ABS|SYN)_MT_
++
++INTEL IDLE DRIVER
++M: Len Brown <lenb@kernel.org>
++L: linux-pm@lists.linux-foundation.org
++T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-idle-2.6.git
++S: Supported
++F: drivers/idle/intel_idle.c
++
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
-M: Sylvain Meyer <sylvain.meyer@worldonline.fr>
+M: Maik Broemme <mbroemme@plusserver.de>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: Documentation/fb/intelfb.txt
S: Maintained
F: drivers/isdn/hardware/eicon/
+IT87 HARDWARE MONITORING DRIVER
+M: Jean Delvare <khali@linux-fr.org>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/it87
+F: drivers/hwmon/it87.c
+
IVTV VIDEO4LINUX DRIVER
--M: Andy Walls <awalls@radix.net>
++M: Andy Walls <awalls@md.metrocast.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: include/linux/kexec.h
F: kernel/kexec.c
-KGDB
+KEYS/KEYRINGS:
+M: David Howells <dhowells@redhat.com>
+L: keyrings@linux-nfs.org
+S: Maintained
+F: Documentation/keys.txt
+F: include/linux/key.h
+F: include/linux/key-type.h
+F: include/keys/
+F: security/keys/
+
- KGDB
++KGDB / KDB /debug_core
M: Jason Wessel <jason.wessel@windriver.com>
++W: http://kgdb.wiki.kernel.org/
L: kgdb-bugreport@lists.sourceforge.net
S: Maintained
F: Documentation/DocBook/kgdb.tmpl
M: Peter Zijlstra <a.p.zijlstra@chello.nl>
M: Paul Mackerras <paulus@samba.org>
M: Ingo Molnar <mingo@elte.hu>
+M: Arnaldo Carvalho de Melo <acme@redhat.com>
S: Supported
--F: kernel/perf_event.c
++F: kernel/perf_event*.c
F: include/linux/perf_event.h
- F: arch/*/kernel/perf_event.c
- F: arch/*/kernel/*/perf_event.c
- F: arch/*/kernel/*/*/perf_event.c
-F: arch/*/*/kernel/perf_event.c
++F: arch/*/kernel/perf_event*.c
++F: arch/*/kernel/*/perf_event*.c
++F: arch/*/kernel/*/*/perf_event*.c
F: arch/*/include/asm/perf_event.h
--F: arch/*/lib/perf_event.c
++F: arch/*/lib/perf_event*.c
F: arch/*/kernel/perf_callchain.c
F: tools/perf/
F: Documentation/networking/LICENSE.qla3xxx
F: drivers/net/qla3xxx.*
+QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
+M: Amit Kumar Salecha <amit.salecha@qlogic.com>
++M: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
+M: linux-driver@qlogic.com
+L: netdev@vger.kernel.org
+S: Supported
+F: drivers/net/qlcnic/
+
QLOGIC QLGE 10Gb ETHERNET DRIVER
M: Ron Mercer <ron.mercer@qlogic.com>
M: linux-driver@qlogic.com
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
S: Maintained
F: arch/sparc/
++F: drivers/sbus
+
+SPARC SERIAL DRIVERS
+M: "David S. Miller" <davem@davemloft.net>
+L: sparclinux@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
+S: Maintained
+F: drivers/serial/suncore.c
+F: drivers/serial/suncore.h
+F: drivers/serial/sunhv.c
+F: drivers/serial/sunsab.c
+F: drivers/serial/sunsab.h
+F: drivers/serial/sunsu.c
+F: drivers/serial/sunzilog.c
+F: drivers/serial/sunzilog.h
+
++SPEAR PLATFORM SUPPORT
++M: Viresh Kumar <viresh.kumar@st.com>
++W: http://www.st.com/spear
++S: Maintained
++F: arch/arm/plat-spear/
++
++SPEAR3XX MACHINE SUPPORT
++M: Viresh Kumar <viresh.kumar@st.com>
++W: http://www.st.com/spear
++S: Maintained
++F: arch/arm/mach-spear3xx/
++
++SPEAR6XX MACHINE SUPPORT
++M: Rajeev Kumar <rajeev-dlh.kumar@st.com>
++W: http://www.st.com/spear
++S: Maintained
++F: arch/arm/mach-spear6xx/
++
++SPEAR CLOCK FRAMEWORK SUPPORT
++M: Viresh Kumar <viresh.kumar@st.com>
++W: http://www.st.com/spear
++S: Maintained
++F: arch/arm/mach-spear*/clock.c
++F: arch/arm/mach-spear*/include/mach/clkdev.h
++F: arch/arm/plat-spear/clock.c
++F: arch/arm/plat-spear/include/plat/clock.h and clkdev.h
++
++SPEAR PAD MULTIPLEXING SUPPORT
++M: Viresh Kumar <viresh.kumar@st.com>
++W: http://www.st.com/spear
++S: Maintained
++F: arch/arm/plat-spear/include/plat/padmux.h
++F: arch/arm/plat-spear/padmux.c
++F: arch/arm/mach-spear*/spear*xx.c
++F: arch/arm/mach-spear*/include/mach/generic.h
++F: arch/arm/mach-spear3xx/spear3*0.c
++F: arch/arm/mach-spear3xx/spear3*0_evb.c
++F: arch/arm/mach-spear6xx/spear600.c
++F: arch/arm/mach-spear6xx/spear600_evb.c
+
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
M: Roger Wolff <R.E.Wolff@BitWizard.nl>
S: Supported
M: David Brownell <dbrownell@users.sourceforge.net>
M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net
+Q: http://patchwork.kernel.org/project/spi-devel-general/list/
++T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
F: Documentation/spi/
F: drivers/spi/
fw_card_put(card);
}
-- static void fw_card_bm_work(struct work_struct *work)
++ static void bm_work(struct work_struct *work)
{
-- struct fw_card *card = container_of(work, struct fw_card, work.work);
- struct fw_device *root_device;
++ struct fw_card *card = container_of(work, struct fw_card, bm_work.work);
- struct fw_device *root_device;
++ struct fw_device *root_device, *irm_device;
struct fw_node *root_node;
-- unsigned long flags;
-- int root_id, new_root_id, irm_id, local_id;
++ int root_id, new_root_id, irm_id, bm_id, local_id;
int gap_count, generation, grace, rcode;
bool do_reset = false;
bool root_device_is_running;
bool root_device_is_cmc;
++ bool irm_is_1394_1995_only;
-- spin_lock_irqsave(&card->lock, flags);
++ spin_lock_irq(&card->lock);
if (card->local_node == NULL) {
-- spin_unlock_irqrestore(&card->lock, flags);
++ spin_unlock_irq(&card->lock);
goto out_put_card;
}
/* Another bus reset, BM work has been rescheduled. */
goto out;
-- if (rcode == RCODE_COMPLETE &&
-- card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {
++ bm_id = be32_to_cpu(card->bm_transaction_data[0]);
+
++ spin_lock_irq(&card->lock);
++ if (rcode == RCODE_COMPLETE && generation == card->generation)
++ card->bm_node_id =
++ bm_id == 0x3f ? local_id : 0xffc0 | bm_id;
++ spin_unlock_irq(&card->lock);
+
++ if (rcode == RCODE_COMPLETE && bm_id != 0x3f) {
/* Somebody else is BM. Only act as IRM. */
if (local_id == irm_id)
allocate_broadcast_channel(card, generation);
kref_init(&card->kref);
init_completion(&card->done);
INIT_LIST_HEAD(&card->transaction_list);
++ INIT_LIST_HEAD(&card->phy_receiver_list);
spin_lock_init(&card->lock);
- setup_timer(&card->flush_timer,
- flush_timer_callback, (unsigned long)card);
card->local_node = NULL;
wait_for_completion(&card->done);
WARN_ON(!list_empty(&card->transaction_list));
- del_timer_sync(&card->flush_timer);
}
EXPORT_SYMBOL(fw_core_remove_card);
--
-- int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
-- {
-- int reg = short_reset ? 5 : 1;
-- int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
--
-- return card->driver->update_phy_reg(card, reg, 0, bit);
-- }
-- EXPORT_SYMBOL(fw_core_initiate_bus_reset);
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
++ #include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
+++#include <linux/time.h>
#include <asm/byteorder.h>
#include <asm/page.h>
#define QUIRK_CYCLE_TIMER 1
#define QUIRK_RESET_PACKET 2
#define QUIRK_BE_HEADERS 4
+ #define QUIRK_NO_1394A 8
++ #define QUIRK_NO_MSI 16
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {
unsigned short vendor, device, flags;
} ohci_quirks[] = {
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
- QUIRK_RESET_PACKET},
+ QUIRK_RESET_PACKET |
+ QUIRK_NO_1394A},
{PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET},
{PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
++ {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
{PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
{PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
{PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER)
", reset packet generation = " __stringify(QUIRK_RESET_PACKET)
", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
+ ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
++ ", disable MSI = " __stringify(QUIRK_NO_MSI)
")");
- #ifdef CONFIG_FIREWIRE_OHCI_DEBUG
-
#define OHCI_PARAM_DEBUG_AT_AR 1
#define OHCI_PARAM_DEBUG_SELFIDS 2
#define OHCI_PARAM_DEBUG_IRQS 4
reg_read(ohci, OHCI1394_Version);
}
- static int ohci_update_phy_reg(struct fw_card *card, int addr,
- int clear_bits, int set_bits)
+ static int read_phy_reg(struct fw_ohci *ohci, int addr)
{
- struct fw_ohci *ohci = fw_ohci(card);
- u32 val, old;
+ u32 val;
+ int i;
reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
- for (i = 0; i < 10; i++) {
- flush_writes(ohci);
- msleep(2);
- val = reg_read(ohci, OHCI1394_PhyControl);
- if ((val & OHCI1394_PhyControl_ReadDone) == 0) {
- fw_error("failed to set phy reg bits.\n");
- return -EBUSY;
++ for (i = 0; i < 3 + 100; i++) {
+ val = reg_read(ohci, OHCI1394_PhyControl);
+ if (val & OHCI1394_PhyControl_ReadDone)
+ return OHCI1394_PhyControl_ReadData(val);
+
- msleep(1);
++ /*
++ * Try a few times without waiting. Sleeping is necessary
++ * only when the link/PHY interface is busy.
++ */
++ if (i >= 3)
++ msleep(1);
}
+ fw_error("failed to read phy reg\n");
+
+ return -EBUSY;
+ }
+
+ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
+ {
+ int i;
- old = OHCI1394_PhyControl_ReadData(val);
- old = (old & ~clear_bits) | set_bits;
reg_write(ohci, OHCI1394_PhyControl,
- OHCI1394_PhyControl_Write(addr, old));
+ OHCI1394_PhyControl_Write(addr, val));
- for (i = 0; i < 100; i++) {
++ for (i = 0; i < 3 + 100; i++) {
+ val = reg_read(ohci, OHCI1394_PhyControl);
+ if (!(val & OHCI1394_PhyControl_WritePending))
+ return 0;
- msleep(1);
- return 0;
++ if (i >= 3)
++ msleep(1);
+ }
+ fw_error("failed to write phy reg\n");
+
+ return -EBUSY;
+ }
+
- static int ohci_update_phy_reg(struct fw_card *card, int addr,
- int clear_bits, int set_bits)
++ static int update_phy_reg(struct fw_ohci *ohci, int addr,
++ int clear_bits, int set_bits)
+ {
- struct fw_ohci *ohci = fw_ohci(card);
- int ret;
-
- ret = read_phy_reg(ohci, addr);
++ int ret = read_phy_reg(ohci, addr);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The interrupt status bits are cleared by writing a one bit.
+ * Avoid clearing them unless explicitly requested in set_bits.
+ */
+ if (addr == 5)
+ clear_bits |= PHY_INT_STATUS_BITS;
+
+ return write_phy_reg(ohci, addr, (ret & ~clear_bits) | set_bits);
+ }
+
+ static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr)
+ {
+ int ret;
+
- ret = ohci_update_phy_reg(&ohci->card, 7, PHY_PAGE_SELECT, page << 5);
++ ret = update_phy_reg(ohci, 7, PHY_PAGE_SELECT, page << 5);
+ if (ret < 0)
+ return ret;
+
+ return read_phy_reg(ohci, addr);
+ }
+
++ static int ohci_read_phy_reg(struct fw_card *card, int addr)
++ {
++ struct fw_ohci *ohci = fw_ohci(card);
++ int ret;
++
++ mutex_lock(&ohci->phy_reg_mutex);
++ ret = read_phy_reg(ohci, addr);
++ mutex_unlock(&ohci->phy_reg_mutex);
++
++ return ret;
++ }
++
++ static int ohci_update_phy_reg(struct fw_card *card, int addr,
++ int clear_bits, int set_bits)
++ {
++ struct fw_ohci *ohci = fw_ohci(card);
++ int ret;
++
++ mutex_lock(&ohci->phy_reg_mutex);
++ ret = update_phy_reg(ohci, addr, clear_bits, set_bits);
++ mutex_unlock(&ohci->phy_reg_mutex);
++
++ return ret;
+ }
+
static int ar_context_add_page(struct ar_context *ctx)
{
struct device *dev = ctx->ohci->card.device;
memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
}
- ret = ohci_update_phy_reg(&ohci->card, 5, clear, set);
+ static int configure_1394a_enhancements(struct fw_ohci *ohci)
+ {
+ bool enable_1394a;
+ int ret, clear, set, offset;
+
+ /* Check if the driver should configure link and PHY. */
+ if (!(reg_read(ohci, OHCI1394_HCControlSet) &
+ OHCI1394_HCControl_programPhyEnable))
+ return 0;
+
+ /* Paranoia: check whether the PHY supports 1394a, too. */
+ enable_1394a = false;
+ ret = read_phy_reg(ohci, 2);
+ if (ret < 0)
+ return ret;
+ if ((ret & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) {
+ ret = read_paged_phy_reg(ohci, 1, 8);
+ if (ret < 0)
+ return ret;
+ if (ret >= 1)
+ enable_1394a = true;
+ }
+
+ if (ohci->quirks & QUIRK_NO_1394A)
+ enable_1394a = false;
+
+ /* Configure PHY and link consistently. */
+ if (enable_1394a) {
+ clear = 0;
+ set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
+ } else {
+ clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
+ set = 0;
+ }
++ ret = update_phy_reg(ohci, 5, clear, set);
+ if (ret < 0)
+ return ret;
+
+ if (enable_1394a)
+ offset = OHCI1394_HCControlSet;
+ else
+ offset = OHCI1394_HCControlClear;
+ reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable);
+
+ /* Clean up: configuration has been taken care of. */
+ reg_write(ohci, OHCI1394_HCControlClear,
+ OHCI1394_HCControl_programPhyEnable);
+
+ return 0;
+ }
+
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{
struct fw_ohci *ohci = fw_ohci(card);
struct pci_dev *dev = to_pci_dev(card->device);
-- u32 lps;
- int i;
++ u32 lps, seconds, version, irqs;
+ int i, ret;
if (software_reset(ohci)) {
fw_error("Failed to reset ohci card.\n");
reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
reg_write(ohci, OHCI1394_IntEventClear, ~0);
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
-- reg_write(ohci, OHCI1394_IntMaskSet,
-- OHCI1394_selfIDComplete |
-- OHCI1394_RQPkt | OHCI1394_RSPkt |
-- OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
-- OHCI1394_isochRx | OHCI1394_isochTx |
-- OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
-- OHCI1394_cycleInconsistent | OHCI1394_regAccessFail |
-- OHCI1394_masterIntEnable);
-- if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
-- reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+
+ ret = configure_1394a_enhancements(ohci);
+ if (ret < 0)
+ return ret;
/* Activate link_on bit and contender bit in our self ID packets.*/
- if (ohci_update_phy_reg(card, 4, 0,
- PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
- return -EIO;
+ ret = ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER);
+ if (ret < 0)
+ return ret;
/*
* When the link is not yet enabled, the atomic config rom
int type, int channel, size_t header_size)
{
struct fw_ohci *ohci = fw_ohci(card);
-- struct iso_context *ctx, *list;
-- descriptor_callback_t callback;
-- u64 *channels, dont_care = ~0ULL;
-- u32 *mask, regs;
++ struct iso_context *uninitialized_var(ctx);
++ descriptor_callback_t uninitialized_var(callback);
++ u64 *uninitialized_var(channels);
++ u32 *uninitialized_var(mask), uninitialized_var(regs);
unsigned long flags;
-- int index, ret = -ENOMEM;
++ int index, ret = -EBUSY;
+
- if (type == FW_ISO_CONTEXT_TRANSMIT) {
- channels = &dont_care;
- mask = &ohci->it_context_mask;
- list = ohci->it_context_list;
++ spin_lock_irqsave(&ohci->lock, flags);
+
- if (type == FW_ISO_CONTEXT_TRANSMIT) {
- channels = &dont_care;
- mask = &ohci->it_context_mask;
- list = ohci->it_context_list;
++ switch (type) {
++ case FW_ISO_CONTEXT_TRANSMIT:
++ mask = &ohci->it_context_mask;
callback = handle_it_packet;
-- } else {
++ index = ffs(*mask) - 1;
++ if (index >= 0) {
++ *mask &= ~(1 << index);
++ regs = OHCI1394_IsoXmitContextBase(index);
++ ctx = &ohci->it_context_list[index];
++ }
++ break;
++
++ case FW_ISO_CONTEXT_RECEIVE:
channels = &ohci->ir_context_channels;
-- mask = &ohci->ir_context_mask;
-- list = ohci->ir_context_list;
++ mask = &ohci->ir_context_mask;
callback = handle_ir_packet_per_buffer;
-- }
++ index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
++ if (index >= 0) {
++ *channels &= ~(1ULL << channel);
++ *mask &= ~(1 << index);
++ regs = OHCI1394_IsoRcvContextBase(index);
++ ctx = &ohci->ir_context_list[index];
++ }
++ break;
-- spin_lock_irqsave(&ohci->lock, flags);
-- index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
-- if (index >= 0) {
-- *channels &= ~(1ULL << channel);
-- *mask &= ~(1 << index);
++ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
++ mask = &ohci->ir_context_mask;
++ callback = handle_ir_buffer_fill;
++ index = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
++ if (index >= 0) {
++ ohci->mc_allocated = true;
++ *mask &= ~(1 << index);
++ regs = OHCI1394_IsoRcvContextBase(index);
++ ctx = &ohci->ir_context_list[index];
++ }
++ break;
++
++ default:
++ index = -1;
++ ret = -ENOSYS;
}
++
spin_unlock_irqrestore(&ohci->lock, flags);
if (index < 0)
-- return ERR_PTR(-EBUSY);
-
- if (type == FW_ISO_CONTEXT_TRANSMIT)
- regs = OHCI1394_IsoXmitContextBase(index);
- else
- regs = OHCI1394_IsoRcvContextBase(index);
++ return ERR_PTR(ret);
- if (type == FW_ISO_CONTEXT_TRANSMIT)
- regs = OHCI1394_IsoXmitContextBase(index);
- else
- regs = OHCI1394_IsoRcvContextBase(index);
-
-- ctx = &list[index];
memset(ctx, 0, sizeof(*ctx));
ctx->header_length = 0;
ctx->header = (void *) __get_free_page(GFP_KERNEL);