]> err.no Git - linux-2.6/blobdiff - drivers/ieee1394/sbp2.c
ieee1394: add preprocessor constant for invalid csr address
[linux-2.6] / drivers / ieee1394 / sbp2.c
index f4206604db0378fb33fda046cb403f4a346cdb45..1d5ceb7ecc8329a22a5d7a3b34ea8fd4a1d8dcd6 100644 (file)
@@ -42,6 +42,7 @@
 #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>
@@ -117,7 +118,8 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default
  */
 static int max_sectors = SBP2_MAX_SECTORS;
 module_param(max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)");
+MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
+                __stringify(SBP2_MAX_SECTORS) ")");
 
 /*
  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
@@ -125,28 +127,57 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 2
  * 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);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)");
 
 /*
- * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on
- * if your sbp2 device is not properly handling the SCSI inquiry command.
- * This hack makes the inquiry look more like a typical MS Windows inquiry
- * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
+ * If any of the following workarounds is required for your device to work,
+ * please submit the kernel messages logged by sbp2 to the linux1394-devel
+ * mailing list.
+ *
+ * - 128kB max transfer
+ *   Limit transfer size. Necessary for some old bridges.
+ *
+ * - 36 byte inquiry
+ *   When scsi_mod probes the device, let the inquiry command look like that
+ *   from MS Windows.
+ *
+ * - skip mode page 8
+ *   Suppress sending of mode_sense for mode page 8 if the device pretends to
+ *   support the SCSI Primary Block commands instead of Reduced Block Commands.
  *
- * If force_inquiry_hack=1 is required for your device to work,
- * please submit the logged sbp2_firmware_revision value of this device to
- * the linux1394-devel mailing list.
+ * - fix capacity
+ *   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);
+MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
+       ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
+       ", 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, "Force SCSI inquiry hack (default = 0)");
+MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
 
 /*
  * Export information about protocols/devices supported by this driver.
@@ -266,14 +297,56 @@ static struct hpsb_protocol_driver sbp2_driver = {
 };
 
 /*
- * List of device firmwares that require the inquiry hack.
- * Yields a few false positives but did not break other devices so far.
+ * List of devices with known bugs.
+ *
+ * The firmware_revision field, masked with 0xffff00, is the best indicator
+ * for the type of bridge chip of a device.  It yields a few false positives
+ * but this did not break correctly behaving devices so far.
  */
-static u32 sbp2_broken_inquiry_list[] = {
-       0x00002800,     /* Stefan Richter <stefanr@s5r6.in-berlin.de> */
-                       /* DViCO Momobay CX-1 */
-       0x00000200      /* Andreas Plesch <plesch@fas.harvard.edu> */
-                       /* QPS Fire DVDBurner */
+static const struct {
+       u32 firmware_revision;
+       u32 model_id;
+       unsigned workarounds;
+} sbp2_workarounds_table[] = {
+       /* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
+               .firmware_revision      = 0x002800,
+               .model_id               = 0x001010,
+               .workarounds            = SBP2_WORKAROUND_INQUIRY_36 |
+                                         SBP2_WORKAROUND_MODE_SENSE_8,
+       },
+       /* Initio bridges, actually only needed for some older ones */ {
+               .firmware_revision      = 0x000200,
+               .workarounds            = SBP2_WORKAROUND_INQUIRY_36,
+       },
+       /* Symbios bridge */ {
+               .firmware_revision      = 0xa0b800,
+               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
+       },
+       /*
+        * Note about the following Apple iPod blacklist entries:
+        *
+        * There are iPods (2nd gen, 3rd gen) with model_id==0.  Since our
+        * matching logic treats 0 as a wildcard, we cannot match this ID
+        * without rewriting the matching routine.  Fortunately these iPods
+        * do not feature the read_capacity bug according to one report.
+        * Read_capacity behaviour as well as model_id could change due to
+        * Apple-supplied firmware updates though.
+        */
+       /* iPod 4th generation */ {
+               .firmware_revision      = 0x0a2700,
+               .model_id               = 0x000021,
+               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
+       },
+       /* iPod mini */ {
+               .firmware_revision      = 0x0a2700,
+               .model_id               = 0x000023,
+               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
+       },
+       /* iPod Photo */ {
+               .firmware_revision      = 0x0a2700,
+               .model_id               = 0x00007e,
+               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
+       }
 };
 
 /**************************************
@@ -721,12 +794,12 @@ 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];
+       scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
        atomic_set(&scsi_id->sbp2_login_complete, 0);
        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;
 
        ud->device.driver_data = scsi_id;
 
@@ -765,12 +838,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;
        }
@@ -1012,9 +1090,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;
 
@@ -1138,13 +1216,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;
@@ -1450,7 +1526,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        struct csr1212_dentry *dentry;
        u64 management_agent_addr;
        u32 command_set_spec_id, command_set, unit_characteristics,
-           firmware_revision, workarounds;
+           firmware_revision;
+       unsigned workarounds;
        int i;
 
        SBP2_DEBUG_ENTER();
@@ -1506,12 +1583,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
                case SBP2_FIRMWARE_REVISION_KEY:
                        /* Firmware revision */
                        firmware_revision = kv->value.immediate;
-                       if (force_inquiry_hack)
-                               SBP2_INFO("sbp2_firmware_revision = %x",
-                                         (unsigned int)firmware_revision);
-                       else
-                               SBP2_DEBUG("sbp2_firmware_revision = %x",
-                                          (unsigned int)firmware_revision);
+                       SBP2_DEBUG("sbp2_firmware_revision = %x",
+                                  (unsigned int)firmware_revision);
                        break;
 
                default:
@@ -1519,41 +1592,44 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
                }
        }
 
