X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fieee1394%2Fsbp2.c;h=2d9cc5a7d23d1f9fbf9be657741592a70052e168;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=b08755e2e68f31115ff11920f598835001ea0bd3;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index b08755e2e..2d9cc5a7d 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -38,10 +38,10 @@ * but the code needs additional debugging. */ +#include #include #include #include -#include #include #include #include @@ -117,8 +117,7 @@ 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 = " - __stringify(SBP2_MAX_SECTORS) ")"); +MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)"); /* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should @@ -126,57 +125,28 @@ 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, 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. + * 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. */ static int exclusive_login = 1; module_param(exclusive_login, int, 0644); MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"); /* - * 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. + * 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. * - * - 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. + * 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. */ -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, "Deprecated, use 'workarounds'"); +MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)"); /* * Export information about protocols/devices supported by this driver. @@ -244,7 +214,6 @@ static u32 global_outstanding_dmas = 0; #endif #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__) /* * Globals @@ -296,56 +265,14 @@ static struct hpsb_protocol_driver sbp2_driver = { }; /* - * 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. + * List of device firmwares that require the inquiry hack. + * Yields a few false positives but did not break other devices so far. */ -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, - } +static u32 sbp2_broken_inquiry_list[] = { + 0x00002800, /* Stefan Richter */ + /* DViCO Momobay CX-1 */ + 0x00000200 /* Andreas Plesch */ + /* QPS Fire DVDBurner */ }; /************************************** @@ -603,7 +530,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( command->Current_SCpnt = Current_SCpnt; list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse); } else { - SBP2_ERR("%s: no orbs available", __FUNCTION__); + SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!"); } spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return command; @@ -617,7 +544,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command) struct hpsb_host *host; if (!scsi_id) { - SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__); + printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__); return; } @@ -676,7 +603,7 @@ static int sbp2_probe(struct device *dev) struct unit_directory *ud; struct scsi_id_instance_data *scsi_id; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_probe"); ud = container_of(dev, struct unit_directory, device); @@ -701,7 +628,7 @@ static int sbp2_remove(struct device *dev) struct scsi_id_instance_data *scsi_id; struct scsi_device *sdev; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_remove"); ud = container_of(dev, struct unit_directory, device); scsi_id = ud->device.driver_data; @@ -733,7 +660,7 @@ static int sbp2_update(struct unit_directory *ud) { struct scsi_id_instance_data *scsi_id = ud->device.driver_data; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_update"); if (sbp2_reconnect_device(scsi_id)) { @@ -781,7 +708,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud struct Scsi_Host *scsi_host = NULL; struct scsi_id_instance_data *scsi_id = NULL; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_alloc_device"); scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL); if (!scsi_id) { @@ -793,12 +720,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; @@ -815,22 +742,12 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* Handle data movement if physical dma is not - * enabled or not supported on host controller */ - if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, - &sbp2_physdma_ops, - 0x0ULL, 0xfffffffcULL)) { - SBP2_ERR("failed to register lower 4GB address range"); - goto failed_alloc; - } + * enabled/supportedon host controller */ + hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops, + 0x0ULL, 0xfffffffcULL); #endif } - /* Prevent unloading of the 1394 host */ - if (!try_module_get(hi->host->driver->owner)) { - SBP2_ERR("failed to get a reference on 1394 host driver"); - goto failed_alloc; - } - scsi_id->hi = hi; list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); @@ -846,8 +763,8 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud 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), - ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); - if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { + 0x010000000000ULL, CSR1212_ALL_SPACE_END); + if (scsi_id->status_fifo_addr == ~0ULL) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; } @@ -897,7 +814,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) struct sbp2scsi_host_info *hi = scsi_id->hi; int error; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_start_device"); /* Login FIFO DMA */ scsi_id->login_response = @@ -972,6 +889,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) * allows someone else to login instead. One second makes sense. */ msleep_interruptible(1000); if (signal_pending(current)) { + SBP2_WARN("aborting sbp2_start_device due to event"); sbp2_remove_device(scsi_id); return -EINTR; } @@ -1024,7 +942,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_remove_device"); if (!scsi_id) return; @@ -1089,15 +1007,12 @@ 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 != CSR1212_INVALID_ADDR_SPACE) + if (scsi_id->status_fifo_addr) hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, - scsi_id->status_fifo_addr); + scsi_id->status_fifo_addr); scsi_id->ud->device.driver_data = NULL; - if (hi) - module_put(hi->host->driver->owner); - SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); kfree(scsi_id); @@ -1156,20 +1071,23 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) int max_logins; int active_logins; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_query_logins"); scsi_id->query_logins_orb->reserved1 = 0x0; scsi_id->query_logins_orb->reserved2 = 0x0; scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma; scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized"); scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); + SBP2_DEBUG("sbp2_query_logins: lun_misc initialized"); scsi_id->query_logins_orb->reserved_resp_length = ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); + SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); scsi_id->query_logins_orb->status_fifo_hi = ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); @@ -1178,19 +1096,25 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); + SBP2_DEBUG("sbp2_query_logins: orb byte-swapped"); + sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb), "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)); + SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset"); + 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); + SBP2_DEBUG("sbp2_query_logins: prepared to write"); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); + SBP2_DEBUG("sbp2_query_logins: written"); if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { SBP2_INFO("Error querying logins to SBP-2 device - timed out"); @@ -1215,11 +1139,13 @@ 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_INFO("Maximum concurrent logins supported: %d", max_logins); + SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins); active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_INFO("Number of active logins: %d", active_logins); + SBP2_DEBUG("Number of active logins: %d", active_logins); if (active_logins >= max_logins) { return -EIO; @@ -1237,10 +1163,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) struct sbp2scsi_host_info *hi = scsi_id->hi; quadlet_t data[2]; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_login_device"); if (!scsi_id->login_orb) { - SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__); + SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!"); return -EIO; } @@ -1254,39 +1180,59 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) /* Set-up login ORB, assume no password */ scsi_id->login_orb->password_hi = 0; scsi_id->login_orb->password_lo = 0; + SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized"); scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma; scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized"); scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */ scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */ scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */ scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); + SBP2_DEBUG("sbp2_login_device: lun_misc initialized"); scsi_id->login_orb->passwd_resp_lengths = ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); + SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); scsi_id->login_orb->status_fifo_hi = ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); scsi_id->login_orb->status_fifo_lo = ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); + /* + * Byte swap ORB if necessary + */ sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb)); + SBP2_DEBUG("sbp2_login_device: orb byte-swapped"); + sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb), "sbp2 login orb", scsi_id->login_orb_dma); + /* + * Initialize login response and status fifo + */ memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response)); memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); + SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset"); + + /* + * 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->login_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); atomic_set(&scsi_id->sbp2_login_complete, 0); + SBP2_DEBUG("sbp2_login_device: prepared to write to %08x", + (unsigned int)scsi_id->sbp2_management_agent_addr); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); + SBP2_DEBUG("sbp2_login_device: written"); /* * Wait for login status (up to 20 seconds)... @@ -1350,7 +1296,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) quadlet_t data[2]; int error; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_logout_device"); /* * Set-up logout ORB @@ -1414,7 +1360,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) quadlet_t data[2]; int error; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_reconnect_device"); /* * Set-up reconnect ORB @@ -1505,11 +1451,17 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) { quadlet_t data; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_set_busy_timeout"); + /* + * Ok, let's write to the target's busy timeout register + */ data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE); - if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) - SBP2_ERR("%s error", __FUNCTION__); + + if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) { + SBP2_ERR("sbp2_set_busy_timeout error"); + } + return 0; } @@ -1525,11 +1477,10 @@ 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; - unsigned workarounds; + firmware_revision, workarounds; int i; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_parse_unit_directory"); management_agent_addr = 0x0; command_set_spec_id = 0x0; @@ -1582,8 +1533,12 @@ 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; - SBP2_DEBUG("sbp2_firmware_revision = %x", - (unsigned int)firmware_revision); + 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); break; default: @@ -1591,44 +1546,41 @@ 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; - } + /* This is the start of our broken device checking. We try to hack + * around oddities and known defects. */ + workarounds = 0x0; - 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 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_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. */ @@ -1648,8 +1600,6 @@ 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 @@ -1662,12 +1612,13 @@ 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(); + SBP2_DEBUG("sbp2_max_speed_and_size"); + /* Initial setting comes from the hosts speed map */ scsi_id->speed_code = - hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)]; + hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 + + NODEID_TO_NODE(scsi_id->ne->nodeid)]; /* Bump down our speed if the user requested it */ if (scsi_id->speed_code > max_speed) { @@ -1678,22 +1629,15 @@ 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. */ - 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--; + scsi_id->max_payload_size = + min(sbp2_speedto_max_payload[scsi_id->speed_code], + (u8) (hi->host->csr.max_rec - 1)); 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], - SBP2_PAYLOAD_TO_BYTES(payload)); + 1 << ((u32) scsi_id->max_payload_size + 2)); - scsi_id->max_payload_size = payload; return 0; } @@ -1706,8 +1650,11 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) u64 addr; int retval; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_agent_reset"); + /* + * Ok, let's write to the target's management agent register + */ data = ntohl(SBP2_AGENT_RESET_DATA); addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; @@ -2055,7 +2002,11 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, unsigned int request_bufflen = SCpnt->request_bufflen; struct sbp2_command_info *command; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_send_command"); +#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) + printk("[scsi command]\n "); + scsi_print_command(SCpnt); +#endif SBP2_DEBUG("SCSI transfer size = %x", request_bufflen); SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg); @@ -2095,7 +2046,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, */ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data) { - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_status_to_sense_data"); /* * Ok, it's pretty ugly... ;-) @@ -2120,6 +2071,33 @@ 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("sbp2_check_sbp2_response"); + + 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 */ @@ -2133,7 +2111,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest struct sbp2_command_info *command; unsigned long flags; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_handle_status_write"); sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); @@ -2282,10 +2260,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, struct sbp2scsi_host_info *hi; int result = DID_NO_CONNECT << 16; - SBP2_DEBUG_ENTER(); -#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) - scsi_print_command(SCpnt); -#endif + SBP2_DEBUG("sbp2scsi_queuecommand"); if (!sbp2util_node_is_available(scsi_id)) goto done; @@ -2363,7 +2338,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id struct sbp2_command_info *command; unsigned long flags; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2scsi_complete_all_commands"); spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { @@ -2396,7 +2371,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, u32 scsi_status, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2scsi_complete_command"); /* * Sanity @@ -2422,7 +2397,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, */ switch (scsi_status) { case SBP2_SCSI_STATUS_GOOD: - SCpnt->result = DID_OK << 16; + SCpnt->result = DID_OK; break; case SBP2_SCSI_STATUS_BUSY: @@ -2432,11 +2407,16 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, case SBP2_SCSI_STATUS_CHECK_CONDITION: SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION"); - SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; + SCpnt->result = CHECK_CONDITION << 1; + + /* + * Debug stuff + */ #if CONFIG_IEEE1394_SBP2_DEBUG >= 1 scsi_print_command(SCpnt); - scsi_print_sense(SBP2_DEVICE_NAME, SCpnt); + scsi_print_sense("bh", SCpnt); #endif + break; case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: @@ -2458,6 +2438,13 @@ 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) { + 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. @@ -2472,8 +2459,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, * If a unit attention occurs, return busy status so it gets * retried... it could have happened because of a 1394 bus reset * or hot-plug... - * XXX DID_BUS_BUSY is actually a bad idea because it will defy - * the scsi layer's retry logic. */ #if 0 if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && @@ -2496,8 +2481,11 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev) scsi_id->sdev = sdev; - if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36) + if (force_inquiry_hack || + scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) { sdev->inquiry_len = 36; + sdev->skip_ms_page_8 = 1; + } return 0; } @@ -2510,11 +2498,13 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) 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) + if ((scsi_id->sbp2_firmware_revision & 0xffff00) == 0x0a2700 && + (scsi_id->ud->model_id == 0x000021 /* gen.4 iPod */ || + scsi_id->ud->model_id == 0x000023 /* iPod mini */ || + scsi_id->ud->model_id == 0x00007e /* iPod Photo */ )) { + SBP2_INFO("enabling iPod workaround: decrement disk 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; @@ -2651,7 +2641,7 @@ static int sbp2_module_init(void) { int ret; - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_module_init"); /* Module load debug option to force one command at a time (serializing I/O) */ if (serialize_io) { @@ -2661,9 +2651,7 @@ static int sbp2_module_init(void) scsi_driver_template.cmd_per_lun = 1; } - if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && - (max_sectors * 512) > (128 * 1024)) - max_sectors = 128 * 1024 / 512; + /* Set max sectors (module load option). Default is 255 sectors. */ scsi_driver_template.max_sectors = max_sectors; /* Register our high level driver with 1394 stack */ @@ -2681,7 +2669,7 @@ static int sbp2_module_init(void) static void __exit sbp2_module_exit(void) { - SBP2_DEBUG_ENTER(); + SBP2_DEBUG("sbp2_module_exit"); hpsb_unregister_protocol(&sbp2_driver);