ieee1394: sbp2: update includes
[safe/jmp/linux-2.6] / drivers / ieee1394 / sbp2.c
index 09e9291..3cb6b47 100644 (file)
  *       but the code needs additional debugging.
  */
 
-#include <linux/config.h>
+#include <linux/blkdev.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/wait.h>
 
-#include <asm/current.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
+#include <asm/errno.h>
+#include <asm/param.h>
 #include <asm/scatterlist.h>
+#include <asm/system.h>
+#include <asm/types.h>
+
+#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+#include <asm/io.h> /* for bus_to_virt */
+#endif
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 
 #include "csr1212.h"
+#include "highlevel.h"
+#include "hosts.h"
 #include "ieee1394.h"
-#include "ieee1394_types.h"
 #include "ieee1394_core.h"
-#include "nodemgr.h"
-#include "hosts.h"
-#include "highlevel.h"
+#include "ieee1394_hotplug.h"
 #include "ieee1394_transactions.h"
+#include "ieee1394_types.h"
+#include "nodemgr.h"
 #include "sbp2.h"
 
 /*
@@ -127,10 +132,12 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
  * talking to a single sbp2 device at the same time (filesystem coherency,
  * etc.). If you're running an sbp2 device that supports multiple logins,
  * and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts (one such filesystem is OpenGFS,
- * see opengfs.sourceforge.net for more info), then set exclusive_login
- * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four
- * concurrent logins.
+ * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster
+ * File System, or Lustre, then set exclusive_login to zero.
+ *
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int exclusive_login = 1;
 module_param(exclusive_login, int, 0644);
@@ -156,6 +163,11 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"
  *   Tell sd_mod to correct the last sector number reported by read_capacity.
  *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
  *   Don't use this with devices which don't have this bug.
+ *
+ * - override internal blacklist
+ *   Instead of adding to the built-in blacklist, use only the workarounds
+ *   specified in the module load parameter.
+ *   Useful if a blacklist entry interfered with a non-broken device.
  */
 static int sbp2_default_workarounds;
 module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
@@ -164,13 +176,9 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
        ", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
        ", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
        ", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
+       ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
        ", or a combination)");
 
-/* legacy parameter */
-static int force_inquiry_hack;
-module_param(force_inquiry_hack, int, 0644);
-MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
-
 /*
  * Export information about protocols/devices supported by this driver.
  */
@@ -201,9 +209,9 @@ static u32 global_outstanding_command_orbs = 0;
 #define outstanding_orb_incr global_outstanding_command_orbs++
 #define outstanding_orb_decr global_outstanding_command_orbs--
 #else
-#define SBP2_ORB_DEBUG(fmt, args...)
-#define outstanding_orb_incr
-#define outstanding_orb_decr
+#define SBP2_ORB_DEBUG(fmt, args...)   do {} while (0)
+#define outstanding_orb_incr           do {} while (0)
+#define outstanding_orb_decr           do {} while (0)
 #endif
 
 #ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA
@@ -215,8 +223,8 @@ static u32 global_outstanding_command_orbs = 0;
                 --global_outstanding_dmas, ## args)
 static u32 global_outstanding_dmas = 0;
 #else
-#define SBP2_DMA_ALLOC(fmt, args...)
-#define SBP2_DMA_FREE(fmt, args...)
+#define SBP2_DMA_ALLOC(fmt, args...)   do {} while (0)
+#define SBP2_DMA_FREE(fmt, args...)    do {} while (0)
 #endif
 
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 2
@@ -230,7 +238,7 @@ static u32 global_outstanding_dmas = 0;
 #define SBP2_NOTICE(fmt, args...)      HPSB_NOTICE("sbp2: "fmt, ## args)
 #define SBP2_WARN(fmt, args...)                HPSB_WARN("sbp2: "fmt, ## args)
 #else
-#define SBP2_DEBUG(fmt, args...)
+#define SBP2_DEBUG(fmt, args...)       do {} while (0)
 #define SBP2_INFO(fmt, args...)                HPSB_INFO("sbp2: "fmt, ## args)
 #define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args)
 #define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args)
