162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SBP2 driver (SCSI over IEEE1394) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * The basic structure of this driver is based on the old storage driver, 1062306a36Sopenharmony_ci * drivers/ieee1394/sbp2.c, originally written by 1162306a36Sopenharmony_ci * James Goodwin <jamesg@filanet.com> 1262306a36Sopenharmony_ci * with later contributions and ongoing maintenance from 1362306a36Sopenharmony_ci * Ben Collins <bcollins@debian.org>, 1462306a36Sopenharmony_ci * Stefan Richter <stefanr@s5r6.in-berlin.de> 1562306a36Sopenharmony_ci * and many others. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/blkdev.h> 1962306a36Sopenharmony_ci#include <linux/bug.h> 2062306a36Sopenharmony_ci#include <linux/completion.h> 2162306a36Sopenharmony_ci#include <linux/delay.h> 2262306a36Sopenharmony_ci#include <linux/device.h> 2362306a36Sopenharmony_ci#include <linux/dma-mapping.h> 2462306a36Sopenharmony_ci#include <linux/firewire.h> 2562306a36Sopenharmony_ci#include <linux/firewire-constants.h> 2662306a36Sopenharmony_ci#include <linux/init.h> 2762306a36Sopenharmony_ci#include <linux/jiffies.h> 2862306a36Sopenharmony_ci#include <linux/kernel.h> 2962306a36Sopenharmony_ci#include <linux/kref.h> 3062306a36Sopenharmony_ci#include <linux/list.h> 3162306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 3262306a36Sopenharmony_ci#include <linux/module.h> 3362306a36Sopenharmony_ci#include <linux/moduleparam.h> 3462306a36Sopenharmony_ci#include <linux/scatterlist.h> 3562306a36Sopenharmony_ci#include <linux/slab.h> 3662306a36Sopenharmony_ci#include <linux/spinlock.h> 3762306a36Sopenharmony_ci#include <linux/string.h> 3862306a36Sopenharmony_ci#include <linux/stringify.h> 3962306a36Sopenharmony_ci#include <linux/workqueue.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include <asm/byteorder.h> 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#include <scsi/scsi.h> 4462306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 4562306a36Sopenharmony_ci#include <scsi/scsi_device.h> 4662306a36Sopenharmony_ci#include <scsi/scsi_host.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * So far only bridges from Oxford Semiconductor are known to support 5062306a36Sopenharmony_ci * concurrent logins. Depending on firmware, four or two concurrent logins 5162306a36Sopenharmony_ci * are possible on OXFW911 and newer Oxsemi bridges. 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Concurrent logins are useful together with cluster filesystems. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cistatic bool sbp2_param_exclusive_login = 1; 5662306a36Sopenharmony_cimodule_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644); 5762306a36Sopenharmony_ciMODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " 5862306a36Sopenharmony_ci "(default = Y, use N for concurrent initiators)"); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * Flags for firmware oddities 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * - 128kB max transfer 6462306a36Sopenharmony_ci * Limit transfer size. Necessary for some old bridges. 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * - 36 byte inquiry 6762306a36Sopenharmony_ci * When scsi_mod probes the device, let the inquiry command look like that 6862306a36Sopenharmony_ci * from MS Windows. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * - skip mode page 8 7162306a36Sopenharmony_ci * Suppress sending of mode_sense for mode page 8 if the device pretends to 7262306a36Sopenharmony_ci * support the SCSI Primary Block commands instead of Reduced Block Commands. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * - fix capacity 7562306a36Sopenharmony_ci * Tell sd_mod to correct the last sector number reported by read_capacity. 7662306a36Sopenharmony_ci * Avoids access beyond actual disk limits on devices with an off-by-one bug. 7762306a36Sopenharmony_ci * Don't use this with devices which don't have this bug. 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * - delay inquiry 8062306a36Sopenharmony_ci * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * - power condition 8362306a36Sopenharmony_ci * Set the power condition field in the START STOP UNIT commands sent by 8462306a36Sopenharmony_ci * sd_mod on suspend, resume, and shutdown (if manage_system_start_stop or 8562306a36Sopenharmony_ci * manage_runtime_start_stop is on). 8662306a36Sopenharmony_ci * Some disks need this to spin down or to resume properly. 8762306a36Sopenharmony_ci * 8862306a36Sopenharmony_ci * - override internal blacklist 8962306a36Sopenharmony_ci * Instead of adding to the built-in blacklist, use only the workarounds 9062306a36Sopenharmony_ci * specified in the module load parameter. 9162306a36Sopenharmony_ci * Useful if a blacklist entry interfered with a non-broken device. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 9462306a36Sopenharmony_ci#define SBP2_WORKAROUND_INQUIRY_36 0x2 9562306a36Sopenharmony_ci#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 9662306a36Sopenharmony_ci#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 9762306a36Sopenharmony_ci#define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 9862306a36Sopenharmony_ci#define SBP2_INQUIRY_DELAY 12 9962306a36Sopenharmony_ci#define SBP2_WORKAROUND_POWER_CONDITION 0x20 10062306a36Sopenharmony_ci#define SBP2_WORKAROUND_OVERRIDE 0x100 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic int sbp2_param_workarounds; 10362306a36Sopenharmony_cimodule_param_named(workarounds, sbp2_param_workarounds, int, 0644); 10462306a36Sopenharmony_ciMODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" 10562306a36Sopenharmony_ci ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) 10662306a36Sopenharmony_ci ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) 10762306a36Sopenharmony_ci ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) 10862306a36Sopenharmony_ci ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) 10962306a36Sopenharmony_ci ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) 11062306a36Sopenharmony_ci ", set power condition in start stop unit = " 11162306a36Sopenharmony_ci __stringify(SBP2_WORKAROUND_POWER_CONDITION) 11262306a36Sopenharmony_ci ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) 11362306a36Sopenharmony_ci ", or a combination)"); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry 11762306a36Sopenharmony_ci * and one struct scsi_device per sbp2_logical_unit. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistruct sbp2_logical_unit { 12062306a36Sopenharmony_ci struct sbp2_target *tgt; 12162306a36Sopenharmony_ci struct list_head link; 12262306a36Sopenharmony_ci struct fw_address_handler address_handler; 12362306a36Sopenharmony_ci struct list_head orb_list; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci u64 command_block_agent_address; 12662306a36Sopenharmony_ci u16 lun; 12762306a36Sopenharmony_ci int login_id; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* 13062306a36Sopenharmony_ci * The generation is updated once we've logged in or reconnected 13162306a36Sopenharmony_ci * to the logical unit. Thus, I/O to the device will automatically 13262306a36Sopenharmony_ci * fail and get retried if it happens in a window where the device 13362306a36Sopenharmony_ci * is not ready, e.g. after a bus reset but before we reconnect. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci int generation; 13662306a36Sopenharmony_ci int retries; 13762306a36Sopenharmony_ci work_func_t workfn; 13862306a36Sopenharmony_ci struct delayed_work work; 13962306a36Sopenharmony_ci bool has_sdev; 14062306a36Sopenharmony_ci bool blocked; 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci queue_delayed_work(fw_workqueue, &lu->work, delay); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* 14962306a36Sopenharmony_ci * We create one struct sbp2_target per IEEE 1212 Unit Directory 15062306a36Sopenharmony_ci * and one struct Scsi_Host per sbp2_target. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cistruct sbp2_target { 15362306a36Sopenharmony_ci struct fw_unit *unit; 15462306a36Sopenharmony_ci struct list_head lu_list; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci u64 management_agent_address; 15762306a36Sopenharmony_ci u64 guid; 15862306a36Sopenharmony_ci int directory_id; 15962306a36Sopenharmony_ci int node_id; 16062306a36Sopenharmony_ci int address_high; 16162306a36Sopenharmony_ci unsigned int workarounds; 16262306a36Sopenharmony_ci unsigned int mgt_orb_timeout; 16362306a36Sopenharmony_ci unsigned int max_payload; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci spinlock_t lock; 16662306a36Sopenharmony_ci int dont_block; /* counter for each logical unit */ 16762306a36Sopenharmony_ci int blocked; /* ditto */ 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic struct fw_device *target_parent_device(struct sbp2_target *tgt) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci return fw_parent_device(tgt->unit); 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic const struct device *tgt_dev(const struct sbp2_target *tgt) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci return &tgt->unit->device; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic const struct device *lu_dev(const struct sbp2_logical_unit *lu) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return &lu->tgt->unit->device; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* Impossible login_id, to detect logout attempt before successful login */ 18662306a36Sopenharmony_ci#define INVALID_LOGIN_ID 0x10000 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci#define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */ 18962306a36Sopenharmony_ci#define SBP2_ORB_NULL 0x80000000 19062306a36Sopenharmony_ci#define SBP2_RETRY_LIMIT 0xf /* 15 retries */ 19162306a36Sopenharmony_ci#define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* 19462306a36Sopenharmony_ci * There is no transport protocol limit to the CDB length, but we implement 19562306a36Sopenharmony_ci * a fixed length only. 16 bytes is enough for disks larger than 2 TB. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ci#define SBP2_MAX_CDB_SIZE 16 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci/* 20062306a36Sopenharmony_ci * The maximum SBP-2 data buffer size is 0xffff. We quadlet-align this 20162306a36Sopenharmony_ci * for compatibility with earlier versions of this driver. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci#define SBP2_MAX_SEG_SIZE 0xfffc 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/* Unit directory keys */ 20662306a36Sopenharmony_ci#define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a 20762306a36Sopenharmony_ci#define SBP2_CSR_FIRMWARE_REVISION 0x3c 20862306a36Sopenharmony_ci#define SBP2_CSR_LOGICAL_UNIT_NUMBER 0x14 20962306a36Sopenharmony_ci#define SBP2_CSR_UNIT_UNIQUE_ID 0x8d 21062306a36Sopenharmony_ci#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY 0xd4 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/* Management orb opcodes */ 21362306a36Sopenharmony_ci#define SBP2_LOGIN_REQUEST 0x0 21462306a36Sopenharmony_ci#define SBP2_QUERY_LOGINS_REQUEST 0x1 21562306a36Sopenharmony_ci#define SBP2_RECONNECT_REQUEST 0x3 21662306a36Sopenharmony_ci#define SBP2_SET_PASSWORD_REQUEST 0x4 21762306a36Sopenharmony_ci#define SBP2_LOGOUT_REQUEST 0x7 21862306a36Sopenharmony_ci#define SBP2_ABORT_TASK_REQUEST 0xb 21962306a36Sopenharmony_ci#define SBP2_ABORT_TASK_SET 0xc 22062306a36Sopenharmony_ci#define SBP2_LOGICAL_UNIT_RESET 0xe 22162306a36Sopenharmony_ci#define SBP2_TARGET_RESET_REQUEST 0xf 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci/* Offsets for command block agent registers */ 22462306a36Sopenharmony_ci#define SBP2_AGENT_STATE 0x00 22562306a36Sopenharmony_ci#define SBP2_AGENT_RESET 0x04 22662306a36Sopenharmony_ci#define SBP2_ORB_POINTER 0x08 22762306a36Sopenharmony_ci#define SBP2_DOORBELL 0x10 22862306a36Sopenharmony_ci#define SBP2_UNSOLICITED_STATUS_ENABLE 0x14 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* Status write response codes */ 23162306a36Sopenharmony_ci#define SBP2_STATUS_REQUEST_COMPLETE 0x0 23262306a36Sopenharmony_ci#define SBP2_STATUS_TRANSPORT_FAILURE 0x1 23362306a36Sopenharmony_ci#define SBP2_STATUS_ILLEGAL_REQUEST 0x2 23462306a36Sopenharmony_ci#define SBP2_STATUS_VENDOR_DEPENDENT 0x3 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci#define STATUS_GET_ORB_HIGH(v) ((v).status & 0xffff) 23762306a36Sopenharmony_ci#define STATUS_GET_SBP_STATUS(v) (((v).status >> 16) & 0xff) 23862306a36Sopenharmony_ci#define STATUS_GET_LEN(v) (((v).status >> 24) & 0x07) 23962306a36Sopenharmony_ci#define STATUS_GET_DEAD(v) (((v).status >> 27) & 0x01) 24062306a36Sopenharmony_ci#define STATUS_GET_RESPONSE(v) (((v).status >> 28) & 0x03) 24162306a36Sopenharmony_ci#define STATUS_GET_SOURCE(v) (((v).status >> 30) & 0x03) 24262306a36Sopenharmony_ci#define STATUS_GET_ORB_LOW(v) ((v).orb_low) 24362306a36Sopenharmony_ci#define STATUS_GET_DATA(v) ((v).data) 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistruct sbp2_status { 24662306a36Sopenharmony_ci u32 status; 24762306a36Sopenharmony_ci u32 orb_low; 24862306a36Sopenharmony_ci u8 data[24]; 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistruct sbp2_pointer { 25262306a36Sopenharmony_ci __be32 high; 25362306a36Sopenharmony_ci __be32 low; 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistruct sbp2_orb { 25762306a36Sopenharmony_ci struct fw_transaction t; 25862306a36Sopenharmony_ci struct kref kref; 25962306a36Sopenharmony_ci dma_addr_t request_bus; 26062306a36Sopenharmony_ci int rcode; 26162306a36Sopenharmony_ci void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status); 26262306a36Sopenharmony_ci struct sbp2_logical_unit *lu; 26362306a36Sopenharmony_ci struct list_head link; 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci#define MANAGEMENT_ORB_LUN(v) ((v)) 26762306a36Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16) 26862306a36Sopenharmony_ci#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20) 26962306a36Sopenharmony_ci#define MANAGEMENT_ORB_EXCLUSIVE(v) ((v) ? 1 << 28 : 0) 27062306a36Sopenharmony_ci#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29) 27162306a36Sopenharmony_ci#define MANAGEMENT_ORB_NOTIFY ((1) << 31) 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#define MANAGEMENT_ORB_RESPONSE_LENGTH(v) ((v)) 27462306a36Sopenharmony_ci#define MANAGEMENT_ORB_PASSWORD_LENGTH(v) ((v) << 16) 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistruct sbp2_management_orb { 27762306a36Sopenharmony_ci struct sbp2_orb base; 27862306a36Sopenharmony_ci struct { 27962306a36Sopenharmony_ci struct sbp2_pointer password; 28062306a36Sopenharmony_ci struct sbp2_pointer response; 28162306a36Sopenharmony_ci __be32 misc; 28262306a36Sopenharmony_ci __be32 length; 28362306a36Sopenharmony_ci struct sbp2_pointer status_fifo; 28462306a36Sopenharmony_ci } request; 28562306a36Sopenharmony_ci __be32 response[4]; 28662306a36Sopenharmony_ci dma_addr_t response_bus; 28762306a36Sopenharmony_ci struct completion done; 28862306a36Sopenharmony_ci struct sbp2_status status; 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistruct sbp2_login_response { 29262306a36Sopenharmony_ci __be32 misc; 29362306a36Sopenharmony_ci struct sbp2_pointer command_block_agent; 29462306a36Sopenharmony_ci __be32 reconnect_hold; 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci#define COMMAND_ORB_DATA_SIZE(v) ((v)) 29762306a36Sopenharmony_ci#define COMMAND_ORB_PAGE_SIZE(v) ((v) << 16) 29862306a36Sopenharmony_ci#define COMMAND_ORB_PAGE_TABLE_PRESENT ((1) << 19) 29962306a36Sopenharmony_ci#define COMMAND_ORB_MAX_PAYLOAD(v) ((v) << 20) 30062306a36Sopenharmony_ci#define COMMAND_ORB_SPEED(v) ((v) << 24) 30162306a36Sopenharmony_ci#define COMMAND_ORB_DIRECTION ((1) << 27) 30262306a36Sopenharmony_ci#define COMMAND_ORB_REQUEST_FORMAT(v) ((v) << 29) 30362306a36Sopenharmony_ci#define COMMAND_ORB_NOTIFY ((1) << 31) 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistruct sbp2_command_orb { 30662306a36Sopenharmony_ci struct sbp2_orb base; 30762306a36Sopenharmony_ci struct { 30862306a36Sopenharmony_ci struct sbp2_pointer next; 30962306a36Sopenharmony_ci struct sbp2_pointer data_descriptor; 31062306a36Sopenharmony_ci __be32 misc; 31162306a36Sopenharmony_ci u8 command_block[SBP2_MAX_CDB_SIZE]; 31262306a36Sopenharmony_ci } request; 31362306a36Sopenharmony_ci struct scsi_cmnd *cmd; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8))); 31662306a36Sopenharmony_ci dma_addr_t page_table_bus; 31762306a36Sopenharmony_ci}; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci#define SBP2_ROM_VALUE_WILDCARD ~0 /* match all */ 32062306a36Sopenharmony_ci#define SBP2_ROM_VALUE_MISSING 0xff000000 /* not present in the unit dir. */ 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/* 32362306a36Sopenharmony_ci * List of devices with known bugs. 32462306a36Sopenharmony_ci * 32562306a36Sopenharmony_ci * The firmware_revision field, masked with 0xffff00, is the best 32662306a36Sopenharmony_ci * indicator for the type of bridge chip of a device. It yields a few 32762306a36Sopenharmony_ci * false positives but this did not break correctly behaving devices 32862306a36Sopenharmony_ci * so far. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_cistatic const struct { 33162306a36Sopenharmony_ci u32 firmware_revision; 33262306a36Sopenharmony_ci u32 model; 33362306a36Sopenharmony_ci unsigned int workarounds; 33462306a36Sopenharmony_ci} sbp2_workarounds_table[] = { 33562306a36Sopenharmony_ci /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { 33662306a36Sopenharmony_ci .firmware_revision = 0x002800, 33762306a36Sopenharmony_ci .model = 0x001010, 33862306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_INQUIRY_36 | 33962306a36Sopenharmony_ci SBP2_WORKAROUND_MODE_SENSE_8 | 34062306a36Sopenharmony_ci SBP2_WORKAROUND_POWER_CONDITION, 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { 34362306a36Sopenharmony_ci .firmware_revision = 0x002800, 34462306a36Sopenharmony_ci .model = 0x000000, 34562306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_POWER_CONDITION, 34662306a36Sopenharmony_ci }, 34762306a36Sopenharmony_ci /* Initio bridges, actually only needed for some older ones */ { 34862306a36Sopenharmony_ci .firmware_revision = 0x000200, 34962306a36Sopenharmony_ci .model = SBP2_ROM_VALUE_WILDCARD, 35062306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_INQUIRY_36, 35162306a36Sopenharmony_ci }, 35262306a36Sopenharmony_ci /* PL-3507 bridge with Prolific firmware */ { 35362306a36Sopenharmony_ci .firmware_revision = 0x012800, 35462306a36Sopenharmony_ci .model = SBP2_ROM_VALUE_WILDCARD, 35562306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_POWER_CONDITION, 35662306a36Sopenharmony_ci }, 35762306a36Sopenharmony_ci /* Symbios bridge */ { 35862306a36Sopenharmony_ci .firmware_revision = 0xa0b800, 35962306a36Sopenharmony_ci .model = SBP2_ROM_VALUE_WILDCARD, 36062306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, 36162306a36Sopenharmony_ci }, 36262306a36Sopenharmony_ci /* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ { 36362306a36Sopenharmony_ci .firmware_revision = 0x002600, 36462306a36Sopenharmony_ci .model = SBP2_ROM_VALUE_WILDCARD, 36562306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, 36662306a36Sopenharmony_ci }, 36762306a36Sopenharmony_ci /* 36862306a36Sopenharmony_ci * iPod 2nd generation: needs 128k max transfer size workaround 36962306a36Sopenharmony_ci * iPod 3rd generation: needs fix capacity workaround 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci { 37262306a36Sopenharmony_ci .firmware_revision = 0x0a2700, 37362306a36Sopenharmony_ci .model = 0x000000, 37462306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS | 37562306a36Sopenharmony_ci SBP2_WORKAROUND_FIX_CAPACITY, 37662306a36Sopenharmony_ci }, 37762306a36Sopenharmony_ci /* iPod 4th generation */ { 37862306a36Sopenharmony_ci .firmware_revision = 0x0a2700, 37962306a36Sopenharmony_ci .model = 0x000021, 38062306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, 38162306a36Sopenharmony_ci }, 38262306a36Sopenharmony_ci /* iPod mini */ { 38362306a36Sopenharmony_ci .firmware_revision = 0x0a2700, 38462306a36Sopenharmony_ci .model = 0x000022, 38562306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, 38662306a36Sopenharmony_ci }, 38762306a36Sopenharmony_ci /* iPod mini */ { 38862306a36Sopenharmony_ci .firmware_revision = 0x0a2700, 38962306a36Sopenharmony_ci .model = 0x000023, 39062306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, 39162306a36Sopenharmony_ci }, 39262306a36Sopenharmony_ci /* iPod Photo */ { 39362306a36Sopenharmony_ci .firmware_revision = 0x0a2700, 39462306a36Sopenharmony_ci .model = 0x00007e, 39562306a36Sopenharmony_ci .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic void free_orb(struct kref *kref) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci kfree(orb); 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic void sbp2_status_write(struct fw_card *card, struct fw_request *request, 40762306a36Sopenharmony_ci int tcode, int destination, int source, 40862306a36Sopenharmony_ci int generation, unsigned long long offset, 40962306a36Sopenharmony_ci void *payload, size_t length, void *callback_data) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct sbp2_logical_unit *lu = callback_data; 41262306a36Sopenharmony_ci struct sbp2_orb *orb = NULL, *iter; 41362306a36Sopenharmony_ci struct sbp2_status status; 41462306a36Sopenharmony_ci unsigned long flags; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (tcode != TCODE_WRITE_BLOCK_REQUEST || 41762306a36Sopenharmony_ci length < 8 || length > sizeof(status)) { 41862306a36Sopenharmony_ci fw_send_response(card, request, RCODE_TYPE_ERROR); 41962306a36Sopenharmony_ci return; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci status.status = be32_to_cpup(payload); 42362306a36Sopenharmony_ci status.orb_low = be32_to_cpup(payload + 4); 42462306a36Sopenharmony_ci memset(status.data, 0, sizeof(status.data)); 42562306a36Sopenharmony_ci if (length > 8) 42662306a36Sopenharmony_ci memcpy(status.data, payload + 8, length - 8); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { 42962306a36Sopenharmony_ci dev_notice(lu_dev(lu), 43062306a36Sopenharmony_ci "non-ORB related status write, not handled\n"); 43162306a36Sopenharmony_ci fw_send_response(card, request, RCODE_COMPLETE); 43262306a36Sopenharmony_ci return; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci /* Lookup the orb corresponding to this status write. */ 43662306a36Sopenharmony_ci spin_lock_irqsave(&lu->tgt->lock, flags); 43762306a36Sopenharmony_ci list_for_each_entry(iter, &lu->orb_list, link) { 43862306a36Sopenharmony_ci if (STATUS_GET_ORB_HIGH(status) == 0 && 43962306a36Sopenharmony_ci STATUS_GET_ORB_LOW(status) == iter->request_bus) { 44062306a36Sopenharmony_ci iter->rcode = RCODE_COMPLETE; 44162306a36Sopenharmony_ci list_del(&iter->link); 44262306a36Sopenharmony_ci orb = iter; 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci spin_unlock_irqrestore(&lu->tgt->lock, flags); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (orb) { 44962306a36Sopenharmony_ci orb->callback(orb, &status); 45062306a36Sopenharmony_ci kref_put(&orb->kref, free_orb); /* orb callback reference */ 45162306a36Sopenharmony_ci } else { 45262306a36Sopenharmony_ci dev_err(lu_dev(lu), "status write for unknown ORB\n"); 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci fw_send_response(card, request, RCODE_COMPLETE); 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic void complete_transaction(struct fw_card *card, int rcode, 45962306a36Sopenharmony_ci void *payload, size_t length, void *data) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci struct sbp2_orb *orb = data; 46262306a36Sopenharmony_ci unsigned long flags; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* 46562306a36Sopenharmony_ci * This is a little tricky. We can get the status write for 46662306a36Sopenharmony_ci * the orb before we get this callback. The status write 46762306a36Sopenharmony_ci * handler above will assume the orb pointer transaction was 46862306a36Sopenharmony_ci * successful and set the rcode to RCODE_COMPLETE for the orb. 46962306a36Sopenharmony_ci * So this callback only sets the rcode if it hasn't already 47062306a36Sopenharmony_ci * been set and only does the cleanup if the transaction 47162306a36Sopenharmony_ci * failed and we didn't already get a status write. 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ci spin_lock_irqsave(&orb->lu->tgt->lock, flags); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci if (orb->rcode == -1) 47662306a36Sopenharmony_ci orb->rcode = rcode; 47762306a36Sopenharmony_ci if (orb->rcode != RCODE_COMPLETE) { 47862306a36Sopenharmony_ci list_del(&orb->link); 47962306a36Sopenharmony_ci spin_unlock_irqrestore(&orb->lu->tgt->lock, flags); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci orb->callback(orb, NULL); 48262306a36Sopenharmony_ci kref_put(&orb->kref, free_orb); /* orb callback reference */ 48362306a36Sopenharmony_ci } else { 48462306a36Sopenharmony_ci spin_unlock_irqrestore(&orb->lu->tgt->lock, flags); 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci kref_put(&orb->kref, free_orb); /* transaction callback reference */ 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, 49162306a36Sopenharmony_ci int node_id, int generation, u64 offset) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 49462306a36Sopenharmony_ci struct sbp2_pointer orb_pointer; 49562306a36Sopenharmony_ci unsigned long flags; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci orb_pointer.high = 0; 49862306a36Sopenharmony_ci orb_pointer.low = cpu_to_be32(orb->request_bus); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci orb->lu = lu; 50162306a36Sopenharmony_ci spin_lock_irqsave(&lu->tgt->lock, flags); 50262306a36Sopenharmony_ci list_add_tail(&orb->link, &lu->orb_list); 50362306a36Sopenharmony_ci spin_unlock_irqrestore(&lu->tgt->lock, flags); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci kref_get(&orb->kref); /* transaction callback reference */ 50662306a36Sopenharmony_ci kref_get(&orb->kref); /* orb callback reference */ 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, 50962306a36Sopenharmony_ci node_id, generation, device->max_speed, offset, 51062306a36Sopenharmony_ci &orb_pointer, 8, complete_transaction, orb); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 51662306a36Sopenharmony_ci struct sbp2_orb *orb, *next; 51762306a36Sopenharmony_ci struct list_head list; 51862306a36Sopenharmony_ci int retval = -ENOENT; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci INIT_LIST_HEAD(&list); 52162306a36Sopenharmony_ci spin_lock_irq(&lu->tgt->lock); 52262306a36Sopenharmony_ci list_splice_init(&lu->orb_list, &list); 52362306a36Sopenharmony_ci spin_unlock_irq(&lu->tgt->lock); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci list_for_each_entry_safe(orb, next, &list, link) { 52662306a36Sopenharmony_ci retval = 0; 52762306a36Sopenharmony_ci if (fw_cancel_transaction(device->card, &orb->t) == 0) 52862306a36Sopenharmony_ci continue; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci orb->rcode = RCODE_CANCELLED; 53162306a36Sopenharmony_ci orb->callback(orb, NULL); 53262306a36Sopenharmony_ci kref_put(&orb->kref, free_orb); /* orb callback reference */ 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci return retval; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic void complete_management_orb(struct sbp2_orb *base_orb, 53962306a36Sopenharmony_ci struct sbp2_status *status) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct sbp2_management_orb *orb = 54262306a36Sopenharmony_ci container_of(base_orb, struct sbp2_management_orb, base); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (status) 54562306a36Sopenharmony_ci memcpy(&orb->status, status, sizeof(*status)); 54662306a36Sopenharmony_ci complete(&orb->done); 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, 55062306a36Sopenharmony_ci int generation, int function, 55162306a36Sopenharmony_ci int lun_or_login_id, void *response) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 55462306a36Sopenharmony_ci struct sbp2_management_orb *orb; 55562306a36Sopenharmony_ci unsigned int timeout; 55662306a36Sopenharmony_ci int retval = -ENOMEM; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device)) 55962306a36Sopenharmony_ci return 0; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci orb = kzalloc(sizeof(*orb), GFP_NOIO); 56262306a36Sopenharmony_ci if (orb == NULL) 56362306a36Sopenharmony_ci return -ENOMEM; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci kref_init(&orb->base.kref); 56662306a36Sopenharmony_ci orb->response_bus = 56762306a36Sopenharmony_ci dma_map_single(device->card->device, &orb->response, 56862306a36Sopenharmony_ci sizeof(orb->response), DMA_FROM_DEVICE); 56962306a36Sopenharmony_ci if (dma_mapping_error(device->card->device, orb->response_bus)) 57062306a36Sopenharmony_ci goto fail_mapping_response; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci orb->request.response.high = 0; 57362306a36Sopenharmony_ci orb->request.response.low = cpu_to_be32(orb->response_bus); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci orb->request.misc = cpu_to_be32( 57662306a36Sopenharmony_ci MANAGEMENT_ORB_NOTIFY | 57762306a36Sopenharmony_ci MANAGEMENT_ORB_FUNCTION(function) | 57862306a36Sopenharmony_ci MANAGEMENT_ORB_LUN(lun_or_login_id)); 57962306a36Sopenharmony_ci orb->request.length = cpu_to_be32( 58062306a36Sopenharmony_ci MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response))); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci orb->request.status_fifo.high = 58362306a36Sopenharmony_ci cpu_to_be32(lu->address_handler.offset >> 32); 58462306a36Sopenharmony_ci orb->request.status_fifo.low = 58562306a36Sopenharmony_ci cpu_to_be32(lu->address_handler.offset); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci if (function == SBP2_LOGIN_REQUEST) { 58862306a36Sopenharmony_ci /* Ask for 2^2 == 4 seconds reconnect grace period */ 58962306a36Sopenharmony_ci orb->request.misc |= cpu_to_be32( 59062306a36Sopenharmony_ci MANAGEMENT_ORB_RECONNECT(2) | 59162306a36Sopenharmony_ci MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login)); 59262306a36Sopenharmony_ci timeout = lu->tgt->mgt_orb_timeout; 59362306a36Sopenharmony_ci } else { 59462306a36Sopenharmony_ci timeout = SBP2_ORB_TIMEOUT; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci init_completion(&orb->done); 59862306a36Sopenharmony_ci orb->base.callback = complete_management_orb; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci orb->base.request_bus = 60162306a36Sopenharmony_ci dma_map_single(device->card->device, &orb->request, 60262306a36Sopenharmony_ci sizeof(orb->request), DMA_TO_DEVICE); 60362306a36Sopenharmony_ci if (dma_mapping_error(device->card->device, orb->base.request_bus)) 60462306a36Sopenharmony_ci goto fail_mapping_request; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci sbp2_send_orb(&orb->base, lu, node_id, generation, 60762306a36Sopenharmony_ci lu->tgt->management_agent_address); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout)); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci retval = -EIO; 61262306a36Sopenharmony_ci if (sbp2_cancel_orbs(lu) == 0) { 61362306a36Sopenharmony_ci dev_err(lu_dev(lu), "ORB reply timed out, rcode 0x%02x\n", 61462306a36Sopenharmony_ci orb->base.rcode); 61562306a36Sopenharmony_ci goto out; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (orb->base.rcode != RCODE_COMPLETE) { 61962306a36Sopenharmony_ci dev_err(lu_dev(lu), "management write failed, rcode 0x%02x\n", 62062306a36Sopenharmony_ci orb->base.rcode); 62162306a36Sopenharmony_ci goto out; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (STATUS_GET_RESPONSE(orb->status) != 0 || 62562306a36Sopenharmony_ci STATUS_GET_SBP_STATUS(orb->status) != 0) { 62662306a36Sopenharmony_ci dev_err(lu_dev(lu), "error status: %d:%d\n", 62762306a36Sopenharmony_ci STATUS_GET_RESPONSE(orb->status), 62862306a36Sopenharmony_ci STATUS_GET_SBP_STATUS(orb->status)); 62962306a36Sopenharmony_ci goto out; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci retval = 0; 63362306a36Sopenharmony_ci out: 63462306a36Sopenharmony_ci dma_unmap_single(device->card->device, orb->base.request_bus, 63562306a36Sopenharmony_ci sizeof(orb->request), DMA_TO_DEVICE); 63662306a36Sopenharmony_ci fail_mapping_request: 63762306a36Sopenharmony_ci dma_unmap_single(device->card->device, orb->response_bus, 63862306a36Sopenharmony_ci sizeof(orb->response), DMA_FROM_DEVICE); 63962306a36Sopenharmony_ci fail_mapping_response: 64062306a36Sopenharmony_ci if (response) 64162306a36Sopenharmony_ci memcpy(response, orb->response, sizeof(orb->response)); 64262306a36Sopenharmony_ci kref_put(&orb->base.kref, free_orb); 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci return retval; 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic void sbp2_agent_reset(struct sbp2_logical_unit *lu) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 65062306a36Sopenharmony_ci __be32 d = 0; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, 65362306a36Sopenharmony_ci lu->tgt->node_id, lu->generation, device->max_speed, 65462306a36Sopenharmony_ci lu->command_block_agent_address + SBP2_AGENT_RESET, 65562306a36Sopenharmony_ci &d, 4); 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic void complete_agent_reset_write_no_wait(struct fw_card *card, 65962306a36Sopenharmony_ci int rcode, void *payload, size_t length, void *data) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci kfree(data); 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 66762306a36Sopenharmony_ci struct fw_transaction *t; 66862306a36Sopenharmony_ci static __be32 d; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci t = kmalloc(sizeof(*t), GFP_ATOMIC); 67162306a36Sopenharmony_ci if (t == NULL) 67262306a36Sopenharmony_ci return; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, 67562306a36Sopenharmony_ci lu->tgt->node_id, lu->generation, device->max_speed, 67662306a36Sopenharmony_ci lu->command_block_agent_address + SBP2_AGENT_RESET, 67762306a36Sopenharmony_ci &d, 4, complete_agent_reset_write_no_wait, t); 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_cistatic inline void sbp2_allow_block(struct sbp2_target *tgt) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci spin_lock_irq(&tgt->lock); 68362306a36Sopenharmony_ci --tgt->dont_block; 68462306a36Sopenharmony_ci spin_unlock_irq(&tgt->lock); 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci/* 68862306a36Sopenharmony_ci * Blocks lu->tgt if all of the following conditions are met: 68962306a36Sopenharmony_ci * - Login, INQUIRY, and high-level SCSI setup of all of the target's 69062306a36Sopenharmony_ci * logical units have been finished (indicated by dont_block == 0). 69162306a36Sopenharmony_ci * - lu->generation is stale. 69262306a36Sopenharmony_ci * 69362306a36Sopenharmony_ci * Note, scsi_block_requests() must be called while holding tgt->lock, 69462306a36Sopenharmony_ci * otherwise it might foil sbp2_[conditionally_]unblock()'s attempt to 69562306a36Sopenharmony_ci * unblock the target. 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_cistatic void sbp2_conditionally_block(struct sbp2_logical_unit *lu) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci struct sbp2_target *tgt = lu->tgt; 70062306a36Sopenharmony_ci struct fw_card *card = target_parent_device(tgt)->card; 70162306a36Sopenharmony_ci struct Scsi_Host *shost = 70262306a36Sopenharmony_ci container_of((void *)tgt, struct Scsi_Host, hostdata[0]); 70362306a36Sopenharmony_ci unsigned long flags; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci spin_lock_irqsave(&tgt->lock, flags); 70662306a36Sopenharmony_ci if (!tgt->dont_block && !lu->blocked && 70762306a36Sopenharmony_ci lu->generation != card->generation) { 70862306a36Sopenharmony_ci lu->blocked = true; 70962306a36Sopenharmony_ci if (++tgt->blocked == 1) 71062306a36Sopenharmony_ci scsi_block_requests(shost); 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci spin_unlock_irqrestore(&tgt->lock, flags); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci/* 71662306a36Sopenharmony_ci * Unblocks lu->tgt as soon as all its logical units can be unblocked. 71762306a36Sopenharmony_ci * Note, it is harmless to run scsi_unblock_requests() outside the 71862306a36Sopenharmony_ci * tgt->lock protected section. On the other hand, running it inside 71962306a36Sopenharmony_ci * the section might clash with shost->host_lock. 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_cistatic void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci struct sbp2_target *tgt = lu->tgt; 72462306a36Sopenharmony_ci struct fw_card *card = target_parent_device(tgt)->card; 72562306a36Sopenharmony_ci struct Scsi_Host *shost = 72662306a36Sopenharmony_ci container_of((void *)tgt, struct Scsi_Host, hostdata[0]); 72762306a36Sopenharmony_ci bool unblock = false; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci spin_lock_irq(&tgt->lock); 73062306a36Sopenharmony_ci if (lu->blocked && lu->generation == card->generation) { 73162306a36Sopenharmony_ci lu->blocked = false; 73262306a36Sopenharmony_ci unblock = --tgt->blocked == 0; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci spin_unlock_irq(&tgt->lock); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci if (unblock) 73762306a36Sopenharmony_ci scsi_unblock_requests(shost); 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci/* 74162306a36Sopenharmony_ci * Prevents future blocking of tgt and unblocks it. 74262306a36Sopenharmony_ci * Note, it is harmless to run scsi_unblock_requests() outside the 74362306a36Sopenharmony_ci * tgt->lock protected section. On the other hand, running it inside 74462306a36Sopenharmony_ci * the section might clash with shost->host_lock. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_cistatic void sbp2_unblock(struct sbp2_target *tgt) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci struct Scsi_Host *shost = 74962306a36Sopenharmony_ci container_of((void *)tgt, struct Scsi_Host, hostdata[0]); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci spin_lock_irq(&tgt->lock); 75262306a36Sopenharmony_ci ++tgt->dont_block; 75362306a36Sopenharmony_ci spin_unlock_irq(&tgt->lock); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci scsi_unblock_requests(shost); 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_cistatic int sbp2_lun2int(u16 lun) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci struct scsi_lun eight_bytes_lun; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); 76362306a36Sopenharmony_ci eight_bytes_lun.scsi_lun[0] = (lun >> 8) & 0xff; 76462306a36Sopenharmony_ci eight_bytes_lun.scsi_lun[1] = lun & 0xff; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci return scsilun_to_int(&eight_bytes_lun); 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci/* 77062306a36Sopenharmony_ci * Write retransmit retry values into the BUSY_TIMEOUT register. 77162306a36Sopenharmony_ci * - The single-phase retry protocol is supported by all SBP-2 devices, but the 77262306a36Sopenharmony_ci * default retry_limit value is 0 (i.e. never retry transmission). We write a 77362306a36Sopenharmony_ci * saner value after logging into the device. 77462306a36Sopenharmony_ci * - The dual-phase retry protocol is optional to implement, and if not 77562306a36Sopenharmony_ci * supported, writes to the dual-phase portion of the register will be 77662306a36Sopenharmony_ci * ignored. We try to write the original 1394-1995 default here. 77762306a36Sopenharmony_ci * - In the case of devices that are also SBP-3-compliant, all writes are 77862306a36Sopenharmony_ci * ignored, as the register is read-only, but contains single-phase retry of 77962306a36Sopenharmony_ci * 15, which is what we're trying to set for all SBP-2 device anyway, so this 78062306a36Sopenharmony_ci * write attempt is safe and yields more consistent behavior for all devices. 78162306a36Sopenharmony_ci * 78262306a36Sopenharmony_ci * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec, 78362306a36Sopenharmony_ci * and section 6.4 of the SBP-3 spec for further details. 78462306a36Sopenharmony_ci */ 78562306a36Sopenharmony_cistatic void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 78862306a36Sopenharmony_ci __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, 79162306a36Sopenharmony_ci lu->tgt->node_id, lu->generation, device->max_speed, 79262306a36Sopenharmony_ci CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &d, 4); 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_cistatic void sbp2_reconnect(struct work_struct *work); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic void sbp2_login(struct work_struct *work) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct sbp2_logical_unit *lu = 80062306a36Sopenharmony_ci container_of(work, struct sbp2_logical_unit, work.work); 80162306a36Sopenharmony_ci struct sbp2_target *tgt = lu->tgt; 80262306a36Sopenharmony_ci struct fw_device *device = target_parent_device(tgt); 80362306a36Sopenharmony_ci struct Scsi_Host *shost; 80462306a36Sopenharmony_ci struct scsi_device *sdev; 80562306a36Sopenharmony_ci struct sbp2_login_response response; 80662306a36Sopenharmony_ci int generation, node_id, local_node_id; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci if (fw_device_is_shutdown(device)) 80962306a36Sopenharmony_ci return; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci generation = device->generation; 81262306a36Sopenharmony_ci smp_rmb(); /* node IDs must not be older than generation */ 81362306a36Sopenharmony_ci node_id = device->node_id; 81462306a36Sopenharmony_ci local_node_id = device->card->node_id; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* If this is a re-login attempt, log out, or we might be rejected. */ 81762306a36Sopenharmony_ci if (lu->has_sdev) 81862306a36Sopenharmony_ci sbp2_send_management_orb(lu, device->node_id, generation, 81962306a36Sopenharmony_ci SBP2_LOGOUT_REQUEST, lu->login_id, NULL); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci if (sbp2_send_management_orb(lu, node_id, generation, 82262306a36Sopenharmony_ci SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { 82362306a36Sopenharmony_ci if (lu->retries++ < 5) { 82462306a36Sopenharmony_ci sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); 82562306a36Sopenharmony_ci } else { 82662306a36Sopenharmony_ci dev_err(tgt_dev(tgt), "failed to login to LUN %04x\n", 82762306a36Sopenharmony_ci lu->lun); 82862306a36Sopenharmony_ci /* Let any waiting I/O fail from now on. */ 82962306a36Sopenharmony_ci sbp2_unblock(lu->tgt); 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci return; 83262306a36Sopenharmony_ci } 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci tgt->node_id = node_id; 83562306a36Sopenharmony_ci tgt->address_high = local_node_id << 16; 83662306a36Sopenharmony_ci smp_wmb(); /* node IDs must not be older than generation */ 83762306a36Sopenharmony_ci lu->generation = generation; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci lu->command_block_agent_address = 84062306a36Sopenharmony_ci ((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff) 84162306a36Sopenharmony_ci << 32) | be32_to_cpu(response.command_block_agent.low); 84262306a36Sopenharmony_ci lu->login_id = be32_to_cpu(response.misc) & 0xffff; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci dev_notice(tgt_dev(tgt), "logged in to LUN %04x (%d retries)\n", 84562306a36Sopenharmony_ci lu->lun, lu->retries); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* set appropriate retry limit(s) in BUSY_TIMEOUT register */ 84862306a36Sopenharmony_ci sbp2_set_busy_timeout(lu); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci lu->workfn = sbp2_reconnect; 85162306a36Sopenharmony_ci sbp2_agent_reset(lu); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci /* This was a re-login. */ 85462306a36Sopenharmony_ci if (lu->has_sdev) { 85562306a36Sopenharmony_ci sbp2_cancel_orbs(lu); 85662306a36Sopenharmony_ci sbp2_conditionally_unblock(lu); 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci return; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) 86262306a36Sopenharmony_ci ssleep(SBP2_INQUIRY_DELAY); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); 86562306a36Sopenharmony_ci sdev = __scsi_add_device(shost, 0, 0, sbp2_lun2int(lu->lun), lu); 86662306a36Sopenharmony_ci /* 86762306a36Sopenharmony_ci * FIXME: We are unable to perform reconnects while in sbp2_login(). 86862306a36Sopenharmony_ci * Therefore __scsi_add_device() will get into trouble if a bus reset 86962306a36Sopenharmony_ci * happens in parallel. It will either fail or leave us with an 87062306a36Sopenharmony_ci * unusable sdev. As a workaround we check for this and retry the 87162306a36Sopenharmony_ci * whole login and SCSI probing. 87262306a36Sopenharmony_ci */ 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci /* Reported error during __scsi_add_device() */ 87562306a36Sopenharmony_ci if (IS_ERR(sdev)) 87662306a36Sopenharmony_ci goto out_logout_login; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci /* Unreported error during __scsi_add_device() */ 87962306a36Sopenharmony_ci smp_rmb(); /* get current card generation */ 88062306a36Sopenharmony_ci if (generation != device->card->generation) { 88162306a36Sopenharmony_ci scsi_remove_device(sdev); 88262306a36Sopenharmony_ci scsi_device_put(sdev); 88362306a36Sopenharmony_ci goto out_logout_login; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci /* No error during __scsi_add_device() */ 88762306a36Sopenharmony_ci lu->has_sdev = true; 88862306a36Sopenharmony_ci scsi_device_put(sdev); 88962306a36Sopenharmony_ci sbp2_allow_block(tgt); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci out_logout_login: 89462306a36Sopenharmony_ci smp_rmb(); /* generation may have changed */ 89562306a36Sopenharmony_ci generation = device->generation; 89662306a36Sopenharmony_ci smp_rmb(); /* node_id must not be older than generation */ 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci sbp2_send_management_orb(lu, device->node_id, generation, 89962306a36Sopenharmony_ci SBP2_LOGOUT_REQUEST, lu->login_id, NULL); 90062306a36Sopenharmony_ci /* 90162306a36Sopenharmony_ci * If a bus reset happened, sbp2_update will have requeued 90262306a36Sopenharmony_ci * lu->work already. Reset the work from reconnect to login. 90362306a36Sopenharmony_ci */ 90462306a36Sopenharmony_ci lu->workfn = sbp2_login; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic void sbp2_reconnect(struct work_struct *work) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci struct sbp2_logical_unit *lu = 91062306a36Sopenharmony_ci container_of(work, struct sbp2_logical_unit, work.work); 91162306a36Sopenharmony_ci struct sbp2_target *tgt = lu->tgt; 91262306a36Sopenharmony_ci struct fw_device *device = target_parent_device(tgt); 91362306a36Sopenharmony_ci int generation, node_id, local_node_id; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci if (fw_device_is_shutdown(device)) 91662306a36Sopenharmony_ci return; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci generation = device->generation; 91962306a36Sopenharmony_ci smp_rmb(); /* node IDs must not be older than generation */ 92062306a36Sopenharmony_ci node_id = device->node_id; 92162306a36Sopenharmony_ci local_node_id = device->card->node_id; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (sbp2_send_management_orb(lu, node_id, generation, 92462306a36Sopenharmony_ci SBP2_RECONNECT_REQUEST, 92562306a36Sopenharmony_ci lu->login_id, NULL) < 0) { 92662306a36Sopenharmony_ci /* 92762306a36Sopenharmony_ci * If reconnect was impossible even though we are in the 92862306a36Sopenharmony_ci * current generation, fall back and try to log in again. 92962306a36Sopenharmony_ci * 93062306a36Sopenharmony_ci * We could check for "Function rejected" status, but 93162306a36Sopenharmony_ci * looking at the bus generation as simpler and more general. 93262306a36Sopenharmony_ci */ 93362306a36Sopenharmony_ci smp_rmb(); /* get current card generation */ 93462306a36Sopenharmony_ci if (generation == device->card->generation || 93562306a36Sopenharmony_ci lu->retries++ >= 5) { 93662306a36Sopenharmony_ci dev_err(tgt_dev(tgt), "failed to reconnect\n"); 93762306a36Sopenharmony_ci lu->retries = 0; 93862306a36Sopenharmony_ci lu->workfn = sbp2_login; 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci return; 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci tgt->node_id = node_id; 94662306a36Sopenharmony_ci tgt->address_high = local_node_id << 16; 94762306a36Sopenharmony_ci smp_wmb(); /* node IDs must not be older than generation */ 94862306a36Sopenharmony_ci lu->generation = generation; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci dev_notice(tgt_dev(tgt), "reconnected to LUN %04x (%d retries)\n", 95162306a36Sopenharmony_ci lu->lun, lu->retries); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci sbp2_agent_reset(lu); 95462306a36Sopenharmony_ci sbp2_cancel_orbs(lu); 95562306a36Sopenharmony_ci sbp2_conditionally_unblock(lu); 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic void sbp2_lu_workfn(struct work_struct *work) 95962306a36Sopenharmony_ci{ 96062306a36Sopenharmony_ci struct sbp2_logical_unit *lu = container_of(to_delayed_work(work), 96162306a36Sopenharmony_ci struct sbp2_logical_unit, work); 96262306a36Sopenharmony_ci lu->workfn(work); 96362306a36Sopenharmony_ci} 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_cistatic int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) 96662306a36Sopenharmony_ci{ 96762306a36Sopenharmony_ci struct sbp2_logical_unit *lu; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci lu = kmalloc(sizeof(*lu), GFP_KERNEL); 97062306a36Sopenharmony_ci if (!lu) 97162306a36Sopenharmony_ci return -ENOMEM; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci lu->address_handler.length = 0x100; 97462306a36Sopenharmony_ci lu->address_handler.address_callback = sbp2_status_write; 97562306a36Sopenharmony_ci lu->address_handler.callback_data = lu; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci if (fw_core_add_address_handler(&lu->address_handler, 97862306a36Sopenharmony_ci &fw_high_memory_region) < 0) { 97962306a36Sopenharmony_ci kfree(lu); 98062306a36Sopenharmony_ci return -ENOMEM; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci lu->tgt = tgt; 98462306a36Sopenharmony_ci lu->lun = lun_entry & 0xffff; 98562306a36Sopenharmony_ci lu->login_id = INVALID_LOGIN_ID; 98662306a36Sopenharmony_ci lu->retries = 0; 98762306a36Sopenharmony_ci lu->has_sdev = false; 98862306a36Sopenharmony_ci lu->blocked = false; 98962306a36Sopenharmony_ci ++tgt->dont_block; 99062306a36Sopenharmony_ci INIT_LIST_HEAD(&lu->orb_list); 99162306a36Sopenharmony_ci lu->workfn = sbp2_login; 99262306a36Sopenharmony_ci INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci list_add_tail(&lu->link, &tgt->lu_list); 99562306a36Sopenharmony_ci return 0; 99662306a36Sopenharmony_ci} 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_cistatic void sbp2_get_unit_unique_id(struct sbp2_target *tgt, 99962306a36Sopenharmony_ci const u32 *leaf) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci if ((leaf[0] & 0xffff0000) == 0x00020000) 100262306a36Sopenharmony_ci tgt->guid = (u64)leaf[1] << 32 | leaf[2]; 100362306a36Sopenharmony_ci} 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, 100662306a36Sopenharmony_ci const u32 *directory) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct fw_csr_iterator ci; 100962306a36Sopenharmony_ci int key, value; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci fw_csr_iterator_init(&ci, directory); 101262306a36Sopenharmony_ci while (fw_csr_iterator_next(&ci, &key, &value)) 101362306a36Sopenharmony_ci if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER && 101462306a36Sopenharmony_ci sbp2_add_logical_unit(tgt, value) < 0) 101562306a36Sopenharmony_ci return -ENOMEM; 101662306a36Sopenharmony_ci return 0; 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_cistatic int sbp2_scan_unit_dir(struct sbp2_target *tgt, const u32 *directory, 102062306a36Sopenharmony_ci u32 *model, u32 *firmware_revision) 102162306a36Sopenharmony_ci{ 102262306a36Sopenharmony_ci struct fw_csr_iterator ci; 102362306a36Sopenharmony_ci int key, value; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci fw_csr_iterator_init(&ci, directory); 102662306a36Sopenharmony_ci while (fw_csr_iterator_next(&ci, &key, &value)) { 102762306a36Sopenharmony_ci switch (key) { 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci case CSR_DEPENDENT_INFO | CSR_OFFSET: 103062306a36Sopenharmony_ci tgt->management_agent_address = 103162306a36Sopenharmony_ci CSR_REGISTER_BASE + 4 * value; 103262306a36Sopenharmony_ci break; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci case CSR_DIRECTORY_ID: 103562306a36Sopenharmony_ci tgt->directory_id = value; 103662306a36Sopenharmony_ci break; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci case CSR_MODEL: 103962306a36Sopenharmony_ci *model = value; 104062306a36Sopenharmony_ci break; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci case SBP2_CSR_FIRMWARE_REVISION: 104362306a36Sopenharmony_ci *firmware_revision = value; 104462306a36Sopenharmony_ci break; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci case SBP2_CSR_UNIT_CHARACTERISTICS: 104762306a36Sopenharmony_ci /* the timeout value is stored in 500ms units */ 104862306a36Sopenharmony_ci tgt->mgt_orb_timeout = (value >> 8 & 0xff) * 500; 104962306a36Sopenharmony_ci break; 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci case SBP2_CSR_LOGICAL_UNIT_NUMBER: 105262306a36Sopenharmony_ci if (sbp2_add_logical_unit(tgt, value) < 0) 105362306a36Sopenharmony_ci return -ENOMEM; 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci case SBP2_CSR_UNIT_UNIQUE_ID: 105762306a36Sopenharmony_ci sbp2_get_unit_unique_id(tgt, ci.p - 1 + value); 105862306a36Sopenharmony_ci break; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci case SBP2_CSR_LOGICAL_UNIT_DIRECTORY: 106162306a36Sopenharmony_ci /* Adjust for the increment in the iterator */ 106262306a36Sopenharmony_ci if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0) 106362306a36Sopenharmony_ci return -ENOMEM; 106462306a36Sopenharmony_ci break; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci } 106762306a36Sopenharmony_ci return 0; 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci/* 107162306a36Sopenharmony_ci * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be 107262306a36Sopenharmony_ci * provided in the config rom. Most devices do provide a value, which 107362306a36Sopenharmony_ci * we'll use for login management orbs, but with some sane limits. 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_cistatic void sbp2_clamp_management_orb_timeout(struct sbp2_target *tgt) 107662306a36Sopenharmony_ci{ 107762306a36Sopenharmony_ci unsigned int timeout = tgt->mgt_orb_timeout; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci if (timeout > 40000) 108062306a36Sopenharmony_ci dev_notice(tgt_dev(tgt), "%ds mgt_ORB_timeout limited to 40s\n", 108162306a36Sopenharmony_ci timeout / 1000); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci tgt->mgt_orb_timeout = clamp_val(timeout, 5000, 40000); 108462306a36Sopenharmony_ci} 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_cistatic void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, 108762306a36Sopenharmony_ci u32 firmware_revision) 108862306a36Sopenharmony_ci{ 108962306a36Sopenharmony_ci int i; 109062306a36Sopenharmony_ci unsigned int w = sbp2_param_workarounds; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (w) 109362306a36Sopenharmony_ci dev_notice(tgt_dev(tgt), 109462306a36Sopenharmony_ci "Please notify linux1394-devel@lists.sf.net " 109562306a36Sopenharmony_ci "if you need the workarounds parameter\n"); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci if (w & SBP2_WORKAROUND_OVERRIDE) 109862306a36Sopenharmony_ci goto out; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci if (sbp2_workarounds_table[i].firmware_revision != 110362306a36Sopenharmony_ci (firmware_revision & 0xffffff00)) 110462306a36Sopenharmony_ci continue; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci if (sbp2_workarounds_table[i].model != model && 110762306a36Sopenharmony_ci sbp2_workarounds_table[i].model != SBP2_ROM_VALUE_WILDCARD) 110862306a36Sopenharmony_ci continue; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci w |= sbp2_workarounds_table[i].workarounds; 111162306a36Sopenharmony_ci break; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci out: 111462306a36Sopenharmony_ci if (w) 111562306a36Sopenharmony_ci dev_notice(tgt_dev(tgt), "workarounds 0x%x " 111662306a36Sopenharmony_ci "(firmware_revision 0x%06x, model_id 0x%06x)\n", 111762306a36Sopenharmony_ci w, firmware_revision, model); 111862306a36Sopenharmony_ci tgt->workarounds = w; 111962306a36Sopenharmony_ci} 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_cistatic const struct scsi_host_template scsi_driver_template; 112262306a36Sopenharmony_cistatic void sbp2_remove(struct fw_unit *unit); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_cistatic int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 112562306a36Sopenharmony_ci{ 112662306a36Sopenharmony_ci struct fw_device *device = fw_parent_device(unit); 112762306a36Sopenharmony_ci struct sbp2_target *tgt; 112862306a36Sopenharmony_ci struct sbp2_logical_unit *lu; 112962306a36Sopenharmony_ci struct Scsi_Host *shost; 113062306a36Sopenharmony_ci u32 model, firmware_revision; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci /* cannot (or should not) handle targets on the local node */ 113362306a36Sopenharmony_ci if (device->is_local) 113462306a36Sopenharmony_ci return -ENODEV; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); 113762306a36Sopenharmony_ci if (shost == NULL) 113862306a36Sopenharmony_ci return -ENOMEM; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci tgt = (struct sbp2_target *)shost->hostdata; 114162306a36Sopenharmony_ci dev_set_drvdata(&unit->device, tgt); 114262306a36Sopenharmony_ci tgt->unit = unit; 114362306a36Sopenharmony_ci INIT_LIST_HEAD(&tgt->lu_list); 114462306a36Sopenharmony_ci spin_lock_init(&tgt->lock); 114562306a36Sopenharmony_ci tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci if (fw_device_enable_phys_dma(device) < 0) 114862306a36Sopenharmony_ci goto fail_shost_put; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci shost->max_cmd_len = SBP2_MAX_CDB_SIZE; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci if (scsi_add_host_with_dma(shost, &unit->device, 115362306a36Sopenharmony_ci device->card->device) < 0) 115462306a36Sopenharmony_ci goto fail_shost_put; 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* implicit directory ID */ 115762306a36Sopenharmony_ci tgt->directory_id = ((unit->directory - device->config_rom) * 4 115862306a36Sopenharmony_ci + CSR_CONFIG_ROM) & 0xffffff; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci firmware_revision = SBP2_ROM_VALUE_MISSING; 116162306a36Sopenharmony_ci model = SBP2_ROM_VALUE_MISSING; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci if (sbp2_scan_unit_dir(tgt, unit->directory, &model, 116462306a36Sopenharmony_ci &firmware_revision) < 0) 116562306a36Sopenharmony_ci goto fail_remove; 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci sbp2_clamp_management_orb_timeout(tgt); 116862306a36Sopenharmony_ci sbp2_init_workarounds(tgt, model, firmware_revision); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci /* 117162306a36Sopenharmony_ci * At S100 we can do 512 bytes per packet, at S200 1024 bytes, 117262306a36Sopenharmony_ci * and so on up to 4096 bytes. The SBP-2 max_payload field 117362306a36Sopenharmony_ci * specifies the max payload size as 2 ^ (max_payload + 2), so 117462306a36Sopenharmony_ci * if we set this to max_speed + 7, we get the right value. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_ci tgt->max_payload = min3(device->max_speed + 7, 10U, 117762306a36Sopenharmony_ci device->card->max_receive - 1); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci /* Do the login in a workqueue so we can easily reschedule retries. */ 118062306a36Sopenharmony_ci list_for_each_entry(lu, &tgt->lu_list, link) 118162306a36Sopenharmony_ci sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci return 0; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci fail_remove: 118662306a36Sopenharmony_ci sbp2_remove(unit); 118762306a36Sopenharmony_ci return -ENOMEM; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci fail_shost_put: 119062306a36Sopenharmony_ci scsi_host_put(shost); 119162306a36Sopenharmony_ci return -ENOMEM; 119262306a36Sopenharmony_ci} 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_cistatic void sbp2_update(struct fw_unit *unit) 119562306a36Sopenharmony_ci{ 119662306a36Sopenharmony_ci struct sbp2_target *tgt = dev_get_drvdata(&unit->device); 119762306a36Sopenharmony_ci struct sbp2_logical_unit *lu; 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci fw_device_enable_phys_dma(fw_parent_device(unit)); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci /* 120262306a36Sopenharmony_ci * Fw-core serializes sbp2_update() against sbp2_remove(). 120362306a36Sopenharmony_ci * Iteration over tgt->lu_list is therefore safe here. 120462306a36Sopenharmony_ci */ 120562306a36Sopenharmony_ci list_for_each_entry(lu, &tgt->lu_list, link) { 120662306a36Sopenharmony_ci sbp2_conditionally_block(lu); 120762306a36Sopenharmony_ci lu->retries = 0; 120862306a36Sopenharmony_ci sbp2_queue_work(lu, 0); 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci} 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_cistatic void sbp2_remove(struct fw_unit *unit) 121362306a36Sopenharmony_ci{ 121462306a36Sopenharmony_ci struct fw_device *device = fw_parent_device(unit); 121562306a36Sopenharmony_ci struct sbp2_target *tgt = dev_get_drvdata(&unit->device); 121662306a36Sopenharmony_ci struct sbp2_logical_unit *lu, *next; 121762306a36Sopenharmony_ci struct Scsi_Host *shost = 121862306a36Sopenharmony_ci container_of((void *)tgt, struct Scsi_Host, hostdata[0]); 121962306a36Sopenharmony_ci struct scsi_device *sdev; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci /* prevent deadlocks */ 122262306a36Sopenharmony_ci sbp2_unblock(tgt); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { 122562306a36Sopenharmony_ci cancel_delayed_work_sync(&lu->work); 122662306a36Sopenharmony_ci sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun)); 122762306a36Sopenharmony_ci if (sdev) { 122862306a36Sopenharmony_ci scsi_remove_device(sdev); 122962306a36Sopenharmony_ci scsi_device_put(sdev); 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci if (lu->login_id != INVALID_LOGIN_ID) { 123262306a36Sopenharmony_ci int generation, node_id; 123362306a36Sopenharmony_ci /* 123462306a36Sopenharmony_ci * tgt->node_id may be obsolete here if we failed 123562306a36Sopenharmony_ci * during initial login or after a bus reset where 123662306a36Sopenharmony_ci * the topology changed. 123762306a36Sopenharmony_ci */ 123862306a36Sopenharmony_ci generation = device->generation; 123962306a36Sopenharmony_ci smp_rmb(); /* node_id vs. generation */ 124062306a36Sopenharmony_ci node_id = device->node_id; 124162306a36Sopenharmony_ci sbp2_send_management_orb(lu, node_id, generation, 124262306a36Sopenharmony_ci SBP2_LOGOUT_REQUEST, 124362306a36Sopenharmony_ci lu->login_id, NULL); 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci fw_core_remove_address_handler(&lu->address_handler); 124662306a36Sopenharmony_ci list_del(&lu->link); 124762306a36Sopenharmony_ci kfree(lu); 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci scsi_remove_host(shost); 125062306a36Sopenharmony_ci dev_notice(&unit->device, "released target %d:0:0\n", shost->host_no); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci scsi_host_put(shost); 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e 125662306a36Sopenharmony_ci#define SBP2_SW_VERSION_ENTRY 0x00010483 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_cistatic const struct ieee1394_device_id sbp2_id_table[] = { 125962306a36Sopenharmony_ci { 126062306a36Sopenharmony_ci .match_flags = IEEE1394_MATCH_SPECIFIER_ID | 126162306a36Sopenharmony_ci IEEE1394_MATCH_VERSION, 126262306a36Sopenharmony_ci .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY, 126362306a36Sopenharmony_ci .version = SBP2_SW_VERSION_ENTRY, 126462306a36Sopenharmony_ci }, 126562306a36Sopenharmony_ci { } 126662306a36Sopenharmony_ci}; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_cistatic struct fw_driver sbp2_driver = { 126962306a36Sopenharmony_ci .driver = { 127062306a36Sopenharmony_ci .owner = THIS_MODULE, 127162306a36Sopenharmony_ci .name = KBUILD_MODNAME, 127262306a36Sopenharmony_ci .bus = &fw_bus_type, 127362306a36Sopenharmony_ci }, 127462306a36Sopenharmony_ci .probe = sbp2_probe, 127562306a36Sopenharmony_ci .update = sbp2_update, 127662306a36Sopenharmony_ci .remove = sbp2_remove, 127762306a36Sopenharmony_ci .id_table = sbp2_id_table, 127862306a36Sopenharmony_ci}; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_cistatic void sbp2_unmap_scatterlist(struct device *card_device, 128162306a36Sopenharmony_ci struct sbp2_command_orb *orb) 128262306a36Sopenharmony_ci{ 128362306a36Sopenharmony_ci scsi_dma_unmap(orb->cmd); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT)) 128662306a36Sopenharmony_ci dma_unmap_single(card_device, orb->page_table_bus, 128762306a36Sopenharmony_ci sizeof(orb->page_table), DMA_TO_DEVICE); 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_cistatic unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) 129162306a36Sopenharmony_ci{ 129262306a36Sopenharmony_ci int sam_status; 129362306a36Sopenharmony_ci int sfmt = (sbp2_status[0] >> 6) & 0x03; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci if (sfmt == 2 || sfmt == 3) { 129662306a36Sopenharmony_ci /* 129762306a36Sopenharmony_ci * Reserved for future standardization (2) or 129862306a36Sopenharmony_ci * Status block format vendor-dependent (3) 129962306a36Sopenharmony_ci */ 130062306a36Sopenharmony_ci return DID_ERROR << 16; 130162306a36Sopenharmony_ci } 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci sense_data[0] = 0x70 | sfmt | (sbp2_status[1] & 0x80); 130462306a36Sopenharmony_ci sense_data[1] = 0x0; 130562306a36Sopenharmony_ci sense_data[2] = ((sbp2_status[1] << 1) & 0xe0) | (sbp2_status[1] & 0x0f); 130662306a36Sopenharmony_ci sense_data[3] = sbp2_status[4]; 130762306a36Sopenharmony_ci sense_data[4] = sbp2_status[5]; 130862306a36Sopenharmony_ci sense_data[5] = sbp2_status[6]; 130962306a36Sopenharmony_ci sense_data[6] = sbp2_status[7]; 131062306a36Sopenharmony_ci sense_data[7] = 10; 131162306a36Sopenharmony_ci sense_data[8] = sbp2_status[8]; 131262306a36Sopenharmony_ci sense_data[9] = sbp2_status[9]; 131362306a36Sopenharmony_ci sense_data[10] = sbp2_status[10]; 131462306a36Sopenharmony_ci sense_data[11] = sbp2_status[11]; 131562306a36Sopenharmony_ci sense_data[12] = sbp2_status[2]; 131662306a36Sopenharmony_ci sense_data[13] = sbp2_status[3]; 131762306a36Sopenharmony_ci sense_data[14] = sbp2_status[12]; 131862306a36Sopenharmony_ci sense_data[15] = sbp2_status[13]; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci sam_status = sbp2_status[0] & 0x3f; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci switch (sam_status) { 132362306a36Sopenharmony_ci case SAM_STAT_GOOD: 132462306a36Sopenharmony_ci case SAM_STAT_CHECK_CONDITION: 132562306a36Sopenharmony_ci case SAM_STAT_CONDITION_MET: 132662306a36Sopenharmony_ci case SAM_STAT_BUSY: 132762306a36Sopenharmony_ci case SAM_STAT_RESERVATION_CONFLICT: 132862306a36Sopenharmony_ci case SAM_STAT_COMMAND_TERMINATED: 132962306a36Sopenharmony_ci return DID_OK << 16 | sam_status; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci default: 133262306a36Sopenharmony_ci return DID_ERROR << 16; 133362306a36Sopenharmony_ci } 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_cistatic void complete_command_orb(struct sbp2_orb *base_orb, 133762306a36Sopenharmony_ci struct sbp2_status *status) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci struct sbp2_command_orb *orb = 134062306a36Sopenharmony_ci container_of(base_orb, struct sbp2_command_orb, base); 134162306a36Sopenharmony_ci struct fw_device *device = target_parent_device(base_orb->lu->tgt); 134262306a36Sopenharmony_ci int result; 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci if (status != NULL) { 134562306a36Sopenharmony_ci if (STATUS_GET_DEAD(*status)) 134662306a36Sopenharmony_ci sbp2_agent_reset_no_wait(base_orb->lu); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci switch (STATUS_GET_RESPONSE(*status)) { 134962306a36Sopenharmony_ci case SBP2_STATUS_REQUEST_COMPLETE: 135062306a36Sopenharmony_ci result = DID_OK << 16; 135162306a36Sopenharmony_ci break; 135262306a36Sopenharmony_ci case SBP2_STATUS_TRANSPORT_FAILURE: 135362306a36Sopenharmony_ci result = DID_BUS_BUSY << 16; 135462306a36Sopenharmony_ci break; 135562306a36Sopenharmony_ci case SBP2_STATUS_ILLEGAL_REQUEST: 135662306a36Sopenharmony_ci case SBP2_STATUS_VENDOR_DEPENDENT: 135762306a36Sopenharmony_ci default: 135862306a36Sopenharmony_ci result = DID_ERROR << 16; 135962306a36Sopenharmony_ci break; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci if (result == DID_OK << 16 && STATUS_GET_LEN(*status) > 1) 136362306a36Sopenharmony_ci result = sbp2_status_to_sense_data(STATUS_GET_DATA(*status), 136462306a36Sopenharmony_ci orb->cmd->sense_buffer); 136562306a36Sopenharmony_ci } else { 136662306a36Sopenharmony_ci /* 136762306a36Sopenharmony_ci * If the orb completes with status == NULL, something 136862306a36Sopenharmony_ci * went wrong, typically a bus reset happened mid-orb 136962306a36Sopenharmony_ci * or when sending the write (less likely). 137062306a36Sopenharmony_ci */ 137162306a36Sopenharmony_ci result = DID_BUS_BUSY << 16; 137262306a36Sopenharmony_ci sbp2_conditionally_block(base_orb->lu); 137362306a36Sopenharmony_ci } 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci dma_unmap_single(device->card->device, orb->base.request_bus, 137662306a36Sopenharmony_ci sizeof(orb->request), DMA_TO_DEVICE); 137762306a36Sopenharmony_ci sbp2_unmap_scatterlist(device->card->device, orb); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci orb->cmd->result = result; 138062306a36Sopenharmony_ci scsi_done(orb->cmd); 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic int sbp2_map_scatterlist(struct sbp2_command_orb *orb, 138462306a36Sopenharmony_ci struct fw_device *device, struct sbp2_logical_unit *lu) 138562306a36Sopenharmony_ci{ 138662306a36Sopenharmony_ci struct scatterlist *sg = scsi_sglist(orb->cmd); 138762306a36Sopenharmony_ci int i, n; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci n = scsi_dma_map(orb->cmd); 139062306a36Sopenharmony_ci if (n <= 0) 139162306a36Sopenharmony_ci goto fail; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci /* 139462306a36Sopenharmony_ci * Handle the special case where there is only one element in 139562306a36Sopenharmony_ci * the scatter list by converting it to an immediate block 139662306a36Sopenharmony_ci * request. This is also a workaround for broken devices such 139762306a36Sopenharmony_ci * as the second generation iPod which doesn't support page 139862306a36Sopenharmony_ci * tables. 139962306a36Sopenharmony_ci */ 140062306a36Sopenharmony_ci if (n == 1) { 140162306a36Sopenharmony_ci orb->request.data_descriptor.high = 140262306a36Sopenharmony_ci cpu_to_be32(lu->tgt->address_high); 140362306a36Sopenharmony_ci orb->request.data_descriptor.low = 140462306a36Sopenharmony_ci cpu_to_be32(sg_dma_address(sg)); 140562306a36Sopenharmony_ci orb->request.misc |= 140662306a36Sopenharmony_ci cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg))); 140762306a36Sopenharmony_ci return 0; 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci for_each_sg(sg, sg, n, i) { 141162306a36Sopenharmony_ci orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16); 141262306a36Sopenharmony_ci orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg)); 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci orb->page_table_bus = 141662306a36Sopenharmony_ci dma_map_single(device->card->device, orb->page_table, 141762306a36Sopenharmony_ci sizeof(orb->page_table), DMA_TO_DEVICE); 141862306a36Sopenharmony_ci if (dma_mapping_error(device->card->device, orb->page_table_bus)) 141962306a36Sopenharmony_ci goto fail_page_table; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci /* 142262306a36Sopenharmony_ci * The data_descriptor pointer is the one case where we need 142362306a36Sopenharmony_ci * to fill in the node ID part of the address. All other 142462306a36Sopenharmony_ci * pointers assume that the data referenced reside on the 142562306a36Sopenharmony_ci * initiator (i.e. us), but data_descriptor can refer to data 142662306a36Sopenharmony_ci * on other nodes so we need to put our ID in descriptor.high. 142762306a36Sopenharmony_ci */ 142862306a36Sopenharmony_ci orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high); 142962306a36Sopenharmony_ci orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus); 143062306a36Sopenharmony_ci orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT | 143162306a36Sopenharmony_ci COMMAND_ORB_DATA_SIZE(n)); 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci return 0; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci fail_page_table: 143662306a36Sopenharmony_ci scsi_dma_unmap(orb->cmd); 143762306a36Sopenharmony_ci fail: 143862306a36Sopenharmony_ci return -ENOMEM; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci/* SCSI stack integration */ 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_cistatic int sbp2_scsi_queuecommand(struct Scsi_Host *shost, 144462306a36Sopenharmony_ci struct scsi_cmnd *cmd) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci struct sbp2_logical_unit *lu = cmd->device->hostdata; 144762306a36Sopenharmony_ci struct fw_device *device = target_parent_device(lu->tgt); 144862306a36Sopenharmony_ci struct sbp2_command_orb *orb; 144962306a36Sopenharmony_ci int generation, retval = SCSI_MLQUEUE_HOST_BUSY; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci orb = kzalloc(sizeof(*orb), GFP_ATOMIC); 145262306a36Sopenharmony_ci if (orb == NULL) 145362306a36Sopenharmony_ci return SCSI_MLQUEUE_HOST_BUSY; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* Initialize rcode to something not RCODE_COMPLETE. */ 145662306a36Sopenharmony_ci orb->base.rcode = -1; 145762306a36Sopenharmony_ci kref_init(&orb->base.kref); 145862306a36Sopenharmony_ci orb->cmd = cmd; 145962306a36Sopenharmony_ci orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL); 146062306a36Sopenharmony_ci orb->request.misc = cpu_to_be32( 146162306a36Sopenharmony_ci COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) | 146262306a36Sopenharmony_ci COMMAND_ORB_SPEED(device->max_speed) | 146362306a36Sopenharmony_ci COMMAND_ORB_NOTIFY); 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci if (cmd->sc_data_direction == DMA_FROM_DEVICE) 146662306a36Sopenharmony_ci orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION); 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci generation = device->generation; 146962306a36Sopenharmony_ci smp_rmb(); /* sbp2_map_scatterlist looks at tgt->address_high */ 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0) 147262306a36Sopenharmony_ci goto out; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len); 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci orb->base.callback = complete_command_orb; 147762306a36Sopenharmony_ci orb->base.request_bus = 147862306a36Sopenharmony_ci dma_map_single(device->card->device, &orb->request, 147962306a36Sopenharmony_ci sizeof(orb->request), DMA_TO_DEVICE); 148062306a36Sopenharmony_ci if (dma_mapping_error(device->card->device, orb->base.request_bus)) { 148162306a36Sopenharmony_ci sbp2_unmap_scatterlist(device->card->device, orb); 148262306a36Sopenharmony_ci goto out; 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation, 148662306a36Sopenharmony_ci lu->command_block_agent_address + SBP2_ORB_POINTER); 148762306a36Sopenharmony_ci retval = 0; 148862306a36Sopenharmony_ci out: 148962306a36Sopenharmony_ci kref_put(&orb->base.kref, free_orb); 149062306a36Sopenharmony_ci return retval; 149162306a36Sopenharmony_ci} 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_cistatic int sbp2_scsi_slave_alloc(struct scsi_device *sdev) 149462306a36Sopenharmony_ci{ 149562306a36Sopenharmony_ci struct sbp2_logical_unit *lu = sdev->hostdata; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci /* (Re-)Adding logical units via the SCSI stack is not supported. */ 149862306a36Sopenharmony_ci if (!lu) 149962306a36Sopenharmony_ci return -ENOSYS; 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci sdev->allow_restart = 1; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci /* 150462306a36Sopenharmony_ci * SBP-2 does not require any alignment, but we set it anyway 150562306a36Sopenharmony_ci * for compatibility with earlier versions of this driver. 150662306a36Sopenharmony_ci */ 150762306a36Sopenharmony_ci blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1); 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36) 151062306a36Sopenharmony_ci sdev->inquiry_len = 36; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci return 0; 151362306a36Sopenharmony_ci} 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_cistatic int sbp2_scsi_slave_configure(struct scsi_device *sdev) 151662306a36Sopenharmony_ci{ 151762306a36Sopenharmony_ci struct sbp2_logical_unit *lu = sdev->hostdata; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci sdev->use_10_for_rw = 1; 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci if (sbp2_param_exclusive_login) { 152262306a36Sopenharmony_ci sdev->manage_system_start_stop = 1; 152362306a36Sopenharmony_ci sdev->manage_runtime_start_stop = 1; 152462306a36Sopenharmony_ci sdev->manage_shutdown = 1; 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci if (sdev->type == TYPE_ROM) 152862306a36Sopenharmony_ci sdev->use_10_for_ms = 1; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci if (sdev->type == TYPE_DISK && 153162306a36Sopenharmony_ci lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) 153262306a36Sopenharmony_ci sdev->skip_ms_page_8 = 1; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) 153562306a36Sopenharmony_ci sdev->fix_capacity = 1; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci if (lu->tgt->workarounds & SBP2_WORKAROUND_POWER_CONDITION) 153862306a36Sopenharmony_ci sdev->start_stop_pwr_cond = 1; 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) 154162306a36Sopenharmony_ci blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci return 0; 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci/* 154762306a36Sopenharmony_ci * Called by scsi stack when something has really gone wrong. Usually 154862306a36Sopenharmony_ci * called when a command has timed-out for some reason. 154962306a36Sopenharmony_ci */ 155062306a36Sopenharmony_cistatic int sbp2_scsi_abort(struct scsi_cmnd *cmd) 155162306a36Sopenharmony_ci{ 155262306a36Sopenharmony_ci struct sbp2_logical_unit *lu = cmd->device->hostdata; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci dev_notice(lu_dev(lu), "sbp2_scsi_abort\n"); 155562306a36Sopenharmony_ci sbp2_agent_reset(lu); 155662306a36Sopenharmony_ci sbp2_cancel_orbs(lu); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci return SUCCESS; 155962306a36Sopenharmony_ci} 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci/* 156262306a36Sopenharmony_ci * Format of /sys/bus/scsi/devices/.../ieee1394_id: 156362306a36Sopenharmony_ci * u64 EUI-64 : u24 directory_ID : u16 LUN (all printed in hexadecimal) 156462306a36Sopenharmony_ci * 156562306a36Sopenharmony_ci * This is the concatenation of target port identifier and logical unit 156662306a36Sopenharmony_ci * identifier as per SAM-2...SAM-4 annex A. 156762306a36Sopenharmony_ci */ 156862306a36Sopenharmony_cistatic ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, 156962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 157062306a36Sopenharmony_ci{ 157162306a36Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(dev); 157262306a36Sopenharmony_ci struct sbp2_logical_unit *lu; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci if (!sdev) 157562306a36Sopenharmony_ci return 0; 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci lu = sdev->hostdata; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci return sprintf(buf, "%016llx:%06x:%04x\n", 158062306a36Sopenharmony_ci (unsigned long long)lu->tgt->guid, 158162306a36Sopenharmony_ci lu->tgt->directory_id, lu->lun); 158262306a36Sopenharmony_ci} 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_cistatic DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_cistatic struct attribute *sbp2_scsi_sysfs_attrs[] = { 158762306a36Sopenharmony_ci &dev_attr_ieee1394_id.attr, 158862306a36Sopenharmony_ci NULL 158962306a36Sopenharmony_ci}; 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ciATTRIBUTE_GROUPS(sbp2_scsi_sysfs); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_cistatic const struct scsi_host_template scsi_driver_template = { 159462306a36Sopenharmony_ci .module = THIS_MODULE, 159562306a36Sopenharmony_ci .name = "SBP-2 IEEE-1394", 159662306a36Sopenharmony_ci .proc_name = "sbp2", 159762306a36Sopenharmony_ci .queuecommand = sbp2_scsi_queuecommand, 159862306a36Sopenharmony_ci .slave_alloc = sbp2_scsi_slave_alloc, 159962306a36Sopenharmony_ci .slave_configure = sbp2_scsi_slave_configure, 160062306a36Sopenharmony_ci .eh_abort_handler = sbp2_scsi_abort, 160162306a36Sopenharmony_ci .this_id = -1, 160262306a36Sopenharmony_ci .sg_tablesize = SG_ALL, 160362306a36Sopenharmony_ci .max_segment_size = SBP2_MAX_SEG_SIZE, 160462306a36Sopenharmony_ci .can_queue = 1, 160562306a36Sopenharmony_ci .sdev_groups = sbp2_scsi_sysfs_groups, 160662306a36Sopenharmony_ci}; 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ciMODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); 160962306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI over IEEE1394"); 161062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 161162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci/* Provide a module alias so root-on-sbp2 initrds don't break. */ 161462306a36Sopenharmony_ciMODULE_ALIAS("sbp2"); 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_cistatic int __init sbp2_init(void) 161762306a36Sopenharmony_ci{ 161862306a36Sopenharmony_ci return driver_register(&sbp2_driver.driver); 161962306a36Sopenharmony_ci} 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_cistatic void __exit sbp2_cleanup(void) 162262306a36Sopenharmony_ci{ 162362306a36Sopenharmony_ci driver_unregister(&sbp2_driver.driver); 162462306a36Sopenharmony_ci} 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_cimodule_init(sbp2_init); 162762306a36Sopenharmony_cimodule_exit(sbp2_cleanup); 1628