Merge firewire branches to be released post v2.6.35
Stefan Richter [Mon, 2 Aug 2010 07:33:25 +0000 (09:33 +0200)]
Conflicts:
drivers/firewire/core-card.c
drivers/firewire/core-cdev.c

and forgotten #include <linux/time.h> in drivers/firewire/ohci.c

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

1  2  3 
MAINTAINERS
drivers/firewire/core-card.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firewire/core-iso.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/ieee1394/sbp2.c
drivers/media/dvb/firewire/firedtv-fw.c
include/linux/firewire-cdev.h

diff --cc MAINTAINERS
@@@@ -971,28 -970,16 -950,6 +971,28 @@@@ M:     Wan ZongShun <mcuos.com@gmail.com
   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>
@@@@ -1007,27 -994,13 -964,6 +1007,27 @@@@ W:   http://www.arm.linux.org.uk
   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>
@@@@ -1583,10 -1555,10 -1488,9 +1583,10 @@@@ F: include/linux/coda*.
   
   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
@@@@ -2898,22 -2851,8 -2756,8 +2899,22 @@@@ T:  git git://git.kernel.org/pub/scm/lin
   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
@@@@ -3166,15 -3104,15 -3008,8 +3167,15 @@@@ W: http://www.melware.d
   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
@@@@ -3340,19 -3275,18 -3171,8 +3341,19 @@@@ S: Maintaine
   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
@@@@ -4421,15 -4352,15 -4221,12 +4422,15 @@@@ PERFORMANCE EVENTS SUBSYSTE
   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/
   
@@@@ -4669,14 -4586,13 -4445,6 +4670,14 @@@@ S: Supporte
   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
@@@@ -5336,63 -5237,22 -5077,7 +5337,63 @@@@ T: git git://git.kernel.org/pub/scm/lin
   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
@@@@ -5403,8 -5263,7 -5088,6 +5404,8 @@@@ SPI SUBSYSTE
   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/
@@@@ -228,23 -228,22 -273,21 +273,22 @@@@ void fw_schedule_bm_work(struct fw_car
                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);
@@@@ -438,7 -431,9 -500,8 +514,8 @@@@ void fw_card_initialize(struct fw_card 
        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;
   
@@@@ -563,14 -558,15 -644,5 +658,5 @@@@ void fw_core_remove_card(struct fw_car
        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/module.h>
   #include <linux/mutex.h>
   #include <linux/poll.h>
-- #include <linux/sched.h>
++ #include <linux/sched.h> /* required for linux/wait.h */
  +#include <linux/slab.h>
   #include <linux/spinlock.h>
   #include <linux/string.h>
   #include <linux/time.h>
@@@@ -959,23 -959,23 -1084,24 +1085,24 @@@@ static int ioctl_queue_iso(struct clien
                u.packet.sy = GET_SY(control);
                u.packet.header_length = GET_HEADER_LENGTH(control);
   
--              if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
--                      if (u.packet.header_length % 4 != 0)
++              switch (ctx->type) {
++              case FW_ISO_CONTEXT_TRANSMIT:
++                      if (u.packet.header_length & 3)
+                               return -EINVAL;
 -                      header_length = u.packet.header_length;
 -              } else {
 -                      /*
 -                       * We require that header_length is a multiple of
 -                       * the fixed header size, ctx->header_size.
 -                       */
 -                      if (ctx->header_size == 0) {
 -                              if (u.packet.header_length > 0)
 -                                      return -EINVAL;
 -                      } else if (u.packet.header_length == 0 ||
 -                                 u.packet.header_length % ctx->header_size != 0) {
++                      transmit_header_bytes = u.packet.header_length;
++                      break;
++ 
++              case FW_ISO_CONTEXT_RECEIVE:
++                      if (u.packet.header_length == 0 ||
++                          u.packet.header_length % ctx->header_size != 0)
 +                              return -EINVAL;
-                       header_length = u.packet.header_length;
-               } else {
-                       /*
-                        * We require that header_length is a multiple of
-                        * the fixed header size, ctx->header_size.
-                        */
-                       if (ctx->header_size == 0) {
-                               if (u.packet.header_length > 0)
-                                       return -EINVAL;
-                       } else if (u.packet.header_length == 0 ||
-                                  u.packet.header_length % ctx->header_size != 0) {
++                      break;
++ 
++              case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
++                      if (u.packet.payload_length == 0 ||
++                          u.packet.payload_length & 3)
                                return -EINVAL;
--                      }
--                      header_length = 0;
++                      break;
                }
   
                next = (struct fw_cdev_iso_packet __user *)
Simple merge
Simple merge
Simple merge
   #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>
@@@@ -236,17 -236,15 -247,19 +248,19 @@@@ static char ohci_driver_name[] = KBUILD
   #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},
@@@@ -259,9 -257,10 -272,10 +273,10 @@@@ MODULE_PARM_DESC(quirks, "Chip quirks (
        ", 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
@@@@ -464,73 -460,29 -480,101 +481,101 @@@@ static inline void flush_writes(const s
        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;
@@@@ -1543,64 -1495,13 -1675,64 +1681,64 @@@@ static void copy_config_rom(__be32 *des
                memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
   }
   
 + 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 = ohci_update_phy_reg(&ohci->card, 5, clear, set);
++      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
@@@@ -2052,42 -1949,42 -2292,62 +2298,62 @@@@ static struct fw_iso_context *ohci_allo
                                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);
   
-       ctx = &list[index];
 -      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);
Simple merge
Simple merge
Simple merge