@@ -300,8 +308,9 @@ static const struct {
        u32 model_id;
        unsigned workarounds;
 } sbp2_workarounds_table[] = {
-       /* TSB42AA9 */ {
+       /* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
                .firmware_revision      = 0x002800,
+               .model_id               = 0x001010,
                .workarounds            = SBP2_WORKAROUND_INQUIRY_36 |
                                          SBP2_WORKAROUND_MODE_SENSE_8,
        },
@@ -348,7 +357,7 @@ static const struct {
 /*
  * Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
  */
-static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
+static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
 {
        u32 *temp = buffer;
 
@@ -361,7 +370,7 @@ static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
 /*
  * Converts a buffer from cpu to be32 byte ordering. Length is in bytes.
  */
-static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
+static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 {
        u32 *temp = buffer;
 
@@ -372,8 +381,8 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 }
 #else /* BIG_ENDIAN */
 /* Why waste the cpu cycles? */
-#define sbp2util_be32_to_cpu_buffer(x,y)
-#define sbp2util_cpu_to_be32_buffer(x,y)
+#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0)
+#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)
 #endif
 
 #ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP
@@ -409,24 +418,26 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
        return;
 }
 #else
-#define sbp2util_packet_dump(w,x,y,z)
+#define sbp2util_packet_dump(w,x,y,z) do {} while (0)
 #endif
 
+static DECLARE_WAIT_QUEUE_HEAD(access_wq);
+
 /*
- * Goofy routine that basically does a down_timeout function.
+ * Waits for completion of an SBP-2 access request.
+ * Returns nonzero if timed out or prematurely interrupted.
  */
-static int sbp2util_down_timeout(atomic_t *done, int timeout)
+static int sbp2util_access_timeout(struct scsi_id_instance_data *scsi_id,
+                                  int timeout)
 {
-       int i;
+       long leftover = wait_event_interruptible_timeout(
+                               access_wq, scsi_id->access_complete, timeout);
 
-       for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
-               if (msleep_interruptible(100))  /* 100ms */
-                       return 1;
-       }
-       return (i > 0) ? 0 : 1;
+       scsi_id->access_complete = 0;
+       return leftover <= 0;
 }
 
-/* Free's an allocated packet */
+/* Frees an allocated packet */
 static void sbp2_free_packet(struct hpsb_packet *packet)
 {
        hpsb_free_tlabel(packet);
@@ -460,6 +471,44 @@ static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
        return 0;
 }
 
+static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id,
+                                       u64 offset, quadlet_t *data, size_t len)
+{
+       /*
+        * There is a small window after a bus reset within which the node
+        * entry's generation is current but the reconnect wasn't completed.
+        */
+       if (atomic_read(&scsi_id->unfinished_reset))
+               return;
+
+       if (hpsb_node_write(scsi_id->ne,
+                           scsi_id->sbp2_command_block_agent_addr + offset,
+                           data, len))
+               SBP2_ERR("sbp2util_notify_fetch_agent failed.");
+       /*
+        * Now accept new SCSI commands, unless a bus reset happended during
+        * hpsb_node_write.
+        */
+       if (!atomic_read(&scsi_id->unfinished_reset))
+               scsi_unblock_requests(scsi_id->scsi_host);
+}
+
+static void sbp2util_write_orb_pointer(void *p)
+{
+       quadlet_t data[2];
+
+       data[0] = ORB_SET_NODE_ID(
+                       ((struct scsi_id_instance_data *)p)->hi->host->node_id);
+       data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma;
+       sbp2util_cpu_to_be32_buffer(data, 8);
+       sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8);
+}
+
+static void sbp2util_write_doorbell(void *p)
+{
+       sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4);
+}
+
 /*
  * This function is called to create a pool of command orbs used for
  * command processing. It is called when a new sbp2 device is detected.
@@ -484,7 +533,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
                command->command_orb_dma =
                    pci_map_single(hi->host->pdev, &command->command_orb,
                                   sizeof(struct sbp2_command_orb),
-                                  PCI_DMA_BIDIRECTIONAL);
+                                  PCI_DMA_TODEVICE);
                SBP2_DMA_ALLOC("single command orb DMA");
                command->sge_dma =
                    pci_map_single(hi->host->pdev,
@@ -517,7 +566,7 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_
                        /* Release our generic DMA's */
                        pci_unmap_single(host->pdev, command->command_orb_dma,
                                         sizeof(struct sbp2_command_orb),
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        PCI_DMA_TODEVICE);
                        SBP2_DMA_FREE("single command orb DMA");
                        pci_unmap_single(host->pdev, command->sge_dma,
                                         sizeof(command->scatter_gather_element),
@@ -707,6 +756,7 @@ static int sbp2_remove(struct device *dev)
                        sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
                /* scsi_remove_device() will trigger shutdown functions of SCSI
                 * highlevel drivers which would deadlock if blocked. */
+               atomic_set(&scsi_id->unfinished_reset, 0);
                scsi_unblock_requests(scsi_id->scsi_host);
        }
        sdev = scsi_id->sdev;