-       /* This is the start of our broken device checking. We try to hack
-        * around oddities and known defects.  */
-       workarounds = 0x0;
+       workarounds = sbp2_default_workarounds;
+       if (force_inquiry_hack) {
+               SBP2_WARN("force_inquiry_hack is deprecated. "
+                         "Use parameter 'workarounds' instead.");
+               workarounds |= SBP2_WORKAROUND_INQUIRY_36;
+       }
 
-       /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
-        * bridge with 128KB max transfer size limitation. For sanity, we
-        * only voice this when the current max_sectors setting
-        * exceeds the 128k limit. By default, that is not the case.
-        *
-        * It would be really nice if we could detect this before the scsi
-        * host gets initialized. That way we can down-force the
-        * max_sectors to account for it. That is not currently
-        * possible.  */
-       if ((firmware_revision & 0xffff00) ==
-                       SBP2_128KB_BROKEN_FIRMWARE &&
-                       (max_sectors * 512) > (128*1024)) {
-               SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
-                               NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
-               SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!",
-                               max_sectors);
-               workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
-       }
-
-       /* Check for a blacklisted set of devices that require us to force
-        * a 36 byte host inquiry. This can be overriden as a module param
-        * (to force all hosts).  */
-       for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) {
-               if ((firmware_revision & 0xffff00) ==
-                               sbp2_broken_inquiry_list[i]) {
-                       SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
-                                       NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
-                       workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
-                       break; /* No need to continue. */
+       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 "
+                         "(firmware_revision 0x%06x, vendor_id 0x%06x,"
+                         " model_id 0x%06x)",
+                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+                         workarounds, firmware_revision,
+                         ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,
+                         ud->model_id);
+
+       /* We would need one SCSI host template for each target to adjust
+        * max_sectors on the fly, therefore warn only. */
+       if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+           (max_sectors * 512) > (128 * 1024))
+               SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
+                         "max transfer size. WARNING: Current max_sectors "
+                         "setting is larger than 128KB (%d sectors)",
+                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+                         max_sectors);
 
        /* If this is a logical unit directory entry, process the parent
         * to get the values. */
@@ -1573,6 +1649,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
@@ -1585,13 +1663,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) {
@@ -1602,15 +1679,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;
 }
 
@@ -2037,33 +2121,6 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
        return sbp2_status[8] & 0x3f;   /* return scsi status */
 }
 
-/*
- * 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
  */
@@ -2402,13 +2459,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
                SCpnt->result = DID_ERROR << 16;
        }
 
-       /*
-        * 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.
@@ -2447,19 +2497,25 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 
        scsi_id->sdev = sdev;
 
-       if (force_inquiry_hack ||
-           scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
+       if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
                sdev->inquiry_len = 36;
-               sdev->skip_ms_page_8 = 1;
-       }
        return 0;
 }
 
 static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 {
+       struct scsi_id_instance_data *scsi_id =
+               (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+
        blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
+
+       if (sdev->type == TYPE_DISK &&
+           scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+               sdev->skip_ms_page_8 = 1;
+       if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+               sdev->fix_capacity = 1;
        return 0;
 }
 
@@ -2603,7 +2659,9 @@ static int sbp2_module_init(void)
                scsi_driver_template.cmd_per_lun = 1;
        }
 
-       /* Set max sectors (module load option). Default is 255 sectors. */
+       if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+           (max_sectors * 512) > (128 * 1024))
+               max_sectors = 128 * 1024 / 512;
        scsi_driver_template.max_sectors = max_sectors;
 
        /* Register our high level driver with 1394 stack */