18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * SBP2 driver (SCSI over IEEE1394)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007  Kristian Hoegsberg <krh@bitplanet.net>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * The basic structure of this driver is based on the old storage driver,
108c2ecf20Sopenharmony_ci * drivers/ieee1394/sbp2.c, originally written by
118c2ecf20Sopenharmony_ci *     James Goodwin <jamesg@filanet.com>
128c2ecf20Sopenharmony_ci * with later contributions and ongoing maintenance from
138c2ecf20Sopenharmony_ci *     Ben Collins <bcollins@debian.org>,
148c2ecf20Sopenharmony_ci *     Stefan Richter <stefanr@s5r6.in-berlin.de>
158c2ecf20Sopenharmony_ci * and many others.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
198c2ecf20Sopenharmony_ci#include <linux/bug.h>
208c2ecf20Sopenharmony_ci#include <linux/completion.h>
218c2ecf20Sopenharmony_ci#include <linux/delay.h>
228c2ecf20Sopenharmony_ci#include <linux/device.h>
238c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
248c2ecf20Sopenharmony_ci#include <linux/firewire.h>
258c2ecf20Sopenharmony_ci#include <linux/firewire-constants.h>
268c2ecf20Sopenharmony_ci#include <linux/init.h>
278c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
288c2ecf20Sopenharmony_ci#include <linux/kernel.h>
298c2ecf20Sopenharmony_ci#include <linux/kref.h>
308c2ecf20Sopenharmony_ci#include <linux/list.h>
318c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
328c2ecf20Sopenharmony_ci#include <linux/module.h>
338c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
348c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
358c2ecf20Sopenharmony_ci#include <linux/slab.h>
368c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
378c2ecf20Sopenharmony_ci#include <linux/string.h>
388c2ecf20Sopenharmony_ci#include <linux/stringify.h>
398c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#include <scsi/scsi.h>
448c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h>
458c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h>
468c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h>
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/*
498c2ecf20Sopenharmony_ci * So far only bridges from Oxford Semiconductor are known to support
508c2ecf20Sopenharmony_ci * concurrent logins. Depending on firmware, four or two concurrent logins
518c2ecf20Sopenharmony_ci * are possible on OXFW911 and newer Oxsemi bridges.
528c2ecf20Sopenharmony_ci *
538c2ecf20Sopenharmony_ci * Concurrent logins are useful together with cluster filesystems.
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_cistatic bool sbp2_param_exclusive_login = 1;
568c2ecf20Sopenharmony_cimodule_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
578c2ecf20Sopenharmony_ciMODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
588c2ecf20Sopenharmony_ci		 "(default = Y, use N for concurrent initiators)");
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/*
618c2ecf20Sopenharmony_ci * Flags for firmware oddities
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * - 128kB max transfer
648c2ecf20Sopenharmony_ci *   Limit transfer size. Necessary for some old bridges.
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci * - 36 byte inquiry
678c2ecf20Sopenharmony_ci *   When scsi_mod probes the device, let the inquiry command look like that
688c2ecf20Sopenharmony_ci *   from MS Windows.
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * - skip mode page 8
718c2ecf20Sopenharmony_ci *   Suppress sending of mode_sense for mode page 8 if the device pretends to
728c2ecf20Sopenharmony_ci *   support the SCSI Primary Block commands instead of Reduced Block Commands.
738c2ecf20Sopenharmony_ci *
748c2ecf20Sopenharmony_ci * - fix capacity
758c2ecf20Sopenharmony_ci *   Tell sd_mod to correct the last sector number reported by read_capacity.
768c2ecf20Sopenharmony_ci *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
778c2ecf20Sopenharmony_ci *   Don't use this with devices which don't have this bug.
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * - delay inquiry
808c2ecf20Sopenharmony_ci *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
818c2ecf20Sopenharmony_ci *
828c2ecf20Sopenharmony_ci * - power condition
838c2ecf20Sopenharmony_ci *   Set the power condition field in the START STOP UNIT commands sent by
848c2ecf20Sopenharmony_ci *   sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
858c2ecf20Sopenharmony_ci *   Some disks need this to spin down or to resume properly.
868c2ecf20Sopenharmony_ci *
878c2ecf20Sopenharmony_ci * - override internal blacklist
888c2ecf20Sopenharmony_ci *   Instead of adding to the built-in blacklist, use only the workarounds
898c2ecf20Sopenharmony_ci *   specified in the module load parameter.
908c2ecf20Sopenharmony_ci *   Useful if a blacklist entry interfered with a non-broken device.
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_128K_MAX_TRANS	0x1
938c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_INQUIRY_36	0x2
948c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_MODE_SENSE_8	0x4
958c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_FIX_CAPACITY	0x8
968c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_DELAY_INQUIRY	0x10
978c2ecf20Sopenharmony_ci#define SBP2_INQUIRY_DELAY		12
988c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_POWER_CONDITION	0x20
998c2ecf20Sopenharmony_ci#define SBP2_WORKAROUND_OVERRIDE	0x100
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic int sbp2_param_workarounds;
1028c2ecf20Sopenharmony_cimodule_param_named(workarounds, sbp2_param_workarounds, int, 0644);
1038c2ecf20Sopenharmony_ciMODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
1048c2ecf20Sopenharmony_ci	", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
1058c2ecf20Sopenharmony_ci	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
1068c2ecf20Sopenharmony_ci	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
1078c2ecf20Sopenharmony_ci	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
1088c2ecf20Sopenharmony_ci	", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
1098c2ecf20Sopenharmony_ci	", set power condition in start stop unit = "
1108c2ecf20Sopenharmony_ci				  __stringify(SBP2_WORKAROUND_POWER_CONDITION)
1118c2ecf20Sopenharmony_ci	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
1128c2ecf20Sopenharmony_ci	", or a combination)");
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci/*
1158c2ecf20Sopenharmony_ci * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry
1168c2ecf20Sopenharmony_ci * and one struct scsi_device per sbp2_logical_unit.
1178c2ecf20Sopenharmony_ci */
1188c2ecf20Sopenharmony_cistruct sbp2_logical_unit {
1198c2ecf20Sopenharmony_ci	struct sbp2_target *tgt;
1208c2ecf20Sopenharmony_ci	struct list_head link;
1218c2ecf20Sopenharmony_ci	struct fw_address_handler address_handler;
1228c2ecf20Sopenharmony_ci	struct list_head orb_list;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	u64 command_block_agent_address;
1258c2ecf20Sopenharmony_ci	u16 lun;
1268c2ecf20Sopenharmony_ci	int login_id;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/*
1298c2ecf20Sopenharmony_ci	 * The generation is updated once we've logged in or reconnected
1308c2ecf20Sopenharmony_ci	 * to the logical unit.  Thus, I/O to the device will automatically
1318c2ecf20Sopenharmony_ci	 * fail and get retried if it happens in a window where the device
1328c2ecf20Sopenharmony_ci	 * is not ready, e.g. after a bus reset but before we reconnect.
1338c2ecf20Sopenharmony_ci	 */
1348c2ecf20Sopenharmony_ci	int generation;
1358c2ecf20Sopenharmony_ci	int retries;
1368c2ecf20Sopenharmony_ci	work_func_t workfn;
1378c2ecf20Sopenharmony_ci	struct delayed_work work;
1388c2ecf20Sopenharmony_ci	bool has_sdev;
1398c2ecf20Sopenharmony_ci	bool blocked;
1408c2ecf20Sopenharmony_ci};
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	queue_delayed_work(fw_workqueue, &lu->work, delay);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci/*
1488c2ecf20Sopenharmony_ci * We create one struct sbp2_target per IEEE 1212 Unit Directory
1498c2ecf20Sopenharmony_ci * and one struct Scsi_Host per sbp2_target.
1508c2ecf20Sopenharmony_ci */
1518c2ecf20Sopenharmony_cistruct sbp2_target {
1528c2ecf20Sopenharmony_ci	struct fw_unit *unit;
1538c2ecf20Sopenharmony_ci	struct list_head lu_list;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	u64 management_agent_address;
1568c2ecf20Sopenharmony_ci	u64 guid;
1578c2ecf20Sopenharmony_ci	int directory_id;
1588c2ecf20Sopenharmony_ci	int node_id;
1598c2ecf20Sopenharmony_ci	int address_high;
1608c2ecf20Sopenharmony_ci	unsigned int workarounds;
1618c2ecf20Sopenharmony_ci	unsigned int mgt_orb_timeout;
1628c2ecf20Sopenharmony_ci	unsigned int max_payload;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	spinlock_t lock;
1658c2ecf20Sopenharmony_ci	int dont_block;	/* counter for each logical unit */
1668c2ecf20Sopenharmony_ci	int blocked;	/* ditto */
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic struct fw_device *target_parent_device(struct sbp2_target *tgt)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	return fw_parent_device(tgt->unit);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic const struct device *tgt_dev(const struct sbp2_target *tgt)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	return &tgt->unit->device;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic const struct device *lu_dev(const struct sbp2_logical_unit *lu)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	return &lu->tgt->unit->device;
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci/* Impossible login_id, to detect logout attempt before successful login */
1858c2ecf20Sopenharmony_ci#define INVALID_LOGIN_ID 0x10000
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci#define SBP2_ORB_TIMEOUT		2000U		/* Timeout in ms */
1888c2ecf20Sopenharmony_ci#define SBP2_ORB_NULL			0x80000000
1898c2ecf20Sopenharmony_ci#define SBP2_RETRY_LIMIT		0xf		/* 15 retries */
1908c2ecf20Sopenharmony_ci#define SBP2_CYCLE_LIMIT		(0xc8 << 12)	/* 200 125us cycles */
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/*
1938c2ecf20Sopenharmony_ci * There is no transport protocol limit to the CDB length,  but we implement
1948c2ecf20Sopenharmony_ci * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
1958c2ecf20Sopenharmony_ci */
1968c2ecf20Sopenharmony_ci#define SBP2_MAX_CDB_SIZE		16
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/*
1998c2ecf20Sopenharmony_ci * The maximum SBP-2 data buffer size is 0xffff.  We quadlet-align this
2008c2ecf20Sopenharmony_ci * for compatibility with earlier versions of this driver.
2018c2ecf20Sopenharmony_ci */
2028c2ecf20Sopenharmony_ci#define SBP2_MAX_SEG_SIZE		0xfffc
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci/* Unit directory keys */
2058c2ecf20Sopenharmony_ci#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
2068c2ecf20Sopenharmony_ci#define SBP2_CSR_FIRMWARE_REVISION	0x3c
2078c2ecf20Sopenharmony_ci#define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
2088c2ecf20Sopenharmony_ci#define SBP2_CSR_UNIT_UNIQUE_ID		0x8d
2098c2ecf20Sopenharmony_ci#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci/* Management orb opcodes */
2128c2ecf20Sopenharmony_ci#define SBP2_LOGIN_REQUEST		0x0
2138c2ecf20Sopenharmony_ci#define SBP2_QUERY_LOGINS_REQUEST	0x1
2148c2ecf20Sopenharmony_ci#define SBP2_RECONNECT_REQUEST		0x3
2158c2ecf20Sopenharmony_ci#define SBP2_SET_PASSWORD_REQUEST	0x4
2168c2ecf20Sopenharmony_ci#define SBP2_LOGOUT_REQUEST		0x7
2178c2ecf20Sopenharmony_ci#define SBP2_ABORT_TASK_REQUEST		0xb
2188c2ecf20Sopenharmony_ci#define SBP2_ABORT_TASK_SET		0xc
2198c2ecf20Sopenharmony_ci#define SBP2_LOGICAL_UNIT_RESET		0xe
2208c2ecf20Sopenharmony_ci#define SBP2_TARGET_RESET_REQUEST	0xf
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/* Offsets for command block agent registers */
2238c2ecf20Sopenharmony_ci#define SBP2_AGENT_STATE		0x00
2248c2ecf20Sopenharmony_ci#define SBP2_AGENT_RESET		0x04
2258c2ecf20Sopenharmony_ci#define SBP2_ORB_POINTER		0x08
2268c2ecf20Sopenharmony_ci#define SBP2_DOORBELL			0x10
2278c2ecf20Sopenharmony_ci#define SBP2_UNSOLICITED_STATUS_ENABLE	0x14
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/* Status write response codes */
2308c2ecf20Sopenharmony_ci#define SBP2_STATUS_REQUEST_COMPLETE	0x0
2318c2ecf20Sopenharmony_ci#define SBP2_STATUS_TRANSPORT_FAILURE	0x1
2328c2ecf20Sopenharmony_ci#define SBP2_STATUS_ILLEGAL_REQUEST	0x2
2338c2ecf20Sopenharmony_ci#define SBP2_STATUS_VENDOR_DEPENDENT	0x3
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci#define STATUS_GET_ORB_HIGH(v)		((v).status & 0xffff)
2368c2ecf20Sopenharmony_ci#define STATUS_GET_SBP_STATUS(v)	(((v).status >> 16) & 0xff)
2378c2ecf20Sopenharmony_ci#define STATUS_GET_LEN(v)		(((v).status >> 24) & 0x07)
2388c2ecf20Sopenharmony_ci#define STATUS_GET_DEAD(v)		(((v).status >> 27) & 0x01)
2398c2ecf20Sopenharmony_ci#define STATUS_GET_RESPONSE(v)		(((v).status >> 28) & 0x03)
2408c2ecf20Sopenharmony_ci#define STATUS_GET_SOURCE(v)		(((v).status >> 30) & 0x03)
2418c2ecf20Sopenharmony_ci#define STATUS_GET_ORB_LOW(v)		((v).orb_low)
2428c2ecf20Sopenharmony_ci#define STATUS_GET_DATA(v)		((v).data)
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistruct sbp2_status {
2458c2ecf20Sopenharmony_ci	u32 status;
2468c2ecf20Sopenharmony_ci	u32 orb_low;
2478c2ecf20Sopenharmony_ci	u8 data[24];
2488c2ecf20Sopenharmony_ci};
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cistruct sbp2_pointer {
2518c2ecf20Sopenharmony_ci	__be32 high;
2528c2ecf20Sopenharmony_ci	__be32 low;
2538c2ecf20Sopenharmony_ci};
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistruct sbp2_orb {
2568c2ecf20Sopenharmony_ci	struct fw_transaction t;
2578c2ecf20Sopenharmony_ci	struct kref kref;
2588c2ecf20Sopenharmony_ci	dma_addr_t request_bus;
2598c2ecf20Sopenharmony_ci	int rcode;
2608c2ecf20Sopenharmony_ci	void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status);
2618c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu;
2628c2ecf20Sopenharmony_ci	struct list_head link;
2638c2ecf20Sopenharmony_ci};
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_LUN(v)			((v))
2668c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_FUNCTION(v)		((v) << 16)
2678c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_RECONNECT(v)		((v) << 20)
2688c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
2698c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_REQUEST_FORMAT(v)	((v) << 29)
2708c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_NOTIFY			((1) << 31)
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_RESPONSE_LENGTH(v)	((v))
2738c2ecf20Sopenharmony_ci#define MANAGEMENT_ORB_PASSWORD_LENGTH(v)	((v) << 16)
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistruct sbp2_management_orb {
2768c2ecf20Sopenharmony_ci	struct sbp2_orb base;
2778c2ecf20Sopenharmony_ci	struct {
2788c2ecf20Sopenharmony_ci		struct sbp2_pointer password;
2798c2ecf20Sopenharmony_ci		struct sbp2_pointer response;
2808c2ecf20Sopenharmony_ci		__be32 misc;
2818c2ecf20Sopenharmony_ci		__be32 length;
2828c2ecf20Sopenharmony_ci		struct sbp2_pointer status_fifo;
2838c2ecf20Sopenharmony_ci	} request;
2848c2ecf20Sopenharmony_ci	__be32 response[4];
2858c2ecf20Sopenharmony_ci	dma_addr_t response_bus;
2868c2ecf20Sopenharmony_ci	struct completion done;
2878c2ecf20Sopenharmony_ci	struct sbp2_status status;
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistruct sbp2_login_response {
2918c2ecf20Sopenharmony_ci	__be32 misc;
2928c2ecf20Sopenharmony_ci	struct sbp2_pointer command_block_agent;
2938c2ecf20Sopenharmony_ci	__be32 reconnect_hold;
2948c2ecf20Sopenharmony_ci};
2958c2ecf20Sopenharmony_ci#define COMMAND_ORB_DATA_SIZE(v)	((v))
2968c2ecf20Sopenharmony_ci#define COMMAND_ORB_PAGE_SIZE(v)	((v) << 16)
2978c2ecf20Sopenharmony_ci#define COMMAND_ORB_PAGE_TABLE_PRESENT	((1) << 19)
2988c2ecf20Sopenharmony_ci#define COMMAND_ORB_MAX_PAYLOAD(v)	((v) << 20)
2998c2ecf20Sopenharmony_ci#define COMMAND_ORB_SPEED(v)		((v) << 24)
3008c2ecf20Sopenharmony_ci#define COMMAND_ORB_DIRECTION		((1) << 27)
3018c2ecf20Sopenharmony_ci#define COMMAND_ORB_REQUEST_FORMAT(v)	((v) << 29)
3028c2ecf20Sopenharmony_ci#define COMMAND_ORB_NOTIFY		((1) << 31)
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistruct sbp2_command_orb {
3058c2ecf20Sopenharmony_ci	struct sbp2_orb base;
3068c2ecf20Sopenharmony_ci	struct {
3078c2ecf20Sopenharmony_ci		struct sbp2_pointer next;
3088c2ecf20Sopenharmony_ci		struct sbp2_pointer data_descriptor;
3098c2ecf20Sopenharmony_ci		__be32 misc;
3108c2ecf20Sopenharmony_ci		u8 command_block[SBP2_MAX_CDB_SIZE];
3118c2ecf20Sopenharmony_ci	} request;
3128c2ecf20Sopenharmony_ci	struct scsi_cmnd *cmd;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
3158c2ecf20Sopenharmony_ci	dma_addr_t page_table_bus;
3168c2ecf20Sopenharmony_ci};
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci#define SBP2_ROM_VALUE_WILDCARD ~0         /* match all */
3198c2ecf20Sopenharmony_ci#define SBP2_ROM_VALUE_MISSING  0xff000000 /* not present in the unit dir. */
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci/*
3228c2ecf20Sopenharmony_ci * List of devices with known bugs.
3238c2ecf20Sopenharmony_ci *
3248c2ecf20Sopenharmony_ci * The firmware_revision field, masked with 0xffff00, is the best
3258c2ecf20Sopenharmony_ci * indicator for the type of bridge chip of a device.  It yields a few
3268c2ecf20Sopenharmony_ci * false positives but this did not break correctly behaving devices
3278c2ecf20Sopenharmony_ci * so far.
3288c2ecf20Sopenharmony_ci */
3298c2ecf20Sopenharmony_cistatic const struct {
3308c2ecf20Sopenharmony_ci	u32 firmware_revision;
3318c2ecf20Sopenharmony_ci	u32 model;
3328c2ecf20Sopenharmony_ci	unsigned int workarounds;
3338c2ecf20Sopenharmony_ci} sbp2_workarounds_table[] = {
3348c2ecf20Sopenharmony_ci	/* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
3358c2ecf20Sopenharmony_ci		.firmware_revision	= 0x002800,
3368c2ecf20Sopenharmony_ci		.model			= 0x001010,
3378c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
3388c2ecf20Sopenharmony_ci					  SBP2_WORKAROUND_MODE_SENSE_8 |
3398c2ecf20Sopenharmony_ci					  SBP2_WORKAROUND_POWER_CONDITION,
3408c2ecf20Sopenharmony_ci	},
3418c2ecf20Sopenharmony_ci	/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
3428c2ecf20Sopenharmony_ci		.firmware_revision	= 0x002800,
3438c2ecf20Sopenharmony_ci		.model			= 0x000000,
3448c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_POWER_CONDITION,
3458c2ecf20Sopenharmony_ci	},
3468c2ecf20Sopenharmony_ci	/* Initio bridges, actually only needed for some older ones */ {
3478c2ecf20Sopenharmony_ci		.firmware_revision	= 0x000200,
3488c2ecf20Sopenharmony_ci		.model			= SBP2_ROM_VALUE_WILDCARD,
3498c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
3508c2ecf20Sopenharmony_ci	},
3518c2ecf20Sopenharmony_ci	/* PL-3507 bridge with Prolific firmware */ {
3528c2ecf20Sopenharmony_ci		.firmware_revision	= 0x012800,
3538c2ecf20Sopenharmony_ci		.model			= SBP2_ROM_VALUE_WILDCARD,
3548c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_POWER_CONDITION,
3558c2ecf20Sopenharmony_ci	},
3568c2ecf20Sopenharmony_ci	/* Symbios bridge */ {
3578c2ecf20Sopenharmony_ci		.firmware_revision	= 0xa0b800,
3588c2ecf20Sopenharmony_ci		.model			= SBP2_ROM_VALUE_WILDCARD,
3598c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
3608c2ecf20Sopenharmony_ci	},
3618c2ecf20Sopenharmony_ci	/* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
3628c2ecf20Sopenharmony_ci		.firmware_revision	= 0x002600,
3638c2ecf20Sopenharmony_ci		.model			= SBP2_ROM_VALUE_WILDCARD,
3648c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
3658c2ecf20Sopenharmony_ci	},
3668c2ecf20Sopenharmony_ci	/*
3678c2ecf20Sopenharmony_ci	 * iPod 2nd generation: needs 128k max transfer size workaround
3688c2ecf20Sopenharmony_ci	 * iPod 3rd generation: needs fix capacity workaround
3698c2ecf20Sopenharmony_ci	 */
3708c2ecf20Sopenharmony_ci	{
3718c2ecf20Sopenharmony_ci		.firmware_revision	= 0x0a2700,
3728c2ecf20Sopenharmony_ci		.model			= 0x000000,
3738c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS |
3748c2ecf20Sopenharmony_ci					  SBP2_WORKAROUND_FIX_CAPACITY,
3758c2ecf20Sopenharmony_ci	},
3768c2ecf20Sopenharmony_ci	/* iPod 4th generation */ {
3778c2ecf20Sopenharmony_ci		.firmware_revision	= 0x0a2700,
3788c2ecf20Sopenharmony_ci		.model			= 0x000021,
3798c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
3808c2ecf20Sopenharmony_ci	},
3818c2ecf20Sopenharmony_ci	/* iPod mini */ {
3828c2ecf20Sopenharmony_ci		.firmware_revision	= 0x0a2700,
3838c2ecf20Sopenharmony_ci		.model			= 0x000022,
3848c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
3858c2ecf20Sopenharmony_ci	},
3868c2ecf20Sopenharmony_ci	/* iPod mini */ {
3878c2ecf20Sopenharmony_ci		.firmware_revision	= 0x0a2700,
3888c2ecf20Sopenharmony_ci		.model			= 0x000023,
3898c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
3908c2ecf20Sopenharmony_ci	},
3918c2ecf20Sopenharmony_ci	/* iPod Photo */ {
3928c2ecf20Sopenharmony_ci		.firmware_revision	= 0x0a2700,
3938c2ecf20Sopenharmony_ci		.model			= 0x00007e,
3948c2ecf20Sopenharmony_ci		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci};
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic void free_orb(struct kref *kref)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	kfree(orb);
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic void sbp2_status_write(struct fw_card *card, struct fw_request *request,
4068c2ecf20Sopenharmony_ci			      int tcode, int destination, int source,
4078c2ecf20Sopenharmony_ci			      int generation, unsigned long long offset,
4088c2ecf20Sopenharmony_ci			      void *payload, size_t length, void *callback_data)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = callback_data;
4118c2ecf20Sopenharmony_ci	struct sbp2_orb *orb = NULL, *iter;
4128c2ecf20Sopenharmony_ci	struct sbp2_status status;
4138c2ecf20Sopenharmony_ci	unsigned long flags;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (tcode != TCODE_WRITE_BLOCK_REQUEST ||
4168c2ecf20Sopenharmony_ci	    length < 8 || length > sizeof(status)) {
4178c2ecf20Sopenharmony_ci		fw_send_response(card, request, RCODE_TYPE_ERROR);
4188c2ecf20Sopenharmony_ci		return;
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	status.status  = be32_to_cpup(payload);
4228c2ecf20Sopenharmony_ci	status.orb_low = be32_to_cpup(payload + 4);
4238c2ecf20Sopenharmony_ci	memset(status.data, 0, sizeof(status.data));
4248c2ecf20Sopenharmony_ci	if (length > 8)
4258c2ecf20Sopenharmony_ci		memcpy(status.data, payload + 8, length - 8);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) {
4288c2ecf20Sopenharmony_ci		dev_notice(lu_dev(lu),
4298c2ecf20Sopenharmony_ci			   "non-ORB related status write, not handled\n");
4308c2ecf20Sopenharmony_ci		fw_send_response(card, request, RCODE_COMPLETE);
4318c2ecf20Sopenharmony_ci		return;
4328c2ecf20Sopenharmony_ci	}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* Lookup the orb corresponding to this status write. */
4358c2ecf20Sopenharmony_ci	spin_lock_irqsave(&lu->tgt->lock, flags);
4368c2ecf20Sopenharmony_ci	list_for_each_entry(iter, &lu->orb_list, link) {
4378c2ecf20Sopenharmony_ci		if (STATUS_GET_ORB_HIGH(status) == 0 &&
4388c2ecf20Sopenharmony_ci		    STATUS_GET_ORB_LOW(status) == iter->request_bus) {
4398c2ecf20Sopenharmony_ci			iter->rcode = RCODE_COMPLETE;
4408c2ecf20Sopenharmony_ci			list_del(&iter->link);
4418c2ecf20Sopenharmony_ci			orb = iter;
4428c2ecf20Sopenharmony_ci			break;
4438c2ecf20Sopenharmony_ci		}
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&lu->tgt->lock, flags);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	if (orb) {
4488c2ecf20Sopenharmony_ci		orb->callback(orb, &status);
4498c2ecf20Sopenharmony_ci		kref_put(&orb->kref, free_orb); /* orb callback reference */
4508c2ecf20Sopenharmony_ci	} else {
4518c2ecf20Sopenharmony_ci		dev_err(lu_dev(lu), "status write for unknown ORB\n");
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	fw_send_response(card, request, RCODE_COMPLETE);
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic void complete_transaction(struct fw_card *card, int rcode,
4588c2ecf20Sopenharmony_ci				 void *payload, size_t length, void *data)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct sbp2_orb *orb = data;
4618c2ecf20Sopenharmony_ci	unsigned long flags;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	/*
4648c2ecf20Sopenharmony_ci	 * This is a little tricky.  We can get the status write for
4658c2ecf20Sopenharmony_ci	 * the orb before we get this callback.  The status write
4668c2ecf20Sopenharmony_ci	 * handler above will assume the orb pointer transaction was
4678c2ecf20Sopenharmony_ci	 * successful and set the rcode to RCODE_COMPLETE for the orb.
4688c2ecf20Sopenharmony_ci	 * So this callback only sets the rcode if it hasn't already
4698c2ecf20Sopenharmony_ci	 * been set and only does the cleanup if the transaction
4708c2ecf20Sopenharmony_ci	 * failed and we didn't already get a status write.
4718c2ecf20Sopenharmony_ci	 */
4728c2ecf20Sopenharmony_ci	spin_lock_irqsave(&orb->lu->tgt->lock, flags);
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	if (orb->rcode == -1)
4758c2ecf20Sopenharmony_ci		orb->rcode = rcode;
4768c2ecf20Sopenharmony_ci	if (orb->rcode != RCODE_COMPLETE) {
4778c2ecf20Sopenharmony_ci		list_del(&orb->link);
4788c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&orb->lu->tgt->lock, flags);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci		orb->callback(orb, NULL);
4818c2ecf20Sopenharmony_ci		kref_put(&orb->kref, free_orb); /* orb callback reference */
4828c2ecf20Sopenharmony_ci	} else {
4838c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&orb->lu->tgt->lock, flags);
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	kref_put(&orb->kref, free_orb); /* transaction callback reference */
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
4908c2ecf20Sopenharmony_ci			  int node_id, int generation, u64 offset)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
4938c2ecf20Sopenharmony_ci	struct sbp2_pointer orb_pointer;
4948c2ecf20Sopenharmony_ci	unsigned long flags;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	orb_pointer.high = 0;
4978c2ecf20Sopenharmony_ci	orb_pointer.low = cpu_to_be32(orb->request_bus);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	orb->lu = lu;
5008c2ecf20Sopenharmony_ci	spin_lock_irqsave(&lu->tgt->lock, flags);
5018c2ecf20Sopenharmony_ci	list_add_tail(&orb->link, &lu->orb_list);
5028c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&lu->tgt->lock, flags);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	kref_get(&orb->kref); /* transaction callback reference */
5058c2ecf20Sopenharmony_ci	kref_get(&orb->kref); /* orb callback reference */
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
5088c2ecf20Sopenharmony_ci			node_id, generation, device->max_speed, offset,
5098c2ecf20Sopenharmony_ci			&orb_pointer, 8, complete_transaction, orb);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
5158c2ecf20Sopenharmony_ci	struct sbp2_orb *orb, *next;
5168c2ecf20Sopenharmony_ci	struct list_head list;
5178c2ecf20Sopenharmony_ci	int retval = -ENOENT;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&list);
5208c2ecf20Sopenharmony_ci	spin_lock_irq(&lu->tgt->lock);
5218c2ecf20Sopenharmony_ci	list_splice_init(&lu->orb_list, &list);
5228c2ecf20Sopenharmony_ci	spin_unlock_irq(&lu->tgt->lock);
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	list_for_each_entry_safe(orb, next, &list, link) {
5258c2ecf20Sopenharmony_ci		retval = 0;
5268c2ecf20Sopenharmony_ci		if (fw_cancel_transaction(device->card, &orb->t) == 0)
5278c2ecf20Sopenharmony_ci			continue;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci		orb->rcode = RCODE_CANCELLED;
5308c2ecf20Sopenharmony_ci		orb->callback(orb, NULL);
5318c2ecf20Sopenharmony_ci		kref_put(&orb->kref, free_orb); /* orb callback reference */
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	return retval;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_cistatic void complete_management_orb(struct sbp2_orb *base_orb,
5388c2ecf20Sopenharmony_ci				    struct sbp2_status *status)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	struct sbp2_management_orb *orb =
5418c2ecf20Sopenharmony_ci		container_of(base_orb, struct sbp2_management_orb, base);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (status)
5448c2ecf20Sopenharmony_ci		memcpy(&orb->status, status, sizeof(*status));
5458c2ecf20Sopenharmony_ci	complete(&orb->done);
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_cistatic int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
5498c2ecf20Sopenharmony_ci				    int generation, int function,
5508c2ecf20Sopenharmony_ci				    int lun_or_login_id, void *response)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
5538c2ecf20Sopenharmony_ci	struct sbp2_management_orb *orb;
5548c2ecf20Sopenharmony_ci	unsigned int timeout;
5558c2ecf20Sopenharmony_ci	int retval = -ENOMEM;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device))
5588c2ecf20Sopenharmony_ci		return 0;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	orb = kzalloc(sizeof(*orb), GFP_NOIO);
5618c2ecf20Sopenharmony_ci	if (orb == NULL)
5628c2ecf20Sopenharmony_ci		return -ENOMEM;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	kref_init(&orb->base.kref);
5658c2ecf20Sopenharmony_ci	orb->response_bus =
5668c2ecf20Sopenharmony_ci		dma_map_single(device->card->device, &orb->response,
5678c2ecf20Sopenharmony_ci			       sizeof(orb->response), DMA_FROM_DEVICE);
5688c2ecf20Sopenharmony_ci	if (dma_mapping_error(device->card->device, orb->response_bus))
5698c2ecf20Sopenharmony_ci		goto fail_mapping_response;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	orb->request.response.high = 0;
5728c2ecf20Sopenharmony_ci	orb->request.response.low  = cpu_to_be32(orb->response_bus);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	orb->request.misc = cpu_to_be32(
5758c2ecf20Sopenharmony_ci		MANAGEMENT_ORB_NOTIFY |
5768c2ecf20Sopenharmony_ci		MANAGEMENT_ORB_FUNCTION(function) |
5778c2ecf20Sopenharmony_ci		MANAGEMENT_ORB_LUN(lun_or_login_id));
5788c2ecf20Sopenharmony_ci	orb->request.length = cpu_to_be32(
5798c2ecf20Sopenharmony_ci		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	orb->request.status_fifo.high =
5828c2ecf20Sopenharmony_ci		cpu_to_be32(lu->address_handler.offset >> 32);
5838c2ecf20Sopenharmony_ci	orb->request.status_fifo.low  =
5848c2ecf20Sopenharmony_ci		cpu_to_be32(lu->address_handler.offset);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	if (function == SBP2_LOGIN_REQUEST) {
5878c2ecf20Sopenharmony_ci		/* Ask for 2^2 == 4 seconds reconnect grace period */
5888c2ecf20Sopenharmony_ci		orb->request.misc |= cpu_to_be32(
5898c2ecf20Sopenharmony_ci			MANAGEMENT_ORB_RECONNECT(2) |
5908c2ecf20Sopenharmony_ci			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
5918c2ecf20Sopenharmony_ci		timeout = lu->tgt->mgt_orb_timeout;
5928c2ecf20Sopenharmony_ci	} else {
5938c2ecf20Sopenharmony_ci		timeout = SBP2_ORB_TIMEOUT;
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	init_completion(&orb->done);
5978c2ecf20Sopenharmony_ci	orb->base.callback = complete_management_orb;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	orb->base.request_bus =
6008c2ecf20Sopenharmony_ci		dma_map_single(device->card->device, &orb->request,
6018c2ecf20Sopenharmony_ci			       sizeof(orb->request), DMA_TO_DEVICE);
6028c2ecf20Sopenharmony_ci	if (dma_mapping_error(device->card->device, orb->base.request_bus))
6038c2ecf20Sopenharmony_ci		goto fail_mapping_request;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	sbp2_send_orb(&orb->base, lu, node_id, generation,
6068c2ecf20Sopenharmony_ci		      lu->tgt->management_agent_address);
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	retval = -EIO;
6118c2ecf20Sopenharmony_ci	if (sbp2_cancel_orbs(lu) == 0) {
6128c2ecf20Sopenharmony_ci		dev_err(lu_dev(lu), "ORB reply timed out, rcode 0x%02x\n",
6138c2ecf20Sopenharmony_ci			orb->base.rcode);
6148c2ecf20Sopenharmony_ci		goto out;
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (orb->base.rcode != RCODE_COMPLETE) {
6188c2ecf20Sopenharmony_ci		dev_err(lu_dev(lu), "management write failed, rcode 0x%02x\n",
6198c2ecf20Sopenharmony_ci			orb->base.rcode);
6208c2ecf20Sopenharmony_ci		goto out;
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	if (STATUS_GET_RESPONSE(orb->status) != 0 ||
6248c2ecf20Sopenharmony_ci	    STATUS_GET_SBP_STATUS(orb->status) != 0) {
6258c2ecf20Sopenharmony_ci		dev_err(lu_dev(lu), "error status: %d:%d\n",
6268c2ecf20Sopenharmony_ci			 STATUS_GET_RESPONSE(orb->status),
6278c2ecf20Sopenharmony_ci			 STATUS_GET_SBP_STATUS(orb->status));
6288c2ecf20Sopenharmony_ci		goto out;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	retval = 0;
6328c2ecf20Sopenharmony_ci out:
6338c2ecf20Sopenharmony_ci	dma_unmap_single(device->card->device, orb->base.request_bus,
6348c2ecf20Sopenharmony_ci			 sizeof(orb->request), DMA_TO_DEVICE);
6358c2ecf20Sopenharmony_ci fail_mapping_request:
6368c2ecf20Sopenharmony_ci	dma_unmap_single(device->card->device, orb->response_bus,
6378c2ecf20Sopenharmony_ci			 sizeof(orb->response), DMA_FROM_DEVICE);
6388c2ecf20Sopenharmony_ci fail_mapping_response:
6398c2ecf20Sopenharmony_ci	if (response)
6408c2ecf20Sopenharmony_ci		memcpy(response, orb->response, sizeof(orb->response));
6418c2ecf20Sopenharmony_ci	kref_put(&orb->base.kref, free_orb);
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	return retval;
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic void sbp2_agent_reset(struct sbp2_logical_unit *lu)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
6498c2ecf20Sopenharmony_ci	__be32 d = 0;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
6528c2ecf20Sopenharmony_ci			   lu->tgt->node_id, lu->generation, device->max_speed,
6538c2ecf20Sopenharmony_ci			   lu->command_block_agent_address + SBP2_AGENT_RESET,
6548c2ecf20Sopenharmony_ci			   &d, 4);
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_cistatic void complete_agent_reset_write_no_wait(struct fw_card *card,
6588c2ecf20Sopenharmony_ci		int rcode, void *payload, size_t length, void *data)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	kfree(data);
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_cistatic void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
6668c2ecf20Sopenharmony_ci	struct fw_transaction *t;
6678c2ecf20Sopenharmony_ci	static __be32 d;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	t = kmalloc(sizeof(*t), GFP_ATOMIC);
6708c2ecf20Sopenharmony_ci	if (t == NULL)
6718c2ecf20Sopenharmony_ci		return;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
6748c2ecf20Sopenharmony_ci			lu->tgt->node_id, lu->generation, device->max_speed,
6758c2ecf20Sopenharmony_ci			lu->command_block_agent_address + SBP2_AGENT_RESET,
6768c2ecf20Sopenharmony_ci			&d, 4, complete_agent_reset_write_no_wait, t);
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_cistatic inline void sbp2_allow_block(struct sbp2_target *tgt)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	spin_lock_irq(&tgt->lock);
6828c2ecf20Sopenharmony_ci	--tgt->dont_block;
6838c2ecf20Sopenharmony_ci	spin_unlock_irq(&tgt->lock);
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci/*
6878c2ecf20Sopenharmony_ci * Blocks lu->tgt if all of the following conditions are met:
6888c2ecf20Sopenharmony_ci *   - Login, INQUIRY, and high-level SCSI setup of all of the target's
6898c2ecf20Sopenharmony_ci *     logical units have been finished (indicated by dont_block == 0).
6908c2ecf20Sopenharmony_ci *   - lu->generation is stale.
6918c2ecf20Sopenharmony_ci *
6928c2ecf20Sopenharmony_ci * Note, scsi_block_requests() must be called while holding tgt->lock,
6938c2ecf20Sopenharmony_ci * otherwise it might foil sbp2_[conditionally_]unblock()'s attempt to
6948c2ecf20Sopenharmony_ci * unblock the target.
6958c2ecf20Sopenharmony_ci */
6968c2ecf20Sopenharmony_cistatic void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = lu->tgt;
6998c2ecf20Sopenharmony_ci	struct fw_card *card = target_parent_device(tgt)->card;
7008c2ecf20Sopenharmony_ci	struct Scsi_Host *shost =
7018c2ecf20Sopenharmony_ci		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
7028c2ecf20Sopenharmony_ci	unsigned long flags;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	spin_lock_irqsave(&tgt->lock, flags);
7058c2ecf20Sopenharmony_ci	if (!tgt->dont_block && !lu->blocked &&
7068c2ecf20Sopenharmony_ci	    lu->generation != card->generation) {
7078c2ecf20Sopenharmony_ci		lu->blocked = true;
7088c2ecf20Sopenharmony_ci		if (++tgt->blocked == 1)
7098c2ecf20Sopenharmony_ci			scsi_block_requests(shost);
7108c2ecf20Sopenharmony_ci	}
7118c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&tgt->lock, flags);
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/*
7158c2ecf20Sopenharmony_ci * Unblocks lu->tgt as soon as all its logical units can be unblocked.
7168c2ecf20Sopenharmony_ci * Note, it is harmless to run scsi_unblock_requests() outside the
7178c2ecf20Sopenharmony_ci * tgt->lock protected section.  On the other hand, running it inside
7188c2ecf20Sopenharmony_ci * the section might clash with shost->host_lock.
7198c2ecf20Sopenharmony_ci */
7208c2ecf20Sopenharmony_cistatic void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = lu->tgt;
7238c2ecf20Sopenharmony_ci	struct fw_card *card = target_parent_device(tgt)->card;
7248c2ecf20Sopenharmony_ci	struct Scsi_Host *shost =
7258c2ecf20Sopenharmony_ci		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
7268c2ecf20Sopenharmony_ci	bool unblock = false;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	spin_lock_irq(&tgt->lock);
7298c2ecf20Sopenharmony_ci	if (lu->blocked && lu->generation == card->generation) {
7308c2ecf20Sopenharmony_ci		lu->blocked = false;
7318c2ecf20Sopenharmony_ci		unblock = --tgt->blocked == 0;
7328c2ecf20Sopenharmony_ci	}
7338c2ecf20Sopenharmony_ci	spin_unlock_irq(&tgt->lock);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	if (unblock)
7368c2ecf20Sopenharmony_ci		scsi_unblock_requests(shost);
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci/*
7408c2ecf20Sopenharmony_ci * Prevents future blocking of tgt and unblocks it.
7418c2ecf20Sopenharmony_ci * Note, it is harmless to run scsi_unblock_requests() outside the
7428c2ecf20Sopenharmony_ci * tgt->lock protected section.  On the other hand, running it inside
7438c2ecf20Sopenharmony_ci * the section might clash with shost->host_lock.
7448c2ecf20Sopenharmony_ci */
7458c2ecf20Sopenharmony_cistatic void sbp2_unblock(struct sbp2_target *tgt)
7468c2ecf20Sopenharmony_ci{
7478c2ecf20Sopenharmony_ci	struct Scsi_Host *shost =
7488c2ecf20Sopenharmony_ci		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	spin_lock_irq(&tgt->lock);
7518c2ecf20Sopenharmony_ci	++tgt->dont_block;
7528c2ecf20Sopenharmony_ci	spin_unlock_irq(&tgt->lock);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	scsi_unblock_requests(shost);
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_cistatic int sbp2_lun2int(u16 lun)
7588c2ecf20Sopenharmony_ci{
7598c2ecf20Sopenharmony_ci	struct scsi_lun eight_bytes_lun;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
7628c2ecf20Sopenharmony_ci	eight_bytes_lun.scsi_lun[0] = (lun >> 8) & 0xff;
7638c2ecf20Sopenharmony_ci	eight_bytes_lun.scsi_lun[1] = lun & 0xff;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	return scsilun_to_int(&eight_bytes_lun);
7668c2ecf20Sopenharmony_ci}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci/*
7698c2ecf20Sopenharmony_ci * Write retransmit retry values into the BUSY_TIMEOUT register.
7708c2ecf20Sopenharmony_ci * - The single-phase retry protocol is supported by all SBP-2 devices, but the
7718c2ecf20Sopenharmony_ci *   default retry_limit value is 0 (i.e. never retry transmission). We write a
7728c2ecf20Sopenharmony_ci *   saner value after logging into the device.
7738c2ecf20Sopenharmony_ci * - The dual-phase retry protocol is optional to implement, and if not
7748c2ecf20Sopenharmony_ci *   supported, writes to the dual-phase portion of the register will be
7758c2ecf20Sopenharmony_ci *   ignored. We try to write the original 1394-1995 default here.
7768c2ecf20Sopenharmony_ci * - In the case of devices that are also SBP-3-compliant, all writes are
7778c2ecf20Sopenharmony_ci *   ignored, as the register is read-only, but contains single-phase retry of
7788c2ecf20Sopenharmony_ci *   15, which is what we're trying to set for all SBP-2 device anyway, so this
7798c2ecf20Sopenharmony_ci *   write attempt is safe and yields more consistent behavior for all devices.
7808c2ecf20Sopenharmony_ci *
7818c2ecf20Sopenharmony_ci * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
7828c2ecf20Sopenharmony_ci * and section 6.4 of the SBP-3 spec for further details.
7838c2ecf20Sopenharmony_ci */
7848c2ecf20Sopenharmony_cistatic void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
7878c2ecf20Sopenharmony_ci	__be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
7908c2ecf20Sopenharmony_ci			   lu->tgt->node_id, lu->generation, device->max_speed,
7918c2ecf20Sopenharmony_ci			   CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &d, 4);
7928c2ecf20Sopenharmony_ci}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic void sbp2_reconnect(struct work_struct *work);
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_cistatic void sbp2_login(struct work_struct *work)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu =
7998c2ecf20Sopenharmony_ci		container_of(work, struct sbp2_logical_unit, work.work);
8008c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = lu->tgt;
8018c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(tgt);
8028c2ecf20Sopenharmony_ci	struct Scsi_Host *shost;
8038c2ecf20Sopenharmony_ci	struct scsi_device *sdev;
8048c2ecf20Sopenharmony_ci	struct sbp2_login_response response;
8058c2ecf20Sopenharmony_ci	int generation, node_id, local_node_id;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	if (fw_device_is_shutdown(device))
8088c2ecf20Sopenharmony_ci		return;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	generation    = device->generation;
8118c2ecf20Sopenharmony_ci	smp_rmb();    /* node IDs must not be older than generation */
8128c2ecf20Sopenharmony_ci	node_id       = device->node_id;
8138c2ecf20Sopenharmony_ci	local_node_id = device->card->node_id;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* If this is a re-login attempt, log out, or we might be rejected. */
8168c2ecf20Sopenharmony_ci	if (lu->has_sdev)
8178c2ecf20Sopenharmony_ci		sbp2_send_management_orb(lu, device->node_id, generation,
8188c2ecf20Sopenharmony_ci				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	if (sbp2_send_management_orb(lu, node_id, generation,
8218c2ecf20Sopenharmony_ci				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
8228c2ecf20Sopenharmony_ci		if (lu->retries++ < 5) {
8238c2ecf20Sopenharmony_ci			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
8248c2ecf20Sopenharmony_ci		} else {
8258c2ecf20Sopenharmony_ci			dev_err(tgt_dev(tgt), "failed to login to LUN %04x\n",
8268c2ecf20Sopenharmony_ci				lu->lun);
8278c2ecf20Sopenharmony_ci			/* Let any waiting I/O fail from now on. */
8288c2ecf20Sopenharmony_ci			sbp2_unblock(lu->tgt);
8298c2ecf20Sopenharmony_ci		}
8308c2ecf20Sopenharmony_ci		return;
8318c2ecf20Sopenharmony_ci	}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	tgt->node_id	  = node_id;
8348c2ecf20Sopenharmony_ci	tgt->address_high = local_node_id << 16;
8358c2ecf20Sopenharmony_ci	smp_wmb();	  /* node IDs must not be older than generation */
8368c2ecf20Sopenharmony_ci	lu->generation	  = generation;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	lu->command_block_agent_address =
8398c2ecf20Sopenharmony_ci		((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
8408c2ecf20Sopenharmony_ci		      << 32) | be32_to_cpu(response.command_block_agent.low);
8418c2ecf20Sopenharmony_ci	lu->login_id = be32_to_cpu(response.misc) & 0xffff;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	dev_notice(tgt_dev(tgt), "logged in to LUN %04x (%d retries)\n",
8448c2ecf20Sopenharmony_ci		   lu->lun, lu->retries);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	/* set appropriate retry limit(s) in BUSY_TIMEOUT register */
8478c2ecf20Sopenharmony_ci	sbp2_set_busy_timeout(lu);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	lu->workfn = sbp2_reconnect;
8508c2ecf20Sopenharmony_ci	sbp2_agent_reset(lu);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	/* This was a re-login. */
8538c2ecf20Sopenharmony_ci	if (lu->has_sdev) {
8548c2ecf20Sopenharmony_ci		sbp2_cancel_orbs(lu);
8558c2ecf20Sopenharmony_ci		sbp2_conditionally_unblock(lu);
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci		return;
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
8618c2ecf20Sopenharmony_ci		ssleep(SBP2_INQUIRY_DELAY);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
8648c2ecf20Sopenharmony_ci	sdev = __scsi_add_device(shost, 0, 0, sbp2_lun2int(lu->lun), lu);
8658c2ecf20Sopenharmony_ci	/*
8668c2ecf20Sopenharmony_ci	 * FIXME:  We are unable to perform reconnects while in sbp2_login().
8678c2ecf20Sopenharmony_ci	 * Therefore __scsi_add_device() will get into trouble if a bus reset
8688c2ecf20Sopenharmony_ci	 * happens in parallel.  It will either fail or leave us with an
8698c2ecf20Sopenharmony_ci	 * unusable sdev.  As a workaround we check for this and retry the
8708c2ecf20Sopenharmony_ci	 * whole login and SCSI probing.
8718c2ecf20Sopenharmony_ci	 */
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	/* Reported error during __scsi_add_device() */
8748c2ecf20Sopenharmony_ci	if (IS_ERR(sdev))
8758c2ecf20Sopenharmony_ci		goto out_logout_login;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	/* Unreported error during __scsi_add_device() */
8788c2ecf20Sopenharmony_ci	smp_rmb(); /* get current card generation */
8798c2ecf20Sopenharmony_ci	if (generation != device->card->generation) {
8808c2ecf20Sopenharmony_ci		scsi_remove_device(sdev);
8818c2ecf20Sopenharmony_ci		scsi_device_put(sdev);
8828c2ecf20Sopenharmony_ci		goto out_logout_login;
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	/* No error during __scsi_add_device() */
8868c2ecf20Sopenharmony_ci	lu->has_sdev = true;
8878c2ecf20Sopenharmony_ci	scsi_device_put(sdev);
8888c2ecf20Sopenharmony_ci	sbp2_allow_block(tgt);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	return;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci out_logout_login:
8938c2ecf20Sopenharmony_ci	smp_rmb(); /* generation may have changed */
8948c2ecf20Sopenharmony_ci	generation = device->generation;
8958c2ecf20Sopenharmony_ci	smp_rmb(); /* node_id must not be older than generation */
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	sbp2_send_management_orb(lu, device->node_id, generation,
8988c2ecf20Sopenharmony_ci				 SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
8998c2ecf20Sopenharmony_ci	/*
9008c2ecf20Sopenharmony_ci	 * If a bus reset happened, sbp2_update will have requeued
9018c2ecf20Sopenharmony_ci	 * lu->work already.  Reset the work from reconnect to login.
9028c2ecf20Sopenharmony_ci	 */
9038c2ecf20Sopenharmony_ci	lu->workfn = sbp2_login;
9048c2ecf20Sopenharmony_ci}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_cistatic void sbp2_reconnect(struct work_struct *work)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu =
9098c2ecf20Sopenharmony_ci		container_of(work, struct sbp2_logical_unit, work.work);
9108c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = lu->tgt;
9118c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(tgt);
9128c2ecf20Sopenharmony_ci	int generation, node_id, local_node_id;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	if (fw_device_is_shutdown(device))
9158c2ecf20Sopenharmony_ci		return;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	generation    = device->generation;
9188c2ecf20Sopenharmony_ci	smp_rmb();    /* node IDs must not be older than generation */
9198c2ecf20Sopenharmony_ci	node_id       = device->node_id;
9208c2ecf20Sopenharmony_ci	local_node_id = device->card->node_id;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	if (sbp2_send_management_orb(lu, node_id, generation,
9238c2ecf20Sopenharmony_ci				     SBP2_RECONNECT_REQUEST,
9248c2ecf20Sopenharmony_ci				     lu->login_id, NULL) < 0) {
9258c2ecf20Sopenharmony_ci		/*
9268c2ecf20Sopenharmony_ci		 * If reconnect was impossible even though we are in the
9278c2ecf20Sopenharmony_ci		 * current generation, fall back and try to log in again.
9288c2ecf20Sopenharmony_ci		 *
9298c2ecf20Sopenharmony_ci		 * We could check for "Function rejected" status, but
9308c2ecf20Sopenharmony_ci		 * looking at the bus generation as simpler and more general.
9318c2ecf20Sopenharmony_ci		 */
9328c2ecf20Sopenharmony_ci		smp_rmb(); /* get current card generation */
9338c2ecf20Sopenharmony_ci		if (generation == device->card->generation ||
9348c2ecf20Sopenharmony_ci		    lu->retries++ >= 5) {
9358c2ecf20Sopenharmony_ci			dev_err(tgt_dev(tgt), "failed to reconnect\n");
9368c2ecf20Sopenharmony_ci			lu->retries = 0;
9378c2ecf20Sopenharmony_ci			lu->workfn = sbp2_login;
9388c2ecf20Sopenharmony_ci		}
9398c2ecf20Sopenharmony_ci		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci		return;
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	tgt->node_id      = node_id;
9458c2ecf20Sopenharmony_ci	tgt->address_high = local_node_id << 16;
9468c2ecf20Sopenharmony_ci	smp_wmb();	  /* node IDs must not be older than generation */
9478c2ecf20Sopenharmony_ci	lu->generation	  = generation;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	dev_notice(tgt_dev(tgt), "reconnected to LUN %04x (%d retries)\n",
9508c2ecf20Sopenharmony_ci		   lu->lun, lu->retries);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	sbp2_agent_reset(lu);
9538c2ecf20Sopenharmony_ci	sbp2_cancel_orbs(lu);
9548c2ecf20Sopenharmony_ci	sbp2_conditionally_unblock(lu);
9558c2ecf20Sopenharmony_ci}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cistatic void sbp2_lu_workfn(struct work_struct *work)
9588c2ecf20Sopenharmony_ci{
9598c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = container_of(to_delayed_work(work),
9608c2ecf20Sopenharmony_ci						struct sbp2_logical_unit, work);
9618c2ecf20Sopenharmony_ci	lu->workfn(work);
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_cistatic int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
9658c2ecf20Sopenharmony_ci{
9668c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	lu = kmalloc(sizeof(*lu), GFP_KERNEL);
9698c2ecf20Sopenharmony_ci	if (!lu)
9708c2ecf20Sopenharmony_ci		return -ENOMEM;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	lu->address_handler.length           = 0x100;
9738c2ecf20Sopenharmony_ci	lu->address_handler.address_callback = sbp2_status_write;
9748c2ecf20Sopenharmony_ci	lu->address_handler.callback_data    = lu;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	if (fw_core_add_address_handler(&lu->address_handler,
9778c2ecf20Sopenharmony_ci					&fw_high_memory_region) < 0) {
9788c2ecf20Sopenharmony_ci		kfree(lu);
9798c2ecf20Sopenharmony_ci		return -ENOMEM;
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	lu->tgt      = tgt;
9838c2ecf20Sopenharmony_ci	lu->lun      = lun_entry & 0xffff;
9848c2ecf20Sopenharmony_ci	lu->login_id = INVALID_LOGIN_ID;
9858c2ecf20Sopenharmony_ci	lu->retries  = 0;
9868c2ecf20Sopenharmony_ci	lu->has_sdev = false;
9878c2ecf20Sopenharmony_ci	lu->blocked  = false;
9888c2ecf20Sopenharmony_ci	++tgt->dont_block;
9898c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&lu->orb_list);
9908c2ecf20Sopenharmony_ci	lu->workfn = sbp2_login;
9918c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	list_add_tail(&lu->link, &tgt->lu_list);
9948c2ecf20Sopenharmony_ci	return 0;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_cistatic void sbp2_get_unit_unique_id(struct sbp2_target *tgt,
9988c2ecf20Sopenharmony_ci				    const u32 *leaf)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	if ((leaf[0] & 0xffff0000) == 0x00020000)
10018c2ecf20Sopenharmony_ci		tgt->guid = (u64)leaf[1] << 32 | leaf[2];
10028c2ecf20Sopenharmony_ci}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_cistatic int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt,
10058c2ecf20Sopenharmony_ci				      const u32 *directory)
10068c2ecf20Sopenharmony_ci{
10078c2ecf20Sopenharmony_ci	struct fw_csr_iterator ci;
10088c2ecf20Sopenharmony_ci	int key, value;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	fw_csr_iterator_init(&ci, directory);
10118c2ecf20Sopenharmony_ci	while (fw_csr_iterator_next(&ci, &key, &value))
10128c2ecf20Sopenharmony_ci		if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER &&
10138c2ecf20Sopenharmony_ci		    sbp2_add_logical_unit(tgt, value) < 0)
10148c2ecf20Sopenharmony_ci			return -ENOMEM;
10158c2ecf20Sopenharmony_ci	return 0;
10168c2ecf20Sopenharmony_ci}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_cistatic int sbp2_scan_unit_dir(struct sbp2_target *tgt, const u32 *directory,
10198c2ecf20Sopenharmony_ci			      u32 *model, u32 *firmware_revision)
10208c2ecf20Sopenharmony_ci{
10218c2ecf20Sopenharmony_ci	struct fw_csr_iterator ci;
10228c2ecf20Sopenharmony_ci	int key, value;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	fw_csr_iterator_init(&ci, directory);
10258c2ecf20Sopenharmony_ci	while (fw_csr_iterator_next(&ci, &key, &value)) {
10268c2ecf20Sopenharmony_ci		switch (key) {
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci		case CSR_DEPENDENT_INFO | CSR_OFFSET:
10298c2ecf20Sopenharmony_ci			tgt->management_agent_address =
10308c2ecf20Sopenharmony_ci					CSR_REGISTER_BASE + 4 * value;
10318c2ecf20Sopenharmony_ci			break;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci		case CSR_DIRECTORY_ID:
10348c2ecf20Sopenharmony_ci			tgt->directory_id = value;
10358c2ecf20Sopenharmony_ci			break;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci		case CSR_MODEL:
10388c2ecf20Sopenharmony_ci			*model = value;
10398c2ecf20Sopenharmony_ci			break;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		case SBP2_CSR_FIRMWARE_REVISION:
10428c2ecf20Sopenharmony_ci			*firmware_revision = value;
10438c2ecf20Sopenharmony_ci			break;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci		case SBP2_CSR_UNIT_CHARACTERISTICS:
10468c2ecf20Sopenharmony_ci			/* the timeout value is stored in 500ms units */
10478c2ecf20Sopenharmony_ci			tgt->mgt_orb_timeout = (value >> 8 & 0xff) * 500;
10488c2ecf20Sopenharmony_ci			break;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
10518c2ecf20Sopenharmony_ci			if (sbp2_add_logical_unit(tgt, value) < 0)
10528c2ecf20Sopenharmony_ci				return -ENOMEM;
10538c2ecf20Sopenharmony_ci			break;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci		case SBP2_CSR_UNIT_UNIQUE_ID:
10568c2ecf20Sopenharmony_ci			sbp2_get_unit_unique_id(tgt, ci.p - 1 + value);
10578c2ecf20Sopenharmony_ci			break;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci		case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
10608c2ecf20Sopenharmony_ci			/* Adjust for the increment in the iterator */
10618c2ecf20Sopenharmony_ci			if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0)
10628c2ecf20Sopenharmony_ci				return -ENOMEM;
10638c2ecf20Sopenharmony_ci			break;
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci	}
10668c2ecf20Sopenharmony_ci	return 0;
10678c2ecf20Sopenharmony_ci}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci/*
10708c2ecf20Sopenharmony_ci * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
10718c2ecf20Sopenharmony_ci * provided in the config rom. Most devices do provide a value, which
10728c2ecf20Sopenharmony_ci * we'll use for login management orbs, but with some sane limits.
10738c2ecf20Sopenharmony_ci */
10748c2ecf20Sopenharmony_cistatic void sbp2_clamp_management_orb_timeout(struct sbp2_target *tgt)
10758c2ecf20Sopenharmony_ci{
10768c2ecf20Sopenharmony_ci	unsigned int timeout = tgt->mgt_orb_timeout;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	if (timeout > 40000)
10798c2ecf20Sopenharmony_ci		dev_notice(tgt_dev(tgt), "%ds mgt_ORB_timeout limited to 40s\n",
10808c2ecf20Sopenharmony_ci			   timeout / 1000);
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	tgt->mgt_orb_timeout = clamp_val(timeout, 5000, 40000);
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_cistatic void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
10868c2ecf20Sopenharmony_ci				  u32 firmware_revision)
10878c2ecf20Sopenharmony_ci{
10888c2ecf20Sopenharmony_ci	int i;
10898c2ecf20Sopenharmony_ci	unsigned int w = sbp2_param_workarounds;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	if (w)
10928c2ecf20Sopenharmony_ci		dev_notice(tgt_dev(tgt),
10938c2ecf20Sopenharmony_ci			   "Please notify linux1394-devel@lists.sf.net "
10948c2ecf20Sopenharmony_ci			   "if you need the workarounds parameter\n");
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	if (w & SBP2_WORKAROUND_OVERRIDE)
10978c2ecf20Sopenharmony_ci		goto out;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci		if (sbp2_workarounds_table[i].firmware_revision !=
11028c2ecf20Sopenharmony_ci		    (firmware_revision & 0xffffff00))
11038c2ecf20Sopenharmony_ci			continue;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		if (sbp2_workarounds_table[i].model != model &&
11068c2ecf20Sopenharmony_ci		    sbp2_workarounds_table[i].model != SBP2_ROM_VALUE_WILDCARD)
11078c2ecf20Sopenharmony_ci			continue;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci		w |= sbp2_workarounds_table[i].workarounds;
11108c2ecf20Sopenharmony_ci		break;
11118c2ecf20Sopenharmony_ci	}
11128c2ecf20Sopenharmony_ci out:
11138c2ecf20Sopenharmony_ci	if (w)
11148c2ecf20Sopenharmony_ci		dev_notice(tgt_dev(tgt), "workarounds 0x%x "
11158c2ecf20Sopenharmony_ci			   "(firmware_revision 0x%06x, model_id 0x%06x)\n",
11168c2ecf20Sopenharmony_ci			   w, firmware_revision, model);
11178c2ecf20Sopenharmony_ci	tgt->workarounds = w;
11188c2ecf20Sopenharmony_ci}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_cistatic struct scsi_host_template scsi_driver_template;
11218c2ecf20Sopenharmony_cistatic void sbp2_remove(struct fw_unit *unit);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistatic int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
11248c2ecf20Sopenharmony_ci{
11258c2ecf20Sopenharmony_ci	struct fw_device *device = fw_parent_device(unit);
11268c2ecf20Sopenharmony_ci	struct sbp2_target *tgt;
11278c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu;
11288c2ecf20Sopenharmony_ci	struct Scsi_Host *shost;
11298c2ecf20Sopenharmony_ci	u32 model, firmware_revision;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	/* cannot (or should not) handle targets on the local node */
11328c2ecf20Sopenharmony_ci	if (device->is_local)
11338c2ecf20Sopenharmony_ci		return -ENODEV;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
11368c2ecf20Sopenharmony_ci	if (shost == NULL)
11378c2ecf20Sopenharmony_ci		return -ENOMEM;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	tgt = (struct sbp2_target *)shost->hostdata;
11408c2ecf20Sopenharmony_ci	dev_set_drvdata(&unit->device, tgt);
11418c2ecf20Sopenharmony_ci	tgt->unit = unit;
11428c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&tgt->lu_list);
11438c2ecf20Sopenharmony_ci	spin_lock_init(&tgt->lock);
11448c2ecf20Sopenharmony_ci	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	if (fw_device_enable_phys_dma(device) < 0)
11478c2ecf20Sopenharmony_ci		goto fail_shost_put;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	if (scsi_add_host_with_dma(shost, &unit->device,
11528c2ecf20Sopenharmony_ci				   device->card->device) < 0)
11538c2ecf20Sopenharmony_ci		goto fail_shost_put;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	/* implicit directory ID */
11568c2ecf20Sopenharmony_ci	tgt->directory_id = ((unit->directory - device->config_rom) * 4
11578c2ecf20Sopenharmony_ci			     + CSR_CONFIG_ROM) & 0xffffff;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	firmware_revision = SBP2_ROM_VALUE_MISSING;
11608c2ecf20Sopenharmony_ci	model		  = SBP2_ROM_VALUE_MISSING;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
11638c2ecf20Sopenharmony_ci			       &firmware_revision) < 0)
11648c2ecf20Sopenharmony_ci		goto fail_remove;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	sbp2_clamp_management_orb_timeout(tgt);
11678c2ecf20Sopenharmony_ci	sbp2_init_workarounds(tgt, model, firmware_revision);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	/*
11708c2ecf20Sopenharmony_ci	 * At S100 we can do 512 bytes per packet, at S200 1024 bytes,
11718c2ecf20Sopenharmony_ci	 * and so on up to 4096 bytes.  The SBP-2 max_payload field
11728c2ecf20Sopenharmony_ci	 * specifies the max payload size as 2 ^ (max_payload + 2), so
11738c2ecf20Sopenharmony_ci	 * if we set this to max_speed + 7, we get the right value.
11748c2ecf20Sopenharmony_ci	 */
11758c2ecf20Sopenharmony_ci	tgt->max_payload = min3(device->max_speed + 7, 10U,
11768c2ecf20Sopenharmony_ci				device->card->max_receive - 1);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	/* Do the login in a workqueue so we can easily reschedule retries. */
11798c2ecf20Sopenharmony_ci	list_for_each_entry(lu, &tgt->lu_list, link)
11808c2ecf20Sopenharmony_ci		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	return 0;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci fail_remove:
11858c2ecf20Sopenharmony_ci	sbp2_remove(unit);
11868c2ecf20Sopenharmony_ci	return -ENOMEM;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci fail_shost_put:
11898c2ecf20Sopenharmony_ci	scsi_host_put(shost);
11908c2ecf20Sopenharmony_ci	return -ENOMEM;
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_cistatic void sbp2_update(struct fw_unit *unit)
11948c2ecf20Sopenharmony_ci{
11958c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
11968c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu;
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	fw_device_enable_phys_dma(fw_parent_device(unit));
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/*
12018c2ecf20Sopenharmony_ci	 * Fw-core serializes sbp2_update() against sbp2_remove().
12028c2ecf20Sopenharmony_ci	 * Iteration over tgt->lu_list is therefore safe here.
12038c2ecf20Sopenharmony_ci	 */
12048c2ecf20Sopenharmony_ci	list_for_each_entry(lu, &tgt->lu_list, link) {
12058c2ecf20Sopenharmony_ci		sbp2_conditionally_block(lu);
12068c2ecf20Sopenharmony_ci		lu->retries = 0;
12078c2ecf20Sopenharmony_ci		sbp2_queue_work(lu, 0);
12088c2ecf20Sopenharmony_ci	}
12098c2ecf20Sopenharmony_ci}
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_cistatic void sbp2_remove(struct fw_unit *unit)
12128c2ecf20Sopenharmony_ci{
12138c2ecf20Sopenharmony_ci	struct fw_device *device = fw_parent_device(unit);
12148c2ecf20Sopenharmony_ci	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
12158c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu, *next;
12168c2ecf20Sopenharmony_ci	struct Scsi_Host *shost =
12178c2ecf20Sopenharmony_ci		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
12188c2ecf20Sopenharmony_ci	struct scsi_device *sdev;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	/* prevent deadlocks */
12218c2ecf20Sopenharmony_ci	sbp2_unblock(tgt);
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
12248c2ecf20Sopenharmony_ci		cancel_delayed_work_sync(&lu->work);
12258c2ecf20Sopenharmony_ci		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
12268c2ecf20Sopenharmony_ci		if (sdev) {
12278c2ecf20Sopenharmony_ci			scsi_remove_device(sdev);
12288c2ecf20Sopenharmony_ci			scsi_device_put(sdev);
12298c2ecf20Sopenharmony_ci		}
12308c2ecf20Sopenharmony_ci		if (lu->login_id != INVALID_LOGIN_ID) {
12318c2ecf20Sopenharmony_ci			int generation, node_id;
12328c2ecf20Sopenharmony_ci			/*
12338c2ecf20Sopenharmony_ci			 * tgt->node_id may be obsolete here if we failed
12348c2ecf20Sopenharmony_ci			 * during initial login or after a bus reset where
12358c2ecf20Sopenharmony_ci			 * the topology changed.
12368c2ecf20Sopenharmony_ci			 */
12378c2ecf20Sopenharmony_ci			generation = device->generation;
12388c2ecf20Sopenharmony_ci			smp_rmb(); /* node_id vs. generation */
12398c2ecf20Sopenharmony_ci			node_id    = device->node_id;
12408c2ecf20Sopenharmony_ci			sbp2_send_management_orb(lu, node_id, generation,
12418c2ecf20Sopenharmony_ci						 SBP2_LOGOUT_REQUEST,
12428c2ecf20Sopenharmony_ci						 lu->login_id, NULL);
12438c2ecf20Sopenharmony_ci		}
12448c2ecf20Sopenharmony_ci		fw_core_remove_address_handler(&lu->address_handler);
12458c2ecf20Sopenharmony_ci		list_del(&lu->link);
12468c2ecf20Sopenharmony_ci		kfree(lu);
12478c2ecf20Sopenharmony_ci	}
12488c2ecf20Sopenharmony_ci	scsi_remove_host(shost);
12498c2ecf20Sopenharmony_ci	dev_notice(&unit->device, "released target %d:0:0\n", shost->host_no);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	scsi_host_put(shost);
12528c2ecf20Sopenharmony_ci}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci#define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
12558c2ecf20Sopenharmony_ci#define SBP2_SW_VERSION_ENTRY	0x00010483
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_cistatic const struct ieee1394_device_id sbp2_id_table[] = {
12588c2ecf20Sopenharmony_ci	{
12598c2ecf20Sopenharmony_ci		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
12608c2ecf20Sopenharmony_ci				IEEE1394_MATCH_VERSION,
12618c2ecf20Sopenharmony_ci		.specifier_id = SBP2_UNIT_SPEC_ID_ENTRY,
12628c2ecf20Sopenharmony_ci		.version      = SBP2_SW_VERSION_ENTRY,
12638c2ecf20Sopenharmony_ci	},
12648c2ecf20Sopenharmony_ci	{ }
12658c2ecf20Sopenharmony_ci};
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_cistatic struct fw_driver sbp2_driver = {
12688c2ecf20Sopenharmony_ci	.driver   = {
12698c2ecf20Sopenharmony_ci		.owner  = THIS_MODULE,
12708c2ecf20Sopenharmony_ci		.name   = KBUILD_MODNAME,
12718c2ecf20Sopenharmony_ci		.bus    = &fw_bus_type,
12728c2ecf20Sopenharmony_ci	},
12738c2ecf20Sopenharmony_ci	.probe    = sbp2_probe,
12748c2ecf20Sopenharmony_ci	.update   = sbp2_update,
12758c2ecf20Sopenharmony_ci	.remove   = sbp2_remove,
12768c2ecf20Sopenharmony_ci	.id_table = sbp2_id_table,
12778c2ecf20Sopenharmony_ci};
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_cistatic void sbp2_unmap_scatterlist(struct device *card_device,
12808c2ecf20Sopenharmony_ci				   struct sbp2_command_orb *orb)
12818c2ecf20Sopenharmony_ci{
12828c2ecf20Sopenharmony_ci	scsi_dma_unmap(orb->cmd);
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT))
12858c2ecf20Sopenharmony_ci		dma_unmap_single(card_device, orb->page_table_bus,
12868c2ecf20Sopenharmony_ci				 sizeof(orb->page_table), DMA_TO_DEVICE);
12878c2ecf20Sopenharmony_ci}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_cistatic unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
12908c2ecf20Sopenharmony_ci{
12918c2ecf20Sopenharmony_ci	int sam_status;
12928c2ecf20Sopenharmony_ci	int sfmt = (sbp2_status[0] >> 6) & 0x03;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	if (sfmt == 2 || sfmt == 3) {
12958c2ecf20Sopenharmony_ci		/*
12968c2ecf20Sopenharmony_ci		 * Reserved for future standardization (2) or
12978c2ecf20Sopenharmony_ci		 * Status block format vendor-dependent (3)
12988c2ecf20Sopenharmony_ci		 */
12998c2ecf20Sopenharmony_ci		return DID_ERROR << 16;
13008c2ecf20Sopenharmony_ci	}
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	sense_data[0] = 0x70 | sfmt | (sbp2_status[1] & 0x80);
13038c2ecf20Sopenharmony_ci	sense_data[1] = 0x0;
13048c2ecf20Sopenharmony_ci	sense_data[2] = ((sbp2_status[1] << 1) & 0xe0) | (sbp2_status[1] & 0x0f);
13058c2ecf20Sopenharmony_ci	sense_data[3] = sbp2_status[4];
13068c2ecf20Sopenharmony_ci	sense_data[4] = sbp2_status[5];
13078c2ecf20Sopenharmony_ci	sense_data[5] = sbp2_status[6];
13088c2ecf20Sopenharmony_ci	sense_data[6] = sbp2_status[7];
13098c2ecf20Sopenharmony_ci	sense_data[7] = 10;
13108c2ecf20Sopenharmony_ci	sense_data[8] = sbp2_status[8];
13118c2ecf20Sopenharmony_ci	sense_data[9] = sbp2_status[9];
13128c2ecf20Sopenharmony_ci	sense_data[10] = sbp2_status[10];
13138c2ecf20Sopenharmony_ci	sense_data[11] = sbp2_status[11];
13148c2ecf20Sopenharmony_ci	sense_data[12] = sbp2_status[2];
13158c2ecf20Sopenharmony_ci	sense_data[13] = sbp2_status[3];
13168c2ecf20Sopenharmony_ci	sense_data[14] = sbp2_status[12];
13178c2ecf20Sopenharmony_ci	sense_data[15] = sbp2_status[13];
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	sam_status = sbp2_status[0] & 0x3f;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	switch (sam_status) {
13228c2ecf20Sopenharmony_ci	case SAM_STAT_GOOD:
13238c2ecf20Sopenharmony_ci	case SAM_STAT_CHECK_CONDITION:
13248c2ecf20Sopenharmony_ci	case SAM_STAT_CONDITION_MET:
13258c2ecf20Sopenharmony_ci	case SAM_STAT_BUSY:
13268c2ecf20Sopenharmony_ci	case SAM_STAT_RESERVATION_CONFLICT:
13278c2ecf20Sopenharmony_ci	case SAM_STAT_COMMAND_TERMINATED:
13288c2ecf20Sopenharmony_ci		return DID_OK << 16 | sam_status;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	default:
13318c2ecf20Sopenharmony_ci		return DID_ERROR << 16;
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci}
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_cistatic void complete_command_orb(struct sbp2_orb *base_orb,
13368c2ecf20Sopenharmony_ci				 struct sbp2_status *status)
13378c2ecf20Sopenharmony_ci{
13388c2ecf20Sopenharmony_ci	struct sbp2_command_orb *orb =
13398c2ecf20Sopenharmony_ci		container_of(base_orb, struct sbp2_command_orb, base);
13408c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(base_orb->lu->tgt);
13418c2ecf20Sopenharmony_ci	int result;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	if (status != NULL) {
13448c2ecf20Sopenharmony_ci		if (STATUS_GET_DEAD(*status))
13458c2ecf20Sopenharmony_ci			sbp2_agent_reset_no_wait(base_orb->lu);
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci		switch (STATUS_GET_RESPONSE(*status)) {
13488c2ecf20Sopenharmony_ci		case SBP2_STATUS_REQUEST_COMPLETE:
13498c2ecf20Sopenharmony_ci			result = DID_OK << 16;
13508c2ecf20Sopenharmony_ci			break;
13518c2ecf20Sopenharmony_ci		case SBP2_STATUS_TRANSPORT_FAILURE:
13528c2ecf20Sopenharmony_ci			result = DID_BUS_BUSY << 16;
13538c2ecf20Sopenharmony_ci			break;
13548c2ecf20Sopenharmony_ci		case SBP2_STATUS_ILLEGAL_REQUEST:
13558c2ecf20Sopenharmony_ci		case SBP2_STATUS_VENDOR_DEPENDENT:
13568c2ecf20Sopenharmony_ci		default:
13578c2ecf20Sopenharmony_ci			result = DID_ERROR << 16;
13588c2ecf20Sopenharmony_ci			break;
13598c2ecf20Sopenharmony_ci		}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci		if (result == DID_OK << 16 && STATUS_GET_LEN(*status) > 1)
13628c2ecf20Sopenharmony_ci			result = sbp2_status_to_sense_data(STATUS_GET_DATA(*status),
13638c2ecf20Sopenharmony_ci							   orb->cmd->sense_buffer);
13648c2ecf20Sopenharmony_ci	} else {
13658c2ecf20Sopenharmony_ci		/*
13668c2ecf20Sopenharmony_ci		 * If the orb completes with status == NULL, something
13678c2ecf20Sopenharmony_ci		 * went wrong, typically a bus reset happened mid-orb
13688c2ecf20Sopenharmony_ci		 * or when sending the write (less likely).
13698c2ecf20Sopenharmony_ci		 */
13708c2ecf20Sopenharmony_ci		result = DID_BUS_BUSY << 16;
13718c2ecf20Sopenharmony_ci		sbp2_conditionally_block(base_orb->lu);
13728c2ecf20Sopenharmony_ci	}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	dma_unmap_single(device->card->device, orb->base.request_bus,
13758c2ecf20Sopenharmony_ci			 sizeof(orb->request), DMA_TO_DEVICE);
13768c2ecf20Sopenharmony_ci	sbp2_unmap_scatterlist(device->card->device, orb);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	orb->cmd->result = result;
13798c2ecf20Sopenharmony_ci	orb->cmd->scsi_done(orb->cmd);
13808c2ecf20Sopenharmony_ci}
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_cistatic int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
13838c2ecf20Sopenharmony_ci		struct fw_device *device, struct sbp2_logical_unit *lu)
13848c2ecf20Sopenharmony_ci{
13858c2ecf20Sopenharmony_ci	struct scatterlist *sg = scsi_sglist(orb->cmd);
13868c2ecf20Sopenharmony_ci	int i, n;
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	n = scsi_dma_map(orb->cmd);
13898c2ecf20Sopenharmony_ci	if (n <= 0)
13908c2ecf20Sopenharmony_ci		goto fail;
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	/*
13938c2ecf20Sopenharmony_ci	 * Handle the special case where there is only one element in
13948c2ecf20Sopenharmony_ci	 * the scatter list by converting it to an immediate block
13958c2ecf20Sopenharmony_ci	 * request. This is also a workaround for broken devices such
13968c2ecf20Sopenharmony_ci	 * as the second generation iPod which doesn't support page
13978c2ecf20Sopenharmony_ci	 * tables.
13988c2ecf20Sopenharmony_ci	 */
13998c2ecf20Sopenharmony_ci	if (n == 1) {
14008c2ecf20Sopenharmony_ci		orb->request.data_descriptor.high =
14018c2ecf20Sopenharmony_ci			cpu_to_be32(lu->tgt->address_high);
14028c2ecf20Sopenharmony_ci		orb->request.data_descriptor.low  =
14038c2ecf20Sopenharmony_ci			cpu_to_be32(sg_dma_address(sg));
14048c2ecf20Sopenharmony_ci		orb->request.misc |=
14058c2ecf20Sopenharmony_ci			cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
14068c2ecf20Sopenharmony_ci		return 0;
14078c2ecf20Sopenharmony_ci	}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	for_each_sg(sg, sg, n, i) {
14108c2ecf20Sopenharmony_ci		orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
14118c2ecf20Sopenharmony_ci		orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
14128c2ecf20Sopenharmony_ci	}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	orb->page_table_bus =
14158c2ecf20Sopenharmony_ci		dma_map_single(device->card->device, orb->page_table,
14168c2ecf20Sopenharmony_ci			       sizeof(orb->page_table), DMA_TO_DEVICE);
14178c2ecf20Sopenharmony_ci	if (dma_mapping_error(device->card->device, orb->page_table_bus))
14188c2ecf20Sopenharmony_ci		goto fail_page_table;
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	/*
14218c2ecf20Sopenharmony_ci	 * The data_descriptor pointer is the one case where we need
14228c2ecf20Sopenharmony_ci	 * to fill in the node ID part of the address.  All other
14238c2ecf20Sopenharmony_ci	 * pointers assume that the data referenced reside on the
14248c2ecf20Sopenharmony_ci	 * initiator (i.e. us), but data_descriptor can refer to data
14258c2ecf20Sopenharmony_ci	 * on other nodes so we need to put our ID in descriptor.high.
14268c2ecf20Sopenharmony_ci	 */
14278c2ecf20Sopenharmony_ci	orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
14288c2ecf20Sopenharmony_ci	orb->request.data_descriptor.low  = cpu_to_be32(orb->page_table_bus);
14298c2ecf20Sopenharmony_ci	orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
14308c2ecf20Sopenharmony_ci					 COMMAND_ORB_DATA_SIZE(n));
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	return 0;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci fail_page_table:
14358c2ecf20Sopenharmony_ci	scsi_dma_unmap(orb->cmd);
14368c2ecf20Sopenharmony_ci fail:
14378c2ecf20Sopenharmony_ci	return -ENOMEM;
14388c2ecf20Sopenharmony_ci}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci/* SCSI stack integration */
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_cistatic int sbp2_scsi_queuecommand(struct Scsi_Host *shost,
14438c2ecf20Sopenharmony_ci				  struct scsi_cmnd *cmd)
14448c2ecf20Sopenharmony_ci{
14458c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = cmd->device->hostdata;
14468c2ecf20Sopenharmony_ci	struct fw_device *device = target_parent_device(lu->tgt);
14478c2ecf20Sopenharmony_ci	struct sbp2_command_orb *orb;
14488c2ecf20Sopenharmony_ci	int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
14518c2ecf20Sopenharmony_ci	if (orb == NULL)
14528c2ecf20Sopenharmony_ci		return SCSI_MLQUEUE_HOST_BUSY;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	/* Initialize rcode to something not RCODE_COMPLETE. */
14558c2ecf20Sopenharmony_ci	orb->base.rcode = -1;
14568c2ecf20Sopenharmony_ci	kref_init(&orb->base.kref);
14578c2ecf20Sopenharmony_ci	orb->cmd = cmd;
14588c2ecf20Sopenharmony_ci	orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
14598c2ecf20Sopenharmony_ci	orb->request.misc = cpu_to_be32(
14608c2ecf20Sopenharmony_ci		COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) |
14618c2ecf20Sopenharmony_ci		COMMAND_ORB_SPEED(device->max_speed) |
14628c2ecf20Sopenharmony_ci		COMMAND_ORB_NOTIFY);
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
14658c2ecf20Sopenharmony_ci		orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	generation = device->generation;
14688c2ecf20Sopenharmony_ci	smp_rmb();    /* sbp2_map_scatterlist looks at tgt->address_high */
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
14718c2ecf20Sopenharmony_ci		goto out;
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	orb->base.callback = complete_command_orb;
14768c2ecf20Sopenharmony_ci	orb->base.request_bus =
14778c2ecf20Sopenharmony_ci		dma_map_single(device->card->device, &orb->request,
14788c2ecf20Sopenharmony_ci			       sizeof(orb->request), DMA_TO_DEVICE);
14798c2ecf20Sopenharmony_ci	if (dma_mapping_error(device->card->device, orb->base.request_bus)) {
14808c2ecf20Sopenharmony_ci		sbp2_unmap_scatterlist(device->card->device, orb);
14818c2ecf20Sopenharmony_ci		goto out;
14828c2ecf20Sopenharmony_ci	}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
14858c2ecf20Sopenharmony_ci		      lu->command_block_agent_address + SBP2_ORB_POINTER);
14868c2ecf20Sopenharmony_ci	retval = 0;
14878c2ecf20Sopenharmony_ci out:
14888c2ecf20Sopenharmony_ci	kref_put(&orb->base.kref, free_orb);
14898c2ecf20Sopenharmony_ci	return retval;
14908c2ecf20Sopenharmony_ci}
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_cistatic int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
14938c2ecf20Sopenharmony_ci{
14948c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = sdev->hostdata;
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	/* (Re-)Adding logical units via the SCSI stack is not supported. */
14978c2ecf20Sopenharmony_ci	if (!lu)
14988c2ecf20Sopenharmony_ci		return -ENOSYS;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	sdev->allow_restart = 1;
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	/*
15038c2ecf20Sopenharmony_ci	 * SBP-2 does not require any alignment, but we set it anyway
15048c2ecf20Sopenharmony_ci	 * for compatibility with earlier versions of this driver.
15058c2ecf20Sopenharmony_ci	 */
15068c2ecf20Sopenharmony_ci	blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
15098c2ecf20Sopenharmony_ci		sdev->inquiry_len = 36;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	return 0;
15128c2ecf20Sopenharmony_ci}
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_cistatic int sbp2_scsi_slave_configure(struct scsi_device *sdev)
15158c2ecf20Sopenharmony_ci{
15168c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = sdev->hostdata;
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	sdev->use_10_for_rw = 1;
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	if (sbp2_param_exclusive_login)
15218c2ecf20Sopenharmony_ci		sdev->manage_start_stop = 1;
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	if (sdev->type == TYPE_ROM)
15248c2ecf20Sopenharmony_ci		sdev->use_10_for_ms = 1;
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	if (sdev->type == TYPE_DISK &&
15278c2ecf20Sopenharmony_ci	    lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
15288c2ecf20Sopenharmony_ci		sdev->skip_ms_page_8 = 1;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
15318c2ecf20Sopenharmony_ci		sdev->fix_capacity = 1;
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci	if (lu->tgt->workarounds & SBP2_WORKAROUND_POWER_CONDITION)
15348c2ecf20Sopenharmony_ci		sdev->start_stop_pwr_cond = 1;
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
15378c2ecf20Sopenharmony_ci		blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512);
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	return 0;
15408c2ecf20Sopenharmony_ci}
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci/*
15438c2ecf20Sopenharmony_ci * Called by scsi stack when something has really gone wrong.  Usually
15448c2ecf20Sopenharmony_ci * called when a command has timed-out for some reason.
15458c2ecf20Sopenharmony_ci */
15468c2ecf20Sopenharmony_cistatic int sbp2_scsi_abort(struct scsi_cmnd *cmd)
15478c2ecf20Sopenharmony_ci{
15488c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu = cmd->device->hostdata;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	dev_notice(lu_dev(lu), "sbp2_scsi_abort\n");
15518c2ecf20Sopenharmony_ci	sbp2_agent_reset(lu);
15528c2ecf20Sopenharmony_ci	sbp2_cancel_orbs(lu);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	return SUCCESS;
15558c2ecf20Sopenharmony_ci}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci/*
15588c2ecf20Sopenharmony_ci * Format of /sys/bus/scsi/devices/.../ieee1394_id:
15598c2ecf20Sopenharmony_ci * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
15608c2ecf20Sopenharmony_ci *
15618c2ecf20Sopenharmony_ci * This is the concatenation of target port identifier and logical unit
15628c2ecf20Sopenharmony_ci * identifier as per SAM-2...SAM-4 annex A.
15638c2ecf20Sopenharmony_ci */
15648c2ecf20Sopenharmony_cistatic ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
15658c2ecf20Sopenharmony_ci			struct device_attribute *attr, char *buf)
15668c2ecf20Sopenharmony_ci{
15678c2ecf20Sopenharmony_ci	struct scsi_device *sdev = to_scsi_device(dev);
15688c2ecf20Sopenharmony_ci	struct sbp2_logical_unit *lu;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	if (!sdev)
15718c2ecf20Sopenharmony_ci		return 0;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	lu = sdev->hostdata;
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	return sprintf(buf, "%016llx:%06x:%04x\n",
15768c2ecf20Sopenharmony_ci			(unsigned long long)lu->tgt->guid,
15778c2ecf20Sopenharmony_ci			lu->tgt->directory_id, lu->lun);
15788c2ecf20Sopenharmony_ci}
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_cistatic DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_cistatic struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
15838c2ecf20Sopenharmony_ci	&dev_attr_ieee1394_id,
15848c2ecf20Sopenharmony_ci	NULL
15858c2ecf20Sopenharmony_ci};
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_cistatic struct scsi_host_template scsi_driver_template = {
15888c2ecf20Sopenharmony_ci	.module			= THIS_MODULE,
15898c2ecf20Sopenharmony_ci	.name			= "SBP-2 IEEE-1394",
15908c2ecf20Sopenharmony_ci	.proc_name		= "sbp2",
15918c2ecf20Sopenharmony_ci	.queuecommand		= sbp2_scsi_queuecommand,
15928c2ecf20Sopenharmony_ci	.slave_alloc		= sbp2_scsi_slave_alloc,
15938c2ecf20Sopenharmony_ci	.slave_configure	= sbp2_scsi_slave_configure,
15948c2ecf20Sopenharmony_ci	.eh_abort_handler	= sbp2_scsi_abort,
15958c2ecf20Sopenharmony_ci	.this_id		= -1,
15968c2ecf20Sopenharmony_ci	.sg_tablesize		= SG_ALL,
15978c2ecf20Sopenharmony_ci	.max_segment_size	= SBP2_MAX_SEG_SIZE,
15988c2ecf20Sopenharmony_ci	.can_queue		= 1,
15998c2ecf20Sopenharmony_ci	.sdev_attrs		= sbp2_scsi_sysfs_attrs,
16008c2ecf20Sopenharmony_ci};
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
16038c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SCSI over IEEE1394");
16048c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
16058c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci/* Provide a module alias so root-on-sbp2 initrds don't break. */
16088c2ecf20Sopenharmony_ciMODULE_ALIAS("sbp2");
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_cistatic int __init sbp2_init(void)
16118c2ecf20Sopenharmony_ci{
16128c2ecf20Sopenharmony_ci	return driver_register(&sbp2_driver.driver);
16138c2ecf20Sopenharmony_ci}
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_cistatic void __exit sbp2_cleanup(void)
16168c2ecf20Sopenharmony_ci{
16178c2ecf20Sopenharmony_ci	driver_unregister(&sbp2_driver.driver);
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cimodule_init(sbp2_init);
16218c2ecf20Sopenharmony_cimodule_exit(sbp2_cleanup);
1622