@@ -758,10 +808,12 @@ static int sbp2_update(struct unit_directory *ud)
         */
        sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
 
-       /* Make sure we unblock requests (since this is likely after a bus
-        * reset). */
-       scsi_unblock_requests(scsi_id->scsi_host);
-
+       /* Accept new commands unless there was another bus reset in the
+        * meantime. */
+       if (hpsb_node_entry_valid(scsi_id->ne)) {
+               atomic_set(&scsi_id->unfinished_reset, 0);
+               scsi_unblock_requests(scsi_id->scsi_host);
+       }
        return 0;
 }
 
@@ -785,12 +837,13 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
        scsi_id->ud = ud;
        scsi_id->speed_code = IEEE1394_SPEED_100;
        scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
+       scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
        INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
        INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
        INIT_LIST_HEAD(&scsi_id->scsi_list);
        spin_lock_init(&scsi_id->sbp2_command_orb_lock);
-       scsi_id->sbp2_lun = 0;
+       atomic_set(&scsi_id->unfinished_reset, 0);
+       INIT_WORK(&scsi_id->protocol_work, NULL, NULL);
 
        ud->device.driver_data = scsi_id;
 
@@ -829,12 +882,17 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
 
        /* Register the status FIFO address range. We could use the same FIFO
         * for targets at different nodes. However we need different FIFOs per
-        * target in order to support multi-unit devices. */
+        * target in order to support multi-unit devices.
+        * The FIFO is located out of the local host controller's physical range
+        * but, if possible, within the posted write area. Status writes will
+        * then be performed as unified transactions. This slightly reduces
+        * bandwidth usage, and some Prolific based devices seem to require it.
+        */
        scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
                        &sbp2_highlevel, ud->ne->host, &sbp2_ops,
                        sizeof(struct sbp2_status_block), sizeof(quadlet_t),
-                       ~0ULL, ~0ULL);
-       if (!scsi_id->status_fifo_addr) {
+                       ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
+       if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
                SBP2_ERR("failed to allocate status FIFO address range");
                goto failed_alloc;
        }
@@ -870,8 +928,10 @@ static void sbp2_host_reset(struct hpsb_host *host)
        hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
 
        if (hi) {
-               list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+               list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) {
+                       atomic_set(&scsi_id->unfinished_reset, 1);
                        scsi_block_requests(scsi_id->scsi_host);
+               }
        }
 }
 
@@ -957,8 +1017,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
         * connected to the sbp2 device being removed. That host would
         * have a certain amount of time to relogin before the sbp2 device
         * allows someone else to login instead. One second makes sense. */
-       msleep_interruptible(1000);
-       if (signal_pending(current)) {
+       if (msleep_interruptible(1000)) {
                sbp2_remove_device(scsi_id);
                return -EINTR;
        }
@@ -1023,7 +1082,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
                scsi_remove_host(scsi_id->scsi_host);
                scsi_host_put(scsi_id->scsi_host);
        }
-
+       flush_scheduled_work();
        sbp2util_remove_command_orb_pool(scsi_id);
 
        list_del(&scsi_id->scsi_list);
@@ -1076,9 +1135,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
                SBP2_DMA_FREE("single query logins data");
        }
 
-       if (scsi_id->status_fifo_addr)
+       if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
                hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
-                       scsi_id->status_fifo_addr);
+                                         scsi_id->status_fifo_addr);
 
        scsi_id->ud->device.driver_data = NULL;
 
@@ -1169,17 +1228,14 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
                             "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
 
        memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->query_logins_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
+       if (sbp2util_access_timeout(scsi_id, 2*HZ)) {
                SBP2_INFO("Error querying logins to SBP-2 device - timed out");
                return -EIO;
        }
