|
@@ -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
|
|
@@ -135,18 +137,45 @@ 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.
|
|
|
*
|
|
|
- * 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.
|
|
|
+ * - 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.
|
|
|
+ *
|
|
|
+ * - 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 +295,55 @@ 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[] = {
|
|
|
+ /* TSB42AA9 */ {
|
|
|
+ .firmware_revision = 0x002800,
|
|
|
+ .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,
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
/**************************************
|
|
@@ -765,11 +835,16 @@ 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);
|
|
|
+ 0x010000000000ULL, CSR1212_ALL_SPACE_END);
|
|
|
if (!scsi_id->status_fifo_addr) {
|
|
|
SBP2_ERR("failed to allocate status FIFO address range");
|
|
|
goto failed_alloc;
|
|
@@ -1450,7 +1525,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 +1582,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 +1591,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. */
|
|
@@ -2447,19 +2522,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 +2684,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 */
|