@@ -1189,11 +1245,8 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
                return -EIO;
        }
 
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_INFO("Error querying logins to SBP-2 device - failed");
                return -EIO;
        }
 
@@ -1202,13 +1255,11 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
        SBP2_DEBUG("length_max_logins = %x",
                   (unsigned int)scsi_id->query_logins_response->length_max_logins);
 
-       SBP2_DEBUG("Query logins to SBP-2 device successful");
-
        max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
-       SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins);
+       SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
 
        active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
-       SBP2_DEBUG("Number of active logins: %d", active_logins);
+       SBP2_INFO("Number of active logins: %d", active_logins);
 
        if (active_logins >= max_logins) {
                return -EIO;
@@ -1267,21 +1318,18 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
                             "sbp2 login orb", scsi_id->login_orb_dma);
 
        memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->login_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
        /*
         * Wait for login status (up to 20 seconds)...
         */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {
-               SBP2_ERR("Error logging into SBP-2 device - login timed-out");
+       if (sbp2util_access_timeout(scsi_id, 20*HZ)) {
+               SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
@@ -1289,18 +1337,12 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
         * Sanity. Make sure status returned matches login orb.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
-               SBP2_ERR("Error logging into SBP-2 device - login timed-out");
+               SBP2_ERR("Error logging into SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Check status
-        */
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_ERR("Error logging into SBP-2 device - login failed");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_ERR("Error logging into SBP-2 device - failed");
                return -EIO;
        }
 
@@ -1324,9 +1366,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
        scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
 
        SBP2_INFO("Logged into SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1376,21 +1416,17 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
        data[1] = scsi_id->logout_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        error = hpsb_node_write(scsi_id->ne,
                                scsi_id->sbp2_management_agent_addr, data, 8);
        if (error)
                return error;
 
        /* Wait for device to logout...1 second. */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ))
+       if (sbp2util_access_timeout(scsi_id, HZ))
                return -EIO;
 
        SBP2_INFO("Logged out of SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1434,20 +1470,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb),
                             "sbp2 reconnect orb", scsi_id->reconnect_orb_dma);
 
-       /*
-        * Initialize status fifo
-        */
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-
-       /*
-        * Ok, let's write to the target's management agent register
-        */
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->reconnect_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
-       atomic_set(&scsi_id->sbp2_login_complete, 0);
-
        error = hpsb_node_write(scsi_id->ne,
                                scsi_id->sbp2_management_agent_addr, data, 8);
        if (error)
@@ -1456,8 +1482,8 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        /*
         * Wait for reconnect status (up to 1 second)...
         */
-       if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
+       if (sbp2util_access_timeout(scsi_id, HZ)) {
+               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
@@ -1465,25 +1491,17 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
         * Sanity. Make sure status returned matches reconnect orb.
         */
        if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
+               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
                return -EIO;
        }
 
-       /*
-        * Check status
-        */
-       if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
-           STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-               SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
+       if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {
+               SBP2_ERR("Error reconnecting to SBP-2 device - failed");
                return -EIO;
        }
 
        HPSB_DEBUG("Reconnected to SBP-2 device");
-
        return 0;
-
 }
 
 /*
@@ -1581,23 +1599,19 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        }
 
        workarounds = sbp2_default_workarounds;
-       if (force_inquiry_hack) {
-               SBP2_WARN("force_inquiry_hack is deprecated. "
-                         "Use parameter 'workarounds' instead.");
-               workarounds |= SBP2_WORKAROUND_INQUIRY_36;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
-               if (sbp2_workarounds_table[i].firmware_revision &&
-                   sbp2_workarounds_table[i].firmware_revision !=
-                   (firmware_revision & 0xffff00))
-                       continue;
-               if (sbp2_workarounds_table[i].model_id &&
-                   sbp2_workarounds_table[i].model_id != ud->model_id)
-                       continue;
-               workarounds |= sbp2_workarounds_table[i].workarounds;
-               break;
-       }
+
+       if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
+               for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
+                       if (sbp2_workarounds_table[i].firmware_revision &&
+                           sbp2_workarounds_table[i].firmware_revision !=
+                           (firmware_revision & 0xffff00))
+                               continue;
+                       if (sbp2_workarounds_table[i].model_id &&
+                           sbp2_workarounds_table[i].model_id != ud->model_id)
+                               continue;
+                       workarounds |= sbp2_workarounds_table[i].workarounds;
+                       break;
+               }
 
        if (workarounds)
                SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
@@ -1636,6 +1650,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        }
 }
 
+#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))
+
 /*
  * This function is called in order to determine the max speed and packet
  * size we can use in our ORBs. Note, that we (the driver and host) only
@@ -1648,13 +1664,12 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 {
        struct sbp2scsi_host_info *hi = scsi_id->hi;
+       u8 payload;
 
        SBP2_DEBUG_ENTER();
 
-       /* Initial setting comes from the hosts speed map */
        scsi_id->speed_code =
-           hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
-                               NODEID_TO_NODE(scsi_id->ne->nodeid)];
+           hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)];
 
        /* Bump down our speed if the user requested it */
        if (scsi_id->speed_code > max_speed) {
@@ -1665,15 +1680,22 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 
        /* Payload size is the lesser of what our speed supports and what
         * our host supports.  */
-       scsi_id->max_payload_size =
-           min(sbp2_speedto_max_payload[scsi_id->speed_code],
-               (u8) (hi->host->csr.max_rec - 1));
+       payload = min(sbp2_speedto_max_payload[scsi_id->speed_code],
+                     (u8) (hi->host->csr.max_rec - 1));
+
+       /* If physical DMA is off, work around limitation in ohci1394:
+        * packet size must not exceed PAGE_SIZE */
+       if (scsi_id->ne->host->low_addr_space < (1ULL << 32))
+               while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
+                      payload)
+                       payload--;
 
        HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
                   NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
                   hpsb_speedto_str[scsi_id->speed_code],
-                  1 << ((u32) scsi_id->max_payload_size + 2));
+                  SBP2_PAYLOAD_TO_BYTES(payload));
 
+       scsi_id->max_payload_size = payload;
        return 0;
 }
 
@@ -1685,9 +1707,14 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        quadlet_t data;
        u64 addr;
        int retval;
+       unsigned long flags;
 
        SBP2_DEBUG_ENTER();
 
+       cancel_delayed_work(&scsi_id->protocol_work);
+       if (wait)
+               flush_scheduled_work();
+
        data = ntohl(SBP2_AGENT_RESET_DATA);
        addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
 
@@ -1704,7 +1731,9 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        /*
         * Need to make sure orb pointer is written on next command
         */
+       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
        scsi_id->last_orb = NULL;
+       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
        return 0;
 }
@@ -1941,13 +1970,17 @@ static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
 /*
  * This function is called in order to begin a regular SBP-2 command.
  */
-static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
+static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
                                 struct sbp2_command_info *command)
 {
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        struct sbp2_command_orb *command_orb = &command->command_orb;
-       struct node_entry *ne = scsi_id->ne;
-       u64 addr;
+       struct sbp2_command_orb *last_orb;
+       dma_addr_t last_orb_dma;
+       u64 addr = scsi_id->sbp2_command_block_agent_addr;
+       quadlet_t data[2];
+       size_t length;
+       unsigned long flags;
 
        outstanding_orb_incr;
        SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
@@ -1955,73 +1988,70 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 
        pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
                                       sizeof(struct sbp2_command_orb),
-                                      PCI_DMA_BIDIRECTIONAL);
+                                      PCI_DMA_TODEVICE);
        pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma,
                                       sizeof(command->scatter_gather_element),
                                       PCI_DMA_BIDIRECTIONAL);
        /*
         * Check to see if there are any previous orbs to use
         */
-       if (scsi_id->last_orb == NULL) {
-               quadlet_t data[2];
-
+       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+       last_orb = scsi_id->last_orb;
+       last_orb_dma = scsi_id->last_orb_dma;
+       if (!last_orb) {
                /*
-                * Ok, let's write to the target's management agent register
+                * last_orb == NULL means: We know that the target's fetch agent
+                * is not active right now.
                 */
-               addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET;
+               addr += SBP2_ORB_POINTER_OFFSET;
                data[0] = ORB_SET_NODE_ID(hi->host->node_id);
                data[1] = command->command_orb_dma;
                sbp2util_cpu_to_be32_buffer(data, 8);
-
-               SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
-
-               if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) {
-                       SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
-                       return -EIO;
-               }
-
-               SBP2_ORB_DEBUG("write command agent complete");
-
-               scsi_id->last_orb = command_orb;
-               scsi_id->last_orb_dma = command->command_orb_dma;
-
+               length = 8;
        } else {
-               quadlet_t data;
-
                /*
-                * We have an orb already sent (maybe or maybe not
-                * processed) that we can append this orb to. So do so,
-                * and ring the doorbell. Have to be very careful
-                * modifying these next orb pointers, as they are accessed
-                * both by the sbp2 device and us.
+                * last_orb != NULL means: We know that the target's fetch agent
+                * is (very probably) not dead or in reset state right now.
+                * We have an ORB already sent that we can append a new one to.
+                * The target's fetch agent may or may not have read this
+                * previous ORB yet.
                 */
-               scsi_id->last_orb->next_ORB_lo =
-                   cpu_to_be32(command->command_orb_dma);
+               pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,
+                                           sizeof(struct sbp2_command_orb),
+                                           PCI_DMA_TODEVICE);
+               last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
+               wmb();
                /* Tells hardware that this pointer is valid */
-               scsi_id->last_orb->next_ORB_hi = 0x0;
-               pci_dma_sync_single_for_device(hi->host->pdev,
-                                              scsi_id->last_orb_dma,
+               last_orb->next_ORB_hi = 0;
+               pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,
                                               sizeof(struct sbp2_command_orb),
-                                              PCI_DMA_BIDIRECTIONAL);
+                                              PCI_DMA_TODEVICE);
+               addr += SBP2_DOORBELL_OFFSET;
+               data[0] = 0;
+               length = 4;
+       }
+       scsi_id->last_orb = command_orb;
+       scsi_id->last_orb_dma = command->command_orb_dma;
+       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
+       SBP2_ORB_DEBUG("write to %s register, command orb %p",
+                       last_orb ? "DOORBELL" : "ORB_POINTER", command_orb);
+       if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) {
                /*
-                * Ring the doorbell
+                * sbp2util_node_write_no_wait failed. We certainly ran out
+                * of transaction labels, perhaps just because there were no
+                * context switches which gave khpsbpkt a chance to collect
+                * free tlabels. Try again in non-atomic context. If necessary,
+                * the workqueue job will sleep to guaranteedly get a tlabel.
+                * We do not accept new commands until the job is over.
                 */
-               data = cpu_to_be32(command->command_orb_dma);
-               addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET;
-
-               SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
-
-               if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
-                       SBP2_ERR("sbp2util_node_write_no_wait failed");
-                       return -EIO;
-               }
-
-               scsi_id->last_orb = command_orb;
-               scsi_id->last_orb_dma = command->command_orb_dma;
-
+               scsi_block_requests(scsi_id->scsi_host);
+               PREPARE_WORK(&scsi_id->protocol_work,
+                            last_orb ? sbp2util_write_doorbell:
+                                       sbp2util_write_orb_pointer,
+                            scsi_id);
+               schedule_work(&scsi_id->protocol_work);
        }
-       return 0;
 }
 
 /*
@@ -2058,11 +2088,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
                             "sbp2 command orb", command->command_orb_dma);
 
        /*
-        * Initialize status fifo
-        */
-       memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-
-       /*
         * Link up the orb, and ring the doorbell if needed
         */
        sbp2_link_orb_command(scsi_id, command);
@@ -2101,41 +2126,16 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
 }
 
 /*
- * This function is called after a command is completed, in order to do any necessary SBP-2
- * response data translations for the SCSI stack
- */
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
-                                    struct scsi_cmnd *SCpnt)
-{
-       u8 *scsi_buf = SCpnt->request_buffer;
-
-       SBP2_DEBUG_ENTER();
-
-       if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
-               /*
-                * Make sure data length is ok. Minimum length is 36 bytes
-                */
-               if (scsi_buf[4] == 0) {
-                       scsi_buf[4] = 36 - 5;
-               }
-
-               /*
-                * Fix ansi revision and response data format
-                */
-               scsi_buf[2] |= 2;
-               scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-       }
-}
-
-/*
  * This function deals with status writes from the SBP-2 device
  */
-static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
-                                   quadlet_t *data, u64 addr, size_t length, u16 fl)
+static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
+                                   int destid, quadlet_t *data, u64 addr,
+                                   size_t length, u16 fl)
 {
        struct sbp2scsi_host_info *hi;
        struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
        struct scsi_cmnd *SCpnt = NULL;
+       struct sbp2_status_block *sb;
        u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
        struct sbp2_command_info *command;
        unsigned long flags;
@@ -2144,18 +2144,19 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 
        sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
 
-       if (!host) {
+       if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {
+               SBP2_ERR("Wrong size of status block");
+               return RCODE_ADDRESS_ERROR;
+       }
+       if (unlikely(!host)) {
                SBP2_ERR("host is NULL - this is bad!");
                return RCODE_ADDRESS_ERROR;
        }
-
        hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-
-       if (!hi) {
+       if (unlikely(!hi)) {
                SBP2_ERR("host info is NULL - this is bad!");
                return RCODE_ADDRESS_ERROR;
        }
-
        /*
         * Find our scsi_id structure by looking at the status fifo address
         * written to by the sbp2 device.
@@ -2167,32 +2168,35 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                        break;
                }
        }
-
-       if (!scsi_id) {
+       if (unlikely(!scsi_id)) {
                SBP2_ERR("scsi_id is NULL - device is gone?");
                return RCODE_ADDRESS_ERROR;
        }
 
        /*
-        * Put response into scsi_id status fifo...
-        */
-       memcpy(&scsi_id->status_block, data, length);
-
-       /*
-        * Byte swap first two quadlets (8 bytes) of status for processing
+        * Put response into scsi_id status fifo buffer. The first two bytes
+        * come in big endian bit order. Often the target writes only a
+        * truncated status block, minimally the first two quadlets. The rest
+        * is implied to be zeros.
         */
-       sbp2util_be32_to_cpu_buffer(&scsi_id->status_block, 8);
+       sb = &scsi_id->status_block;
+       memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));
+       memcpy(sb, data, length);
+       sbp2util_be32_to_cpu_buffer(sb, 8);
 
        /*
-        * Handle command ORB status here if necessary. First, need to match status with command.
+        * Ignore unsolicited status. Handle command ORB status.
         */
-       command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo);
+       if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))
+               command = NULL;
+       else
+               command = sbp2util_find_command_for_orb(scsi_id,
+                                                       sb->ORB_offset_lo);
        if (command) {
-
                SBP2_DEBUG("Found status for command ORB");
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
                                            sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_BIDIRECTIONAL);
+                                           PCI_DMA_TODEVICE);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
                                            sizeof(command->scatter_gather_element),
                                            PCI_DMA_BIDIRECTIONAL);
@@ -2201,7 +2205,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                outstanding_orb_decr;
 
                /*
-                * Matched status with command, now grab scsi command pointers and check status
+                * Matched status with command, now grab scsi command pointers
+                * and check status.
+                */
+               /*
+                * FIXME: If the src field in the status is 1, the ORB DMA must
+                * not be reused until status for a subsequent ORB is received.
                 */
                SCpnt = command->Current_SCpnt;
                spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
@@ -2209,61 +2218,64 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
                if (SCpnt) {
-
+                       u32 h = sb->ORB_offset_hi_misc;
+                       u32 r = STATUS_GET_RESP(h);
+
+                       if (r != RESP_STATUS_REQUEST_COMPLETE) {
+                               SBP2_WARN("resp 0x%x, sbp_status 0x%x",
+                                         r, STATUS_GET_SBP_STATUS(h));
+                               scsi_status =
+                                       r == RESP_STATUS_TRANSPORT_FAILURE ?
+                                       SBP2_SCSI_STATUS_BUSY :
+                                       SBP2_SCSI_STATUS_COMMAND_TERMINATED;
+                       }
                        /*
-                        * See if the target stored any scsi status information
+                        * See if the target stored any scsi status information.
                         */
-                       if (STATUS_GET_LENGTH(scsi_id->status_block.ORB_offset_hi_misc) > 1) {
-                               /*
-                                * Translate SBP-2 status to SCSI sense data
-                                */
+                       if (STATUS_GET_LEN(h) > 1) {
                                SBP2_DEBUG("CHECK CONDITION");
-                               scsi_status = sbp2_status_to_sense_data((unchar *)&scsi_id->status_block, SCpnt->sense_buffer);
+                               scsi_status = sbp2_status_to_sense_data(
+                                       (unchar *)sb, SCpnt->sense_buffer);
                        }
-
                        /*
-                        * Check to see if the dead bit is set. If so, we'll have to initiate
-                        * a fetch agent reset.
+                        * Check to see if the dead bit is set. If so, we'll
+                        * have to initiate a fetch agent reset.
                         */
-                       if (STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc)) {
-
-                               /*
-                                * Initiate a fetch agent reset.
-                                */
-                               SBP2_DEBUG("Dead bit set - initiating fetch agent reset");
+                       if (STATUS_TEST_DEAD(h)) {
+                               SBP2_DEBUG("Dead bit set - "
+                                          "initiating fetch agent reset");
                                 sbp2_agent_reset(scsi_id, 0);
                        }
-
                        SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb);
                }
 
                /*
-                * Check here to see if there are no commands in-use. If there are none, we can
-                * null out last orb so that next time around we write directly to the orb pointer...
-                * Quick start saves one 1394 bus transaction.
+                * Check here to see if there are no commands in-use. If there
+                * are none, we know that the fetch agent left the active state
+                * _and_ that we did not reactivate it yet. Therefore clear
+                * last_orb so that next time we write directly to the
+                * ORB_POINTER register. That way the fetch agent does not need
+                * to refetch the next_ORB.
                 */
                spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-               if (list_empty(&scsi_id->sbp2_command_orb_inuse)) {
+               if (list_empty(&scsi_id->sbp2_command_orb_inuse))
                        scsi_id->last_orb = NULL;
-               }
                spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
        } else {
-
                /*
                 * It's probably a login/logout/reconnect status.
                 */
-               if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) ||
-                   (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) {
-                       atomic_set(&scsi_id->sbp2_login_complete, 1);
+               if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->login_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) ||
+                   (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) {
+                       scsi_id->access_complete = 1;
+                       wake_up_interruptible(&access_wq);
                }
        }
 
        if (SCpnt) {
-
-               /* Complete the SCSI command. */
                SBP2_DEBUG("Completing SCSI command");
                sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt,
                                          command->Current_done);
@@ -2379,7 +2391,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
                command = list_entry(lh, struct sbp2_command_info, list);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma,
                                            sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_BIDIRECTIONAL);
+                                           PCI_DMA_TODEVICE);
                pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma,
                                            sizeof(command->scatter_gather_element),
                                            PCI_DMA_BIDIRECTIONAL);
@@ -2466,13 +2478,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
        }
 
        /*
-        * Take care of any sbp2 response data mucking here (RBC stuff, etc.)
-        */
-       if (SCpnt->result == DID_OK << 16) {
-               sbp2_check_sbp2_response(scsi_id, SCpnt);
-       }
-
-       /*
         * If a bus reset is in progress and there was an error, complete
         * the command as busy so that it will get retried.
         */
@@ -2529,6 +2534,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
                sdev->skip_ms_page_8 = 1;
        if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
                sdev->fix_capacity = 1;
+       if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
+           (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
+               sdev->allow_restart = 1;
        return 0;
 }
 
@@ -2566,7 +2574,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                        pci_dma_sync_single_for_cpu(hi->host->pdev,
                                                    command->command_orb_dma,
                                                    sizeof(struct sbp2_command_orb),
-                                                   PCI_DMA_BIDIRECTIONAL);
+                                                   PCI_DMA_TODEVICE);
                        pci_dma_sync_single_for_cpu(hi->host->pdev,
                                                    command->sge_dma,
                                                    sizeof(command->scatter_gather_element),
@@ -2582,7 +2590,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                /*
                 * Initiate a fetch agent reset.
                 */
-               sbp2_agent_reset(scsi_id, 0);
+               sbp2_agent_reset(scsi_id, 1);
                sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
        }
 
@@ -2601,7 +2609,7 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 
        if (sbp2util_node_is_available(scsi_id)) {
                SBP2_ERR("Generating sbp2 fetch agent reset");
-               sbp2_agent_reset(scsi_id, 0);
+               sbp2_agent_reset(scsi_id, 1);
        }
 
        return SUCCESS;